Merge tag 'topic/drm-misc-2016-01-17' of git://anongit.freedesktop.org/drm-intel into drm-next

Since your main drm-next pull isn't out of the door yet I figured I might
as well flush out drm-misc instead of delaying for 4.6. It's really just
random stuff all over, biggest thing probably connector_mask tracking from
Maarten.

* tag 'topic/drm-misc-2016-01-17' of git://anongit.freedesktop.org/drm-intel: (24 commits)
  drm/fb_cma_helper: Remove implicit call to disable_unused_functions
  drm/sysfs: use kobj_to_dev()
  drm/i915: Init power domains early in driver load
  drm: Do not set connector->encoder in drivers
  apple-gmux: Add initial documentation
  drm: move MODULE_PARM_DESC to other file
  drm/edid: index CEA/HDMI mode tables using the VIC
  drm/atomic: Remove drm_atomic_connectors_for_crtc.
  drm/i915: Update connector_mask during readout, v2.
  drm: Remove opencoded drm_gem_object_release_handle()
  drm: Do not set outparam on error during GEM handle allocation
  drm/docs: more leftovers from the big vtable documentation pile
  drm/atomic-helper: Reject legacy flips on a disabled pipe
  drm/atomic: add connector mask to drm_crtc_state.
  drm/tegra: Use __drm_atomic_helper_reset_connector for subclassing connector state, v2.
  drm/atomic: Add __drm_atomic_helper_connector_reset, v2.
  drm/i915: Set connector_state->connector using the helper.
  drm: Use a normal idr allocation for the obj->name
  drm: Only bump object-reference count when adding first handle
  drm: Balance error path for GEM handle allocation
  ...
diff --git a/Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt b/Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt
new file mode 100644
index 0000000..ed5e0a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/etnaviv/etnaviv-drm.txt
@@ -0,0 +1,54 @@
+Etnaviv DRM master device
+=========================
+
+The Etnaviv DRM master device is a virtual device needed to list all
+Vivante GPU cores that comprise the GPU subsystem.
+
+Required properties:
+- compatible: Should be one of
+    "fsl,imx-gpu-subsystem"
+    "marvell,dove-gpu-subsystem"
+- cores: Should contain a list of phandles pointing to Vivante GPU devices
+
+example:
+
+gpu-subsystem {
+	compatible = "fsl,imx-gpu-subsystem";
+	cores = <&gpu_2d>, <&gpu_3d>;
+};
+
+
+Vivante GPU core devices
+========================
+
+Required properties:
+- compatible: Should be "vivante,gc"
+  A more specific compatible is not needed, as the cores contain chip
+  identification registers at fixed locations, which provide all the
+  necessary information to the driver.
+- reg: should be register base and length as documented in the
+  datasheet
+- interrupts: Should contain the cores interrupt line
+- clocks: should contain one clock for entry in clock-names
+  see Documentation/devicetree/bindings/clock/clock-bindings.txt
+- clock-names:
+   - "bus":    AXI/register clock
+   - "core":   GPU core clock
+   - "shader": Shader clock (only required if GPU has feature PIPE_3D)
+
+Optional properties:
+- power-domains: a power domain consumer specifier according to
+  Documentation/devicetree/bindings/power/power_domain.txt
+
+example:
+
+gpu_3d: gpu@00130000 {
+	compatible = "vivante,gc";
+	reg = <0x00130000 0x4000>;
+	interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&clks IMX6QDL_CLK_GPU3D_AXI>,
+	         <&clks IMX6QDL_CLK_GPU3D_CORE>,
+	         <&clks IMX6QDL_CLK_GPU3D_SHADER>;
+	clock-names = "bus", "core", "shader";
+	power-domains = <&gpc 1>;
+};
diff --git a/Documentation/devicetree/bindings/display/panel/boe,tv080wum-nl0.txt b/Documentation/devicetree/bindings/display/panel/boe,tv080wum-nl0.txt
new file mode 100644
index 0000000..50be5e2
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/boe,tv080wum-nl0.txt
@@ -0,0 +1,7 @@
+Boe Corporation 8.0" WUXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "boe,tv080wum-nl0"
+
+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/display/panel/innolux,g121x1-l03.txt b/Documentation/devicetree/bindings/display/panel/innolux,g121x1-l03.txt
new file mode 100644
index 0000000..6497446
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,g121x1-l03.txt
@@ -0,0 +1,7 @@
+Innolux Corporation 12.1" G121X1-L03 XGA (1024x768) TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,g121x1-l03"
+
+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/display/panel/kyo,tcg121xglp.txt b/Documentation/devicetree/bindings/display/panel/kyo,tcg121xglp.txt
new file mode 100644
index 0000000..a8e940f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/kyo,tcg121xglp.txt
@@ -0,0 +1,7 @@
+Kyocera Corporation 12.1" XGA (1024x768) TFT LCD panel
+
+Required properties:
+- compatible: should be "kyo,tcg121xglp"
+
+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/display/panel/panasonic,vvx10f034n00.txt b/Documentation/devicetree/bindings/display/panel/panasonic,vvx10f034n00.txt
new file mode 100644
index 0000000..37dedf6
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/panasonic,vvx10f034n00.txt
@@ -0,0 +1,20 @@
+Panasonic 10" WUXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "panasonic,vvx10f034n00"
+- reg: DSI virtual channel of the peripheral
+- power-supply: phandle of the regulator that provides the supply voltage
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+	mdss_dsi@fd922800 {
+		panel@0 {
+			compatible = "panasonic,vvx10f034n00";
+			reg = <0>;
+			power-supply = <&vreg_vsp>;
+			backlight = <&lp8566_wled>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/display/panel/qiaodian,qd43003c0-40.txt b/Documentation/devicetree/bindings/display/panel/qiaodian,qd43003c0-40.txt
new file mode 100644
index 0000000..0fbdab8
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/qiaodian,qd43003c0-40.txt
@@ -0,0 +1,7 @@
+QiaoDian XianShi Corporation 4"3 TFT LCD panel
+
+Required properties:
+- compatible: should be "qiaodian,qd43003c0-40"
+
+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/display/panel/sharp,ls043t1le01.txt b/Documentation/devicetree/bindings/display/panel/sharp,ls043t1le01.txt
new file mode 100644
index 0000000..3770a11
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/sharp,ls043t1le01.txt
@@ -0,0 +1,22 @@
+Sharp Microelectronics 4.3" qHD TFT LCD panel
+
+Required properties:
+- compatible: should be "sharp,ls043t1le01-qhd"
+- reg: DSI virtual channel of the peripheral
+- power-supply: phandle of the regulator that provides the supply voltage
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+- reset-gpios: a GPIO spec for the reset pin
+
+Example:
+
+	mdss_dsi@fd922800 {
+		panel@0 {
+			compatible = "sharp,ls043t1le01-qhd";
+			reg = <0>;
+			avdd-supply = <&pm8941_l22>;
+			backlight = <&pm8941_wled>;
+			reset-gpios = <&pm8941_gpios 19 GPIO_ACTIVE_HIGH>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
new file mode 100644
index 0000000..1753f0c
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
@@ -0,0 +1,60 @@
+Rockchip specific extensions to the Synopsys Designware MIPI DSI
+================================
+
+Required properties:
+- #address-cells: Should be <1>.
+- #size-cells: Should be <0>.
+- compatible: "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi".
+- reg: Represent the physical address range of the controller.
+- interrupts: Represent the controller's interrupt to the CPU(s).
+- clocks, clock-names: Phandles to the controller's pll reference
+  clock(ref) and APB clock(pclk), as described in [1].
+- rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
+- ports: contain a port node with endpoint definitions as defined in [2].
+  For vopb,set the reg = <0> and set the reg = <1> for vopl.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/media/video-interfaces.txt
+
+Example:
+	mipi_dsi: mipi@ff960000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi";
+		reg = <0xff960000 0x4000>;
+		interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_MIPI_24M>, <&cru PCLK_MIPI_DSI0>;
+		clock-names = "ref", "pclk";
+		rockchip,grf = <&grf>;
+		status = "okay";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			mipi_in: port {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				mipi_in_vopb: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vopb_out_mipi>;
+				};
+				mipi_in_vopl: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&vopl_out_mipi>;
+				};
+			};
+		};
+
+		panel {
+			compatible ="boe,tv080wum-nl0";
+			reg = <0>;
+
+			enable-gpios = <&gpio7 3 GPIO_ACTIVE_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&lcd_en>;
+			backlight = <&backlight>;
+			status = "okay";
+		};
+	};
diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
index d15351f..5489b59 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
@@ -7,6 +7,7 @@
 Required properties:
 - compatible: value should be one of the following
 		"rockchip,rk3288-vop";
+		"rockchip,rk3036-vop";
 
 - interrupts: should contain a list of all VOP IP block interrupts in the
 		 order: VSYNC, LCD_SYSTEM. The interrupt specifier
diff --git a/Documentation/devicetree/bindings/dma/ti-edma.txt b/Documentation/devicetree/bindings/dma/ti-edma.txt
index d3d0a4f..079b42a 100644
--- a/Documentation/devicetree/bindings/dma/ti-edma.txt
+++ b/Documentation/devicetree/bindings/dma/ti-edma.txt
@@ -22,8 +22,7 @@
 Optional properties:
 - ti,hwmods:	Name of the hwmods associated to the eDMA CC
 - ti,edma-memcpy-channels: List of channels allocated to be used for memcpy, iow
-		these channels will be SW triggered channels. The list must
-		contain 16 bits numbers, see example.
+		these channels will be SW triggered channels. See example.
 - ti,edma-reserved-slot-ranges: PaRAM slot ranges which should not be used by
 		the driver, they are allocated to be used by for example the
 		DSP. See example.
@@ -56,10 +55,9 @@
 	ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 7>, <&edma_tptc2 0>;
 
 	/* Channel 20 and 21 is allocated for memcpy */
-	ti,edma-memcpy-channels = /bits/ 16 <20 21>;
-	/* The following PaRAM slots are reserved: 35-45 and 100-110 */
-	ti,edma-reserved-slot-ranges = /bits/ 16 <35 10>,
-				       /bits/ 16 <100 10>;
+	ti,edma-memcpy-channels = <20 21>;
+	/* The following PaRAM slots are reserved: 35-44 and 100-109 */
+	ti,edma-reserved-slot-ranges = <35 10>, <100 10>;
 };
 
 edma_tptc0: tptc@49800000 {
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
index f2455c5..120bc49 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
@@ -11,6 +11,10 @@
       0 = active high
       1 = active low
 
+Optional properties:
+- little-endian : GPIO registers are used as little endian. If not
+                  present registers are used as big endian by default.
+
 Example:
 
 gpio0: gpio@1100 {
diff --git a/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt b/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt
index b9c32f6..4357e49 100644
--- a/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt
+++ b/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt
@@ -12,7 +12,7 @@
 Required subnode-properties:
 	- label: Descriptive name of the key.
 	- linux,code: Keycode to emit.
-	- channel: Channel this key is attached to, mut be 0 or 1.
+	- channel: Channel this key is attached to, must be 0 or 1.
 	- voltage: Voltage in µV at lradc input when this key is pressed.
 
 Example:
diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt
index f1e2a02..1c63e40 100644
--- a/Documentation/devicetree/bindings/mtd/partition.txt
+++ b/Documentation/devicetree/bindings/mtd/partition.txt
@@ -6,7 +6,9 @@
 as RedBoot.
 
 The partition table should be a subnode of the mtd node and should be named
-'partitions'. Partitions are defined in subnodes of the partitions node.
+'partitions'. This node should have the following property:
+- compatible : (required) must be "fixed-partitions"
+Partitions are then defined in subnodes of the partitions node.
 
 For backwards compatibility partitions as direct subnodes of the mtd device are
 supported. This use is discouraged.
@@ -36,6 +38,7 @@
 
 flash@0 {
 	partitions {
+		compatible = "fixed-partitions";
 		#address-cells = <1>;
 		#size-cells = <1>;
 
@@ -53,6 +56,7 @@
 
 flash@1 {
 	partitions {
+		compatible = "fixed-partitions";
 		#address-cells = <1>;
 		#size-cells = <2>;
 
@@ -66,6 +70,7 @@
 
 flash@2 {
 	partitions {
+		compatible = "fixed-partitions";
 		#address-cells = <2>;
 		#size-cells = <2>;
 
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 55df1d4..b123731 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -33,6 +33,7 @@
 avago	Avago Technologies
 avic	Shanghai AVIC Optoelectronics Co., Ltd.
 axis	Axis Communications AB
+boe	BOE Technology Group Co., Ltd.
 bosch	Bosch Sensortec GmbH
 boundary	Boundary Devices Inc.
 brcm	Broadcom Corporation
@@ -123,6 +124,7 @@
 karo	Ka-Ro electronics GmbH
 keymile	Keymile GmbH
 kinetic Kinetic Technologies
+kyo	Kyocera Corporation
 lacie	LaCie
 lantiq	Lantiq Semiconductor
 lenovo	Lenovo Group Ltd.
@@ -180,6 +182,7 @@
 qcom	Qualcomm Technologies, Inc
 qemu	QEMU, a generic and open source machine emulator and virtualizer
 qi	Qi Hardware
+qiaodian	QiaoDian XianShi Corporation
 qnap	QNAP Systems, Inc.
 radxa	Radxa
 raidsonic	RaidSonic Technology GmbH
@@ -238,6 +241,7 @@
 variscite	Variscite Ltd.
 via	VIA Technologies, Inc.
 virtio	Virtual I/O Device Specification, developed by the OASIS consortium
+vivante	Vivante Corporation
 voipac	Voipac Technologies s.r.o.
 wexler	Wexler
 winbond Winbond Electronics corp.
diff --git a/Documentation/networking/e100.txt b/Documentation/networking/e100.txt
index f862cf3..42ddbd4 100644
--- a/Documentation/networking/e100.txt
+++ b/Documentation/networking/e100.txt
@@ -181,17 +181,3 @@
 If an issue is identified with the released source code on the supported
 kernel with a supported adapter, email the specific information related to the
 issue to e1000-devel@lists.sourceforge.net.
-
-
-License
-=======
-
-This software program is released under the terms of a license agreement
-between you ('Licensee') and Intel. Do not use or load this software or any
-associated materials (collectively, the 'Software') until you have carefully
-read the full terms and conditions of the file COPYING located in this software
-package. By loading or using the Software, you agree to the terms of this
-Agreement. If you do not agree with the terms of this Agreement, do not install
-or use the Software.
-
-* Other names and brands may be claimed as the property of others.
diff --git a/MAINTAINERS b/MAINTAINERS
index 69c8a9c..32eda9d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2975,6 +2975,7 @@
 CONTROL GROUP - MEMORY RESOURCE CONTROLLER (MEMCG)
 M:	Johannes Weiner <hannes@cmpxchg.org>
 M:	Michal Hocko <mhocko@kernel.org>
+M:	Vladimir Davydov <vdavydov@virtuozzo.com>
 L:	cgroups@vger.kernel.org
 L:	linux-mm@kvack.org
 S:	Maintained
@@ -3743,6 +3744,15 @@
 F:	drivers/gpu/drm/sti
 F:	Documentation/devicetree/bindings/display/st,stih4xx.txt
 
+DRM DRIVERS FOR VIVANTE GPU IP
+M:	Lucas Stach <l.stach@pengutronix.de>
+R:	Russell King <linux+etnaviv@arm.linux.org.uk>
+R:	Christian Gmeiner <christian.gmeiner@gmail.com>
+L:	dri-devel@lists.freedesktop.org
+S:	Maintained
+F:	drivers/gpu/drm/etnaviv
+F:	Documentation/devicetree/bindings/display/etnaviv
+
 DSBR100 USB FM RADIO DRIVER
 M:	Alexey Klimov <klimov.linux@gmail.com>
 L:	linux-media@vger.kernel.org
@@ -5577,7 +5587,7 @@
 R:	Shannon Nelson <shannon.nelson@intel.com>
 R:	Carolyn Wyborny <carolyn.wyborny@intel.com>
 R:	Don Skidmore <donald.c.skidmore@intel.com>
-R:	Matthew Vick <matthew.vick@intel.com>
+R:	Bruce Allan <bruce.w.allan@intel.com>
 R:	John Ronciak <john.ronciak@intel.com>
 R:	Mitch Williams <mitch.a.williams@intel.com>
 L:	intel-wired-lan@lists.osuosl.org
@@ -8286,7 +8296,7 @@
 F:	kernel/delayacct.c
 
 PERFORMANCE EVENTS SUBSYSTEM
-M:	Peter Zijlstra <a.p.zijlstra@chello.nl>
+M:	Peter Zijlstra <peterz@infradead.org>
 M:	Ingo Molnar <mingo@redhat.com>
 M:	Arnaldo Carvalho de Melo <acme@kernel.org>
 L:	linux-kernel@vger.kernel.org
@@ -8379,6 +8389,14 @@
 S:	Maintained
 F:	drivers/pinctrl/samsung/
 
+PIN CONTROLLER - SINGLE
+M:	Tony Lindgren <tony@atomide.com>
+M:	Haojian Zhuang <haojian.zhuang@linaro.org>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:	linux-omap@vger.kernel.org
+S:	Maintained
+F:	drivers/pinctrl/pinctrl-single.c
+
 PIN CONTROLLER - ST SPEAR
 M:	Viresh Kumar <vireshk@kernel.org>
 L:	spear-devel@list.st.com
@@ -8945,6 +8963,13 @@
 F:	Documentation/rpmsg.txt
 F:	include/linux/rpmsg.h
 
+RENESAS ETHERNET DRIVERS
+R:	Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+L:	netdev@vger.kernel.org
+L:	linux-sh@vger.kernel.org
+F:	drivers/net/ethernet/renesas/
+F:	include/linux/sh_eth.h
+
 RESET CONTROLLER FRAMEWORK
 M:	Philipp Zabel <p.zabel@pengutronix.de>
 S:	Maintained
diff --git a/Makefile b/Makefile
index d644f6e..4e2b18d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 4
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc6
 NAME = Blurry Fish Butt
 
 # *DOCUMENTATION*
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 2c2ac3f..6312f60 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -445,6 +445,7 @@
 	  However some customers have peripherals mapped at this addr, so
 	  Linux needs to be scooted a bit.
 	  If you don't know what the above means, leave this setting alone.
+	  This needs to match memory start address specified in Device Tree
 
 config HIGHMEM
 	bool "High Memory Support"
diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index f3db321..44a578c 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -46,6 +46,7 @@
 			snps,pbl = < 32 >;
 			clocks = <&apbclk>;
 			clock-names = "stmmaceth";
+			max-speed = <100>;
 		};
 
 		ehci@0x40000 {
diff --git a/arch/arc/boot/dts/nsim_hs.dts b/arch/arc/boot/dts/nsim_hs.dts
index b0eb0e7..fc81879 100644
--- a/arch/arc/boot/dts/nsim_hs.dts
+++ b/arch/arc/boot/dts/nsim_hs.dts
@@ -17,7 +17,8 @@
 
 	memory {
 		device_type = "memory";
-		reg = <0x0 0x80000000 0x0 0x40000000	/* 1 GB low mem */
+		/* CONFIG_LINUX_LINK_BASE needs to match low mem start */
+		reg = <0x0 0x80000000 0x0 0x20000000	/* 512 MB low mem */
 		       0x1 0x00000000 0x0 0x40000000>;	/* 1 GB highmem */
 	};
 
diff --git a/arch/arc/include/asm/mach_desc.h b/arch/arc/include/asm/mach_desc.h
index 6ff657a..c28e6c3 100644
--- a/arch/arc/include/asm/mach_desc.h
+++ b/arch/arc/include/asm/mach_desc.h
@@ -23,7 +23,7 @@
  * @dt_compat:		Array of device tree 'compatible' strings
  * 			(XXX: although only 1st entry is looked at)
  * @init_early:		Very early callback [called from setup_arch()]
- * @init_cpu_smp:	for each CPU as it is coming up (SMP as well as UP)
+ * @init_per_cpu:	for each CPU as it is coming up (SMP as well as UP)
  * 			[(M):init_IRQ(), (o):start_kernel_secondary()]
  * @init_machine:	arch initcall level callback (e.g. populate static
  * 			platform devices or parse Devicetree)
@@ -35,7 +35,7 @@
 	const char		**dt_compat;
 	void			(*init_early)(void);
 #ifdef CONFIG_SMP
-	void			(*init_cpu_smp)(unsigned int);
+	void			(*init_per_cpu)(unsigned int);
 #endif
 	void			(*init_machine)(void);
 	void			(*init_late)(void);
diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
index 133c867..9913804 100644
--- a/arch/arc/include/asm/smp.h
+++ b/arch/arc/include/asm/smp.h
@@ -48,7 +48,7 @@
  * @init_early_smp:	A SMP specific h/w block can init itself
  * 			Could be common across platforms so not covered by
  * 			mach_desc->init_early()
- * @init_irq_cpu:	Called for each core so SMP h/w block driver can do
+ * @init_per_cpu:	Called for each core so SMP h/w block driver can do
  * 			any needed setup per cpu (e.g. IPI request)
  * @cpu_kick:		For Master to kickstart a cpu (optionally at a PC)
  * @ipi_send:		To send IPI to a @cpu
@@ -57,7 +57,7 @@
 struct plat_smp_ops {
 	const char 	*info;
 	void		(*init_early_smp)(void);
-	void		(*init_irq_cpu)(int cpu);
+	void		(*init_per_cpu)(int cpu);
 	void		(*cpu_kick)(int cpu, unsigned long pc);
 	void		(*ipi_send)(int cpu);
 	void		(*ipi_clear)(int irq);
diff --git a/arch/arc/include/asm/unwind.h b/arch/arc/include/asm/unwind.h
index 7ca628b..c11a25b 100644
--- a/arch/arc/include/asm/unwind.h
+++ b/arch/arc/include/asm/unwind.h
@@ -112,7 +112,6 @@
 
 extern int arc_unwind(struct unwind_frame_info *frame);
 extern void arc_unwind_init(void);
-extern void arc_unwind_setup(void);
 extern void *unwind_add_table(struct module *module, const void *table_start,
 			      unsigned long table_size);
 extern void unwind_remove_table(void *handle, int init_only);
@@ -152,9 +151,6 @@
 {
 }
 
-static inline void arc_unwind_setup(void)
-{
-}
 #define unwind_add_table(a, b, c)
 #define unwind_remove_table(a, b)
 
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 26c1568..0394f9f 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -106,10 +106,21 @@
 static int arcv2_irq_map(struct irq_domain *d, unsigned int irq,
 			 irq_hw_number_t hw)
 {
-	if (irq == TIMER0_IRQ || irq == IPI_IRQ)
+	/*
+	 * core intc IRQs [16, 23]:
+	 * Statically assigned always private-per-core (Timers, WDT, IPI, PCT)
+	 */
+	if (hw < 24) {
+		/*
+		 * A subsequent request_percpu_irq() fails if percpu_devid is
+		 * not set. That in turns sets NOAUTOEN, meaning each core needs
+		 * to call enable_percpu_irq()
+		 */
+		irq_set_percpu_devid(irq);
 		irq_set_chip_and_handler(irq, &arcv2_irq_chip, handle_percpu_irq);
-	else
+	} else {
 		irq_set_chip_and_handler(irq, &arcv2_irq_chip, handle_level_irq);
+	}
 
 	return 0;
 }
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 2ee2265..ba17f85 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -29,11 +29,11 @@
 
 #ifdef CONFIG_SMP
 	/* a SMP H/w block could do IPI IRQ request here */
-	if (plat_smp_ops.init_irq_cpu)
-		plat_smp_ops.init_irq_cpu(smp_processor_id());
+	if (plat_smp_ops.init_per_cpu)
+		plat_smp_ops.init_per_cpu(smp_processor_id());
 
-	if (machine_desc->init_cpu_smp)
-		machine_desc->init_cpu_smp(smp_processor_id());
+	if (machine_desc->init_per_cpu)
+		machine_desc->init_per_cpu(smp_processor_id());
 #endif
 }
 
@@ -51,6 +51,18 @@
 	set_irq_regs(old_regs);
 }
 
+/*
+ * API called for requesting percpu interrupts - called by each CPU
+ *  - For boot CPU, actually request the IRQ with genirq core + enables
+ *  - For subsequent callers only enable called locally
+ *
+ * Relies on being called by boot cpu first (i.e. request called ahead) of
+ * any enable as expected by genirq. Hence Suitable only for TIMER, IPI
+ * which are guaranteed to be setup on boot core first.
+ * Late probed peripherals such as perf can't use this as there no guarantee
+ * of being called on boot CPU first.
+ */
+
 void arc_request_percpu_irq(int irq, int cpu,
                             irqreturn_t (*isr)(int irq, void *dev),
                             const char *irq_nm,
@@ -60,14 +72,17 @@
 	if (!cpu) {
 		int rc;
 
+#ifdef CONFIG_ISA_ARCOMPACT
 		/*
-		 * These 2 calls are essential to making percpu IRQ APIs work
-		 * Ideally these details could be hidden in irq chip map function
-		 * but the issue is IPIs IRQs being static (non-DT) and platform
-		 * specific, so we can't identify them there.
+		 * A subsequent request_percpu_irq() fails if percpu_devid is
+		 * not set. That in turns sets NOAUTOEN, meaning each core needs
+		 * to call enable_percpu_irq()
+		 *
+		 * For ARCv2, this is done in irq map function since we know
+		 * which irqs are strictly per cpu
 		 */
 		irq_set_percpu_devid(irq);
-		irq_modify_status(irq, IRQ_NOAUTOEN, 0);  /* @irq, @clr, @set */
+#endif
 
 		rc = request_percpu_irq(irq, isr, irq_nm, percpu_dev);
 		if (rc)
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 74a9b07..bd237ac 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -132,7 +132,7 @@
 struct plat_smp_ops plat_smp_ops = {
 	.info		= smp_cpuinfo_buf,
 	.init_early_smp	= mcip_probe_n_setup,
-	.init_irq_cpu	= mcip_setup_per_cpu,
+	.init_per_cpu	= mcip_setup_per_cpu,
 	.ipi_send	= mcip_ipi_send,
 	.ipi_clear	= mcip_ipi_clear,
 };
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index 0c08bb1..8b134cf 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -428,12 +428,11 @@
 
 #endif /* CONFIG_ISA_ARCV2 */
 
-void arc_cpu_pmu_irq_init(void)
+static void arc_cpu_pmu_irq_init(void *data)
 {
-	struct arc_pmu_cpu *pmu_cpu = this_cpu_ptr(&arc_pmu_cpu);
+	int irq = *(int *)data;
 
-	arc_request_percpu_irq(arc_pmu->irq, smp_processor_id(), arc_pmu_intr,
-			       "ARC perf counters", pmu_cpu);
+	enable_percpu_irq(irq, IRQ_TYPE_NONE);
 
 	/* Clear all pending interrupt flags */
 	write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
@@ -515,7 +514,6 @@
 
 	if (has_interrupts) {
 		int irq = platform_get_irq(pdev, 0);
-		unsigned long flags;
 
 		if (irq < 0) {
 			pr_err("Cannot get IRQ number for the platform\n");
@@ -524,24 +522,12 @@
 
 		arc_pmu->irq = irq;
 
-		/*
-		 * arc_cpu_pmu_irq_init() needs to be called on all cores for
-		 * their respective local PMU.
-		 * However we use opencoded on_each_cpu() to ensure it is called
-		 * on core0 first, so that arc_request_percpu_irq() sets up
-		 * AUTOEN etc. Otherwise enable_percpu_irq() fails to enable
-		 * perf IRQ on non master cores.
-		 * see arc_request_percpu_irq()
-		 */
-		preempt_disable();
-		local_irq_save(flags);
-		arc_cpu_pmu_irq_init();
-		local_irq_restore(flags);
-		smp_call_function((smp_call_func_t)arc_cpu_pmu_irq_init, 0, 1);
-		preempt_enable();
+		/* intc map function ensures irq_set_percpu_devid() called */
+		request_percpu_irq(irq, arc_pmu_intr, "ARC perf counters",
+				   this_cpu_ptr(&arc_pmu_cpu));
 
-		/* Clean all pending interrupt flags */
-		write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
+		on_each_cpu(arc_cpu_pmu_irq_init, &irq, 1);
+
 	} else
 		arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index c33e77c..e1b8744 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -429,7 +429,6 @@
 #endif
 
 	arc_unwind_init();
-	arc_unwind_setup();
 }
 
 static int __init customize_machine(void)
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index 5805878..ef6e9e1 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -132,11 +132,11 @@
 	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
 
 	/* Some SMP H/w setup - for each cpu */
-	if (plat_smp_ops.init_irq_cpu)
-		plat_smp_ops.init_irq_cpu(cpu);
+	if (plat_smp_ops.init_per_cpu)
+		plat_smp_ops.init_per_cpu(cpu);
 
-	if (machine_desc->init_cpu_smp)
-		machine_desc->init_cpu_smp(cpu);
+	if (machine_desc->init_per_cpu)
+		machine_desc->init_per_cpu(cpu);
 
 	arc_local_timer_setup();
 
diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c
index 7352475..cf2828a 100644
--- a/arch/arc/kernel/unwind.c
+++ b/arch/arc/kernel/unwind.c
@@ -170,6 +170,23 @@
 
 static unsigned long read_pointer(const u8 **pLoc,
 				  const void *end, signed ptrType);
+static void init_unwind_hdr(struct unwind_table *table,
+			    void *(*alloc) (unsigned long));
+
+/*
+ * wrappers for header alloc (vs. calling one vs. other at call site)
+ * to elide section mismatches warnings
+ */
+static void *__init unw_hdr_alloc_early(unsigned long sz)
+{
+	return __alloc_bootmem_nopanic(sz, sizeof(unsigned int),
+				       MAX_DMA_ADDRESS);
+}
+
+static void *unw_hdr_alloc(unsigned long sz)
+{
+	return kmalloc(sz, GFP_KERNEL);
+}
 
 static void init_unwind_table(struct unwind_table *table, const char *name,
 			      const void *core_start, unsigned long core_size,
@@ -209,6 +226,8 @@
 			  __start_unwind, __end_unwind - __start_unwind,
 			  NULL, 0);
 	  /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
+
+	init_unwind_hdr(&root_table, unw_hdr_alloc_early);
 }
 
 static const u32 bad_cie, not_fde;
@@ -241,8 +260,8 @@
 	e2->fde = v;
 }
 
-static void __init setup_unwind_table(struct unwind_table *table,
-				      void *(*alloc) (unsigned long))
+static void init_unwind_hdr(struct unwind_table *table,
+			    void *(*alloc) (unsigned long))
 {
 	const u8 *ptr;
 	unsigned long tableSize = table->size, hdrSize;
@@ -274,13 +293,13 @@
 		const u32 *cie = cie_for_fde(fde, table);
 		signed ptrType;
 
-		if (cie == &not_fde)
+		if (cie == &not_fde)	/* only process FDE here */
 			continue;
 		if (cie == NULL || cie == &bad_cie)
-			return;
+			continue;	/* say FDE->CIE.version != 1 */
 		ptrType = fde_pointer_type(cie);
 		if (ptrType < 0)
-			return;
+			continue;
 
 		ptr = (const u8 *)(fde + 2);
 		if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
@@ -300,9 +319,11 @@
 
 	hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
 	    + 2 * n * sizeof(unsigned long);
+
 	header = alloc(hdrSize);
 	if (!header)
 		return;
+
 	header->version = 1;
 	header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
 	header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
@@ -322,6 +343,10 @@
 
 		if (fde[1] == 0xffffffff)
 			continue;	/* this is a CIE */
+
+		if (*(u8 *)(cie + 2) != 1)
+			continue;	/* FDE->CIE.version not supported */
+
 		ptr = (const u8 *)(fde + 2);
 		header->table[n].start = read_pointer(&ptr,
 						      (const u8 *)(fde + 1) +
@@ -342,18 +367,6 @@
 	table->header = (const void *)header;
 }
 
-static void *__init balloc(unsigned long sz)
-{
-	return __alloc_bootmem_nopanic(sz,
-				       sizeof(unsigned int),
-				       __pa(MAX_DMA_ADDRESS));
-}
-
-void __init arc_unwind_setup(void)
-{
-	setup_unwind_table(&root_table, balloc);
-}
-
 #ifdef CONFIG_MODULES
 
 static struct unwind_table *last_table;
@@ -377,6 +390,8 @@
 			  table_start, table_size,
 			  NULL, 0);
 
+	init_unwind_hdr(table, unw_hdr_alloc);
+
 #ifdef UNWIND_DEBUG
 	unw_debug("Table added for [%s] %lx %lx\n",
 		module->name, table->core.pc, table->core.range);
@@ -439,6 +454,7 @@
 	info.init_only = init_only;
 
 	unlink_table(&info); /* XXX: SMP */
+	kfree(table->header);
 	kfree(table);
 }
 
@@ -507,7 +523,8 @@
 
 	if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
 	    || (*cie & (sizeof(*cie) - 1))
-	    || (cie[1] != 0xffffffff))
+	    || (cie[1] != 0xffffffff)
+	    || ( *(u8 *)(cie + 2) != 1))   /* version 1 supported */
 		return NULL;	/* this is not a (valid) CIE */
 	return cie;
 }
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index a9305b5..7d2c4fb 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -51,7 +51,9 @@
 	int in_use = 0;
 
 	if (!low_mem_sz) {
-		BUG_ON(base != low_mem_start);
+		if (base != low_mem_start)
+			panic("CONFIG_LINUX_LINK_BASE != DT memory { }");
+
 		low_mem_sz = size;
 		in_use = 1;
 	} else {
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index d83ff9c..de8791a 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -74,7 +74,7 @@
 		reg = <0x48240200 0x100>;
 		interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-parent = <&gic>;
-		clocks = <&dpll_mpu_m2_ck>;
+		clocks = <&mpu_periphclk>;
 	};
 
 	local_timer: timer@48240600 {
@@ -82,7 +82,7 @@
 		reg = <0x48240600 0x100>;
 		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-parent = <&gic>;
-		clocks = <&dpll_mpu_m2_ck>;
+		clocks = <&mpu_periphclk>;
 	};
 
 	l2-cache-controller@48242000 {
diff --git a/arch/arm/boot/dts/am43xx-clocks.dtsi b/arch/arm/boot/dts/am43xx-clocks.dtsi
index cc88728..a38af2b 100644
--- a/arch/arm/boot/dts/am43xx-clocks.dtsi
+++ b/arch/arm/boot/dts/am43xx-clocks.dtsi
@@ -259,6 +259,14 @@
 		ti,invert-autoidle-bit;
 	};
 
+	mpu_periphclk: mpu_periphclk {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_mpu_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
 	dpll_ddr_ck: dpll_ddr_ck {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-clock";
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index ad6de73..e74df32 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -184,6 +184,7 @@
 							regulator-name = "VDD_SDHC_1V8";
 							regulator-min-microvolt = <1800000>;
 							regulator-max-microvolt = <1800000>;
+							regulator-always-on;
 						};
 					};
 				};
diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index 8ea177f..fb1da99 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -118,7 +118,8 @@
 		sdhci0: sdhci@ab0000 {
 			compatible = "mrvl,pxav3-mmc";
 			reg = <0xab0000 0x200>;
-			clocks = <&chip_clk CLKID_SDIO1XIN>;
+			clocks = <&chip_clk CLKID_SDIO1XIN>, <&chip_clk CLKID_SDIO>;
+			clock-names = "io", "core";
 			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
@@ -126,7 +127,8 @@
 		sdhci1: sdhci@ab0800 {
 			compatible = "mrvl,pxav3-mmc";
 			reg = <0xab0800 0x200>;
-			clocks = <&chip_clk CLKID_SDIO1XIN>;
+			clocks = <&chip_clk CLKID_SDIO1XIN>, <&chip_clk CLKID_SDIO>;
+			clock-names = "io", "core";
 			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
@@ -135,7 +137,7 @@
 			compatible = "mrvl,pxav3-mmc";
 			reg = <0xab1000 0x200>;
 			interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&chip_clk CLKID_NFC_ECC>, <&chip_clk CLKID_NFC>;
+			clocks = <&chip_clk CLKID_NFC_ECC>, <&chip_clk CLKID_SDIO>;
 			clock-names = "io", "core";
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/dm816x.dtsi b/arch/arm/boot/dts/dm816x.dtsi
index 3c99cfa..eee636d 100644
--- a/arch/arm/boot/dts/dm816x.dtsi
+++ b/arch/arm/boot/dts/dm816x.dtsi
@@ -218,6 +218,7 @@
 			reg = <0x480c8000 0x2000>;
 			interrupts = <77>;
 			ti,hwmods = "mailbox";
+			#mbox-cells = <1>;
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <12>;
 			mbox_dsp: mbox_dsp {
@@ -279,8 +280,11 @@
 			ti,spi-num-cs = <4>;
 			ti,hwmods = "mcspi1";
 			dmas = <&edma 16 &edma 17
-				&edma 18 &edma 19>;
-			dma-names = "tx0", "rx0", "tx1", "rx1";
+				&edma 18 &edma 19
+				&edma 20 &edma 21
+				&edma 22 &edma 23>;
+			dma-names = "tx0", "rx0", "tx1", "rx1",
+				    "tx2", "rx2", "tx3", "rx3";
 		};
 
 		mmc1: mmc@48060000 {
diff --git a/arch/arm/boot/dts/vf610-colibri.dtsi b/arch/arm/boot/dts/vf610-colibri.dtsi
index 19fe045..2d7eab7 100644
--- a/arch/arm/boot/dts/vf610-colibri.dtsi
+++ b/arch/arm/boot/dts/vf610-colibri.dtsi
@@ -18,8 +18,3 @@
 		reg = <0x80000000 0x10000000>;
 	};
 };
-
-&L2 {
-	arm,data-latency = <2 1 2>;
-	arm,tag-latency = <3 2 3>;
-};
diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 5f8eb1b..58bc6e4 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -19,7 +19,7 @@
 		reg = <0x40006000 0x1000>;
 		cache-unified;
 		cache-level = <2>;
-		arm,data-latency = <1 1 1>;
+		arm,data-latency = <3 3 3>;
 		arm,tag-latency = <2 2 2>;
 	};
 };
diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index 0d5acc2..3cd1b27 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -178,8 +178,10 @@
 				compatible = "fsl,vf610-sai";
 				reg = <0x40031000 0x1000>;
 				interrupts = <86 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clks VF610_CLK_SAI2>;
-				clock-names = "sai";
+				clocks = <&clks VF610_CLK_SAI2>,
+					<&clks VF610_CLK_SAI2_DIV>,
+					<&clks 0>, <&clks 0>;
+				clock-names = "bus", "mclk1", "mclk2", "mclk3";
 				dma-names = "tx", "rx";
 				dmas = <&edma0 0 21>,
 					<&edma0 0 20>;
diff --git a/arch/arm/include/asm/arch_gicv3.h b/arch/arm/include/asm/arch_gicv3.h
index 6607d97..7da5503 100644
--- a/arch/arm/include/asm/arch_gicv3.h
+++ b/arch/arm/include/asm/arch_gicv3.h
@@ -21,6 +21,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/io.h>
+#include <asm/barrier.h>
 
 #define __ACCESS_CP15(CRn, Op1, CRm, Op2)	p15, Op1, %0, CRn, CRm, Op2
 #define __ACCESS_CP15_64(Op1, CRm)		p15, Op1, %Q0, %R0, CRm
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 8cc85a4..35c9db8 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -510,10 +510,14 @@
 static inline unsigned long __must_check
 __copy_to_user(void __user *to, const void *from, unsigned long n)
 {
+#ifndef CONFIG_UACCESS_WITH_MEMCPY
 	unsigned int __ua_flags = uaccess_save_and_enable();
 	n = arm_copy_to_user(to, from, n);
 	uaccess_restore(__ua_flags);
 	return n;
+#else
+	return arm_copy_to_user(to, from, n);
+#endif
 }
 
 extern unsigned long __must_check
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 7a7c4ce..4adfb46 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -95,6 +95,22 @@
 {
 	unsigned long flags;
 	char buf[64];
+#ifndef CONFIG_CPU_V7M
+	unsigned int domain;
+#ifdef CONFIG_CPU_SW_DOMAIN_PAN
+	/*
+	 * Get the domain register for the parent context. In user
+	 * mode, we don't save the DACR, so lets use what it should
+	 * be. For other modes, we place it after the pt_regs struct.
+	 */
+	if (user_mode(regs))
+		domain = DACR_UACCESS_ENABLE;
+	else
+		domain = *(unsigned int *)(regs + 1);
+#else
+	domain = get_domain();
+#endif
+#endif
 
 	show_regs_print_info(KERN_DEFAULT);
 
@@ -123,21 +139,8 @@
 
 #ifndef CONFIG_CPU_V7M
 	{
-		unsigned int domain = get_domain();
 		const char *segment;
 
-#ifdef CONFIG_CPU_SW_DOMAIN_PAN
-		/*
-		 * Get the domain register for the parent context. In user
-		 * mode, we don't save the DACR, so lets use what it should
-		 * be. For other modes, we place it after the pt_regs struct.
-		 */
-		if (user_mode(regs))
-			domain = DACR_UACCESS_ENABLE;
-		else
-			domain = *(unsigned int *)(regs + 1);
-#endif
-
 		if ((domain & domain_mask(DOMAIN_USER)) ==
 		    domain_val(DOMAIN_USER, DOMAIN_NOACCESS))
 			segment = "none";
@@ -163,11 +166,11 @@
 		buf[0] = '\0';
 #ifdef CONFIG_CPU_CP15_MMU
 		{
-			unsigned int transbase, dac = get_domain();
+			unsigned int transbase;
 			asm("mrc p15, 0, %0, c2, c0\n\t"
 			    : "=r" (transbase));
 			snprintf(buf, sizeof(buf), "  Table: %08x  DAC: %08x",
-			  	transbase, dac);
+				transbase, domain);
 		}
 #endif
 		asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl));
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index 5b26e7e..c3fe769d 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -36,10 +36,10 @@
  */
 #define __user_swpX_asm(data, addr, res, temp, B)		\
 	__asm__ __volatile__(					\
-	"	mov		%2, %1\n"			\
-	"0:	ldrex"B"	%1, [%3]\n"			\
-	"1:	strex"B"	%0, %2, [%3]\n"			\
+	"0:	ldrex"B"	%2, [%3]\n"			\
+	"1:	strex"B"	%0, %1, [%3]\n"			\
 	"	cmp		%0, #0\n"			\
+	"	moveq		%1, %2\n"			\
 	"	movne		%0, %4\n"			\
 	"2:\n"							\
 	"	.section	 .text.fixup,\"ax\"\n"		\
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c
index d72b909..588bbc2 100644
--- a/arch/arm/lib/uaccess_with_memcpy.c
+++ b/arch/arm/lib/uaccess_with_memcpy.c
@@ -88,6 +88,7 @@
 static unsigned long noinline
 __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
 {
+	unsigned long ua_flags;
 	int atomic;
 
 	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
@@ -118,7 +119,9 @@
 		if (tocopy > n)
 			tocopy = n;
 
+		ua_flags = uaccess_save_and_enable();
 		memcpy((void *)to, from, tocopy);
+		uaccess_restore(ua_flags);
 		to += tocopy;
 		from += tocopy;
 		n -= tocopy;
@@ -145,14 +148,21 @@
 	 * With frame pointer disabled, tail call optimization kicks in
 	 * as well making this test almost invisible.
 	 */
-	if (n < 64)
-		return __copy_to_user_std(to, from, n);
-	return __copy_to_user_memcpy(to, from, n);
+	if (n < 64) {
+		unsigned long ua_flags = uaccess_save_and_enable();
+		n = __copy_to_user_std(to, from, n);
+		uaccess_restore(ua_flags);
+	} else {
+		n = __copy_to_user_memcpy(to, from, n);
+	}
+	return n;
 }
 	
 static unsigned long noinline
 __clear_user_memset(void __user *addr, unsigned long n)
 {
+	unsigned long ua_flags;
+
 	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
 		memset((void *)addr, 0, n);
 		return 0;
@@ -175,7 +185,9 @@
 		if (tocopy > n)
 			tocopy = n;
 
+		ua_flags = uaccess_save_and_enable();
 		memset((void *)addr, 0, tocopy);
+		uaccess_restore(ua_flags);
 		addr += tocopy;
 		n -= tocopy;
 
@@ -193,9 +205,14 @@
 unsigned long arm_clear_user(void __user *addr, unsigned long n)
 {
 	/* See rational for this in __copy_to_user() above. */
-	if (n < 64)
-		return __clear_user_std(addr, n);
-	return __clear_user_memset(addr, n);
+	if (n < 64) {
+		unsigned long ua_flags = uaccess_save_and_enable();
+		n = __clear_user_std(addr, n);
+		uaccess_restore(ua_flags);
+	} else {
+		n = __clear_user_memset(addr, n);
+	}
+	return n;
 }
 
 #if 0
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 9267300..28656c2 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -4,7 +4,6 @@
 	select ARCH_REQUIRE_GPIOLIB
 	select COMMON_CLK_AT91
 	select PINCTRL
-	select PINCTRL_AT91
 	select SOC_BUS
 
 if ARCH_AT91
@@ -17,6 +16,7 @@
 	select HAVE_AT91_USB_CLK
 	select HAVE_AT91_H32MX
 	select HAVE_AT91_GENERATED_CLK
+	select PINCTRL_AT91PIO4
 	help
 	  Select this if ou are using one of Atmel's SAMA5D2 family SoC.
 
@@ -27,6 +27,7 @@
 	select HAVE_AT91_UTMI
 	select HAVE_AT91_SMD
 	select HAVE_AT91_USB_CLK
+	select PINCTRL_AT91
 	help
 	  Select this if you are using one of Atmel's SAMA5D3 family SoC.
 	  This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35, SAMA5D36.
@@ -40,6 +41,7 @@
 	select HAVE_AT91_SMD
 	select HAVE_AT91_USB_CLK
 	select HAVE_AT91_H32MX
+	select PINCTRL_AT91
 	help
 	  Select this if you are using one of Atmel's SAMA5D4 family SoC.
 
@@ -50,6 +52,7 @@
 	select CPU_ARM920T
 	select HAVE_AT91_USB_CLK
 	select MIGHT_HAVE_PCI
+	select PINCTRL_AT91
 	select SOC_SAM_V4_V5
 	select SRAM if PM
 	help
@@ -65,6 +68,7 @@
 	select HAVE_AT91_UTMI
 	select HAVE_FB_ATMEL
 	select MEMORY
+	select PINCTRL_AT91
 	select SOC_SAM_V4_V5
 	select SRAM if PM
 	help
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 80e277c..23726fb 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -41,8 +41,10 @@
  * implementation should be moved down into the pinctrl driver and get
  * called as part of the generic suspend/resume path.
  */
+#ifdef CONFIG_PINCTRL_AT91
 extern void at91_pinctrl_gpio_suspend(void);
 extern void at91_pinctrl_gpio_resume(void);
+#endif
 
 static struct {
 	unsigned long uhp_udp_mask;
@@ -151,8 +153,9 @@
 
 static int at91_pm_enter(suspend_state_t state)
 {
+#ifdef CONFIG_PINCTRL_AT91
 	at91_pinctrl_gpio_suspend();
-
+#endif
 	switch (state) {
 	/*
 	 * Suspend-to-RAM is like STANDBY plus slow clock mode, so
@@ -192,7 +195,9 @@
 error:
 	target_state = PM_SUSPEND_ON;
 
+#ifdef CONFIG_PINCTRL_AT91
 	at91_pinctrl_gpio_resume();
+#endif
 	return 0;
 }
 
diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
index de68938..c21e41d 100644
--- a/arch/arm/mach-exynos/pmu.c
+++ b/arch/arm/mach-exynos/pmu.c
@@ -748,8 +748,12 @@
 void exynos_sys_powerdown_conf(enum sys_powerdown mode)
 {
 	unsigned int i;
+	const struct exynos_pmu_data *pmu_data;
 
-	const struct exynos_pmu_data *pmu_data = pmu_context->pmu_data;
+	if (!pmu_context)
+		return;
+
+	pmu_data = pmu_context->pmu_data;
 
 	if (pmu_data->powerdown_conf)
 		pmu_data->powerdown_conf(mode);
diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h
index b0243901..7a0c13b 100644
--- a/arch/arm/mach-ixp4xx/include/mach/io.h
+++ b/arch/arm/mach-ixp4xx/include/mach/io.h
@@ -143,7 +143,7 @@
 		writel(*vaddr++, bus_addr);
 }
 
-static inline unsigned char __indirect_readb(const volatile void __iomem *p)
+static inline u8 __indirect_readb(const volatile void __iomem *p)
 {
 	u32 addr = (u32)p;
 	u32 n, byte_enables, data;
@@ -166,7 +166,7 @@
 		*vaddr++ = readb(bus_addr);
 }
 
-static inline unsigned short __indirect_readw(const volatile void __iomem *p)
+static inline u16 __indirect_readw(const volatile void __iomem *p)
 {
 	u32 addr = (u32)p;
 	u32 n, byte_enables, data;
@@ -189,7 +189,7 @@
 		*vaddr++ = readw(bus_addr);
 }
 
-static inline unsigned long __indirect_readl(const volatile void __iomem *p)
+static inline u32 __indirect_readl(const volatile void __iomem *p)
 {
 	u32 addr = (__force u32)p;
 	u32 data;
@@ -350,7 +350,7 @@
 					((unsigned long)p <= (PIO_MASK + PIO_OFFSET)))
 
 #define	ioread8(p)			ioread8(p)
-static inline unsigned int ioread8(const void __iomem *addr)
+static inline u8 ioread8(const void __iomem *addr)
 {
 	unsigned long port = (unsigned long __force)addr;
 	if (__is_io_address(port))
@@ -378,7 +378,7 @@
 }
 
 #define	ioread16(p)			ioread16(p)
-static inline unsigned int ioread16(const void __iomem *addr)
+static inline u16 ioread16(const void __iomem *addr)
 {
 	unsigned long port = (unsigned long __force)addr;
 	if (__is_io_address(port))
@@ -407,7 +407,7 @@
 }
 
 #define	ioread32(p)			ioread32(p)
-static inline unsigned int ioread32(const void __iomem *addr)
+static inline u32 ioread32(const void __iomem *addr)
 {
 	unsigned long port = (unsigned long __force)addr;
 	if (__is_io_address(port))
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 5076d3f..4b4371d 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -121,6 +121,7 @@
 	select NEON if CPU_V7
 	select PM
 	select REGULATOR
+	select REGULATOR_FIXED_VOLTAGE
 	select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
 	select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
 	select VFP
@@ -201,7 +202,6 @@
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CBB
-	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config MACH_NOKIA_N810
        bool
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index 9a9c15b..7c0d561 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -889,6 +889,7 @@
 
 	pxa_set_keypad_info(&e680_keypad_platform_data);
 
+	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
 	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
 	platform_add_devices(ARRAY_AND_SIZE(e680_devices));
 }
@@ -956,6 +957,7 @@
 
 	pxa_set_keypad_info(&a1200_keypad_platform_data);
 
+	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
 	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
 	platform_add_devices(ARRAY_AND_SIZE(a1200_devices));
 }
@@ -1148,6 +1150,7 @@
 		platform_device_register(&a910_camera);
 	}
 
+	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
 	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
 	platform_add_devices(ARRAY_AND_SIZE(a910_devices));
 }
@@ -1215,6 +1218,7 @@
 
 	pxa_set_keypad_info(&e6_keypad_platform_data);
 
+	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
 	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
 	platform_add_devices(ARRAY_AND_SIZE(e6_devices));
 }
@@ -1256,6 +1260,7 @@
 
 	pxa_set_keypad_info(&e2_keypad_platform_data);
 
+	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
 	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
 	platform_add_devices(ARRAY_AND_SIZE(e2_devices));
 }
diff --git a/arch/arm/mach-s3c24xx/pll-s3c2440-12000000.c b/arch/arm/mach-s3c24xx/pll-s3c2440-12000000.c
index a19460e..b355fca 100644
--- a/arch/arm/mach-s3c24xx/pll-s3c2440-12000000.c
+++ b/arch/arm/mach-s3c24xx/pll-s3c2440-12000000.c
@@ -20,7 +20,7 @@
 #include <plat/cpu.h>
 #include <plat/cpu-freq-core.h>
 
-static struct cpufreq_frequency_table s3c2440_plls_12[] __initdata = {
+static struct cpufreq_frequency_table s3c2440_plls_12[] = {
 	{ .frequency = 75000000,	.driver_data = PLLVAL(0x75, 3, 3),  }, 	/* FVco 600.000000 */
 	{ .frequency = 80000000,	.driver_data = PLLVAL(0x98, 4, 3),  }, 	/* FVco 640.000000 */
 	{ .frequency = 90000000,	.driver_data = PLLVAL(0x70, 2, 3),  }, 	/* FVco 720.000000 */
diff --git a/arch/arm/mach-s3c24xx/pll-s3c2440-16934400.c b/arch/arm/mach-s3c24xx/pll-s3c2440-16934400.c
index 1191b29..be9a248 100644
--- a/arch/arm/mach-s3c24xx/pll-s3c2440-16934400.c
+++ b/arch/arm/mach-s3c24xx/pll-s3c2440-16934400.c
@@ -20,7 +20,7 @@
 #include <plat/cpu.h>
 #include <plat/cpu-freq-core.h>
 
-static struct cpufreq_frequency_table s3c2440_plls_169344[] __initdata = {
+static struct cpufreq_frequency_table s3c2440_plls_169344[] = {
 	{ .frequency = 78019200,	.driver_data = PLLVAL(121, 5, 3), 	}, 	/* FVco 624.153600 */
 	{ .frequency = 84067200,	.driver_data = PLLVAL(131, 5, 3), 	}, 	/* FVco 672.537600 */
 	{ .frequency = 90115200,	.driver_data = PLLVAL(141, 5, 3), 	}, 	/* FVco 720.921600 */
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 845769e..c8c8b9e 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -165,13 +165,28 @@
 		__flush_icache_all();
 }
 
-static int is_reserved_asid(u64 asid)
+static bool check_update_reserved_asid(u64 asid, u64 newasid)
 {
 	int cpu;
-	for_each_possible_cpu(cpu)
-		if (per_cpu(reserved_asids, cpu) == asid)
-			return 1;
-	return 0;
+	bool hit = false;
+
+	/*
+	 * Iterate over the set of reserved ASIDs looking for a match.
+	 * If we find one, then we can update our mm to use newasid
+	 * (i.e. the same ASID in the current generation) but we can't
+	 * exit the loop early, since we need to ensure that all copies
+	 * of the old ASID are updated to reflect the mm. Failure to do
+	 * so could result in us missing the reserved ASID in a future
+	 * generation.
+	 */
+	for_each_possible_cpu(cpu) {
+		if (per_cpu(reserved_asids, cpu) == asid) {
+			hit = true;
+			per_cpu(reserved_asids, cpu) = newasid;
+		}
+	}
+
+	return hit;
 }
 
 static u64 new_context(struct mm_struct *mm, unsigned int cpu)
@@ -181,12 +196,14 @@
 	u64 generation = atomic64_read(&asid_generation);
 
 	if (asid != 0) {
+		u64 newasid = generation | (asid & ~ASID_MASK);
+
 		/*
 		 * If our current ASID was active during a rollover, we
 		 * can continue to use it and this was just a false alarm.
 		 */
-		if (is_reserved_asid(asid))
-			return generation | (asid & ~ASID_MASK);
+		if (check_update_reserved_asid(asid, newasid))
+			return newasid;
 
 		/*
 		 * We had a valid ASID in a previous life, so try to re-use
@@ -194,7 +211,7 @@
 		 */
 		asid &= ~ASID_MASK;
 		if (!__test_and_set_bit(asid, asid_map))
-			goto bump_gen;
+			return newasid;
 	}
 
 	/*
@@ -216,11 +233,8 @@
 
 	__set_bit(asid, asid_map);
 	cur_idx = asid;
-
-bump_gen:
-	asid |= generation;
 	cpumask_clear(mm_cpumask(mm));
-	return asid;
+	return asid | generation;
 }
 
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index e62400e..534a60a 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1521,7 +1521,7 @@
 		return -ENOMEM;
 
 	for (count = 0, s = sg; count < (size >> PAGE_SHIFT); s = sg_next(s)) {
-		phys_addr_t phys = sg_phys(s) & PAGE_MASK;
+		phys_addr_t phys = page_to_phys(sg_page(s));
 		unsigned int len = PAGE_ALIGN(s->offset + s->length);
 
 		if (!is_coherent &&
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 8a63b4c..7f8cd1b 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -22,6 +22,7 @@
 #include <linux/memblock.h>
 #include <linux/dma-contiguous.h>
 #include <linux/sizes.h>
+#include <linux/stop_machine.h>
 
 #include <asm/cp15.h>
 #include <asm/mach-types.h>
@@ -627,12 +628,10 @@
  * safe to be called with preemption disabled, as under stop_machine().
  */
 static inline void section_update(unsigned long addr, pmdval_t mask,
-				  pmdval_t prot)
+				  pmdval_t prot, struct mm_struct *mm)
 {
-	struct mm_struct *mm;
 	pmd_t *pmd;
 
-	mm = current->active_mm;
 	pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr);
 
 #ifdef CONFIG_ARM_LPAE
@@ -656,49 +655,82 @@
 	return !!(get_cr() & CR_XP);
 }
 
-#define set_section_perms(perms, field)	{				\
-	size_t i;							\
-	unsigned long addr;						\
-									\
-	if (!arch_has_strict_perms())					\
-		return;							\
-									\
-	for (i = 0; i < ARRAY_SIZE(perms); i++) {			\
-		if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) ||	\
-		    !IS_ALIGNED(perms[i].end, SECTION_SIZE)) {		\
-			pr_err("BUG: section %lx-%lx not aligned to %lx\n", \
-				perms[i].start, perms[i].end,		\
-				SECTION_SIZE);				\
-			continue;					\
-		}							\
-									\
-		for (addr = perms[i].start;				\
-		     addr < perms[i].end;				\
-		     addr += SECTION_SIZE)				\
-			section_update(addr, perms[i].mask,		\
-				       perms[i].field);			\
-	}								\
+void set_section_perms(struct section_perm *perms, int n, bool set,
+			struct mm_struct *mm)
+{
+	size_t i;
+	unsigned long addr;
+
+	if (!arch_has_strict_perms())
+		return;
+
+	for (i = 0; i < n; i++) {
+		if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) ||
+		    !IS_ALIGNED(perms[i].end, SECTION_SIZE)) {
+			pr_err("BUG: section %lx-%lx not aligned to %lx\n",
+				perms[i].start, perms[i].end,
+				SECTION_SIZE);
+			continue;
+		}
+
+		for (addr = perms[i].start;
+		     addr < perms[i].end;
+		     addr += SECTION_SIZE)
+			section_update(addr, perms[i].mask,
+				set ? perms[i].prot : perms[i].clear, mm);
+	}
+
 }
 
-static inline void fix_kernmem_perms(void)
+static void update_sections_early(struct section_perm perms[], int n)
 {
-	set_section_perms(nx_perms, prot);
+	struct task_struct *t, *s;
+
+	read_lock(&tasklist_lock);
+	for_each_process(t) {
+		if (t->flags & PF_KTHREAD)
+			continue;
+		for_each_thread(t, s)
+			set_section_perms(perms, n, true, s->mm);
+	}
+	read_unlock(&tasklist_lock);
+	set_section_perms(perms, n, true, current->active_mm);
+	set_section_perms(perms, n, true, &init_mm);
+}
+
+int __fix_kernmem_perms(void *unused)
+{
+	update_sections_early(nx_perms, ARRAY_SIZE(nx_perms));
+	return 0;
+}
+
+void fix_kernmem_perms(void)
+{
+	stop_machine(__fix_kernmem_perms, NULL, NULL);
 }
 
 #ifdef CONFIG_DEBUG_RODATA
+int __mark_rodata_ro(void *unused)
+{
+	update_sections_early(ro_perms, ARRAY_SIZE(ro_perms));
+	return 0;
+}
+
 void mark_rodata_ro(void)
 {
-	set_section_perms(ro_perms, prot);
+	stop_machine(__mark_rodata_ro, NULL, NULL);
 }
 
 void set_kernel_text_rw(void)
 {
-	set_section_perms(ro_perms, clear);
+	set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), false,
+				current->active_mm);
 }
 
 void set_kernel_text_ro(void)
 {
-	set_section_perms(ro_perms, prot);
+	set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true,
+				current->active_mm);
 }
 #endif /* CONFIG_DEBUG_RODATA */
 
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index de2b246..8e1ea43 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -95,7 +95,7 @@
 .equ	cpu_v7_suspend_size, 4 * 9
 #ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_v7_do_suspend)
-	stmfd	sp!, {r4 - r10, lr}
+	stmfd	sp!, {r4 - r11, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
 	mrc	p15, 0, r5, c13, c0, 3	@ User r/o thread ID
 	stmia	r0!, {r4 - r5}
@@ -112,7 +112,7 @@
 	mrc	p15, 0, r9, c1, c0, 1	@ Auxiliary control register
 	mrc	p15, 0, r10, c1, c0, 2	@ Co-processor access control
 	stmia	r0, {r5 - r11}
-	ldmfd	sp!, {r4 - r10, pc}
+	ldmfd	sp!, {r4 - r11, pc}
 ENDPROC(cpu_v7_do_suspend)
 
 ENTRY(cpu_v7_do_resume)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index e81cd48..925552e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -269,6 +269,7 @@
 			clock-frequency = <0>;	/* Updated by bootloader */
 			voltage-ranges = <1800 1800 3300 3300>;
 			sdhci,auto-cmd12;
+			little-endian;
 			bus-width = <4>;
 		};
 
@@ -277,6 +278,7 @@
 			reg = <0x0 0x2300000 0x0 0x10000>;
 			interrupts = <0 36 0x4>; /* Level high type */
 			gpio-controller;
+			little-endian;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
@@ -287,6 +289,7 @@
 			reg = <0x0 0x2310000 0x0 0x10000>;
 			interrupts = <0 36 0x4>; /* Level high type */
 			gpio-controller;
+			little-endian;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
@@ -297,6 +300,7 @@
 			reg = <0x0 0x2320000 0x0 0x10000>;
 			interrupts = <0 37 0x4>; /* Level high type */
 			gpio-controller;
+			little-endian;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
@@ -307,6 +311,7 @@
 			reg = <0x0 0x2330000 0x0 0x10000>;
 			interrupts = <0 37 0x4>; /* Level high type */
 			gpio-controller;
+			little-endian;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
diff --git a/arch/arm64/include/asm/arch_gicv3.h b/arch/arm64/include/asm/arch_gicv3.h
index 030cdcb..2731d3b 100644
--- a/arch/arm64/include/asm/arch_gicv3.h
+++ b/arch/arm64/include/asm/arch_gicv3.h
@@ -77,6 +77,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/stringify.h>
+#include <asm/barrier.h>
 
 /*
  * Low-level accessors
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 7e074f9..63f52b5 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -276,10 +276,14 @@
 	 * hardware updates of the pte (ptep_set_access_flags safely changes
 	 * valid ptes without going through an invalid entry).
 	 */
-	if (IS_ENABLED(CONFIG_DEBUG_VM) && IS_ENABLED(CONFIG_ARM64_HW_AFDBM) &&
-	    pte_valid(*ptep)) {
-		BUG_ON(!pte_young(pte));
-		BUG_ON(pte_write(*ptep) && !pte_dirty(pte));
+	if (IS_ENABLED(CONFIG_ARM64_HW_AFDBM) &&
+	    pte_valid(*ptep) && pte_valid(pte)) {
+		VM_WARN_ONCE(!pte_young(pte),
+			     "%s: racy access flag clearing: 0x%016llx -> 0x%016llx",
+			     __func__, pte_val(*ptep), pte_val(pte));
+		VM_WARN_ONCE(pte_write(*ptep) && !pte_dirty(pte),
+			     "%s: racy dirty state clearing: 0x%016llx -> 0x%016llx",
+			     __func__, pte_val(*ptep), pte_val(pte));
 	}
 
 	set_pte(ptep, pte);
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 1ee2c39..71426a78 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -5,6 +5,7 @@
  */
 
 #include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
@@ -140,7 +141,7 @@
 		ARM_EXIT_KEEP(EXIT_DATA)
 	}
 
-	PERCPU_SECTION(64)
+	PERCPU_SECTION(L1_CACHE_BYTES)
 
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;
@@ -158,7 +159,7 @@
 	. = ALIGN(PAGE_SIZE);
 	_data = .;
 	_sdata = .;
-	RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE)
+	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
 	PECOFF_EDATA_PADDING
 	_edata = .;
 
diff --git a/arch/blackfin/kernel/perf_event.c b/arch/blackfin/kernel/perf_event.c
index 1e9c8b0..170d786 100644
--- a/arch/blackfin/kernel/perf_event.c
+++ b/arch/blackfin/kernel/perf_event.c
@@ -14,7 +14,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
  *
  * ppc:
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index db73390..74c132d 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -11,7 +11,7 @@
 
 
 
-#define NR_syscalls			322 /* length of syscall table */
+#define NR_syscalls			323 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h
index 9038726..762edce 100644
--- a/arch/ia64/include/uapi/asm/unistd.h
+++ b/arch/ia64/include/uapi/asm/unistd.h
@@ -335,5 +335,6 @@
 #define __NR_userfaultfd		1343
 #define __NR_membarrier			1344
 #define __NR_kcmp			1345
+#define __NR_mlock2			1346
 
 #endif /* _UAPI_ASM_IA64_UNISTD_H */
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index dcd97f8..534a74a 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1771,5 +1771,6 @@
 	data8 sys_userfaultfd
 	data8 sys_membarrier
 	data8 sys_kcmp				// 1345
+	data8 sys_mlock2
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
index c89da63..bf4dec2 100644
--- a/arch/microblaze/kernel/dma.c
+++ b/arch/microblaze/kernel/dma.c
@@ -61,7 +61,8 @@
 	/* FIXME this part of code is untested */
 	for_each_sg(sgl, sg, nents, i) {
 		sg->dma_address = sg_phys(sg);
-		__dma_sync(sg_phys(sg), sg->length, direction);
+		__dma_sync(page_to_phys(sg_page(sg)) + sg->offset,
+							sg->length, direction);
 	}
 
 	return nents;
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index d8117be..730d394 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -145,7 +145,7 @@
 
 	gfp = massage_gfp_flags(dev, gfp);
 
-	if (IS_ENABLED(CONFIG_DMA_CMA) && !(gfp & GFP_ATOMIC))
+	if (IS_ENABLED(CONFIG_DMA_CMA) && gfpflags_allow_blocking(gfp))
 		page = dma_alloc_from_contiguous(dev,
 					count, get_order(size));
 	if (!page)
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index d8534f9..291cee2 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -372,7 +372,8 @@
  */
 #ifdef CONFIG_HUGETLB_PAGE
 #define pte_huge(pte)           (pte_val(pte) & _PAGE_HUGE)
-#define pte_mkhuge(pte)         (__pte(pte_val(pte) | _PAGE_HUGE))
+#define pte_mkhuge(pte)         (__pte(pte_val(pte) | \
+				 (parisc_requires_coherency() ? 0 : _PAGE_HUGE)))
 #else
 #define pte_huge(pte)           (0)
 #define pte_mkhuge(pte)         (pte)
diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h
index 3317038..35bdccb 100644
--- a/arch/parisc/include/uapi/asm/unistd.h
+++ b/arch/parisc/include/uapi/asm/unistd.h
@@ -360,8 +360,9 @@
 #define __NR_execveat		(__NR_Linux + 342)
 #define __NR_membarrier		(__NR_Linux + 343)
 #define __NR_userfaultfd	(__NR_Linux + 344)
+#define __NR_mlock2		(__NR_Linux + 345)
 
-#define __NR_Linux_syscalls	(__NR_userfaultfd + 1)
+#define __NR_Linux_syscalls	(__NR_mlock2 + 1)
 
 
 #define __IGNORE_select		/* newselect */
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index 64f2764..c99f3dd 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -171,24 +171,6 @@
 }
 
 
-void __init pcibios_init_bus(struct pci_bus *bus)
-{
-	struct pci_dev *dev = bus->self;
-	unsigned short bridge_ctl;
-
-	/* We deal only with pci controllers and pci-pci bridges. */
-	if (!dev || (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
-		return;
-
-	/* PCI-PCI bridge - set the cache line and default latency
-	   (32) for primary and secondary buses. */
-	pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32);
-
-	pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl);
-	bridge_ctl |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
-	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl);
-}
-
 /*
  * pcibios align resources() is called every time generic PCI code
  * wants to generate a new address. The process of looking for
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 78c3ef8..d4ffcfb 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -440,6 +440,7 @@
 	ENTRY_COMP(execveat)
 	ENTRY_SAME(membarrier)
 	ENTRY_SAME(userfaultfd)
+	ENTRY_SAME(mlock2)		/* 345 */
 
 
 .ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b))
diff --git a/arch/powerpc/boot/dts/sbc8641d.dts b/arch/powerpc/boot/dts/sbc8641d.dts
index 631ede7..68f0ed7 100644
--- a/arch/powerpc/boot/dts/sbc8641d.dts
+++ b/arch/powerpc/boot/dts/sbc8641d.dts
@@ -227,23 +227,15 @@
 				reg = <0x520 0x20>;
 
 				phy0: ethernet-phy@1f {
-					interrupt-parent = <&mpic>;
-					interrupts = <10 1>;
 					reg = <0x1f>;
 				};
 				phy1: ethernet-phy@0 {
-					interrupt-parent = <&mpic>;
-					interrupts = <10 1>;
 					reg = <0>;
 				};
 				phy2: ethernet-phy@1 {
-					interrupt-parent = <&mpic>;
-					interrupts = <10 1>;
 					reg = <1>;
 				};
 				phy3: ethernet-phy@2 {
-					interrupt-parent = <&mpic>;
-					interrupts = <10 1>;
 					reg = <2>;
 				};
 				tbi0: tbi-phy@11 {
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index f2b0b1b..5654ece 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -370,16 +370,16 @@
 PPC64ONLY(switch_endian)
 SYSCALL_SPU(userfaultfd)
 SYSCALL_SPU(membarrier)
-SYSCALL(semop)
-SYSCALL(semget)
-COMPAT_SYS(semctl)
-COMPAT_SYS(semtimedop)
-COMPAT_SYS(msgsnd)
-COMPAT_SYS(msgrcv)
-SYSCALL(msgget)
-COMPAT_SYS(msgctl)
-COMPAT_SYS(shmat)
-SYSCALL(shmdt)
-SYSCALL(shmget)
-COMPAT_SYS(shmctl)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
 SYSCALL(mlock2)
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h
index 1effea5..12a0565 100644
--- a/arch/powerpc/include/uapi/asm/unistd.h
+++ b/arch/powerpc/include/uapi/asm/unistd.h
@@ -388,18 +388,6 @@
 #define __NR_switch_endian	363
 #define __NR_userfaultfd	364
 #define __NR_membarrier		365
-#define __NR_semop		366
-#define __NR_semget		367
-#define __NR_semctl		368
-#define __NR_semtimedop		369
-#define __NR_msgsnd		370
-#define __NR_msgrcv		371
-#define __NR_msgget		372
-#define __NR_msgctl		373
-#define __NR_shmat		374
-#define __NR_shmdt		375
-#define __NR_shmget		376
-#define __NR_shmctl		377
 #define __NR_mlock2		378
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 80dfe89..8d14feb 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -590,16 +590,10 @@
 	eeh_ops->configure_bridge(pe);
 	eeh_pe_restore_bars(pe);
 
-	/*
-	 * If it's PHB PE, the frozen state on all available PEs should have
-	 * been cleared by the PHB reset. Otherwise, we unfreeze the PE and its
-	 * child PEs because they might be in frozen state.
-	 */
-	if (!(pe->type & EEH_PE_PHB)) {
-		rc = eeh_clear_pe_frozen_state(pe, false);
-		if (rc)
-			return rc;
-	}
+	/* Clear frozen state */
+	rc = eeh_clear_pe_frozen_state(pe, false);
+	if (rc)
+		return rc;
 
 	/* Give the system 5 seconds to finish running the user-space
 	 * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes,
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 54b45b7..a7352b5 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -224,6 +224,12 @@
 
 static void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr)
 {
+	/*
+	 * Check for illegal transactional state bit combination
+	 * and if we find it, force the TS field to a safe state.
+	 */
+	if ((msr & MSR_TS_MASK) == MSR_TS_MASK)
+		msr &= ~MSR_TS_MASK;
 	vcpu->arch.shregs.msr = msr;
 	kvmppc_end_cede(vcpu);
 }
diff --git a/arch/powerpc/platforms/powernv/opal-irqchip.c b/arch/powerpc/platforms/powernv/opal-irqchip.c
index 6ccfb6c..e505223b 100644
--- a/arch/powerpc/platforms/powernv/opal-irqchip.c
+++ b/arch/powerpc/platforms/powernv/opal-irqchip.c
@@ -43,11 +43,34 @@
 static unsigned int *opal_irqs;
 
 static void opal_handle_irq_work(struct irq_work *work);
-static __be64 last_outstanding_events;
+static u64 last_outstanding_events;
 static struct irq_work opal_event_irq_work = {
 	.func = opal_handle_irq_work,
 };
 
+void opal_handle_events(uint64_t events)
+{
+	int virq, hwirq = 0;
+	u64 mask = opal_event_irqchip.mask;
+
+	if (!in_irq() && (events & mask)) {
+		last_outstanding_events = events;
+		irq_work_queue(&opal_event_irq_work);
+		return;
+	}
+
+	while (events & mask) {
+		hwirq = fls64(events) - 1;
+		if (BIT_ULL(hwirq) & mask) {
+			virq = irq_find_mapping(opal_event_irqchip.domain,
+						hwirq);
+			if (virq)
+				generic_handle_irq(virq);
+		}
+		events &= ~BIT_ULL(hwirq);
+	}
+}
+
 static void opal_event_mask(struct irq_data *d)
 {
 	clear_bit(d->hwirq, &opal_event_irqchip.mask);
@@ -55,9 +78,21 @@
 
 static void opal_event_unmask(struct irq_data *d)
 {
+	__be64 events;
+
 	set_bit(d->hwirq, &opal_event_irqchip.mask);
 
-	opal_poll_events(&last_outstanding_events);
+	opal_poll_events(&events);
+	last_outstanding_events = be64_to_cpu(events);
+
+	/*
+	 * We can't just handle the events now with opal_handle_events().
+	 * If we did we would deadlock when opal_event_unmask() is called from
+	 * handle_level_irq() with the irq descriptor lock held, because
+	 * calling opal_handle_events() would call generic_handle_irq() and
+	 * then handle_level_irq() which would try to take the descriptor lock
+	 * again. Instead queue the events for later.
+	 */
 	if (last_outstanding_events & opal_event_irqchip.mask)
 		/* Need to retrigger the interrupt */
 		irq_work_queue(&opal_event_irq_work);
@@ -96,29 +131,6 @@
 	return 0;
 }
 
-void opal_handle_events(uint64_t events)
-{
-	int virq, hwirq = 0;
-	u64 mask = opal_event_irqchip.mask;
-
-	if (!in_irq() && (events & mask)) {
-		last_outstanding_events = events;
-		irq_work_queue(&opal_event_irq_work);
-		return;
-	}
-
-	while (events & mask) {
-		hwirq = fls64(events) - 1;
-		if (BIT_ULL(hwirq) & mask) {
-			virq = irq_find_mapping(opal_event_irqchip.domain,
-						hwirq);
-			if (virq)
-				generic_handle_irq(virq);
-		}
-		events &= ~BIT_ULL(hwirq);
-	}
-}
-
 static irqreturn_t opal_interrupt(int irq, void *data)
 {
 	__be64 events;
@@ -131,7 +143,7 @@
 
 static void opal_handle_irq_work(struct irq_work *work)
 {
-	opal_handle_events(be64_to_cpu(last_outstanding_events));
+	opal_handle_events(last_outstanding_events);
 }
 
 static int opal_event_match(struct irq_domain *h, struct device_node *node,
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 4296d55..57cffb8 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -278,7 +278,7 @@
 
 	/* Sanity check */
 	if (type >= OPAL_MSG_TYPE_MAX) {
-		pr_warning("%s: Unknown message type: %u\n", __func__, type);
+		pr_warn_once("%s: Unknown message type: %u\n", __func__, type);
 		return;
 	}
 	opal_message_do_notify(type, (void *)&msg);
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index 8140d10..6e72961 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -1920,16 +1920,23 @@
 			}
 			if (separator)
 				ptr += sprintf(ptr, "%c", separator);
+			/*
+			 * Use four '%' characters below because of the
+			 * following two conversions:
+			 *
+			 *  1) sprintf: %%%%r -> %%r
+			 *  2) printk : %%r   -> %r
+			 */
 			if (operand->flags & OPERAND_GPR)
-				ptr += sprintf(ptr, "%%r%i", value);
+				ptr += sprintf(ptr, "%%%%r%i", value);
 			else if (operand->flags & OPERAND_FPR)
-				ptr += sprintf(ptr, "%%f%i", value);
+				ptr += sprintf(ptr, "%%%%f%i", value);
 			else if (operand->flags & OPERAND_AR)
-				ptr += sprintf(ptr, "%%a%i", value);
+				ptr += sprintf(ptr, "%%%%a%i", value);
 			else if (operand->flags & OPERAND_CR)
-				ptr += sprintf(ptr, "%%c%i", value);
+				ptr += sprintf(ptr, "%%%%c%i", value);
 			else if (operand->flags & OPERAND_VR)
-				ptr += sprintf(ptr, "%%v%i", value);
+				ptr += sprintf(ptr, "%%%%v%i", value);
 			else if (operand->flags & OPERAND_PCREL)
 				ptr += sprintf(ptr, "%lx", (signed int) value
 								      + addr);
diff --git a/arch/sh/include/uapi/asm/unistd_64.h b/arch/sh/include/uapi/asm/unistd_64.h
index e6820c8..47ebd5b 100644
--- a/arch/sh/include/uapi/asm/unistd_64.h
+++ b/arch/sh/include/uapi/asm/unistd_64.h
@@ -278,7 +278,7 @@
 #define __NR_fsetxattr		256
 #define __NR_getxattr		257
 #define __NR_lgetxattr		258
-#define __NR_fgetxattr		269
+#define __NR_fgetxattr		259
 #define __NR_listxattr		260
 #define __NR_llistxattr		261
 #define __NR_flistxattr		262
diff --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c
index 7cfd7f1..4dca183 100644
--- a/arch/sh/kernel/perf_event.c
+++ b/arch/sh/kernel/perf_event.c
@@ -10,7 +10,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
  *
  * ppc:
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index b0da5ae..3091267 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -9,7 +9,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  */
 
 #include <linux/perf_event.h>
diff --git a/arch/tile/kernel/perf_event.c b/arch/tile/kernel/perf_event.c
index bb509ce..8767060 100644
--- a/arch/tile/kernel/perf_event.c
+++ b/arch/tile/kernel/perf_event.c
@@ -21,7 +21,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
  *  Copyright (C) 2009 Google, Inc., Stephane Eranian
  */
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 25ed409..e3abe6f 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -131,7 +131,7 @@
 # The wrappers will select whether using "malloc" or the kernel allocator.
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 
-LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt)) -lrt
+LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt))
 
 # Used by link-vmlinux.sh which has special support for um link
 export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index e697a41..e9f8445 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -249,21 +249,23 @@
 
 char *split_if_spec(char *str, ...)
 {
-	char **arg, *end;
+	char **arg, *end, *ret = NULL;
 	va_list ap;
 
 	va_start(ap, str);
 	while ((arg = va_arg(ap, char **)) != NULL) {
 		if (*str == '\0')
-			return NULL;
+			goto out;
 		end = strchr(str, ',');
 		if (end != str)
 			*arg = str;
 		if (end == NULL)
-			return NULL;
+			goto out;
 		*end++ = '\0';
 		str = end;
 	}
+	ret = str;
+out:
 	va_end(ap);
-	return str;
+	return ret;
 }
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 57acbd6..fc8be0e 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -69,7 +69,7 @@
 	struct ksignal ksig;
 	int handled_sig = 0;
 
-	while (get_signal(&ksig)) {
+	if (get_signal(&ksig)) {
 		handled_sig = 1;
 		/* Whee!  Actually deliver the signal.  */
 		handle_signal(&ksig, regs);
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 4562cf0..2bf79d7 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -5,7 +5,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
  *  Copyright (C) 2009 Google, Inc., Stephane Eranian
  *
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 499f533..d0e35eb 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -5,7 +5,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
  *  Copyright (C) 2009 Google, Inc., Stephane Eranian
  *
@@ -387,7 +387,7 @@
 /* Check flags and event code/umask, and set the HSW N/A flag */
 #define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(code, n) \
 	__EVENT_CONSTRAINT(code, n, 			\
-			  INTEL_ARCH_EVENT_MASK|INTEL_ARCH_EVENT_MASK, \
+			  INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
 			  HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_NA_HSW)
 
 
@@ -627,6 +627,7 @@
 	u64 lbr_from[MAX_LBR_ENTRIES];
 	u64 lbr_to[MAX_LBR_ENTRIES];
 	u64 lbr_info[MAX_LBR_ENTRIES];
+	int tos;
 	int lbr_callstack_users;
 	int lbr_stack_state;
 };
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index f63360b..e2a4300 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -232,7 +232,7 @@
 	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
 	FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
 	FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
-	INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.* */
+	INTEL_UEVENT_CONSTRAINT(0x148, 0x4),	/* L1D_PEND_MISS.PENDING */
 	INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
 	INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
 	/* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_cqm.c b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
index 377e8f8..a316ca9 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_cqm.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
@@ -298,7 +298,7 @@
 static inline struct perf_cgroup *event_to_cgroup(struct perf_event *event)
 {
 	if (event->attach_state & PERF_ATTACH_TASK)
-		return perf_cgroup_from_task(event->hw.target);
+		return perf_cgroup_from_task(event->hw.target, event->ctx);
 
 	return event->cgrp;
 }
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index bfd0b71..659f01e 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -239,7 +239,7 @@
 	}
 
 	mask = x86_pmu.lbr_nr - 1;
-	tos = intel_pmu_lbr_tos();
+	tos = task_ctx->tos;
 	for (i = 0; i < tos; i++) {
 		lbr_idx = (tos - i) & mask;
 		wrmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
@@ -247,6 +247,7 @@
 		if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
 			wrmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
 	}
+	wrmsrl(x86_pmu.lbr_tos, tos);
 	task_ctx->lbr_stack_state = LBR_NONE;
 }
 
@@ -270,6 +271,7 @@
 		if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
 			rdmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
 	}
+	task_ctx->tos = tos;
 	task_ctx->lbr_stack_state = LBR_VALID;
 }
 
diff --git a/arch/x86/kernel/irq_work.c b/arch/x86/kernel/irq_work.c
index dc5fa6a..3512ba6 100644
--- a/arch/x86/kernel/irq_work.c
+++ b/arch/x86/kernel/irq_work.c
@@ -1,7 +1,7 @@
 /*
  * x86 specific code for irq_work
  *
- * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra
  */
 
 #include <linux/kernel.h>
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 06332cb..3f5c48d 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -38,6 +38,14 @@
 	return best && (best->ecx & bit(X86_FEATURE_XSAVE));
 }
 
+static inline bool guest_cpuid_has_mtrr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+
+	best = kvm_find_cpuid_entry(vcpu, 1, 0);
+	return best && (best->edx & bit(X86_FEATURE_MTRR));
+}
+
 static inline bool guest_cpuid_has_tsc_adjust(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c
index 9e8bf13..3f8c732 100644
--- a/arch/x86/kvm/mtrr.c
+++ b/arch/x86/kvm/mtrr.c
@@ -120,14 +120,22 @@
 	return mtrr_state->deftype & IA32_MTRR_DEF_TYPE_TYPE_MASK;
 }
 
-static u8 mtrr_disabled_type(void)
+static u8 mtrr_disabled_type(struct kvm_vcpu *vcpu)
 {
 	/*
 	 * Intel SDM 11.11.2.2: all MTRRs are disabled when
 	 * IA32_MTRR_DEF_TYPE.E bit is cleared, and the UC
 	 * memory type is applied to all of physical memory.
+	 *
+	 * However, virtual machines can be run with CPUID such that
+	 * there are no MTRRs.  In that case, the firmware will never
+	 * enable MTRRs and it is obviously undesirable to run the
+	 * guest entirely with UC memory and we use WB.
 	 */
-	return MTRR_TYPE_UNCACHABLE;
+	if (guest_cpuid_has_mtrr(vcpu))
+		return MTRR_TYPE_UNCACHABLE;
+	else
+		return MTRR_TYPE_WRBACK;
 }
 
 /*
@@ -267,7 +275,7 @@
 
 	for (seg = 0; seg < seg_num; seg++) {
 		mtrr_seg = &fixed_seg_table[seg];
-		if (mtrr_seg->start >= addr && addr < mtrr_seg->end)
+		if (mtrr_seg->start <= addr && addr < mtrr_seg->end)
 			return seg;
 	}
 
@@ -300,7 +308,6 @@
 	*start = range->base & PAGE_MASK;
 
 	mask = range->mask & PAGE_MASK;
-	mask |= ~0ULL << boot_cpu_data.x86_phys_bits;
 
 	/* This cannot overflow because writing to the reserved bits of
 	 * variable MTRRs causes a #GP.
@@ -356,10 +363,14 @@
 	if (var_mtrr_range_is_valid(cur))
 		list_del(&mtrr_state->var_ranges[index].node);
 
+	/* Extend the mask with all 1 bits to the left, since those
+	 * bits must implicitly be 0.  The bits are then cleared
+	 * when reading them.
+	 */
 	if (!is_mtrr_mask)
 		cur->base = data;
 	else
-		cur->mask = data;
+		cur->mask = data | (-1LL << cpuid_maxphyaddr(vcpu));
 
 	/* add it to the list if it's enabled. */
 	if (var_mtrr_range_is_valid(cur)) {
@@ -426,6 +437,8 @@
 			*pdata = vcpu->arch.mtrr_state.var_ranges[index].base;
 		else
 			*pdata = vcpu->arch.mtrr_state.var_ranges[index].mask;
+
+		*pdata &= (1ULL << cpuid_maxphyaddr(vcpu)) - 1;
 	}
 
 	return 0;
@@ -670,7 +683,7 @@
 	}
 
 	if (iter.mtrr_disabled)
-		return mtrr_disabled_type();
+		return mtrr_disabled_type(vcpu);
 
 	/* not contained in any MTRRs. */
 	if (type == -1)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 83a1c64..899c40f 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -3422,6 +3422,8 @@
 	struct kvm_run *kvm_run = vcpu->run;
 	u32 exit_code = svm->vmcb->control.exit_code;
 
+	trace_kvm_exit(exit_code, vcpu, KVM_ISA_SVM);
+
 	if (!is_cr_intercept(svm, INTERCEPT_CR0_WRITE))
 		vcpu->arch.cr0 = svm->vmcb->save.cr0;
 	if (npt_enabled)
@@ -3892,8 +3894,6 @@
 	vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
 	vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
-	trace_kvm_exit(svm->vmcb->control.exit_code, vcpu, KVM_ISA_SVM);
-
 	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
 		kvm_before_handle_nmi(&svm->vcpu);
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index af823a3..44976a5 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2803,7 +2803,7 @@
 		msr_info->data = vcpu->arch.ia32_xss;
 		break;
 	case MSR_TSC_AUX:
-		if (!guest_cpuid_has_rdtscp(vcpu))
+		if (!guest_cpuid_has_rdtscp(vcpu) && !msr_info->host_initiated)
 			return 1;
 		/* Otherwise falls through */
 	default:
@@ -2909,7 +2909,7 @@
 			clear_atomic_switch_msr(vmx, MSR_IA32_XSS);
 		break;
 	case MSR_TSC_AUX:
-		if (!guest_cpuid_has_rdtscp(vcpu))
+		if (!guest_cpuid_has_rdtscp(vcpu) && !msr_info->host_initiated)
 			return 1;
 		/* Check reserved bit, higher 32 bits should be zero */
 		if ((data >> 32) != 0)
@@ -8042,6 +8042,8 @@
 	u32 exit_reason = vmx->exit_reason;
 	u32 vectoring_info = vmx->idt_vectoring_info;
 
+	trace_kvm_exit(exit_reason, vcpu, KVM_ISA_VMX);
+
 	/*
 	 * Flush logged GPAs PML buffer, this will make dirty_bitmap more
 	 * updated. Another good is, in kvm_vm_ioctl_get_dirty_log, before
@@ -8668,7 +8670,6 @@
 	vmx->loaded_vmcs->launched = 1;
 
 	vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
-	trace_kvm_exit(vmx->exit_reason, vcpu, KVM_ISA_VMX);
 
 	/*
 	 * the KVM_REQ_EVENT optimization bit is only on for one entry, and if
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index eed3228..7ffc224 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3572,9 +3572,11 @@
 
 static int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps)
 {
+	int i;
 	mutex_lock(&kvm->arch.vpit->pit_state.lock);
 	memcpy(&kvm->arch.vpit->pit_state, ps, sizeof(struct kvm_pit_state));
-	kvm_pit_load_count(kvm, 0, ps->channels[0].count, 0);
+	for (i = 0; i < 3; i++)
+		kvm_pit_load_count(kvm, i, ps->channels[i].count, 0);
 	mutex_unlock(&kvm->arch.vpit->pit_state.lock);
 	return 0;
 }
@@ -3593,6 +3595,7 @@
 static int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
 {
 	int start = 0;
+	int i;
 	u32 prev_legacy, cur_legacy;
 	mutex_lock(&kvm->arch.vpit->pit_state.lock);
 	prev_legacy = kvm->arch.vpit->pit_state.flags & KVM_PIT_FLAGS_HPET_LEGACY;
@@ -3602,7 +3605,8 @@
 	memcpy(&kvm->arch.vpit->pit_state.channels, &ps->channels,
 	       sizeof(kvm->arch.vpit->pit_state.channels));
 	kvm->arch.vpit->pit_state.flags = ps->flags;
-	kvm_pit_load_count(kvm, 0, kvm->arch.vpit->pit_state.channels[0].count, start);
+	for (i = 0; i < 3; i++)
+		kvm_pit_load_count(kvm, i, kvm->arch.vpit->pit_state.channels[i].count, start);
 	mutex_unlock(&kvm->arch.vpit->pit_state.lock);
 	return 0;
 }
@@ -6515,6 +6519,8 @@
 	if (req_immediate_exit)
 		smp_send_reschedule(vcpu->cpu);
 
+	trace_kvm_entry(vcpu->vcpu_id);
+	wait_lapic_expire(vcpu);
 	__kvm_guest_enter();
 
 	if (unlikely(vcpu->arch.switch_db_regs)) {
@@ -6527,8 +6533,6 @@
 		vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
 	}
 
-	trace_kvm_entry(vcpu->vcpu_id);
-	wait_lapic_expire(vcpu);
 	kvm_x86_ops->run(vcpu);
 
 	/*
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index a035c2a..0f1c6fc 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -89,7 +89,7 @@
 	{ 0/* VMALLOC_START */, "vmalloc() Area" },
 	{ 0/*VMALLOC_END*/,     "vmalloc() End" },
 # ifdef CONFIG_HIGHMEM
-	{ 0/*PKMAP_BASE*/,      "Persisent kmap() Area" },
+	{ 0/*PKMAP_BASE*/,      "Persistent kmap() Area" },
 # endif
 	{ 0/*FIXADDR_START*/,   "Fixmap Area" },
 #endif
diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c
index 06934a8..14fcd01 100644
--- a/arch/x86/um/signal.c
+++ b/arch/x86/um/signal.c
@@ -211,7 +211,7 @@
 		if (err)
 			return 1;
 
-		err = convert_fxsr_from_user(&fpx, sc.fpstate);
+		err = convert_fxsr_from_user(&fpx, (void *)sc.fpstate);
 		if (err)
 			return 1;
 
@@ -227,7 +227,7 @@
 	{
 		struct user_i387_struct fp;
 
-		err = copy_from_user(&fp, sc.fpstate,
+		err = copy_from_user(&fp, (void *)sc.fpstate,
 				     sizeof(struct user_i387_struct));
 		if (err)
 			return 1;
@@ -291,7 +291,7 @@
 #endif
 #undef PUTREG
 	sc.oldmask = mask;
-	sc.fpstate = to_fp;
+	sc.fpstate = (unsigned long)to_fp;
 
 	err = copy_to_user(to, &sc, sizeof(struct sigcontext));
 	if (err)
@@ -468,12 +468,10 @@
 	struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
 	sigset_t set;
 	struct sigcontext __user *sc = &frame->sc;
-	unsigned long __user *oldmask = &sc->oldmask;
-	unsigned long __user *extramask = frame->extramask;
 	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
 
-	if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
-	    copy_from_user(&set.sig[1], extramask, sig_size))
+	if (copy_from_user(&set.sig[0], &sc->oldmask, sizeof(set.sig[0])) ||
+	    copy_from_user(&set.sig[1], frame->extramask, sig_size))
 		goto segfault;
 
 	set_current_blocked(&set);
@@ -505,6 +503,7 @@
 {
 	struct rt_sigframe __user *frame;
 	int err = 0, sig = ksig->sig;
+	unsigned long fp_to;
 
 	frame = (struct rt_sigframe __user *)
 		round_down(stack_top - sizeof(struct rt_sigframe), 16);
@@ -526,7 +525,10 @@
 	err |= __save_altstack(&frame->uc.uc_stack, PT_REGS_SP(regs));
 	err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
 			       set->sig[0]);
-	err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
+
+	fp_to = (unsigned long)&frame->fpstate;
+
+	err |= __put_user(fp_to, &frame->uc.uc_mcontext.fpstate);
 	if (sizeof(*set) == 16) {
 		err |= __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
 		err |= __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index ac161db..cb5e266 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2495,14 +2495,9 @@
 {
 	x86_init.paging.pagetable_init = xen_pagetable_init;
 
-	/* Optimization - we can use the HVM one but it has no idea which
-	 * VCPUs are descheduled - which means that it will needlessly IPI
-	 * them. Xen knows so let it do the job.
-	 */
-	if (xen_feature(XENFEAT_auto_translated_physmap)) {
-		pv_mmu_ops.flush_tlb_others = xen_flush_tlb_others;
+	if (xen_feature(XENFEAT_auto_translated_physmap))
 		return;
-	}
+
 	pv_mmu_ops = xen_mmu_ops;
 
 	memset(dummy_mapping, 0xff, PAGE_SIZE);
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index feddabd..3705eab 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -68,26 +68,16 @@
 
 void xen_arch_pre_suspend(void)
 {
-	int cpu;
-
-	for_each_online_cpu(cpu)
-		xen_pmu_finish(cpu);
-
 	if (xen_pv_domain())
 		xen_pv_pre_suspend();
 }
 
 void xen_arch_post_suspend(int cancelled)
 {
-	int cpu;
-
 	if (xen_pv_domain())
 		xen_pv_post_suspend(cancelled);
 	else
 		xen_hvm_post_suspend(cancelled);
-
-	for_each_online_cpu(cpu)
-		xen_pmu_init(cpu);
 }
 
 static void xen_vcpu_notify_restore(void *data)
@@ -106,10 +96,20 @@
 
 void xen_arch_resume(void)
 {
+	int cpu;
+
 	on_each_cpu(xen_vcpu_notify_restore, NULL, 1);
+
+	for_each_online_cpu(cpu)
+		xen_pmu_init(cpu);
 }
 
 void xen_arch_suspend(void)
 {
+	int cpu;
+
+	for_each_online_cpu(cpu)
+		xen_pmu_finish(cpu);
+
 	on_each_cpu(xen_vcpu_notify_suspend, NULL, 1);
 }
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 5bcdfc1..5a37188 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -1127,15 +1127,15 @@
  * of the main cic data structures.  For now we allow a task to change
  * its cgroup only if it's the only owner of its ioc.
  */
-static int blkcg_can_attach(struct cgroup_subsys_state *css,
-			    struct cgroup_taskset *tset)
+static int blkcg_can_attach(struct cgroup_taskset *tset)
 {
 	struct task_struct *task;
+	struct cgroup_subsys_state *dst_css;
 	struct io_context *ioc;
 	int ret = 0;
 
 	/* task_lock() is needed to avoid races with exit_io_context() */
-	cgroup_taskset_for_each(task, tset) {
+	cgroup_taskset_for_each(task, dst_css, tset) {
 		task_lock(task);
 		ioc = task->io_context;
 		if (ioc && atomic_read(&ioc->nr_tasks) > 1)
diff --git a/block/blk-core.c b/block/blk-core.c
index a0af404..c487b94 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1689,8 +1689,6 @@
 	struct request *req;
 	unsigned int request_count = 0;
 
-	blk_queue_split(q, &bio, q->bio_split);
-
 	/*
 	 * low level driver can indicate that it wants pages above a
 	 * certain limit bounced to low memory (ie for highmem, or even
@@ -1698,6 +1696,8 @@
 	 */
 	blk_queue_bounce(q, &bio);
 
+	blk_queue_split(q, &bio, q->bio_split);
+
 	if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
 		bio->bi_error = -EIO;
 		bio_endio(bio);
@@ -3405,6 +3405,9 @@
 {
 	int ret = 0;
 
+	if (!q->dev)
+		return ret;
+
 	spin_lock_irq(q->queue_lock);
 	if (q->nr_pending) {
 		ret = -EBUSY;
@@ -3432,6 +3435,9 @@
  */
 void blk_post_runtime_suspend(struct request_queue *q, int err)
 {
+	if (!q->dev)
+		return;
+
 	spin_lock_irq(q->queue_lock);
 	if (!err) {
 		q->rpm_status = RPM_SUSPENDED;
@@ -3456,6 +3462,9 @@
  */
 void blk_pre_runtime_resume(struct request_queue *q)
 {
+	if (!q->dev)
+		return;
+
 	spin_lock_irq(q->queue_lock);
 	q->rpm_status = RPM_RESUMING;
 	spin_unlock_irq(q->queue_lock);
@@ -3478,6 +3487,9 @@
  */
 void blk_post_runtime_resume(struct request_queue *q, int err)
 {
+	if (!q->dev)
+		return;
+
 	spin_lock_irq(q->queue_lock);
 	if (!err) {
 		q->rpm_status = RPM_ACTIVE;
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index b4ffc5b..e5b5721 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -277,12 +277,12 @@
 	if (WARN_ON_ONCE(in_irq()))
 		return -EDEADLK;
 
+	walk->iv = req->info;
 	walk->nbytes = walk->total;
 	if (unlikely(!walk->total))
 		return 0;
 
 	walk->iv_buffer = NULL;
-	walk->iv = req->info;
 	if (unlikely(((unsigned long)walk->iv & alignmask))) {
 		int err = ablkcipher_copy_iv(walk, tfm, alignmask);
 
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 11b9814..8cc1622 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -326,12 +326,12 @@
 	if (WARN_ON_ONCE(in_irq()))
 		return -EDEADLK;
 
+	walk->iv = desc->info;
 	walk->nbytes = walk->total;
 	if (unlikely(!walk->total))
 		return 0;
 
 	walk->buffer = NULL;
-	walk->iv = desc->info;
 	if (unlikely(((unsigned long)walk->iv & walk->alignmask))) {
 		int err = blkcipher_copy_iv(walk);
 		if (err)
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
index e7ed39b..aa45d48 100644
--- a/drivers/acpi/nfit.c
+++ b/drivers/acpi/nfit.c
@@ -1810,7 +1810,7 @@
 	if (!dev->driver) {
 		/* dev->driver may be null if we're being removed */
 		dev_dbg(dev, "%s: no driver found for dev\n", __func__);
-		return;
+		goto out_unlock;
 	}
 
 	if (!acpi_desc) {
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index ff02bb4..cdfbcc5 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -314,16 +314,6 @@
 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
-	{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
-	{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
-	{ PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
-	{ PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
-	{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
-	{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
-	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
-	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
-	{ PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
-	{ PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
 	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
@@ -350,10 +340,22 @@
 	{ PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */
 	{ PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */
 	{ PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */
+	{ PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */
 	{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
 	{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
+	{ PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */
 	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
 	{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
+	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
+	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
+	{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
+	{ PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
+	{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
+	{ PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
+	{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
+	{ PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
+	{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
+	{ PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c
index 8490d37..f7a7fa8 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_mvebu.c
@@ -62,6 +62,7 @@
 	writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int ahci_mvebu_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	return ahci_platform_suspend_host(&pdev->dev);
@@ -81,6 +82,10 @@
 
 	return ahci_platform_resume_host(&pdev->dev);
 }
+#else
+#define ahci_mvebu_suspend NULL
+#define ahci_mvebu_resume NULL
+#endif
 
 static const struct ata_port_info ahci_mvebu_port_info = {
 	.flags	   = AHCI_FLAG_COMMON,
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 096064c..4665512 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1273,6 +1273,15 @@
 	ata_tf_to_fis(tf, pmp, is_cmd, fis);
 	ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12));
 
+	/* set port value for softreset of Port Multiplier */
+	if (pp->fbs_enabled && pp->fbs_last_dev != pmp) {
+		tmp = readl(port_mmio + PORT_FBS);
+		tmp &= ~(PORT_FBS_DEV_MASK | PORT_FBS_DEC);
+		tmp |= pmp << PORT_FBS_DEV_OFFSET;
+		writel(tmp, port_mmio + PORT_FBS);
+		pp->fbs_last_dev = pmp;
+	}
+
 	/* issue & wait */
 	writel(1, port_mmio + PORT_CMD_ISSUE);
 
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index cb0508a..961acc7 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1505,12 +1505,20 @@
 unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
 			       u8 page, void *buf, unsigned int sectors)
 {
+	unsigned long ap_flags = dev->link->ap->flags;
 	struct ata_taskfile tf;
 	unsigned int err_mask;
 	bool dma = false;
 
 	DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
 
+	/*
+	 * Return error without actually issuing the command on controllers
+	 * which e.g. lockup on a read log page.
+	 */
+	if (ap_flags & ATA_FLAG_NO_LOG_PAGE)
+		return AC_ERR_DEV;
+
 retry:
 	ata_tf_init(dev, &tf);
 	if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) &&
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 5389579..a723ae92 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -45,7 +45,8 @@
 	SATA_FSL_MAX_PRD_DIRECT	= 16,	/* Direct PRDT entries */
 
 	SATA_FSL_HOST_FLAGS	= (ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
-				ATA_FLAG_PMP | ATA_FLAG_NCQ | ATA_FLAG_AN),
+				   ATA_FLAG_PMP | ATA_FLAG_NCQ |
+				   ATA_FLAG_AN | ATA_FLAG_NO_LOG_PAGE),
 
 	SATA_FSL_MAX_CMDS	= SATA_FSL_QUEUE_DEPTH,
 	SATA_FSL_CMD_HDR_SIZE	= 16,	/* 4 DWORDS */
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index dea6edcb..29bcff0 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -630,6 +630,9 @@
 	unsigned int n, quirks = 0;
 	unsigned char model_num[ATA_ID_PROD_LEN + 1];
 
+	/* This controller doesn't support trim */
+	dev->horkage |= ATA_HORKAGE_NOTRIM;
+
 	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
 	for (n = 0; sil_blacklist[n].product; n++)
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 2804aed..25425d3 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -303,6 +303,10 @@
 	if (mem->state == MEM_OFFLINE)
 		return 0;
 
+	/* Can't offline block with non-present sections */
+	if (mem->section_count != sections_per_block)
+		return -EINVAL;
+
 	return memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
 }
 
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 167418e..65f50ec 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -390,6 +390,7 @@
 	struct generic_pm_domain *genpd;
 	bool (*stop_ok)(struct device *__dev);
 	struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
+	bool runtime_pm = pm_runtime_enabled(dev);
 	ktime_t time_start;
 	s64 elapsed_ns;
 	int ret;
@@ -400,12 +401,19 @@
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
+	/*
+	 * A runtime PM centric subsystem/driver may re-use the runtime PM
+	 * callbacks for other purposes than runtime PM. In those scenarios
+	 * runtime PM is disabled. Under these circumstances, we shall skip
+	 * validating/measuring the PM QoS latency.
+	 */
 	stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
-	if (stop_ok && !stop_ok(dev))
+	if (runtime_pm && stop_ok && !stop_ok(dev))
 		return -EBUSY;
 
 	/* Measure suspend latency. */
-	time_start = ktime_get();
+	if (runtime_pm)
+		time_start = ktime_get();
 
 	ret = genpd_save_dev(genpd, dev);
 	if (ret)
@@ -418,13 +426,15 @@
 	}
 
 	/* Update suspend latency value if the measured time exceeds it. */
-	elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
-	if (elapsed_ns > td->suspend_latency_ns) {
-		td->suspend_latency_ns = elapsed_ns;
-		dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
-			elapsed_ns);
-		genpd->max_off_time_changed = true;
-		td->constraint_changed = true;
+	if (runtime_pm) {
+		elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
+		if (elapsed_ns > td->suspend_latency_ns) {
+			td->suspend_latency_ns = elapsed_ns;
+			dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
+				elapsed_ns);
+			genpd->max_off_time_changed = true;
+			td->constraint_changed = true;
+		}
 	}
 
 	/*
@@ -453,6 +463,7 @@
 {
 	struct generic_pm_domain *genpd;
 	struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
+	bool runtime_pm = pm_runtime_enabled(dev);
 	ktime_t time_start;
 	s64 elapsed_ns;
 	int ret;
@@ -479,14 +490,14 @@
 
  out:
 	/* Measure resume latency. */
-	if (timed)
+	if (timed && runtime_pm)
 		time_start = ktime_get();
 
 	genpd_start_dev(genpd, dev);
 	genpd_restore_dev(genpd, dev);
 
 	/* Update resume latency value if the measured time exceeds it. */
-	if (timed) {
+	if (timed && runtime_pm) {
 		elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
 		if (elapsed_ns > td->resume_latency_ns) {
 			td->resume_latency_ns = elapsed_ns;
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c
index 0c3940e..a428e4e 100644
--- a/drivers/block/null_blk.c
+++ b/drivers/block/null_blk.c
@@ -219,6 +219,9 @@
 {
 	struct request_queue *q = NULL;
 
+	if (cmd->rq)
+		q = cmd->rq->q;
+
 	switch (queue_mode)  {
 	case NULL_Q_MQ:
 		blk_mq_end_request(cmd->rq, 0);
@@ -232,9 +235,6 @@
 		goto free_cmd;
 	}
 
-	if (cmd->rq)
-		q = cmd->rq->q;
-
 	/* Restart queue if needed, as we are freeing a tag */
 	if (q && !q->mq_ops && blk_queue_stopped(q)) {
 		unsigned long flags;
@@ -444,8 +444,9 @@
 	blk_put_request(rq);
 }
 
-static int null_lnvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
+static int null_lnvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
 {
+	struct request_queue *q = dev->q;
 	struct request *rq;
 	struct bio *bio = rqd->bio;
 
@@ -470,7 +471,7 @@
 	return 0;
 }
 
-static int null_lnvm_id(struct request_queue *q, struct nvm_id *id)
+static int null_lnvm_id(struct nvm_dev *dev, struct nvm_id *id)
 {
 	sector_t size = gb * 1024 * 1024 * 1024ULL;
 	sector_t blksize;
@@ -523,7 +524,7 @@
 	return 0;
 }
 
-static void *null_lnvm_create_dma_pool(struct request_queue *q, char *name)
+static void *null_lnvm_create_dma_pool(struct nvm_dev *dev, char *name)
 {
 	mempool_t *virtmem_pool;
 
@@ -541,7 +542,7 @@
 	mempool_destroy(pool);
 }
 
-static void *null_lnvm_dev_dma_alloc(struct request_queue *q, void *pool,
+static void *null_lnvm_dev_dma_alloc(struct nvm_dev *dev, void *pool,
 				gfp_t mem_flags, dma_addr_t *dma_handler)
 {
 	return mempool_alloc(pool, mem_flags);
@@ -765,7 +766,9 @@
 
 static int __init null_init(void)
 {
+	int ret = 0;
 	unsigned int i;
+	struct nullb *nullb;
 
 	if (bs > PAGE_SIZE) {
 		pr_warn("null_blk: invalid block size\n");
@@ -807,22 +810,29 @@
 								0, 0, NULL);
 		if (!ppa_cache) {
 			pr_err("null_blk: unable to create ppa cache\n");
-			return -ENOMEM;
-		}
-	}
-
-	for (i = 0; i < nr_devices; i++) {
-		if (null_add_dev()) {
-			unregister_blkdev(null_major, "nullb");
+			ret = -ENOMEM;
 			goto err_ppa;
 		}
 	}
 
+	for (i = 0; i < nr_devices; i++) {
+		ret = null_add_dev();
+		if (ret)
+			goto err_dev;
+	}
+
 	pr_info("null: module loaded\n");
 	return 0;
-err_ppa:
+
+err_dev:
+	while (!list_empty(&nullb_list)) {
+		nullb = list_entry(nullb_list.next, struct nullb, list);
+		null_del_dev(nullb);
+	}
 	kmem_cache_destroy(ppa_cache);
-	return -EINVAL;
+err_ppa:
+	unregister_blkdev(null_major, "nullb");
+	return ret;
 }
 
 static void __exit null_exit(void)
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index f909994..41fb1a9 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -950,6 +950,8 @@
 		goto unmap;
 
 	for (n = 0, i = 0; n < nseg; n++) {
+		uint8_t first_sect, last_sect;
+
 		if ((n % SEGS_PER_INDIRECT_FRAME) == 0) {
 			/* Map indirect segments */
 			if (segments)
@@ -957,15 +959,18 @@
 			segments = kmap_atomic(pages[n/SEGS_PER_INDIRECT_FRAME]->page);
 		}
 		i = n % SEGS_PER_INDIRECT_FRAME;
+
 		pending_req->segments[n]->gref = segments[i].gref;
-		seg[n].nsec = segments[i].last_sect -
-			segments[i].first_sect + 1;
-		seg[n].offset = (segments[i].first_sect << 9);
-		if ((segments[i].last_sect >= (XEN_PAGE_SIZE >> 9)) ||
-		    (segments[i].last_sect < segments[i].first_sect)) {
+
+		first_sect = READ_ONCE(segments[i].first_sect);
+		last_sect = READ_ONCE(segments[i].last_sect);
+		if (last_sect >= (XEN_PAGE_SIZE >> 9) || last_sect < first_sect) {
 			rc = -EINVAL;
 			goto unmap;
 		}
+
+		seg[n].nsec = last_sect - first_sect + 1;
+		seg[n].offset = first_sect << 9;
 		preq->nr_sects += seg[n].nsec;
 	}
 
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index 68e87a0..c929ae2 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -408,8 +408,8 @@
 					struct blkif_x86_32_request *src)
 {
 	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST, j;
-	dst->operation = src->operation;
-	switch (src->operation) {
+	dst->operation = READ_ONCE(src->operation);
+	switch (dst->operation) {
 	case BLKIF_OP_READ:
 	case BLKIF_OP_WRITE:
 	case BLKIF_OP_WRITE_BARRIER:
@@ -456,8 +456,8 @@
 					struct blkif_x86_64_request *src)
 {
 	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST, j;
-	dst->operation = src->operation;
-	switch (src->operation) {
+	dst->operation = READ_ONCE(src->operation);
+	switch (dst->operation) {
 	case BLKIF_OP_READ:
 	case BLKIF_OP_WRITE:
 	case BLKIF_OP_WRITE_BARRIER:
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 55fe902..4cc72fa 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1230,14 +1230,14 @@
 
 	new_smi->intf = intf;
 
-	/* Try to claim any interrupts. */
-	if (new_smi->irq_setup)
-		new_smi->irq_setup(new_smi);
-
 	/* Set up the timer that drives the interface. */
 	setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
 	smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES);
 
+	/* Try to claim any interrupts. */
+	if (new_smi->irq_setup)
+		new_smi->irq_setup(new_smi);
+
 	/*
 	 * Check if the user forcefully enabled the daemon.
 	 */
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
index 10819e2..335322d 100644
--- a/drivers/clk/clk-gpio.c
+++ b/drivers/clk/clk-gpio.c
@@ -209,6 +209,8 @@
 
 struct clk_gpio_delayed_register_data {
 	const char *gpio_name;
+	int num_parents;
+	const char **parent_names;
 	struct device_node *node;
 	struct mutex lock;
 	struct clk *clk;
@@ -222,8 +224,6 @@
 {
 	struct clk_gpio_delayed_register_data *data = _data;
 	struct clk *clk;
-	const char **parent_names;
-	int i, num_parents;
 	int gpio;
 	enum of_gpio_flags of_flags;
 
@@ -248,26 +248,14 @@
 		return ERR_PTR(gpio);
 	}
 
-	num_parents = of_clk_get_parent_count(data->node);
-
-	parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
-	if (!parent_names) {
-		clk = ERR_PTR(-ENOMEM);
-		goto out;
-	}
-
-	for (i = 0; i < num_parents; i++)
-		parent_names[i] = of_clk_get_parent_name(data->node, i);
-
-	clk = data->clk_register_get(data->node->name, parent_names,
-			num_parents, gpio, of_flags & OF_GPIO_ACTIVE_LOW);
+	clk = data->clk_register_get(data->node->name, data->parent_names,
+			data->num_parents, gpio, of_flags & OF_GPIO_ACTIVE_LOW);
 	if (IS_ERR(clk))
 		goto out;
 
 	data->clk = clk;
 out:
 	mutex_unlock(&data->lock);
-	kfree(parent_names);
 
 	return clk;
 }
@@ -296,11 +284,24 @@
 				unsigned gpio, bool active_low))
 {
 	struct clk_gpio_delayed_register_data *data;
+	const char **parent_names;
+	int i, num_parents;
 
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return;
 
+	num_parents = of_clk_get_parent_count(node);
+
+	parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		return;
+
+	for (i = 0; i < num_parents; i++)
+		parent_names[i] = of_clk_get_parent_name(node, i);
+
+	data->num_parents = num_parents;
+	data->parent_names = parent_names;
 	data->node = node;
 	data->gpio_name = gpio_name;
 	data->clk_register_get = clk_register_get;
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 1ab0fb8..7bc1c45 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -778,8 +778,10 @@
 	 */
 	clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
 	div = get_pll_div(cg, hwc, clksel);
-	if (!div)
+	if (!div) {
+		kfree(hwc);
 		return NULL;
+	}
 
 	pct80_rate = clk_get_rate(div->clk);
 	pct80_rate *= 8;
diff --git a/drivers/clk/clk-scpi.c b/drivers/clk/clk-scpi.c
index 0b501a9..cd0f272 100644
--- a/drivers/clk/clk-scpi.c
+++ b/drivers/clk/clk-scpi.c
@@ -292,6 +292,7 @@
 		ret = scpi_clk_add(dev, child, match);
 		if (ret) {
 			scpi_clocks_remove(pdev);
+			of_node_put(child);
 			return ret;
 		}
 	}
diff --git a/drivers/clk/imx/clk-pllv1.c b/drivers/clk/imx/clk-pllv1.c
index 8564e43..82fe366 100644
--- a/drivers/clk/imx/clk-pllv1.c
+++ b/drivers/clk/imx/clk-pllv1.c
@@ -52,7 +52,7 @@
 		unsigned long parent_rate)
 {
 	struct clk_pllv1 *pll = to_clk_pllv1(hw);
-	long long ll;
+	unsigned long long ull;
 	int mfn_abs;
 	unsigned int mfi, mfn, mfd, pd;
 	u32 reg;
@@ -94,16 +94,16 @@
 	rate = parent_rate * 2;
 	rate /= pd + 1;
 
-	ll = (unsigned long long)rate * mfn_abs;
+	ull = (unsigned long long)rate * mfn_abs;
 
-	do_div(ll, mfd + 1);
+	do_div(ull, mfd + 1);
 
 	if (mfn_is_negative(pll, mfn))
-		ll = -ll;
+		ull = (rate * mfi) - ull;
+	else
+		ull = (rate * mfi) + ull;
 
-	ll = (rate * mfi) + ll;
-
-	return ll;
+	return ull;
 }
 
 static struct clk_ops clk_pllv1_ops = {
diff --git a/drivers/clk/imx/clk-pllv2.c b/drivers/clk/imx/clk-pllv2.c
index b18f875..4aeda56 100644
--- a/drivers/clk/imx/clk-pllv2.c
+++ b/drivers/clk/imx/clk-pllv2.c
@@ -79,7 +79,7 @@
 {
 	long mfi, mfn, mfd, pdf, ref_clk;
 	unsigned long dbl;
-	s64 temp;
+	u64 temp;
 
 	dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
 
@@ -98,8 +98,9 @@
 	temp = (u64) ref_clk * abs(mfn);
 	do_div(temp, mfd + 1);
 	if (mfn < 0)
-		temp = -temp;
-	temp = (ref_clk * mfi) + temp;
+		temp = (ref_clk * mfi) - temp;
+	else
+		temp = (ref_clk * mfi) + temp;
 
 	return temp;
 }
@@ -126,7 +127,7 @@
 {
 	u32 reg;
 	long mfi, pdf, mfn, mfd = 999999;
-	s64 temp64;
+	u64 temp64;
 	unsigned long quad_parent_rate;
 
 	quad_parent_rate = 4 * parent_rate;
diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c
index d1b1c95..0a94d96 100644
--- a/drivers/clk/imx/clk-vf610.c
+++ b/drivers/clk/imx/clk-vf610.c
@@ -335,22 +335,22 @@
 	clk[VF610_CLK_SAI0_SEL] = imx_clk_mux("sai0_sel", CCM_CSCMR1, 0, 2, sai_sels, 4);
 	clk[VF610_CLK_SAI0_EN] = imx_clk_gate("sai0_en", "sai0_sel", CCM_CSCDR1, 16);
 	clk[VF610_CLK_SAI0_DIV] = imx_clk_divider("sai0_div", "sai0_en", CCM_CSCDR1, 0, 4);
-	clk[VF610_CLK_SAI0] = imx_clk_gate2("sai0", "sai0_div", CCM_CCGR0, CCM_CCGRx_CGn(15));
+	clk[VF610_CLK_SAI0] = imx_clk_gate2("sai0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(15));
 
 	clk[VF610_CLK_SAI1_SEL] = imx_clk_mux("sai1_sel", CCM_CSCMR1, 2, 2, sai_sels, 4);
 	clk[VF610_CLK_SAI1_EN] = imx_clk_gate("sai1_en", "sai1_sel", CCM_CSCDR1, 17);
 	clk[VF610_CLK_SAI1_DIV] = imx_clk_divider("sai1_div", "sai1_en", CCM_CSCDR1, 4, 4);
-	clk[VF610_CLK_SAI1] = imx_clk_gate2("sai1", "sai1_div", CCM_CCGR1, CCM_CCGRx_CGn(0));
+	clk[VF610_CLK_SAI1] = imx_clk_gate2("sai1", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(0));
 
 	clk[VF610_CLK_SAI2_SEL] = imx_clk_mux("sai2_sel", CCM_CSCMR1, 4, 2, sai_sels, 4);
 	clk[VF610_CLK_SAI2_EN] = imx_clk_gate("sai2_en", "sai2_sel", CCM_CSCDR1, 18);
 	clk[VF610_CLK_SAI2_DIV] = imx_clk_divider("sai2_div", "sai2_en", CCM_CSCDR1, 8, 4);
-	clk[VF610_CLK_SAI2] = imx_clk_gate2("sai2", "sai2_div", CCM_CCGR1, CCM_CCGRx_CGn(1));
+	clk[VF610_CLK_SAI2] = imx_clk_gate2("sai2", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(1));
 
 	clk[VF610_CLK_SAI3_SEL] = imx_clk_mux("sai3_sel", CCM_CSCMR1, 6, 2, sai_sels, 4);
 	clk[VF610_CLK_SAI3_EN] = imx_clk_gate("sai3_en", "sai3_sel", CCM_CSCDR1, 19);
 	clk[VF610_CLK_SAI3_DIV] = imx_clk_divider("sai3_div", "sai3_en", CCM_CSCDR1, 12, 4);
-	clk[VF610_CLK_SAI3] = imx_clk_gate2("sai3", "sai3_div", CCM_CCGR1, CCM_CCGRx_CGn(2));
+	clk[VF610_CLK_SAI3] = imx_clk_gate2("sai3", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(2));
 
 	clk[VF610_CLK_NFC_SEL] = imx_clk_mux("nfc_sel", CCM_CSCMR1, 12, 2, nfc_sels, 4);
 	clk[VF610_CLK_NFC_EN] = imx_clk_gate("nfc_en", "nfc_sel", CCM_CSCDR2, 9);
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index 09d2832..71fd293 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -9,6 +9,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
index 93e967c..7524491 100644
--- a/drivers/clk/mmp/clk-pxa168.c
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -9,6 +9,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
index 993abcd..37ba04b 100644
--- a/drivers/clk/mmp/clk-pxa910.c
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -9,6 +9,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
diff --git a/drivers/clk/sunxi/clk-a10-pll2.c b/drivers/clk/sunxi/clk-a10-pll2.c
index 5484c31e..0ee1f36 100644
--- a/drivers/clk/sunxi/clk-a10-pll2.c
+++ b/drivers/clk/sunxi/clk-a10-pll2.c
@@ -41,15 +41,10 @@
 
 #define SUN4I_PLL2_OUTPUTS		4
 
-struct sun4i_pll2_data {
-	u32	post_div_offset;
-	u32	pre_div_flags;
-};
-
 static DEFINE_SPINLOCK(sun4i_a10_pll2_lock);
 
 static void __init sun4i_pll2_setup(struct device_node *node,
-				    struct sun4i_pll2_data *data)
+				    int post_div_offset)
 {
 	const char *clk_name = node->name, *parent;
 	struct clk **clks, *base_clk, *prediv_clk;
@@ -76,7 +71,7 @@
 					  parent, 0, reg,
 					  SUN4I_PLL2_PRE_DIV_SHIFT,
 					  SUN4I_PLL2_PRE_DIV_WIDTH,
-					  data->pre_div_flags,
+					  CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
 					  &sun4i_a10_pll2_lock);
 	if (!prediv_clk) {
 		pr_err("Couldn't register the prediv clock\n");
@@ -127,7 +122,7 @@
 	 */
 	val = readl(reg);
 	val &= ~(SUN4I_PLL2_POST_DIV_MASK << SUN4I_PLL2_POST_DIV_SHIFT);
-	val |= (SUN4I_PLL2_POST_DIV_VALUE - data->post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT;
+	val |= (SUN4I_PLL2_POST_DIV_VALUE - post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT;
 	writel(val, reg);
 
 	of_property_read_string_index(node, "clock-output-names",
@@ -191,25 +186,17 @@
 	iounmap(reg);
 }
 
-static struct sun4i_pll2_data sun4i_a10_pll2_data = {
-	.pre_div_flags	= CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
-};
-
 static void __init sun4i_a10_pll2_setup(struct device_node *node)
 {
-	sun4i_pll2_setup(node, &sun4i_a10_pll2_data);
+	sun4i_pll2_setup(node, 0);
 }
 
 CLK_OF_DECLARE(sun4i_a10_pll2, "allwinner,sun4i-a10-pll2-clk",
 	       sun4i_a10_pll2_setup);
 
-static struct sun4i_pll2_data sun5i_a13_pll2_data = {
-	.post_div_offset	= 1,
-};
-
 static void __init sun5i_a13_pll2_setup(struct device_node *node)
 {
-	sun4i_pll2_setup(node, &sun5i_a13_pll2_data);
+	sun4i_pll2_setup(node, 1);
 }
 
 CLK_OF_DECLARE(sun5i_a13_pll2, "allwinner,sun5i-a13-pll2-clk",
diff --git a/drivers/clk/ti/clk-816x.c b/drivers/clk/ti/clk-816x.c
index 1dfad0c..2a5d84f 100644
--- a/drivers/clk/ti/clk-816x.c
+++ b/drivers/clk/ti/clk-816x.c
@@ -20,6 +20,8 @@
 	DT_CLK(NULL, "sys_clkin", "sys_clkin_ck"),
 	DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"),
 	DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"),
+	DT_CLK(NULL, "timer_32k_ck", "sysclk18_ck"),
+	DT_CLK(NULL, "timer_ext_ck", "tclkin_ck"),
 	DT_CLK(NULL, "mpu_ck", "mpu_ck"),
 	DT_CLK(NULL, "timer1_fck", "timer1_fck"),
 	DT_CLK(NULL, "timer2_fck", "timer2_fck"),
diff --git a/drivers/clk/ti/clkt_dpll.c b/drivers/clk/ti/clkt_dpll.c
index 9023ca9..b5cc6f6 100644
--- a/drivers/clk/ti/clkt_dpll.c
+++ b/drivers/clk/ti/clkt_dpll.c
@@ -240,7 +240,7 @@
  */
 unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
 {
-	long long dpll_clk;
+	u64 dpll_clk;
 	u32 dpll_mult, dpll_div, v;
 	struct dpll_data *dd;
 
@@ -262,7 +262,7 @@
 	dpll_div = v & dd->div1_mask;
 	dpll_div >>= __ffs(dd->div1_mask);
 
-	dpll_clk = (long long)clk_get_rate(dd->clk_ref) * dpll_mult;
+	dpll_clk = (u64)clk_get_rate(dd->clk_ref) * dpll_mult;
 	do_div(dpll_clk, dpll_div + 1);
 
 	return dpll_clk;
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index 5b17268..df25583 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -214,7 +214,6 @@
 {
 	struct clk_divider *divider;
 	unsigned int div, value;
-	unsigned long flags = 0;
 	u32 val;
 
 	if (!hw || !rate)
@@ -228,9 +227,6 @@
 	if (value > div_mask(divider))
 		value = div_mask(divider);
 
-	if (divider->lock)
-		spin_lock_irqsave(divider->lock, flags);
-
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
@@ -240,9 +236,6 @@
 	val |= value << divider->shift;
 	ti_clk_ll_ops->clk_writel(val, divider->reg);
 
-	if (divider->lock)
-		spin_unlock_irqrestore(divider->lock, flags);
-
 	return 0;
 }
 
@@ -256,8 +249,7 @@
 				     const char *parent_name,
 				     unsigned long flags, void __iomem *reg,
 				     u8 shift, u8 width, u8 clk_divider_flags,
-				     const struct clk_div_table *table,
-				     spinlock_t *lock)
+				     const struct clk_div_table *table)
 {
 	struct clk_divider *div;
 	struct clk *clk;
@@ -288,7 +280,6 @@
 	div->shift = shift;
 	div->width = width;
 	div->flags = clk_divider_flags;
-	div->lock = lock;
 	div->hw.init = &init;
 	div->table = table;
 
@@ -421,7 +412,7 @@
 
 	clk = _register_divider(NULL, setup->name, div->parent,
 				flags, (void __iomem *)reg, div->bit_shift,
-				width, div_flags, table, NULL);
+				width, div_flags, table);
 
 	if (IS_ERR(clk))
 		kfree(table);
@@ -584,8 +575,7 @@
 		goto cleanup;
 
 	clk = _register_divider(NULL, node->name, parent_name, flags, reg,
-				shift, width, clk_divider_flags, table,
-				NULL);
+				shift, width, clk_divider_flags, table);
 
 	if (!IS_ERR(clk)) {
 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
index f4b2e98..66a0d0e 100644
--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -168,7 +168,7 @@
 {
 	struct fapll_data *fd = to_fapll(hw);
 	u32 fapll_n, fapll_p, v;
-	long long rate;
+	u64 rate;
 
 	if (ti_fapll_clock_is_bypass(fd))
 		return parent_rate;
@@ -314,7 +314,7 @@
 {
 	struct fapll_synth *synth = to_synth(hw);
 	u32 synth_div_m;
-	long long rate;
+	u64 rate;
 
 	/* The audio_pll_clk1 is hardwired to produce 32.768KiHz clock */
 	if (!synth->div)
diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
index 69f08a1..dab9ba8 100644
--- a/drivers/clk/ti/mux.c
+++ b/drivers/clk/ti/mux.c
@@ -69,7 +69,6 @@
 {
 	struct clk_mux *mux = to_clk_mux(hw);
 	u32 val;
-	unsigned long flags = 0;
 
 	if (mux->table) {
 		index = mux->table[index];
@@ -81,9 +80,6 @@
 			index++;
 	}
 
-	if (mux->lock)
-		spin_lock_irqsave(mux->lock, flags);
-
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
@@ -93,9 +89,6 @@
 	val |= index << mux->shift;
 	ti_clk_ll_ops->clk_writel(val, mux->reg);
 
-	if (mux->lock)
-		spin_unlock_irqrestore(mux->lock, flags);
-
 	return 0;
 }
 
@@ -109,7 +102,7 @@
 				 const char **parent_names, u8 num_parents,
 				 unsigned long flags, void __iomem *reg,
 				 u8 shift, u32 mask, u8 clk_mux_flags,
-				 u32 *table, spinlock_t *lock)
+				 u32 *table)
 {
 	struct clk_mux *mux;
 	struct clk *clk;
@@ -133,7 +126,6 @@
 	mux->shift = shift;
 	mux->mask = mask;
 	mux->flags = clk_mux_flags;
-	mux->lock = lock;
 	mux->table = table;
 	mux->hw.init = &init;
 
@@ -175,7 +167,7 @@
 
 	return _register_mux(NULL, setup->name, mux->parents, mux->num_parents,
 			     flags, (void __iomem *)reg, mux->bit_shift, mask,
-			     mux_flags, NULL, NULL);
+			     mux_flags, NULL);
 }
 
 /**
@@ -227,8 +219,7 @@
 	mask = (1 << fls(mask)) - 1;
 
 	clk = _register_mux(NULL, node->name, parent_names, num_parents,
-			    flags, reg, shift, mask, clk_mux_flags, NULL,
-			    NULL);
+			    flags, reg, shift, mask, clk_mux_flags, NULL);
 
 	if (!IS_ERR(clk))
 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
diff --git a/drivers/clocksource/mmio.c b/drivers/clocksource/mmio.c
index 1593ade..c4f7d7a 100644
--- a/drivers/clocksource/mmio.c
+++ b/drivers/clocksource/mmio.c
@@ -55,7 +55,7 @@
 {
 	struct clocksource_mmio *cs;
 
-	if (bits > 32 || bits < 16)
+	if (bits > 64 || bits < 16)
 		return -EINVAL;
 
 	cs = kzalloc(sizeof(struct clocksource_mmio), GFP_KERNEL);
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 235a1ba..b1f8a73 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -226,7 +226,7 @@
 
 config ARM_TEGRA124_CPUFREQ
 	tristate "Tegra124 CPUFreq support"
-	depends on ARCH_TEGRA && CPUFREQ_DT
+	depends on ARCH_TEGRA && CPUFREQ_DT && REGULATOR
 	default y
 	help
 	  This adds the CPUFreq driver support for Tegra124 SOCs.
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 4d07cbd..98fb882 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1123,7 +1123,7 @@
 				   limits->max_sysfs_pct);
 	limits->max_perf_pct = max(limits->min_policy_pct,
 				   limits->max_perf_pct);
-	limits->max_perf = round_up(limits->max_perf, 8);
+	limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
 
 	/* Make sure min_perf_pct <= max_perf_pct */
 	limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c
index 733aa51..68ef8fd 100644
--- a/drivers/cpufreq/s3c24xx-cpufreq.c
+++ b/drivers/cpufreq/s3c24xx-cpufreq.c
@@ -648,7 +648,7 @@
  *
  * Register the given set of PLLs with the system.
  */
-int __init s3c_plltab_register(struct cpufreq_frequency_table *plls,
+int s3c_plltab_register(struct cpufreq_frequency_table *plls,
 			       unsigned int plls_no)
 {
 	struct cpufreq_frequency_table *vals;
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 7f039de..370c661 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -156,7 +156,7 @@
 #define		AT_XDMAC_CC_WRIP	(0x1 << 23)	/* Write in Progress (read only) */
 #define			AT_XDMAC_CC_WRIP_DONE		(0x0 << 23)
 #define			AT_XDMAC_CC_WRIP_IN_PROGRESS	(0x1 << 23)
-#define		AT_XDMAC_CC_PERID(i)	(0x7f & (h) << 24)	/* Channel Peripheral Identifier */
+#define		AT_XDMAC_CC_PERID(i)	(0x7f & (i) << 24)	/* Channel Peripheral Identifier */
 #define AT_XDMAC_CDS_MSP	0x2C	/* Channel Data Stride Memory Set Pattern */
 #define AT_XDMAC_CSUS		0x30	/* Channel Source Microblock Stride */
 #define AT_XDMAC_CDUS		0x34	/* Channel Destination Microblock Stride */
@@ -965,7 +965,9 @@
 							NULL,
 							src_addr, dst_addr,
 							xt, xt->sgl);
-		for (i = 0; i < xt->numf; i++)
+
+		/* Length of the block is (BLEN+1) microblocks. */
+		for (i = 0; i < xt->numf - 1; i++)
 			at_xdmac_increment_block_count(chan, first);
 
 		dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
@@ -1086,6 +1088,7 @@
 		/* Check remaining length and change data width if needed. */
 		dwidth = at_xdmac_align_width(chan,
 					      src_addr | dst_addr | xfer_size);
+		chan_cc &= ~AT_XDMAC_CC_DWIDTH_MASK;
 		chan_cc |= AT_XDMAC_CC_DWIDTH(dwidth);
 
 		ublen = xfer_size >> dwidth;
@@ -1333,7 +1336,7 @@
 		 * since we don't care about the stride anymore.
 		 */
 		if ((i == (sg_len - 1)) &&
-		    sg_dma_len(ppsg) == sg_dma_len(psg)) {
+		    sg_dma_len(psg) == sg_dma_len(sg)) {
 			dev_dbg(chan2dev(chan),
 				"%s: desc 0x%p can be merged with desc 0x%p\n",
 				__func__, desc, pdesc);
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index c92d6a7..996c4b0 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -31,6 +31,7 @@
  */
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -62,6 +63,11 @@
 	uint32_t pad[2];
 };
 
+struct bcm2835_cb_entry {
+	struct bcm2835_dma_cb *cb;
+	dma_addr_t paddr;
+};
+
 struct bcm2835_chan {
 	struct virt_dma_chan vc;
 	struct list_head node;
@@ -72,18 +78,18 @@
 
 	int ch;
 	struct bcm2835_desc *desc;
+	struct dma_pool *cb_pool;
 
 	void __iomem *chan_base;
 	int irq_number;
 };
 
 struct bcm2835_desc {
+	struct bcm2835_chan *c;
 	struct virt_dma_desc vd;
 	enum dma_transfer_direction dir;
 
-	unsigned int control_block_size;
-	struct bcm2835_dma_cb *control_block_base;
-	dma_addr_t control_block_base_phys;
+	struct bcm2835_cb_entry *cb_list;
 
 	unsigned int frames;
 	size_t size;
@@ -143,10 +149,13 @@
 static void bcm2835_dma_desc_free(struct virt_dma_desc *vd)
 {
 	struct bcm2835_desc *desc = container_of(vd, struct bcm2835_desc, vd);
-	dma_free_coherent(desc->vd.tx.chan->device->dev,
-			desc->control_block_size,
-			desc->control_block_base,
-			desc->control_block_base_phys);
+	int i;
+
+	for (i = 0; i < desc->frames; i++)
+		dma_pool_free(desc->c->cb_pool, desc->cb_list[i].cb,
+			      desc->cb_list[i].paddr);
+
+	kfree(desc->cb_list);
 	kfree(desc);
 }
 
@@ -199,7 +208,7 @@
 
 	c->desc = d = to_bcm2835_dma_desc(&vd->tx);
 
-	writel(d->control_block_base_phys, c->chan_base + BCM2835_DMA_ADDR);
+	writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
 	writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
 }
 
@@ -232,9 +241,16 @@
 static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+	struct device *dev = c->vc.chan.device->dev;
 
-	dev_dbg(c->vc.chan.device->dev,
-			"Allocating DMA channel %d\n", c->ch);
+	dev_dbg(dev, "Allocating DMA channel %d\n", c->ch);
+
+	c->cb_pool = dma_pool_create(dev_name(dev), dev,
+				     sizeof(struct bcm2835_dma_cb), 0, 0);
+	if (!c->cb_pool) {
+		dev_err(dev, "unable to allocate descriptor pool\n");
+		return -ENOMEM;
+	}
 
 	return request_irq(c->irq_number,
 			bcm2835_dma_callback, 0, "DMA IRQ", c);
@@ -246,6 +262,7 @@
 
 	vchan_free_chan_resources(&c->vc);
 	free_irq(c->irq_number, c);
+	dma_pool_destroy(c->cb_pool);
 
 	dev_dbg(c->vc.chan.device->dev, "Freeing DMA channel %u\n", c->ch);
 }
@@ -261,8 +278,7 @@
 	size_t size;
 
 	for (size = i = 0; i < d->frames; i++) {
-		struct bcm2835_dma_cb *control_block =
-			&d->control_block_base[i];
+		struct bcm2835_dma_cb *control_block = d->cb_list[i].cb;
 		size_t this_size = control_block->length;
 		dma_addr_t dma;
 
@@ -343,6 +359,7 @@
 	dma_addr_t dev_addr;
 	unsigned int es, sync_type;
 	unsigned int frame;
+	int i;
 
 	/* Grab configuration */
 	if (!is_slave_direction(direction)) {
@@ -374,27 +391,31 @@
 	if (!d)
 		return NULL;
 
+	d->c = c;
 	d->dir = direction;
 	d->frames = buf_len / period_len;
 
-	/* Allocate memory for control blocks */
-	d->control_block_size = d->frames * sizeof(struct bcm2835_dma_cb);
-	d->control_block_base = dma_zalloc_coherent(chan->device->dev,
-			d->control_block_size, &d->control_block_base_phys,
-			GFP_NOWAIT);
-
-	if (!d->control_block_base) {
+	d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL);
+	if (!d->cb_list) {
 		kfree(d);
 		return NULL;
 	}
+	/* Allocate memory for control blocks */
+	for (i = 0; i < d->frames; i++) {
+		struct bcm2835_cb_entry *cb_entry = &d->cb_list[i];
+
+		cb_entry->cb = dma_pool_zalloc(c->cb_pool, GFP_ATOMIC,
+					       &cb_entry->paddr);
+		if (!cb_entry->cb)
+			goto error_cb;
+	}
 
 	/*
 	 * Iterate over all frames, create a control block
 	 * for each frame and link them together.
 	 */
 	for (frame = 0; frame < d->frames; frame++) {
-		struct bcm2835_dma_cb *control_block =
-			&d->control_block_base[frame];
+		struct bcm2835_dma_cb *control_block = d->cb_list[frame].cb;
 
 		/* Setup adresses */
 		if (d->dir == DMA_DEV_TO_MEM) {
@@ -428,12 +449,21 @@
 		 * This DMA engine driver currently only supports cyclic DMA.
 		 * Therefore, wrap around at number of frames.
 		 */
-		control_block->next = d->control_block_base_phys +
-			sizeof(struct bcm2835_dma_cb)
-			* ((frame + 1) % d->frames);
+		control_block->next = d->cb_list[((frame + 1) % d->frames)].paddr;
 	}
 
 	return vchan_tx_prep(&c->vc, &d->vd, flags);
+error_cb:
+	i--;
+	for (; i >= 0; i--) {
+		struct bcm2835_cb_entry *cb_entry = &d->cb_list[i];
+
+		dma_pool_free(c->cb_pool, cb_entry->cb, cb_entry->paddr);
+	}
+
+	kfree(d->cb_list);
+	kfree(d);
+	return NULL;
 }
 
 static int bcm2835_dma_slave_config(struct dma_chan *chan,
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 0675e26..16fe773 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -1752,16 +1752,14 @@
 	return ret;
 }
 
-static bool edma_is_memcpy_channel(int ch_num, u16 *memcpy_channels)
+static bool edma_is_memcpy_channel(int ch_num, s32 *memcpy_channels)
 {
-	s16 *memcpy_ch = memcpy_channels;
-
 	if (!memcpy_channels)
 		return false;
-	while (*memcpy_ch != -1) {
-		if (*memcpy_ch == ch_num)
+	while (*memcpy_channels != -1) {
+		if (*memcpy_channels == ch_num)
 			return true;
-		memcpy_ch++;
+		memcpy_channels++;
 	}
 	return false;
 }
@@ -1775,7 +1773,7 @@
 {
 	struct dma_device *s_ddev = &ecc->dma_slave;
 	struct dma_device *m_ddev = NULL;
-	s16 *memcpy_channels = ecc->info->memcpy_channels;
+	s32 *memcpy_channels = ecc->info->memcpy_channels;
 	int i, j;
 
 	dma_cap_zero(s_ddev->cap_mask);
@@ -1996,16 +1994,16 @@
 	prop = of_find_property(dev->of_node, "ti,edma-memcpy-channels", &sz);
 	if (prop) {
 		const char pname[] = "ti,edma-memcpy-channels";
-		size_t nelm = sz / sizeof(s16);
-		s16 *memcpy_ch;
+		size_t nelm = sz / sizeof(s32);
+		s32 *memcpy_ch;
 
-		memcpy_ch = devm_kcalloc(dev, nelm + 1, sizeof(s16),
+		memcpy_ch = devm_kcalloc(dev, nelm + 1, sizeof(s32),
 					 GFP_KERNEL);
 		if (!memcpy_ch)
 			return ERR_PTR(-ENOMEM);
 
-		ret = of_property_read_u16_array(dev->of_node, pname,
-						 (u16 *)memcpy_ch, nelm);
+		ret = of_property_read_u32_array(dev->of_node, pname,
+						 (u32 *)memcpy_ch, nelm);
 		if (ret)
 			return ERR_PTR(ret);
 
@@ -2017,31 +2015,50 @@
 				&sz);
 	if (prop) {
 		const char pname[] = "ti,edma-reserved-slot-ranges";
+		u32 (*tmp)[2];
 		s16 (*rsv_slots)[2];
-		size_t nelm = sz / sizeof(*rsv_slots);
+		size_t nelm = sz / sizeof(*tmp);
 		struct edma_rsv_info *rsv_info;
+		int i;
 
 		if (!nelm)
 			return info;
 
-		rsv_info = devm_kzalloc(dev, sizeof(*rsv_info), GFP_KERNEL);
-		if (!rsv_info)
+		tmp = kcalloc(nelm, sizeof(*tmp), GFP_KERNEL);
+		if (!tmp)
 			return ERR_PTR(-ENOMEM);
 
+		rsv_info = devm_kzalloc(dev, sizeof(*rsv_info), GFP_KERNEL);
+		if (!rsv_info) {
+			kfree(tmp);
+			return ERR_PTR(-ENOMEM);
+		}
+
 		rsv_slots = devm_kcalloc(dev, nelm + 1, sizeof(*rsv_slots),
 					 GFP_KERNEL);
-		if (!rsv_slots)
+		if (!rsv_slots) {
+			kfree(tmp);
 			return ERR_PTR(-ENOMEM);
+		}
 
-		ret = of_property_read_u16_array(dev->of_node, pname,
-						 (u16 *)rsv_slots, nelm * 2);
-		if (ret)
+		ret = of_property_read_u32_array(dev->of_node, pname,
+						 (u32 *)tmp, nelm * 2);
+		if (ret) {
+			kfree(tmp);
 			return ERR_PTR(ret);
+		}
 
+		for (i = 0; i < nelm; i++) {
+			rsv_slots[i][0] = tmp[i][0];
+			rsv_slots[i][1] = tmp[i][1];
+		}
 		rsv_slots[nelm][0] = -1;
 		rsv_slots[nelm][1] = -1;
+
 		info->rsv = rsv_info;
 		info->rsv->rsv_slots = (const s16 (*)[2])rsv_slots;
+
+		kfree(tmp);
 	}
 
 	return info;
diff --git a/drivers/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c
index 068e920..cddfa8d 100644
--- a/drivers/dma/mic_x100_dma.c
+++ b/drivers/dma/mic_x100_dma.c
@@ -317,6 +317,7 @@
 	struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
 	struct device *dev = mic_dma_ch_to_device(mic_ch);
 	int result;
+	struct dma_async_tx_descriptor *tx = NULL;
 
 	if (!len && !flags)
 		return NULL;
@@ -324,10 +325,13 @@
 	spin_lock(&mic_ch->prep_lock);
 	result = mic_dma_do_dma(mic_ch, flags, dma_src, dma_dest, len);
 	if (result >= 0)
-		return allocate_tx(mic_ch);
-	dev_err(dev, "Error enqueueing dma, error=%d\n", result);
+		tx = allocate_tx(mic_ch);
+
+	if (!tx)
+		dev_err(dev, "Error enqueueing dma, error=%d\n", result);
+
 	spin_unlock(&mic_ch->prep_lock);
-	return NULL;
+	return tx;
 }
 
 static struct dma_async_tx_descriptor *
@@ -335,13 +339,14 @@
 {
 	struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
 	int ret;
+	struct dma_async_tx_descriptor *tx = NULL;
 
 	spin_lock(&mic_ch->prep_lock);
 	ret = mic_dma_do_dma(mic_ch, flags, 0, 0, 0);
 	if (!ret)
-		return allocate_tx(mic_ch);
+		tx = allocate_tx(mic_ch);
 	spin_unlock(&mic_ch->prep_lock);
-	return NULL;
+	return tx;
 }
 
 /* Return the status of the transaction */
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
index a24f5cb..953dc91 100644
--- a/drivers/fpga/fpga-mgr.c
+++ b/drivers/fpga/fpga-mgr.c
@@ -122,12 +122,10 @@
 	}
 
 	ret = fpga_mgr_buf_load(mgr, flags, fw->data, fw->size);
-	if (ret)
-		return ret;
 
 	release_firmware(fw);
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(fpga_mgr_firmware_load);
 
@@ -256,7 +254,6 @@
 		      void *priv)
 {
 	struct fpga_manager *mgr;
-	const char *dt_label;
 	int id, ret;
 
 	if (!mops || !mops->write_init || !mops->write ||
@@ -300,11 +297,9 @@
 	mgr->dev.id = id;
 	dev_set_drvdata(dev, mgr);
 
-	dt_label = of_get_property(mgr->dev.of_node, "label", NULL);
-	if (dt_label)
-		ret = dev_set_name(&mgr->dev, "%s", dt_label);
-	else
-		ret = dev_set_name(&mgr->dev, "fpga%d", id);
+	ret = dev_set_name(&mgr->dev, "fpga%d", id);
+	if (ret)
+		goto error_device;
 
 	ret = device_add(&mgr->dev);
 	if (ret)
diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c
index e5827a5..5eaea8b 100644
--- a/drivers/gpio/gpio-ath79.c
+++ b/drivers/gpio/gpio-ath79.c
@@ -113,7 +113,7 @@
 		__raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR);
 
 	__raw_writel(
-		__raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & BIT(offset),
+		__raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset),
 		ctrl->base + AR71XX_GPIO_REG_OE);
 
 	spin_unlock_irqrestore(&ctrl->lock, flags);
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index bd5193c..88ae70d 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -141,9 +141,9 @@
 	unsigned long pinmask = bgc->pin2mask(bgc, gpio);
 
 	if (bgc->dir & pinmask)
-		return bgc->read_reg(bgc->reg_set) & pinmask;
+		return !!(bgc->read_reg(bgc->reg_set) & pinmask);
 	else
-		return bgc->read_reg(bgc->reg_dat) & pinmask;
+		return !!(bgc->read_reg(bgc->reg_dat) & pinmask);
 }
 
 static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 2a91f32..4e4c308 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1279,7 +1279,13 @@
 	chip = desc->chip;
 	offset = gpio_chip_hwgpio(desc);
 	value = chip->get ? chip->get(chip, offset) : -EIO;
-	value = value < 0 ? value : !!value;
+	/*
+	 * FIXME: fix all drivers to clamp to [0,1] or return negative,
+	 * then change this to:
+	 * value = value < 0 ? value : !!value;
+	 * so we can properly propagate error codes.
+	 */
+	value = !!value;
 	trace_gpio_value(desc_to_gpio(desc), 1, value);
 	return value;
 }
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index c4bf9a1..59babd5 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -160,6 +160,7 @@
 	  If M is selected, the module will be called amdgpu.
 
 source "drivers/gpu/drm/amd/amdgpu/Kconfig"
+source "drivers/gpu/drm/amd/powerplay/Kconfig"
 
 source "drivers/gpu/drm/nouveau/Kconfig"
 
@@ -266,3 +267,5 @@
 source "drivers/gpu/drm/imx/Kconfig"
 
 source "drivers/gpu/drm/vc4/Kconfig"
+
+source "drivers/gpu/drm/etnaviv/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 1e9ff4c..f858aa2 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -75,3 +75,4 @@
 obj-y			+= panel/
 obj-y			+= bridge/
 obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
+obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 04c2707..66f729e 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -2,10 +2,13 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/amd/include/asic_reg \
-	-Idrivers/gpu/drm/amd/include \
-	-Idrivers/gpu/drm/amd/amdgpu \
-	-Idrivers/gpu/drm/amd/scheduler
+FULL_AMD_PATH=$(src)/..
+
+ccflags-y := -Iinclude/drm -I$(FULL_AMD_PATH)/include/asic_reg \
+	-I$(FULL_AMD_PATH)/include \
+	-I$(FULL_AMD_PATH)/amdgpu \
+	-I$(FULL_AMD_PATH)/scheduler \
+	-I$(FULL_AMD_PATH)/powerplay/inc
 
 amdgpu-y := amdgpu_drv.o
 
@@ -44,6 +47,7 @@
 # add SMC block
 amdgpu-y += \
 	amdgpu_dpm.o \
+	amdgpu_powerplay.o \
 	cz_smc.o cz_dpm.o \
 	tonga_smc.o tonga_dpm.o \
 	fiji_smc.o fiji_dpm.o \
@@ -94,6 +98,14 @@
 amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o
 amdgpu-$(CONFIG_MMU_NOTIFIER) += amdgpu_mn.o
 
+ifneq ($(CONFIG_DRM_AMD_POWERPLAY),)
+
+include $(FULL_AMD_PATH)/powerplay/Makefile
+
+amdgpu-y += $(AMD_POWERPLAY_FILES)
+
+endif
+
 obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o
 
 CFLAGS_amdgpu_trace_points.o := -I$(src)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 5a5f04d..313b0cc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -52,6 +52,7 @@
 #include "amdgpu_irq.h"
 #include "amdgpu_ucode.h"
 #include "amdgpu_gds.h"
+#include "amd_powerplay.h"
 
 #include "gpu_scheduler.h"
 
@@ -85,6 +86,7 @@
 extern int amdgpu_sched_jobs;
 extern int amdgpu_sched_hw_submission;
 extern int amdgpu_enable_semaphores;
+extern int amdgpu_powerplay;
 
 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS	        3000
 #define AMDGPU_MAX_USEC_TIMEOUT			100000	/* 100 ms */
@@ -918,8 +920,8 @@
 #define AMDGPU_VM_FAULT_STOP_ALWAYS	2
 
 struct amdgpu_vm_pt {
-	struct amdgpu_bo	*bo;
-	uint64_t		addr;
+	struct amdgpu_bo_list_entry	entry;
+	uint64_t			addr;
 };
 
 struct amdgpu_vm_id {
@@ -981,9 +983,12 @@
 void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
 int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
-struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
-					       struct amdgpu_vm *vm,
-					       struct list_head *head);
+void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
+			 struct list_head *validated,
+			 struct amdgpu_bo_list_entry *entry);
+void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates);
+void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
+				  struct amdgpu_vm *vm);
 int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
 		      struct amdgpu_sync *sync);
 void amdgpu_vm_flush(struct amdgpu_ring *ring,
@@ -1024,11 +1029,9 @@
  * context related structures
  */
 
-#define AMDGPU_CTX_MAX_CS_PENDING	16
-
 struct amdgpu_ctx_ring {
 	uint64_t		sequence;
-	struct fence		*fences[AMDGPU_CTX_MAX_CS_PENDING];
+	struct fence		**fences;
 	struct amd_sched_entity	entity;
 };
 
@@ -1037,6 +1040,7 @@
 	struct amdgpu_device    *adev;
 	unsigned		reset_counter;
 	spinlock_t		ring_lock;
+	struct fence            **fences;
 	struct amdgpu_ctx_ring	rings[AMDGPU_MAX_RINGS];
 };
 
@@ -1047,7 +1051,7 @@
 	struct idr		ctx_handles;
 };
 
-int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel,
+int amdgpu_ctx_init(struct amdgpu_device *adev, enum amd_sched_priority pri,
 		    struct amdgpu_ctx *ctx);
 void amdgpu_ctx_fini(struct amdgpu_ctx *ctx);
 
@@ -1254,7 +1258,7 @@
 	unsigned		nchunks;
 	struct amdgpu_cs_chunk	*chunks;
 	/* relocations */
-	struct amdgpu_bo_list_entry	*vm_bos;
+	struct amdgpu_bo_list_entry	vm_pd;
 	struct list_head	validated;
 	struct fence		*fence;
 
@@ -1264,7 +1268,8 @@
 	struct ww_acquire_ctx	ticket;
 
 	/* user fence */
-	struct amdgpu_user_fence uf;
+	struct amdgpu_user_fence	uf;
+	struct amdgpu_bo_list_entry	uf_entry;
 };
 
 struct amdgpu_job {
@@ -1300,31 +1305,7 @@
 int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb);
 void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb);
 
-/**
- * struct amdgpu_pm - power management datas
- * It keeps track of various data needed to take powermanagement decision.
- */
 
-enum amdgpu_pm_state_type {
-	/* not used for dpm */
-	POWER_STATE_TYPE_DEFAULT,
-	POWER_STATE_TYPE_POWERSAVE,
-	/* user selectable states */
-	POWER_STATE_TYPE_BATTERY,
-	POWER_STATE_TYPE_BALANCED,
-	POWER_STATE_TYPE_PERFORMANCE,
-	/* internal states */
-	POWER_STATE_TYPE_INTERNAL_UVD,
-	POWER_STATE_TYPE_INTERNAL_UVD_SD,
-	POWER_STATE_TYPE_INTERNAL_UVD_HD,
-	POWER_STATE_TYPE_INTERNAL_UVD_HD2,
-	POWER_STATE_TYPE_INTERNAL_UVD_MVC,
-	POWER_STATE_TYPE_INTERNAL_BOOT,
-	POWER_STATE_TYPE_INTERNAL_THERMAL,
-	POWER_STATE_TYPE_INTERNAL_ACPI,
-	POWER_STATE_TYPE_INTERNAL_ULV,
-	POWER_STATE_TYPE_INTERNAL_3DPERF,
-};
 
 enum amdgpu_int_thermal_type {
 	THERMAL_TYPE_NONE,
@@ -1606,8 +1587,8 @@
 	/* vce requirements */
 	struct amdgpu_vce_state vce_states[AMDGPU_MAX_VCE_LEVELS];
 	enum amdgpu_vce_level vce_level;
-	enum amdgpu_pm_state_type state;
-	enum amdgpu_pm_state_type user_state;
+	enum amd_pm_state_type state;
+	enum amd_pm_state_type user_state;
 	u32                     platform_caps;
 	u32                     voltage_response_time;
 	u32                     backbias_response_time;
@@ -1660,8 +1641,13 @@
 	const struct firmware	*fw;	/* SMC firmware */
 	uint32_t                fw_version;
 	const struct amdgpu_dpm_funcs *funcs;
+	uint32_t                pcie_gen_mask;
+	uint32_t                pcie_mlw_mask;
+	struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */
 };
 
+void amdgpu_get_pcie_info(struct amdgpu_device *adev);
+
 /*
  * UVD
  */
@@ -1829,6 +1815,8 @@
  */
 struct amdgpu_asic_funcs {
 	bool (*read_disabled_bios)(struct amdgpu_device *adev);
+	bool (*read_bios_from_rom)(struct amdgpu_device *adev,
+				   u8 *bios, u32 length_bytes);
 	int (*read_register)(struct amdgpu_device *adev, u32 se_num,
 			     u32 sh_num, u32 reg_offset, u32 *value);
 	void (*set_vga_state)(struct amdgpu_device *adev, bool state);
@@ -2059,6 +2047,10 @@
 	/* interrupts */
 	struct amdgpu_irq		irq;
 
+	/* powerplay */
+	struct amd_powerplay		powerplay;
+	bool				pp_enabled;
+
 	/* dpm */
 	struct amdgpu_pm		pm;
 	u32				cg_flags;
@@ -2235,6 +2227,7 @@
 #define amdgpu_asic_set_vce_clocks(adev, ev, ec) (adev)->asic_funcs->set_vce_clocks((adev), (ev), (ec))
 #define amdgpu_asic_get_gpu_clock_counter(adev) (adev)->asic_funcs->get_gpu_clock_counter((adev))
 #define amdgpu_asic_read_disabled_bios(adev) (adev)->asic_funcs->read_disabled_bios((adev))
+#define amdgpu_asic_read_bios_from_rom(adev, b, l) (adev)->asic_funcs->read_bios_from_rom((adev), (b), (l))
 #define amdgpu_asic_read_register(adev, se, sh, offset, v)((adev)->asic_funcs->read_register((adev), (se), (sh), (offset), (v)))
 #define amdgpu_asic_get_cu_info(adev, info) (adev)->asic_funcs->get_cu_info((adev), (info))
 #define amdgpu_gart_flush_gpu_tlb(adev, vmid) (adev)->gart.gart_funcs->flush_gpu_tlb((adev), (vmid))
@@ -2276,24 +2269,78 @@
 #define amdgpu_display_resume_mc_access(adev, s) (adev)->mode_info.funcs->resume_mc_access((adev), (s))
 #define amdgpu_emit_copy_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((ib),  (s), (d), (b))
 #define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b))
-#define amdgpu_dpm_get_temperature(adev) (adev)->pm.funcs->get_temperature((adev))
 #define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev))
 #define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev))
 #define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev))
 #define amdgpu_dpm_display_configuration_changed(adev) (adev)->pm.funcs->display_configuration_changed((adev))
-#define amdgpu_dpm_get_sclk(adev, l) (adev)->pm.funcs->get_sclk((adev), (l))
-#define amdgpu_dpm_get_mclk(adev, l) (adev)->pm.funcs->get_mclk((adev), (l))
 #define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps))
-#define amdgpu_dpm_debugfs_print_current_performance_level(adev, m) (adev)->pm.funcs->debugfs_print_current_performance_level((adev), (m))
-#define amdgpu_dpm_force_performance_level(adev, l) (adev)->pm.funcs->force_performance_level((adev), (l))
 #define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev))
-#define amdgpu_dpm_powergate_uvd(adev, g) (adev)->pm.funcs->powergate_uvd((adev), (g))
-#define amdgpu_dpm_powergate_vce(adev, g) (adev)->pm.funcs->powergate_vce((adev), (g))
 #define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e))
-#define amdgpu_dpm_set_fan_control_mode(adev, m) (adev)->pm.funcs->set_fan_control_mode((adev), (m))
-#define amdgpu_dpm_get_fan_control_mode(adev) (adev)->pm.funcs->get_fan_control_mode((adev))
-#define amdgpu_dpm_set_fan_speed_percent(adev, s) (adev)->pm.funcs->set_fan_speed_percent((adev), (s))
-#define amdgpu_dpm_get_fan_speed_percent(adev, s) (adev)->pm.funcs->get_fan_speed_percent((adev), (s))
+
+#define amdgpu_dpm_get_temperature(adev) \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \
+	      (adev)->pm.funcs->get_temperature((adev))
+
+#define amdgpu_dpm_set_fan_control_mode(adev, m) \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \
+	      (adev)->pm.funcs->set_fan_control_mode((adev), (m))
+
+#define amdgpu_dpm_get_fan_control_mode(adev) \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \
+	      (adev)->pm.funcs->get_fan_control_mode((adev))
+
+#define amdgpu_dpm_set_fan_speed_percent(adev, s) \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \
+	      (adev)->pm.funcs->set_fan_speed_percent((adev), (s))
+
+#define amdgpu_dpm_get_fan_speed_percent(adev, s) \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \
+	      (adev)->pm.funcs->get_fan_speed_percent((adev), (s))
+
+#define amdgpu_dpm_get_sclk(adev, l) \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \
+		(adev)->pm.funcs->get_sclk((adev), (l))
+
+#define amdgpu_dpm_get_mclk(adev, l)  \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \
+	      (adev)->pm.funcs->get_mclk((adev), (l))
+
+
+#define amdgpu_dpm_force_performance_level(adev, l) \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \
+	      (adev)->pm.funcs->force_performance_level((adev), (l))
+
+#define amdgpu_dpm_powergate_uvd(adev, g) \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \
+	      (adev)->pm.funcs->powergate_uvd((adev), (g))
+
+#define amdgpu_dpm_powergate_vce(adev, g) \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \
+	      (adev)->pm.funcs->powergate_vce((adev), (g))
+
+#define amdgpu_dpm_debugfs_print_current_performance_level(adev, m) \
+	(adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->print_current_performance_level((adev)->powerplay.pp_handle, (m)) : \
+	      (adev)->pm.funcs->debugfs_print_current_performance_level((adev), (m))
+
+#define amdgpu_dpm_get_current_power_state(adev) \
+	(adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle)
+
+#define amdgpu_dpm_get_performance_level(adev) \
+	(adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)
+
+#define amdgpu_dpm_dispatch_task(adev, event_id, input, output)		\
+	(adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output))
 
 #define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a))
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index a142d5a..5cd7b73 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -29,66 +29,10 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include "amdgpu.h"
-#include "amdgpu_acpi.h"
+#include "amd_acpi.h"
 #include "atom.h"
 
-#define ACPI_AC_CLASS           "ac_adapter"
-
 extern void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev);
-
-struct atif_verify_interface {
-	u16 size;		/* structure size in bytes (includes size field) */
-	u16 version;		/* version */
-	u32 notification_mask;	/* supported notifications mask */
-	u32 function_bits;	/* supported functions bit vector */
-} __packed;
-
-struct atif_system_params {
-	u16 size;		/* structure size in bytes (includes size field) */
-	u32 valid_mask;		/* valid flags mask */
-	u32 flags;		/* flags */
-	u8 command_code;	/* notify command code */
-} __packed;
-
-struct atif_sbios_requests {
-	u16 size;		/* structure size in bytes (includes size field) */
-	u32 pending;		/* pending sbios requests */
-	u8 panel_exp_mode;	/* panel expansion mode */
-	u8 thermal_gfx;		/* thermal state: target gfx controller */
-	u8 thermal_state;	/* thermal state: state id (0: exit state, non-0: state) */
-	u8 forced_power_gfx;	/* forced power state: target gfx controller */
-	u8 forced_power_state;	/* forced power state: state id */
-	u8 system_power_src;	/* system power source */
-	u8 backlight_level;	/* panel backlight level (0-255) */
-} __packed;
-
-#define ATIF_NOTIFY_MASK	0x3
-#define ATIF_NOTIFY_NONE	0
-#define ATIF_NOTIFY_81		1
-#define ATIF_NOTIFY_N		2
-
-struct atcs_verify_interface {
-	u16 size;		/* structure size in bytes (includes size field) */
-	u16 version;		/* version */
-	u32 function_bits;	/* supported functions bit vector */
-} __packed;
-
-#define ATCS_VALID_FLAGS_MASK	0x3
-
-struct atcs_pref_req_input {
-	u16 size;		/* structure size in bytes (includes size field) */
-	u16 client_id;		/* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */
-	u16 valid_flags_mask;	/* valid flags mask */
-	u16 flags;		/* flags */
-	u8 req_type;		/* request type */
-	u8 perf_req;		/* performance request */
-} __packed;
-
-struct atcs_pref_req_output {
-	u16 size;		/* structure size in bytes (includes size field) */
-	u8 ret_val;		/* return value */
-} __packed;
-
 /* Call the ATIF method
  */
 /**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 5a8fbad..3c89586 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -11,7 +11,7 @@
 #include <linux/acpi.h>
 #include <linux/pci.h>
 
-#include "amdgpu_acpi.h"
+#include "amd_acpi.h"
 
 struct amdgpu_atpx_functions {
 	bool px_params;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index c44c0c6..80add22 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -35,6 +35,13 @@
  * BIOS.
  */
 
+#define AMD_VBIOS_SIGNATURE " 761295520"
+#define AMD_VBIOS_SIGNATURE_OFFSET 0x30
+#define AMD_VBIOS_SIGNATURE_SIZE sizeof(AMD_VBIOS_SIGNATURE)
+#define AMD_VBIOS_SIGNATURE_END (AMD_VBIOS_SIGNATURE_OFFSET + AMD_VBIOS_SIGNATURE_SIZE)
+#define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA)
+#define AMD_VBIOS_LENGTH(p) ((p)[2] << 9)
+
 /* If you boot an IGP board with a discrete card as the primary,
  * the IGP rom is not accessible via the rom bar as the IGP rom is
  * part of the system bios.  On boot, the system bios puts a
@@ -58,7 +65,7 @@
 		return false;
 	}
 
-	if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+	if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) {
 		iounmap(bios);
 		return false;
 	}
@@ -74,7 +81,7 @@
 
 bool amdgpu_read_bios(struct amdgpu_device *adev)
 {
-	uint8_t __iomem *bios, val1, val2;
+	uint8_t __iomem *bios, val[2];
 	size_t size;
 
 	adev->bios = NULL;
@@ -84,10 +91,10 @@
 		return false;
 	}
 
-	val1 = readb(&bios[0]);
-	val2 = readb(&bios[1]);
+	val[0] = readb(&bios[0]);
+	val[1] = readb(&bios[1]);
 
-	if (size == 0 || val1 != 0x55 || val2 != 0xaa) {
+	if (size == 0 || !AMD_IS_VALID_VBIOS(val)) {
 		pci_unmap_rom(adev->pdev, bios);
 		return false;
 	}
@@ -101,6 +108,38 @@
 	return true;
 }
 
+static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
+{
+	u8 header[AMD_VBIOS_SIGNATURE_END+1] = {0};
+	int len;
+
+	if (!adev->asic_funcs->read_bios_from_rom)
+		return false;
+
+	/* validate VBIOS signature */
+	if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header)) == false)
+		return false;
+	header[AMD_VBIOS_SIGNATURE_END] = 0;
+
+	if ((!AMD_IS_VALID_VBIOS(header)) ||
+	    0 != memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],
+			AMD_VBIOS_SIGNATURE,
+			strlen(AMD_VBIOS_SIGNATURE)))
+		return false;
+
+	/* valid vbios, go on */
+	len = AMD_VBIOS_LENGTH(header);
+	len = ALIGN(len, 4);
+	adev->bios = kmalloc(len, GFP_KERNEL);
+	if (!adev->bios) {
+		DRM_ERROR("no memory to allocate for BIOS\n");
+		return false;
+	}
+
+	/* read complete BIOS */
+	return amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
+}
+
 static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
 {
 	uint8_t __iomem *bios;
@@ -113,7 +152,7 @@
 		return false;
 	}
 
-	if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+	if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) {
 		return false;
 	}
 	adev->bios = kmemdup(bios, size, GFP_KERNEL);
@@ -230,7 +269,7 @@
 			break;
 	}
 
-	if (i == 0 || adev->bios[0] != 0x55 || adev->bios[1] != 0xaa) {
+	if (i == 0 || !AMD_IS_VALID_VBIOS(adev->bios)) {
 		kfree(adev->bios);
 		return false;
 	}
@@ -320,6 +359,9 @@
 	if (r == false)
 		r = amdgpu_read_bios(adev);
 	if (r == false) {
+		r = amdgpu_read_bios_from_rom(adev);
+	}
+	if (r == false) {
 		r = amdgpu_read_disabled_bios(adev);
 	}
 	if (r == false) {
@@ -330,7 +372,7 @@
 		adev->bios = NULL;
 		return false;
 	}
-	if (adev->bios[0] != 0x55 || adev->bios[1] != 0xaa) {
+	if (!AMD_IS_VALID_VBIOS(adev->bios)) {
 		printk("BIOS signature incorrect %x %x\n", adev->bios[0], adev->bios[1]);
 		goto free_bios;
 	}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
index 8e99514..a081dda 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
@@ -24,6 +24,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
+#include <linux/acpi.h>
 #include <drm/drmP.h>
 #include <linux/firmware.h>
 #include <drm/amdgpu_drm.h>
@@ -32,7 +33,6 @@
 #include "atom.h"
 #include "amdgpu_ucode.h"
 
-
 struct amdgpu_cgs_device {
 	struct cgs_device base;
 	struct amdgpu_device *adev;
@@ -398,6 +398,41 @@
 	WARN(ret, "pci_write_config_dword error");
 }
 
+
+static int amdgpu_cgs_get_pci_resource(void *cgs_device,
+				       enum cgs_resource_type resource_type,
+				       uint64_t size,
+				       uint64_t offset,
+				       uint64_t *resource_base)
+{
+	CGS_FUNC_ADEV;
+
+	if (resource_base == NULL)
+		return -EINVAL;
+
+	switch (resource_type) {
+	case CGS_RESOURCE_TYPE_MMIO:
+		if (adev->rmmio_size == 0)
+			return -ENOENT;
+		if ((offset + size) > adev->rmmio_size)
+			return -EINVAL;
+		*resource_base = adev->rmmio_base;
+		return 0;
+	case CGS_RESOURCE_TYPE_DOORBELL:
+		if (adev->doorbell.size == 0)
+			return -ENOENT;
+		if ((offset + size) > adev->doorbell.size)
+			return -EINVAL;
+		*resource_base = adev->doorbell.base;
+		return 0;
+	case CGS_RESOURCE_TYPE_FB:
+	case CGS_RESOURCE_TYPE_IO:
+	case CGS_RESOURCE_TYPE_ROM:
+	default:
+		return -EINVAL;
+	}
+}
+
 static const void *amdgpu_cgs_atom_get_data_table(void *cgs_device,
 						  unsigned table, uint16_t *size,
 						  uint8_t *frev, uint8_t *crev)
@@ -703,6 +738,9 @@
 		case CHIP_TONGA:
 			strcpy(fw_name, "amdgpu/tonga_smc.bin");
 			break;
+		case CHIP_FIJI:
+			strcpy(fw_name, "amdgpu/fiji_smc.bin");
+			break;
 		default:
 			DRM_ERROR("SMC firmware not supported\n");
 			return -EINVAL;
@@ -736,6 +774,288 @@
 	return 0;
 }
 
+static int amdgpu_cgs_query_system_info(void *cgs_device,
+				struct cgs_system_info *sys_info)
+{
+	CGS_FUNC_ADEV;
+
+	if (NULL == sys_info)
+		return -ENODEV;
+
+	if (sizeof(struct cgs_system_info) != sys_info->size)
+		return -ENODEV;
+
+	switch (sys_info->info_id) {
+	case CGS_SYSTEM_INFO_ADAPTER_BDF_ID:
+		sys_info->value = adev->pdev->devfn | (adev->pdev->bus->number << 8);
+		break;
+	case CGS_SYSTEM_INFO_PCIE_GEN_INFO:
+		sys_info->value = adev->pm.pcie_gen_mask;
+		break;
+	case CGS_SYSTEM_INFO_PCIE_MLW:
+		sys_info->value = adev->pm.pcie_mlw_mask;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int amdgpu_cgs_get_active_displays_info(void *cgs_device,
+					  struct cgs_display_info *info)
+{
+	CGS_FUNC_ADEV;
+	struct amdgpu_crtc *amdgpu_crtc;
+	struct drm_device *ddev = adev->ddev;
+	struct drm_crtc *crtc;
+	uint32_t line_time_us, vblank_lines;
+
+	if (info == NULL)
+		return -EINVAL;
+
+	if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
+		list_for_each_entry(crtc,
+				&ddev->mode_config.crtc_list, head) {
+			amdgpu_crtc = to_amdgpu_crtc(crtc);
+			if (crtc->enabled) {
+				info->active_display_mask |= (1 << amdgpu_crtc->crtc_id);
+				info->display_count++;
+			}
+			if (info->mode_info != NULL &&
+				crtc->enabled && amdgpu_crtc->enabled &&
+				amdgpu_crtc->hw_mode.clock) {
+				line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) /
+							amdgpu_crtc->hw_mode.clock;
+				vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end -
+							amdgpu_crtc->hw_mode.crtc_vdisplay +
+							(amdgpu_crtc->v_border * 2);
+				info->mode_info->vblank_time_us = vblank_lines * line_time_us;
+				info->mode_info->refresh_rate = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
+				info->mode_info->ref_clock = adev->clock.spll.reference_freq;
+				info->mode_info++;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/** \brief evaluate acpi namespace object, handle or pathname must be valid
+ *  \param cgs_device
+ *  \param info input/output arguments for the control method
+ *  \return status
+ */
+
+#if defined(CONFIG_ACPI)
+static int amdgpu_cgs_acpi_eval_object(void *cgs_device,
+				    struct cgs_acpi_method_info *info)
+{
+	CGS_FUNC_ADEV;
+	acpi_handle handle;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *params = NULL;
+	union acpi_object *obj = NULL;
+	uint8_t name[5] = {'\0'};
+	struct cgs_acpi_method_argument *argument = NULL;
+	uint32_t i, count;
+	acpi_status status;
+	int result;
+	uint32_t func_no = 0xFFFFFFFF;
+
+	handle = ACPI_HANDLE(&adev->pdev->dev);
+	if (!handle)
+		return -ENODEV;
+
+	memset(&input, 0, sizeof(struct acpi_object_list));
+
+	/* validate input info */
+	if (info->size != sizeof(struct cgs_acpi_method_info))
+		return -EINVAL;
+
+	input.count = info->input_count;
+	if (info->input_count > 0) {
+		if (info->pinput_argument == NULL)
+			return -EINVAL;
+		argument = info->pinput_argument;
+		func_no = argument->value;
+		for (i = 0; i < info->input_count; i++) {
+			if (((argument->type == ACPI_TYPE_STRING) ||
+			     (argument->type == ACPI_TYPE_BUFFER)) &&
+			    (argument->pointer == NULL))
+				return -EINVAL;
+			argument++;
+		}
+	}
+
+	if (info->output_count > 0) {
+		if (info->poutput_argument == NULL)
+			return -EINVAL;
+		argument = info->poutput_argument;
+		for (i = 0; i < info->output_count; i++) {
+			if (((argument->type == ACPI_TYPE_STRING) ||
+				(argument->type == ACPI_TYPE_BUFFER))
+				&& (argument->pointer == NULL))
+				return -EINVAL;
+			argument++;
+		}
+	}
+
+	/* The path name passed to acpi_evaluate_object should be null terminated */
+	if ((info->field & CGS_ACPI_FIELD_METHOD_NAME) != 0) {
+		strncpy(name, (char *)&(info->name), sizeof(uint32_t));
+		name[4] = '\0';
+	}
+
+	/* parse input parameters */
+	if (input.count > 0) {
+		input.pointer = params =
+				kzalloc(sizeof(union acpi_object) * input.count, GFP_KERNEL);
+		if (params == NULL)
+			return -EINVAL;
+
+		argument = info->pinput_argument;
+
+		for (i = 0; i < input.count; i++) {
+			params->type = argument->type;
+			switch (params->type) {
+			case ACPI_TYPE_INTEGER:
+				params->integer.value = argument->value;
+				break;
+			case ACPI_TYPE_STRING:
+				params->string.length = argument->method_length;
+				params->string.pointer = argument->pointer;
+				break;
+			case ACPI_TYPE_BUFFER:
+				params->buffer.length = argument->method_length;
+				params->buffer.pointer = argument->pointer;
+				break;
+			default:
+				break;
+			}
+			params++;
+			argument++;
+		}
+	}
+
+	/* parse output info */
+	count = info->output_count;
+	argument = info->poutput_argument;
+
+	/* evaluate the acpi method */
+	status = acpi_evaluate_object(handle, name, &input, &output);
+
+	if (ACPI_FAILURE(status)) {
+		result = -EIO;
+		goto error;
+	}
+
+	/* return the output info */
+	obj = output.pointer;
+
+	if (count > 1) {
+		if ((obj->type != ACPI_TYPE_PACKAGE) ||
+			(obj->package.count != count)) {
+			result = -EIO;
+			goto error;
+		}
+		params = obj->package.elements;
+	} else
+		params = obj;
+
+	if (params == NULL) {
+		result = -EIO;
+		goto error;
+	}
+
+	for (i = 0; i < count; i++) {
+		if (argument->type != params->type) {
+			result = -EIO;
+			goto error;
+		}
+		switch (params->type) {
+		case ACPI_TYPE_INTEGER:
+			argument->value = params->integer.value;
+			break;
+		case ACPI_TYPE_STRING:
+			if ((params->string.length != argument->data_length) ||
+				(params->string.pointer == NULL)) {
+				result = -EIO;
+				goto error;
+			}
+			strncpy(argument->pointer,
+				params->string.pointer,
+				params->string.length);
+			break;
+		case ACPI_TYPE_BUFFER:
+			if (params->buffer.pointer == NULL) {
+				result = -EIO;
+				goto error;
+			}
+			memcpy(argument->pointer,
+				params->buffer.pointer,
+				argument->data_length);
+			break;
+		default:
+			break;
+		}
+		argument++;
+		params++;
+	}
+
+error:
+	if (obj != NULL)
+		kfree(obj);
+	kfree((void *)input.pointer);
+	return result;
+}
+#else
+static int amdgpu_cgs_acpi_eval_object(void *cgs_device,
+				struct cgs_acpi_method_info *info)
+{
+	return -EIO;
+}
+#endif
+
+int amdgpu_cgs_call_acpi_method(void *cgs_device,
+					uint32_t acpi_method,
+					uint32_t acpi_function,
+					void *pinput, void *poutput,
+					uint32_t output_count,
+					uint32_t input_size,
+					uint32_t output_size)
+{
+	struct cgs_acpi_method_argument acpi_input[2] = { {0}, {0} };
+	struct cgs_acpi_method_argument acpi_output = {0};
+	struct cgs_acpi_method_info info = {0};
+
+	acpi_input[0].type = CGS_ACPI_TYPE_INTEGER;
+	acpi_input[0].method_length = sizeof(uint32_t);
+	acpi_input[0].data_length = sizeof(uint32_t);
+	acpi_input[0].value = acpi_function;
+
+	acpi_input[1].type = CGS_ACPI_TYPE_BUFFER;
+	acpi_input[1].method_length = CGS_ACPI_MAX_BUFFER_SIZE;
+	acpi_input[1].data_length = input_size;
+	acpi_input[1].pointer = pinput;
+
+	acpi_output.type = CGS_ACPI_TYPE_BUFFER;
+	acpi_output.method_length = CGS_ACPI_MAX_BUFFER_SIZE;
+	acpi_output.data_length = output_size;
+	acpi_output.pointer = poutput;
+
+	info.size = sizeof(struct cgs_acpi_method_info);
+	info.field = CGS_ACPI_FIELD_METHOD_NAME | CGS_ACPI_FIELD_INPUT_ARGUMENT_COUNT;
+	info.input_count = 2;
+	info.name = acpi_method;
+	info.pinput_argument = acpi_input;
+	info.output_count = output_count;
+	info.poutput_argument = &acpi_output;
+
+	return amdgpu_cgs_acpi_eval_object(cgs_device, &info);
+}
+
 static const struct cgs_ops amdgpu_cgs_ops = {
 	amdgpu_cgs_gpu_mem_info,
 	amdgpu_cgs_gmap_kmem,
@@ -756,6 +1076,7 @@
 	amdgpu_cgs_write_pci_config_byte,
 	amdgpu_cgs_write_pci_config_word,
 	amdgpu_cgs_write_pci_config_dword,
+	amdgpu_cgs_get_pci_resource,
 	amdgpu_cgs_atom_get_data_table,
 	amdgpu_cgs_atom_get_cmd_table_revs,
 	amdgpu_cgs_atom_exec_cmd_table,
@@ -768,7 +1089,10 @@
 	amdgpu_cgs_set_camera_voltages,
 	amdgpu_cgs_get_firmware_info,
 	amdgpu_cgs_set_powergating_state,
-	amdgpu_cgs_set_clockgating_state
+	amdgpu_cgs_set_clockgating_state,
+	amdgpu_cgs_get_active_displays_info,
+	amdgpu_cgs_call_acpi_method,
+	amdgpu_cgs_query_system_info,
 };
 
 static const struct cgs_os_ops amdgpu_cgs_os_ops = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 4f352ec..6f89f8e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -127,6 +127,37 @@
 	return 0;
 }
 
+static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p,
+				      struct drm_amdgpu_cs_chunk_fence *fence_data)
+{
+	struct drm_gem_object *gobj;
+	uint32_t handle;
+
+	handle = fence_data->handle;
+	gobj = drm_gem_object_lookup(p->adev->ddev, p->filp,
+				     fence_data->handle);
+	if (gobj == NULL)
+		return -EINVAL;
+
+	p->uf.bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
+	p->uf.offset = fence_data->offset;
+
+	if (amdgpu_ttm_tt_has_userptr(p->uf.bo->tbo.ttm)) {
+		drm_gem_object_unreference_unlocked(gobj);
+		return -EINVAL;
+	}
+
+	p->uf_entry.robj = amdgpu_bo_ref(p->uf.bo);
+	p->uf_entry.prefered_domains = AMDGPU_GEM_DOMAIN_GTT;
+	p->uf_entry.allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
+	p->uf_entry.priority = 0;
+	p->uf_entry.tv.bo = &p->uf_entry.robj->tbo;
+	p->uf_entry.tv.shared = true;
+
+	drm_gem_object_unreference_unlocked(gobj);
+	return 0;
+}
+
 int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
 {
 	union drm_amdgpu_cs *cs = data;
@@ -207,28 +238,15 @@
 
 		case AMDGPU_CHUNK_ID_FENCE:
 			size = sizeof(struct drm_amdgpu_cs_chunk_fence);
-			if (p->chunks[i].length_dw * sizeof(uint32_t) >= size) {
-				uint32_t handle;
-				struct drm_gem_object *gobj;
-				struct drm_amdgpu_cs_chunk_fence *fence_data;
-
-				fence_data = (void *)p->chunks[i].kdata;
-				handle = fence_data->handle;
-				gobj = drm_gem_object_lookup(p->adev->ddev,
-							     p->filp, handle);
-				if (gobj == NULL) {
-					ret = -EINVAL;
-					goto free_partial_kdata;
-				}
-
-				p->uf.bo = gem_to_amdgpu_bo(gobj);
-				amdgpu_bo_ref(p->uf.bo);
-				drm_gem_object_unreference_unlocked(gobj);
-				p->uf.offset = fence_data->offset;
-			} else {
+			if (p->chunks[i].length_dw * sizeof(uint32_t) < size) {
 				ret = -EINVAL;
 				goto free_partial_kdata;
 			}
+
+			ret = amdgpu_cs_user_fence_chunk(p, (void *)p->chunks[i].kdata);
+			if (ret)
+				goto free_partial_kdata;
+
 			break;
 
 		case AMDGPU_CHUNK_ID_DEPENDENCIES:
@@ -388,26 +406,32 @@
 		amdgpu_cs_buckets_get_list(&buckets, &p->validated);
 	}
 
-	p->vm_bos = amdgpu_vm_get_bos(p->adev, &fpriv->vm,
-				      &p->validated);
+	INIT_LIST_HEAD(&duplicates);
+	amdgpu_vm_get_pd_bo(&fpriv->vm, &p->validated, &p->vm_pd);
+
+	if (p->uf.bo)
+		list_add(&p->uf_entry.tv.head, &p->validated);
 
 	if (need_mmap_lock)
 		down_read(&current->mm->mmap_sem);
 
-	INIT_LIST_HEAD(&duplicates);
 	r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, &duplicates);
 	if (unlikely(r != 0))
 		goto error_reserve;
 
-	r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated);
+	amdgpu_vm_get_pt_bos(&fpriv->vm, &duplicates);
+
+	r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &duplicates);
 	if (r)
 		goto error_validate;
 
-	r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &duplicates);
+	r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated);
 
 error_validate:
-	if (r)
+	if (r) {
+		amdgpu_vm_move_pt_bos_in_lru(p->adev, &fpriv->vm);
 		ttm_eu_backoff_reservation(&p->ticket, &p->validated);
+	}
 
 error_reserve:
 	if (need_mmap_lock)
@@ -451,8 +475,11 @@
  **/
 static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
 {
+	struct amdgpu_fpriv *fpriv = parser->filp->driver_priv;
 	unsigned i;
 
+	amdgpu_vm_move_pt_bos_in_lru(parser->adev, &fpriv->vm);
+
 	if (!error) {
 		/* Sort the buffer list from the smallest to largest buffer,
 		 * which affects the order of buffers in the LRU list.
@@ -480,7 +507,6 @@
 	if (parser->bo_list)
 		amdgpu_bo_list_put(parser->bo_list);
 
-	drm_free_large(parser->vm_bos);
 	for (i = 0; i < parser->nchunks; i++)
 		drm_free_large(parser->chunks[i].kdata);
 	kfree(parser->chunks);
@@ -488,8 +514,8 @@
 		for (i = 0; i < parser->num_ibs; i++)
 			amdgpu_ib_free(parser->adev, &parser->ibs[i]);
 	kfree(parser->ibs);
-	if (parser->uf.bo)
-		amdgpu_bo_unref(&parser->uf.bo);
+	amdgpu_bo_unref(&parser->uf.bo);
+	amdgpu_bo_unref(&parser->uf_entry.robj);
 }
 
 static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index fec65f0..17d1fb1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -25,7 +25,7 @@
 #include <drm/drmP.h>
 #include "amdgpu.h"
 
-int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel,
+int amdgpu_ctx_init(struct amdgpu_device *adev, enum amd_sched_priority pri,
 		    struct amdgpu_ctx *ctx)
 {
 	unsigned i, j;
@@ -35,17 +35,25 @@
 	ctx->adev = adev;
 	kref_init(&ctx->refcount);
 	spin_lock_init(&ctx->ring_lock);
-	for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
-		ctx->rings[i].sequence = 1;
+	ctx->fences = kzalloc(sizeof(struct fence *) * amdgpu_sched_jobs *
+			 AMDGPU_MAX_RINGS, GFP_KERNEL);
+	if (!ctx->fences)
+		return -ENOMEM;
 
+	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
+		ctx->rings[i].sequence = 1;
+		ctx->rings[i].fences = (void *)ctx->fences + sizeof(struct fence *) *
+			amdgpu_sched_jobs * i;
+	}
 	if (amdgpu_enable_scheduler) {
 		/* create context entity for each ring */
 		for (i = 0; i < adev->num_rings; i++) {
 			struct amd_sched_rq *rq;
-			if (kernel)
-				rq = &adev->rings[i]->sched.kernel_rq;
-			else
-				rq = &adev->rings[i]->sched.sched_rq;
+			if (pri >= AMD_SCHED_MAX_PRIORITY) {
+				kfree(ctx->fences);
+				return -EINVAL;
+			}
+			rq = &adev->rings[i]->sched.sched_rq[pri];
 			r = amd_sched_entity_init(&adev->rings[i]->sched,
 						  &ctx->rings[i].entity,
 						  rq, amdgpu_sched_jobs);
@@ -57,7 +65,7 @@
 			for (j = 0; j < i; j++)
 				amd_sched_entity_fini(&adev->rings[j]->sched,
 						      &ctx->rings[j].entity);
-			kfree(ctx);
+			kfree(ctx->fences);
 			return r;
 		}
 	}
@@ -73,8 +81,9 @@
 		return;
 
 	for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
-		for (j = 0; j < AMDGPU_CTX_MAX_CS_PENDING; ++j)
+		for (j = 0; j < amdgpu_sched_jobs; ++j)
 			fence_put(ctx->rings[i].fences[j]);
+	kfree(ctx->fences);
 
 	if (amdgpu_enable_scheduler) {
 		for (i = 0; i < adev->num_rings; i++)
@@ -103,9 +112,13 @@
 		return r;
 	}
 	*id = (uint32_t)r;
-	r = amdgpu_ctx_init(adev, false, ctx);
+	r = amdgpu_ctx_init(adev, AMD_SCHED_PRIORITY_NORMAL, ctx);
+	if (r) {
+		idr_remove(&mgr->ctx_handles, *id);
+		*id = 0;
+		kfree(ctx);
+	}
 	mutex_unlock(&mgr->lock);
-
 	return r;
 }
 
@@ -239,7 +252,7 @@
 	unsigned idx = 0;
 	struct fence *other = NULL;
 
-	idx = seq % AMDGPU_CTX_MAX_CS_PENDING;
+	idx = seq & (amdgpu_sched_jobs - 1);
 	other = cring->fences[idx];
 	if (other) {
 		signed long r;
@@ -274,12 +287,12 @@
 	}
 
 
-	if (seq + AMDGPU_CTX_MAX_CS_PENDING < cring->sequence) {
+	if (seq + amdgpu_sched_jobs < cring->sequence) {
 		spin_unlock(&ctx->ring_lock);
 		return NULL;
 	}
 
-	fence = fence_get(cring->fences[seq % AMDGPU_CTX_MAX_CS_PENDING]);
+	fence = fence_get(cring->fences[seq & (amdgpu_sched_jobs - 1)]);
 	spin_unlock(&ctx->ring_lock);
 
 	return fence;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index d5b4213..6553146 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -38,6 +38,7 @@
 #include "amdgpu_i2c.h"
 #include "atom.h"
 #include "amdgpu_atombios.h"
+#include "amd_pcie.h"
 #ifdef CONFIG_DRM_AMDGPU_CIK
 #include "cik.h"
 #endif
@@ -949,6 +950,15 @@
  */
 static void amdgpu_check_arguments(struct amdgpu_device *adev)
 {
+	if (amdgpu_sched_jobs < 4) {
+		dev_warn(adev->dev, "sched jobs (%d) must be at least 4\n",
+			 amdgpu_sched_jobs);
+		amdgpu_sched_jobs = 4;
+	} else if (!amdgpu_check_pot_argument(amdgpu_sched_jobs)){
+		dev_warn(adev->dev, "sched jobs (%d) must be a power of 2\n",
+			 amdgpu_sched_jobs);
+		amdgpu_sched_jobs = roundup_pow_of_two(amdgpu_sched_jobs);
+	}
 	/* vramlimit must be a power of two */
 	if (!amdgpu_check_pot_argument(amdgpu_vram_limit)) {
 		dev_warn(adev->dev, "vram limit (%d) must be a power of 2\n",
@@ -1214,12 +1224,14 @@
 		} else {
 			if (adev->ip_blocks[i].funcs->early_init) {
 				r = adev->ip_blocks[i].funcs->early_init((void *)adev);
-				if (r == -ENOENT)
+				if (r == -ENOENT) {
 					adev->ip_block_status[i].valid = false;
-				else if (r)
+				} else if (r) {
+					DRM_ERROR("early_init %d failed %d\n", i, r);
 					return r;
-				else
+				} else {
 					adev->ip_block_status[i].valid = true;
+				}
 			} else {
 				adev->ip_block_status[i].valid = true;
 			}
@@ -1237,20 +1249,28 @@
 		if (!adev->ip_block_status[i].valid)
 			continue;
 		r = adev->ip_blocks[i].funcs->sw_init((void *)adev);
-		if (r)
+		if (r) {
+			DRM_ERROR("sw_init %d failed %d\n", i, r);
 			return r;
+		}
 		adev->ip_block_status[i].sw = true;
 		/* need to do gmc hw init early so we can allocate gpu mem */
 		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
 			r = amdgpu_vram_scratch_init(adev);
-			if (r)
+			if (r) {
+				DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r);
 				return r;
+			}
 			r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
-			if (r)
+			if (r) {
+				DRM_ERROR("hw_init %d failed %d\n", i, r);
 				return r;
+			}
 			r = amdgpu_wb_init(adev);
-			if (r)
+			if (r) {
+				DRM_ERROR("amdgpu_wb_init failed %d\n", r);
 				return r;
+			}
 			adev->ip_block_status[i].hw = true;
 		}
 	}
@@ -1262,8 +1282,10 @@
 		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC)
 			continue;
 		r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
-		if (r)
+		if (r) {
+			DRM_ERROR("hw_init %d failed %d\n", i, r);
 			return r;
+		}
 		adev->ip_block_status[i].hw = true;
 	}
 
@@ -1280,12 +1302,16 @@
 		/* enable clockgating to save power */
 		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
 								    AMD_CG_STATE_GATE);
-		if (r)
+		if (r) {
+			DRM_ERROR("set_clockgating_state(gate) %d failed %d\n", i, r);
 			return r;
+		}
 		if (adev->ip_blocks[i].funcs->late_init) {
 			r = adev->ip_blocks[i].funcs->late_init((void *)adev);
-			if (r)
+			if (r) {
+				DRM_ERROR("late_init %d failed %d\n", i, r);
 				return r;
+			}
 		}
 	}
 
@@ -1306,10 +1332,15 @@
 		/* ungate blocks before hw fini so that we can shutdown the blocks safely */
 		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
 								    AMD_CG_STATE_UNGATE);
-		if (r)
+		if (r) {
+			DRM_ERROR("set_clockgating_state(ungate) %d failed %d\n", i, r);
 			return r;
+		}
 		r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
 		/* XXX handle errors */
+		if (r) {
+			DRM_DEBUG("hw_fini %d failed %d\n", i, r);
+		}
 		adev->ip_block_status[i].hw = false;
 	}
 
@@ -1318,6 +1349,9 @@
 			continue;
 		r = adev->ip_blocks[i].funcs->sw_fini((void *)adev);
 		/* XXX handle errors */
+		if (r) {
+			DRM_DEBUG("sw_fini %d failed %d\n", i, r);
+		}
 		adev->ip_block_status[i].sw = false;
 		adev->ip_block_status[i].valid = false;
 	}
@@ -1335,9 +1369,15 @@
 		/* ungate blocks so that suspend can properly shut them down */
 		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
 								    AMD_CG_STATE_UNGATE);
+		if (r) {
+			DRM_ERROR("set_clockgating_state(ungate) %d failed %d\n", i, r);
+		}
 		/* XXX handle errors */
 		r = adev->ip_blocks[i].funcs->suspend(adev);
 		/* XXX handle errors */
+		if (r) {
+			DRM_ERROR("suspend %d failed %d\n", i, r);
+		}
 	}
 
 	return 0;
@@ -1351,8 +1391,10 @@
 		if (!adev->ip_block_status[i].valid)
 			continue;
 		r = adev->ip_blocks[i].funcs->resume(adev);
-		if (r)
+		if (r) {
+			DRM_ERROR("resume %d failed %d\n", i, r);
 			return r;
+		}
 	}
 
 	return 0;
@@ -1484,8 +1526,10 @@
 		return -EINVAL;
 	}
 	r = amdgpu_atombios_init(adev);
-	if (r)
+	if (r) {
+		dev_err(adev->dev, "amdgpu_atombios_init failed\n");
 		return r;
+	}
 
 	/* Post card if necessary */
 	if (!amdgpu_card_posted(adev)) {
@@ -1499,21 +1543,26 @@
 
 	/* Initialize clocks */
 	r = amdgpu_atombios_get_clock_info(adev);
-	if (r)
+	if (r) {
+		dev_err(adev->dev, "amdgpu_atombios_get_clock_info failed\n");
 		return r;
+	}
 	/* init i2c buses */
 	amdgpu_atombios_i2c_init(adev);
 
 	/* Fence driver */
 	r = amdgpu_fence_driver_init(adev);
-	if (r)
+	if (r) {
+		dev_err(adev->dev, "amdgpu_fence_driver_init failed\n");
 		return r;
+	}
 
 	/* init the mode config */
 	drm_mode_config_init(adev->ddev);
 
 	r = amdgpu_init(adev);
 	if (r) {
+		dev_err(adev->dev, "amdgpu_init failed\n");
 		amdgpu_fini(adev);
 		return r;
 	}
@@ -1528,7 +1577,7 @@
 		return r;
 	}
 
-	r = amdgpu_ctx_init(adev, true, &adev->kernel_ctx);
+	r = amdgpu_ctx_init(adev, AMD_SCHED_PRIORITY_KERNEL, &adev->kernel_ctx);
 	if (r) {
 		dev_err(adev->dev, "failed to create kernel context (%d).\n", r);
 		return r;
@@ -1570,8 +1619,10 @@
 	 * explicit gating rather than handling it automatically.
 	 */
 	r = amdgpu_late_init(adev);
-	if (r)
+	if (r) {
+		dev_err(adev->dev, "amdgpu_late_init failed\n");
 		return r;
+	}
 
 	return 0;
 }
@@ -1788,6 +1839,7 @@
 	}
 
 	drm_kms_helper_poll_enable(dev);
+	drm_helper_hpd_irq_event(dev);
 
 	if (fbcon) {
 		amdgpu_fbdev_set_suspend(adev, 0);
@@ -1881,6 +1933,83 @@
 	return r;
 }
 
+void amdgpu_get_pcie_info(struct amdgpu_device *adev)
+{
+	u32 mask;
+	int ret;
+
+	if (pci_is_root_bus(adev->pdev->bus))
+		return;
+
+	if (amdgpu_pcie_gen2 == 0)
+		return;
+
+	if (adev->flags & AMD_IS_APU)
+		return;
+
+	ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask);
+	if (!ret) {
+		adev->pm.pcie_gen_mask = (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
+					  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
+					  CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3);
+
+		if (mask & DRM_PCIE_SPEED_25)
+			adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1;
+		if (mask & DRM_PCIE_SPEED_50)
+			adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2;
+		if (mask & DRM_PCIE_SPEED_80)
+			adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3;
+	}
+	ret = drm_pcie_get_max_link_width(adev->ddev, &mask);
+	if (!ret) {
+		switch (mask) {
+		case 32:
+			adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+			break;
+		case 16:
+			adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+			break;
+		case 12:
+			adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+			break;
+		case 8:
+			adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+			break;
+		case 4:
+			adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+			break;
+		case 2:
+			adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+						  CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+			break;
+		case 1:
+			adev->pm.pcie_mlw_mask = CAIL_PCIE_LINK_WIDTH_SUPPORT_X1;
+			break;
+		default:
+			break;
+		}
+	}
+}
 
 /*
  * Debugfs
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 0508c5c..b5dbbb5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -79,9 +79,10 @@
 int amdgpu_vm_debug = 0;
 int amdgpu_exp_hw_support = 0;
 int amdgpu_enable_scheduler = 1;
-int amdgpu_sched_jobs = 16;
+int amdgpu_sched_jobs = 32;
 int amdgpu_sched_hw_submission = 2;
 int amdgpu_enable_semaphores = 0;
+int amdgpu_powerplay = -1;
 
 MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");
 module_param_named(vramlimit, amdgpu_vram_limit, int, 0600);
@@ -155,7 +156,7 @@
 MODULE_PARM_DESC(enable_scheduler, "enable SW GPU scheduler (1 = enable (default), 0 = disable)");
 module_param_named(enable_scheduler, amdgpu_enable_scheduler, int, 0444);
 
-MODULE_PARM_DESC(sched_jobs, "the max number of jobs supported in the sw queue (default 16)");
+MODULE_PARM_DESC(sched_jobs, "the max number of jobs supported in the sw queue (default 32)");
 module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444);
 
 MODULE_PARM_DESC(sched_hw_submission, "the max number of HW submissions (default 2)");
@@ -164,6 +165,11 @@
 MODULE_PARM_DESC(enable_semaphores, "Enable semaphores (1 = enable, 0 = disable (default))");
 module_param_named(enable_semaphores, amdgpu_enable_semaphores, int, 0644);
 
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 = auto (default))");
+module_param_named(powerplay, amdgpu_powerplay, int, 0444);
+#endif
+
 static struct pci_device_id pciidlist[] = {
 #ifdef CONFIG_DRM_AMDGPU_CIK
 	/* Kaveri */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 6fcbbcc..cfb6caa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -263,7 +263,7 @@
 
 	}
 	if (fb && ret) {
-		drm_gem_object_unreference(gobj);
+		drm_gem_object_unreference_unlocked(gobj);
 		drm_framebuffer_unregister_private(fb);
 		drm_framebuffer_cleanup(fb);
 		kfree(fb);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index f6ea4b4..7380f78 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -448,7 +448,7 @@
 				    struct amdgpu_bo_va *bo_va, uint32_t operation)
 {
 	struct ttm_validate_buffer tv, *entry;
-	struct amdgpu_bo_list_entry *vm_bos;
+	struct amdgpu_bo_list_entry vm_pd;
 	struct ww_acquire_ctx ticket;
 	struct list_head list, duplicates;
 	unsigned domain;
@@ -461,15 +461,14 @@
 	tv.shared = true;
 	list_add(&tv.head, &list);
 
-	vm_bos = amdgpu_vm_get_bos(adev, bo_va->vm, &list);
-	if (!vm_bos)
-		return;
+	amdgpu_vm_get_pd_bo(bo_va->vm, &list, &vm_pd);
 
 	/* Provide duplicates to avoid -EALREADY */
 	r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
 	if (r)
-		goto error_free;
+		goto error_print;
 
+	amdgpu_vm_get_pt_bos(bo_va->vm, &duplicates);
 	list_for_each_entry(entry, &list, head) {
 		domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
 		/* if anything is swapped out don't swap it in here,
@@ -477,6 +476,14 @@
 		if (domain == AMDGPU_GEM_DOMAIN_CPU)
 			goto error_unreserve;
 	}
+	list_for_each_entry(entry, &duplicates, head) {
+		domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
+		/* if anything is swapped out don't swap it in here,
+		   just abort and wait for the next CS */
+		if (domain == AMDGPU_GEM_DOMAIN_CPU)
+			goto error_unreserve;
+	}
+
 	r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
 	if (r)
 		goto error_unreserve;
@@ -491,9 +498,7 @@
 error_unreserve:
 	ttm_eu_backoff_reservation(&ticket, &list);
 
-error_free:
-	drm_free_large(vm_bos);
-
+error_print:
 	if (r && r != -ERESTARTSYS)
 		DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index 7c42ff6..f594cfa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -25,6 +25,7 @@
  *          Alex Deucher
  *          Jerome Glisse
  */
+#include <linux/irq.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/amdgpu_drm.h>
@@ -312,6 +313,7 @@
 	}
 
 	adev->irq.sources[src_id] = source;
+
 	return 0;
 }
 
@@ -335,15 +337,19 @@
 		return;
 	}
 
-	src = adev->irq.sources[src_id];
-	if (!src) {
-		DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id);
-		return;
-	}
+	if (adev->irq.virq[src_id]) {
+		generic_handle_irq(irq_find_mapping(adev->irq.domain, src_id));
+	} else {
+		src = adev->irq.sources[src_id];
+		if (!src) {
+			DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id);
+			return;
+		}
 
-	r = src->funcs->process(adev, src, entry);
-	if (r)
-		DRM_ERROR("error processing interrupt (%d)\n", r);
+		r = src->funcs->process(adev, src, entry);
+		if (r)
+			DRM_ERROR("error processing interrupt (%d)\n", r);
+	}
 }
 
 /**
@@ -461,3 +467,90 @@
 
 	return !!atomic_read(&src->enabled_types[type]);
 }
+
+/* gen irq */
+static void amdgpu_irq_mask(struct irq_data *irqd)
+{
+	/* XXX */
+}
+
+static void amdgpu_irq_unmask(struct irq_data *irqd)
+{
+	/* XXX */
+}
+
+static struct irq_chip amdgpu_irq_chip = {
+	.name = "amdgpu-ih",
+	.irq_mask = amdgpu_irq_mask,
+	.irq_unmask = amdgpu_irq_unmask,
+};
+
+static int amdgpu_irqdomain_map(struct irq_domain *d,
+				unsigned int irq, irq_hw_number_t hwirq)
+{
+	if (hwirq >= AMDGPU_MAX_IRQ_SRC_ID)
+		return -EPERM;
+
+	irq_set_chip_and_handler(irq,
+				 &amdgpu_irq_chip, handle_simple_irq);
+	return 0;
+}
+
+static struct irq_domain_ops amdgpu_hw_irqdomain_ops = {
+	.map = amdgpu_irqdomain_map,
+};
+
+/**
+ * amdgpu_irq_add_domain - create a linear irq domain
+ *
+ * @adev: amdgpu device pointer
+ *
+ * Create an irq domain for GPU interrupt sources
+ * that may be driven by another driver (e.g., ACP).
+ */
+int amdgpu_irq_add_domain(struct amdgpu_device *adev)
+{
+	adev->irq.domain = irq_domain_add_linear(NULL, AMDGPU_MAX_IRQ_SRC_ID,
+						 &amdgpu_hw_irqdomain_ops, adev);
+	if (!adev->irq.domain) {
+		DRM_ERROR("GPU irq add domain failed\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/**
+ * amdgpu_irq_remove_domain - remove the irq domain
+ *
+ * @adev: amdgpu device pointer
+ *
+ * Remove the irq domain for GPU interrupt sources
+ * that may be driven by another driver (e.g., ACP).
+ */
+void amdgpu_irq_remove_domain(struct amdgpu_device *adev)
+{
+	if (adev->irq.domain) {
+		irq_domain_remove(adev->irq.domain);
+		adev->irq.domain = NULL;
+	}
+}
+
+/**
+ * amdgpu_irq_create_mapping - create a mapping between a domain irq and a
+ *                             Linux irq
+ *
+ * @adev: amdgpu device pointer
+ * @src_id: IH source id
+ *
+ * Create a mapping between a domain irq (GPU IH src id) and a Linux irq
+ * Use this for components that generate a GPU interrupt, but are driven
+ * by a different driver (e.g., ACP).
+ * Returns the Linux irq.
+ */
+unsigned amdgpu_irq_create_mapping(struct amdgpu_device *adev, unsigned src_id)
+{
+	adev->irq.virq[src_id] = irq_create_mapping(adev->irq.domain, src_id);
+
+	return adev->irq.virq[src_id];
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
index 17b01aef..e124b59 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
@@ -24,6 +24,7 @@
 #ifndef __AMDGPU_IRQ_H__
 #define __AMDGPU_IRQ_H__
 
+#include <linux/irqdomain.h>
 #include "amdgpu_ih.h"
 
 #define AMDGPU_MAX_IRQ_SRC_ID	0x100
@@ -65,6 +66,10 @@
 	/* interrupt ring */
 	struct amdgpu_ih_ring		ih;
 	const struct amdgpu_ih_funcs	*ih_funcs;
+
+	/* gen irq stuff */
+	struct irq_domain		*domain; /* GPU irq controller domain */
+	unsigned			virq[AMDGPU_MAX_IRQ_SRC_ID];
 };
 
 void amdgpu_irq_preinstall(struct drm_device *dev);
@@ -90,4 +95,8 @@
 bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
 			unsigned type);
 
+int amdgpu_irq_add_domain(struct amdgpu_device *adev);
+void amdgpu_irq_remove_domain(struct amdgpu_device *adev);
+unsigned amdgpu_irq_create_mapping(struct amdgpu_device *adev, unsigned src_id);
+
 #endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index ea756e7..5107fb2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -96,6 +96,7 @@
  */
 static inline u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
 {
+	WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
 	return bo->tbo.offset;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 22a8c7d..7d8d84e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -30,10 +30,16 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 
+#include "amd_powerplay.h"
+
 static int amdgpu_debugfs_pm_init(struct amdgpu_device *adev);
 
 void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev)
 {
+	if (adev->pp_enabled)
+		/* TODO */
+		return;
+
 	if (adev->pm.dpm_enabled) {
 		mutex_lock(&adev->pm.mutex);
 		if (power_supply_is_system_supplied() > 0)
@@ -52,7 +58,12 @@
 {
 	struct drm_device *ddev = dev_get_drvdata(dev);
 	struct amdgpu_device *adev = ddev->dev_private;
-	enum amdgpu_pm_state_type pm = adev->pm.dpm.user_state;
+	enum amd_pm_state_type pm;
+
+	if (adev->pp_enabled) {
+		pm = amdgpu_dpm_get_current_power_state(adev);
+	} else
+		pm = adev->pm.dpm.user_state;
 
 	return snprintf(buf, PAGE_SIZE, "%s\n",
 			(pm == POWER_STATE_TYPE_BATTERY) ? "battery" :
@@ -66,40 +77,57 @@
 {
 	struct drm_device *ddev = dev_get_drvdata(dev);
 	struct amdgpu_device *adev = ddev->dev_private;
+	enum amd_pm_state_type  state;
 
-	mutex_lock(&adev->pm.mutex);
 	if (strncmp("battery", buf, strlen("battery")) == 0)
-		adev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY;
+		state = POWER_STATE_TYPE_BATTERY;
 	else if (strncmp("balanced", buf, strlen("balanced")) == 0)
-		adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED;
+		state = POWER_STATE_TYPE_BALANCED;
 	else if (strncmp("performance", buf, strlen("performance")) == 0)
-		adev->pm.dpm.user_state = POWER_STATE_TYPE_PERFORMANCE;
+		state = POWER_STATE_TYPE_PERFORMANCE;
 	else {
-		mutex_unlock(&adev->pm.mutex);
 		count = -EINVAL;
 		goto fail;
 	}
-	mutex_unlock(&adev->pm.mutex);
 
-	/* Can't set dpm state when the card is off */
-	if (!(adev->flags & AMD_IS_PX) ||
-	    (ddev->switch_power_state == DRM_SWITCH_POWER_ON))
-		amdgpu_pm_compute_clocks(adev);
+	if (adev->pp_enabled) {
+		amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL);
+	} else {
+		mutex_lock(&adev->pm.mutex);
+		adev->pm.dpm.user_state = state;
+		mutex_unlock(&adev->pm.mutex);
+
+		/* Can't set dpm state when the card is off */
+		if (!(adev->flags & AMD_IS_PX) ||
+		    (ddev->switch_power_state == DRM_SWITCH_POWER_ON))
+			amdgpu_pm_compute_clocks(adev);
+	}
 fail:
 	return count;
 }
 
 static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev,
-						       struct device_attribute *attr,
-						       char *buf)
+						struct device_attribute *attr,
+								char *buf)
 {
 	struct drm_device *ddev = dev_get_drvdata(dev);
 	struct amdgpu_device *adev = ddev->dev_private;
-	enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level;
 
-	return snprintf(buf, PAGE_SIZE, "%s\n",
-			(level == AMDGPU_DPM_FORCED_LEVEL_AUTO) ? "auto" :
-			(level == AMDGPU_DPM_FORCED_LEVEL_LOW) ? "low" : "high");
+	if (adev->pp_enabled) {
+		enum amd_dpm_forced_level level;
+
+		level = amdgpu_dpm_get_performance_level(adev);
+		return snprintf(buf, PAGE_SIZE, "%s\n",
+				(level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" :
+				(level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" : "high");
+	} else {
+		enum amdgpu_dpm_forced_level level;
+
+		level = adev->pm.dpm.forced_level;
+		return snprintf(buf, PAGE_SIZE, "%s\n",
+				(level == AMDGPU_DPM_FORCED_LEVEL_AUTO) ? "auto" :
+				(level == AMDGPU_DPM_FORCED_LEVEL_LOW) ? "low" : "high");
+	}
 }
 
 static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
@@ -112,7 +140,6 @@
 	enum amdgpu_dpm_forced_level level;
 	int ret = 0;
 
-	mutex_lock(&adev->pm.mutex);
 	if (strncmp("low", buf, strlen("low")) == 0) {
 		level = AMDGPU_DPM_FORCED_LEVEL_LOW;
 	} else if (strncmp("high", buf, strlen("high")) == 0) {
@@ -123,7 +150,11 @@
 		count = -EINVAL;
 		goto fail;
 	}
-	if (adev->pm.funcs->force_performance_level) {
+
+	if (adev->pp_enabled)
+		amdgpu_dpm_force_performance_level(adev, level);
+	else {
+		mutex_lock(&adev->pm.mutex);
 		if (adev->pm.dpm.thermal_active) {
 			count = -EINVAL;
 			goto fail;
@@ -131,6 +162,9 @@
 		ret = amdgpu_dpm_force_performance_level(adev, level);
 		if (ret)
 			count = -EINVAL;
+		else
+			adev->pm.dpm.forced_level = level;
+		mutex_unlock(&adev->pm.mutex);
 	}
 fail:
 	mutex_unlock(&adev->pm.mutex);
@@ -150,10 +184,10 @@
 	struct amdgpu_device *adev = dev_get_drvdata(dev);
 	int temp;
 
-	if (adev->pm.funcs->get_temperature)
-		temp = amdgpu_dpm_get_temperature(adev);
-	else
+	if (!adev->pp_enabled && !adev->pm.funcs->get_temperature)
 		temp = 0;
+	else
+		temp = amdgpu_dpm_get_temperature(adev);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", temp);
 }
@@ -181,8 +215,10 @@
 	struct amdgpu_device *adev = dev_get_drvdata(dev);
 	u32 pwm_mode = 0;
 
-	if (adev->pm.funcs->get_fan_control_mode)
-		pwm_mode = amdgpu_dpm_get_fan_control_mode(adev);
+	if (!adev->pp_enabled && !adev->pm.funcs->get_fan_control_mode)
+		return -EINVAL;
+
+	pwm_mode = amdgpu_dpm_get_fan_control_mode(adev);
 
 	/* never 0 (full-speed), fuse or smc-controlled always */
 	return sprintf(buf, "%i\n", pwm_mode == FDO_PWM_MODE_STATIC ? 1 : 2);
@@ -197,7 +233,7 @@
 	int err;
 	int value;
 
-	if(!adev->pm.funcs->set_fan_control_mode)
+	if (!adev->pp_enabled && !adev->pm.funcs->set_fan_control_mode)
 		return -EINVAL;
 
 	err = kstrtoint(buf, 10, &value);
@@ -290,11 +326,11 @@
 static umode_t hwmon_attributes_visible(struct kobject *kobj,
 					struct attribute *attr, int index)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
+	struct device *dev = kobj_to_dev(kobj);
 	struct amdgpu_device *adev = dev_get_drvdata(dev);
 	umode_t effective_mode = attr->mode;
 
-	/* Skip attributes if DPM is not enabled */
+	/* Skip limit attributes if DPM is not enabled */
 	if (!adev->pm.dpm_enabled &&
 	    (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
 	     attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr ||
@@ -304,6 +340,9 @@
 	     attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
 		return 0;
 
+	if (adev->pp_enabled)
+		return effective_mode;
+
 	/* Skip fan attributes if fan is not present */
 	if (adev->pm.no_fan &&
 	    (attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
@@ -351,7 +390,7 @@
 		container_of(work, struct amdgpu_device,
 			     pm.dpm.thermal.work);
 	/* switch to the thermal state */
-	enum amdgpu_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
+	enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
 
 	if (!adev->pm.dpm_enabled)
 		return;
@@ -379,7 +418,7 @@
 }
 
 static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev,
-						     enum amdgpu_pm_state_type dpm_state)
+						     enum amd_pm_state_type dpm_state)
 {
 	int i;
 	struct amdgpu_ps *ps;
@@ -516,7 +555,7 @@
 {
 	int i;
 	struct amdgpu_ps *ps;
-	enum amdgpu_pm_state_type dpm_state;
+	enum amd_pm_state_type dpm_state;
 	int ret;
 
 	/* if dpm init failed */
@@ -635,49 +674,54 @@
 
 void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable)
 {
-	if (adev->pm.funcs->powergate_uvd) {
-		mutex_lock(&adev->pm.mutex);
-		/* enable/disable UVD */
+	if (adev->pp_enabled)
 		amdgpu_dpm_powergate_uvd(adev, !enable);
-		mutex_unlock(&adev->pm.mutex);
-	} else {
-		if (enable) {
+	else {
+		if (adev->pm.funcs->powergate_uvd) {
 			mutex_lock(&adev->pm.mutex);
-			adev->pm.dpm.uvd_active = true;
-			adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD;
+			/* enable/disable UVD */
+			amdgpu_dpm_powergate_uvd(adev, !enable);
 			mutex_unlock(&adev->pm.mutex);
 		} else {
-			mutex_lock(&adev->pm.mutex);
-			adev->pm.dpm.uvd_active = false;
-			mutex_unlock(&adev->pm.mutex);
+			if (enable) {
+				mutex_lock(&adev->pm.mutex);
+				adev->pm.dpm.uvd_active = true;
+				adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD;
+				mutex_unlock(&adev->pm.mutex);
+			} else {
+				mutex_lock(&adev->pm.mutex);
+				adev->pm.dpm.uvd_active = false;
+				mutex_unlock(&adev->pm.mutex);
+			}
+			amdgpu_pm_compute_clocks(adev);
 		}
 
-		amdgpu_pm_compute_clocks(adev);
 	}
 }
 
 void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
 {
-	if (adev->pm.funcs->powergate_vce) {
-		mutex_lock(&adev->pm.mutex);
-		/* enable/disable VCE */
+	if (adev->pp_enabled)
 		amdgpu_dpm_powergate_vce(adev, !enable);
-
-		mutex_unlock(&adev->pm.mutex);
-	} else {
-		if (enable) {
+	else {
+		if (adev->pm.funcs->powergate_vce) {
 			mutex_lock(&adev->pm.mutex);
-			adev->pm.dpm.vce_active = true;
-			/* XXX select vce level based on ring/task */
-			adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL;
+			amdgpu_dpm_powergate_vce(adev, !enable);
 			mutex_unlock(&adev->pm.mutex);
 		} else {
-			mutex_lock(&adev->pm.mutex);
-			adev->pm.dpm.vce_active = false;
-			mutex_unlock(&adev->pm.mutex);
+			if (enable) {
+				mutex_lock(&adev->pm.mutex);
+				adev->pm.dpm.vce_active = true;
+				/* XXX select vce level based on ring/task */
+				adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL;
+				mutex_unlock(&adev->pm.mutex);
+			} else {
+				mutex_lock(&adev->pm.mutex);
+				adev->pm.dpm.vce_active = false;
+				mutex_unlock(&adev->pm.mutex);
+			}
+			amdgpu_pm_compute_clocks(adev);
 		}
-
-		amdgpu_pm_compute_clocks(adev);
 	}
 }
 
@@ -685,10 +729,13 @@
 {
 	int i;
 
-	for (i = 0; i < adev->pm.dpm.num_ps; i++) {
-		printk("== power state %d ==\n", i);
+	if (adev->pp_enabled)
+		/* TO DO */
+		return;
+
+	for (i = 0; i < adev->pm.dpm.num_ps; i++)
 		amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]);
-	}
+
 }
 
 int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
@@ -698,8 +745,11 @@
 	if (adev->pm.sysfs_initialized)
 		return 0;
 
-	if (adev->pm.funcs->get_temperature == NULL)
-		return 0;
+	if (!adev->pp_enabled) {
+		if (adev->pm.funcs->get_temperature == NULL)
+			return 0;
+	}
+
 	adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev,
 								   DRIVER_NAME, adev,
 								   hwmon_groups);
@@ -748,32 +798,43 @@
 	if (!adev->pm.dpm_enabled)
 		return;
 
-	mutex_lock(&adev->pm.mutex);
+	if (adev->pp_enabled) {
+		int i = 0;
 
-	/* update active crtc counts */
-	adev->pm.dpm.new_active_crtcs = 0;
-	adev->pm.dpm.new_active_crtc_count = 0;
-	if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
-		list_for_each_entry(crtc,
-				    &ddev->mode_config.crtc_list, head) {
-			amdgpu_crtc = to_amdgpu_crtc(crtc);
-			if (crtc->enabled) {
-				adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id);
-				adev->pm.dpm.new_active_crtc_count++;
+		amdgpu_display_bandwidth_update(adev);
+		mutex_lock(&adev->ring_lock);
+			for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
+				struct amdgpu_ring *ring = adev->rings[i];
+				if (ring && ring->ready)
+					amdgpu_fence_wait_empty(ring);
+			}
+		mutex_unlock(&adev->ring_lock);
+
+		amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, NULL, NULL);
+	} else {
+		mutex_lock(&adev->pm.mutex);
+		adev->pm.dpm.new_active_crtcs = 0;
+		adev->pm.dpm.new_active_crtc_count = 0;
+		if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
+			list_for_each_entry(crtc,
+					    &ddev->mode_config.crtc_list, head) {
+				amdgpu_crtc = to_amdgpu_crtc(crtc);
+				if (crtc->enabled) {
+					adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id);
+					adev->pm.dpm.new_active_crtc_count++;
+				}
 			}
 		}
+		/* update battery/ac status */
+		if (power_supply_is_system_supplied() > 0)
+			adev->pm.dpm.ac_power = true;
+		else
+			adev->pm.dpm.ac_power = false;
+
+		amdgpu_dpm_change_power_state_locked(adev);
+
+		mutex_unlock(&adev->pm.mutex);
 	}
-
-	/* update battery/ac status */
-	if (power_supply_is_system_supplied() > 0)
-		adev->pm.dpm.ac_power = true;
-	else
-		adev->pm.dpm.ac_power = false;
-
-	amdgpu_dpm_change_power_state_locked(adev);
-
-	mutex_unlock(&adev->pm.mutex);
-
 }
 
 /*
@@ -787,7 +848,13 @@
 	struct drm_device *dev = node->minor->dev;
 	struct amdgpu_device *adev = dev->dev_private;
 
-	if (adev->pm.dpm_enabled) {
+	if (!adev->pm.dpm_enabled) {
+		seq_printf(m, "dpm not enabled\n");
+		return 0;
+	}
+	if (adev->pp_enabled) {
+		amdgpu_dpm_debugfs_print_current_performance_level(adev, m);
+	} else {
 		mutex_lock(&adev->pm.mutex);
 		if (adev->pm.funcs->debugfs_print_current_performance_level)
 			amdgpu_dpm_debugfs_print_current_performance_level(adev, m);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
new file mode 100644
index 0000000..5ee9a06
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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: AMD
+ *
+ */
+#include "atom.h"
+#include "amdgpu.h"
+#include "amd_shared.h"
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include "amdgpu_pm.h"
+#include <drm/amdgpu_drm.h>
+#include "amdgpu_powerplay.h"
+#include "cik_dpm.h"
+#include "vi_dpm.h"
+
+static int amdgpu_powerplay_init(struct amdgpu_device *adev)
+{
+	int ret = 0;
+	struct amd_powerplay *amd_pp;
+
+	amd_pp = &(adev->powerplay);
+
+	if (adev->pp_enabled) {
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+		struct amd_pp_init *pp_init;
+
+		pp_init = kzalloc(sizeof(struct amd_pp_init), GFP_KERNEL);
+
+		if (pp_init == NULL)
+			return -ENOMEM;
+
+		pp_init->chip_family = adev->family;
+		pp_init->chip_id = adev->asic_type;
+		pp_init->device = amdgpu_cgs_create_device(adev);
+
+		ret = amd_powerplay_init(pp_init, amd_pp);
+		kfree(pp_init);
+#endif
+	} else {
+		amd_pp->pp_handle = (void *)adev;
+
+		switch (adev->asic_type) {
+#ifdef CONFIG_DRM_AMDGPU_CIK
+		case CHIP_BONAIRE:
+		case CHIP_HAWAII:
+			amd_pp->ip_funcs = &ci_dpm_ip_funcs;
+			break;
+		case CHIP_KABINI:
+		case CHIP_MULLINS:
+		case CHIP_KAVERI:
+			amd_pp->ip_funcs = &kv_dpm_ip_funcs;
+			break;
+#endif
+		case CHIP_TOPAZ:
+			amd_pp->ip_funcs = &iceland_dpm_ip_funcs;
+			break;
+		case CHIP_TONGA:
+			amd_pp->ip_funcs = &tonga_dpm_ip_funcs;
+			break;
+		case CHIP_FIJI:
+			amd_pp->ip_funcs = &fiji_dpm_ip_funcs;
+			break;
+		case CHIP_CARRIZO:
+		case CHIP_STONEY:
+			amd_pp->ip_funcs = &cz_dpm_ip_funcs;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int amdgpu_pp_early_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int ret = 0;
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	switch (adev->asic_type) {
+		case CHIP_TONGA:
+		case CHIP_FIJI:
+			adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false;
+			break;
+		default:
+			adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false;
+			break;
+	}
+#else
+	adev->pp_enabled = false;
+#endif
+
+	ret = amdgpu_powerplay_init(adev);
+	if (ret)
+		return ret;
+
+	if (adev->powerplay.ip_funcs->early_init)
+		ret = adev->powerplay.ip_funcs->early_init(
+					adev->powerplay.pp_handle);
+	return ret;
+}
+
+
+static int amdgpu_pp_late_init(void *handle)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->late_init)
+		ret = adev->powerplay.ip_funcs->late_init(
+					adev->powerplay.pp_handle);
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	if (adev->pp_enabled)
+		amdgpu_pm_sysfs_init(adev);
+#endif
+	return ret;
+}
+
+static int amdgpu_pp_sw_init(void *handle)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->sw_init)
+		ret = adev->powerplay.ip_funcs->sw_init(
+					adev->powerplay.pp_handle);
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	if (adev->pp_enabled) {
+		if (amdgpu_dpm == 0)
+			adev->pm.dpm_enabled = false;
+		else
+			adev->pm.dpm_enabled = true;
+	}
+#endif
+
+	return ret;
+}
+
+static int amdgpu_pp_sw_fini(void *handle)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->sw_fini)
+		ret = adev->powerplay.ip_funcs->sw_fini(
+					adev->powerplay.pp_handle);
+	if (ret)
+		return ret;
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	if (adev->pp_enabled) {
+		amdgpu_pm_sysfs_fini(adev);
+		amd_powerplay_fini(adev->powerplay.pp_handle);
+	}
+#endif
+
+	return ret;
+}
+
+static int amdgpu_pp_hw_init(void *handle)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->pp_enabled && adev->firmware.smu_load)
+		amdgpu_ucode_init_bo(adev);
+
+	if (adev->powerplay.ip_funcs->hw_init)
+		ret = adev->powerplay.ip_funcs->hw_init(
+					adev->powerplay.pp_handle);
+
+	return ret;
+}
+
+static int amdgpu_pp_hw_fini(void *handle)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->hw_fini)
+		ret = adev->powerplay.ip_funcs->hw_fini(
+					adev->powerplay.pp_handle);
+
+	if (adev->pp_enabled && adev->firmware.smu_load)
+		amdgpu_ucode_fini_bo(adev);
+
+	return ret;
+}
+
+static int amdgpu_pp_suspend(void *handle)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->suspend)
+		ret = adev->powerplay.ip_funcs->suspend(
+					 adev->powerplay.pp_handle);
+	return ret;
+}
+
+static int amdgpu_pp_resume(void *handle)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->resume)
+		ret = adev->powerplay.ip_funcs->resume(
+					adev->powerplay.pp_handle);
+	return ret;
+}
+
+static int amdgpu_pp_set_clockgating_state(void *handle,
+					enum amd_clockgating_state state)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->set_clockgating_state)
+		ret = adev->powerplay.ip_funcs->set_clockgating_state(
+				adev->powerplay.pp_handle, state);
+	return ret;
+}
+
+static int amdgpu_pp_set_powergating_state(void *handle,
+					enum amd_powergating_state state)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->set_powergating_state)
+		ret = adev->powerplay.ip_funcs->set_powergating_state(
+				 adev->powerplay.pp_handle, state);
+	return ret;
+}
+
+
+static bool amdgpu_pp_is_idle(void *handle)
+{
+	bool ret = true;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->is_idle)
+		ret = adev->powerplay.ip_funcs->is_idle(
+					adev->powerplay.pp_handle);
+	return ret;
+}
+
+static int amdgpu_pp_wait_for_idle(void *handle)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->wait_for_idle)
+		ret = adev->powerplay.ip_funcs->wait_for_idle(
+					adev->powerplay.pp_handle);
+	return ret;
+}
+
+static int amdgpu_pp_soft_reset(void *handle)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->soft_reset)
+		ret = adev->powerplay.ip_funcs->soft_reset(
+					adev->powerplay.pp_handle);
+	return ret;
+}
+
+static void amdgpu_pp_print_status(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->powerplay.ip_funcs->print_status)
+		adev->powerplay.ip_funcs->print_status(
+					adev->powerplay.pp_handle);
+}
+
+const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
+	.early_init = amdgpu_pp_early_init,
+	.late_init = amdgpu_pp_late_init,
+	.sw_init = amdgpu_pp_sw_init,
+	.sw_fini = amdgpu_pp_sw_fini,
+	.hw_init = amdgpu_pp_hw_init,
+	.hw_fini = amdgpu_pp_hw_fini,
+	.suspend = amdgpu_pp_suspend,
+	.resume = amdgpu_pp_resume,
+	.is_idle = amdgpu_pp_is_idle,
+	.wait_for_idle = amdgpu_pp_wait_for_idle,
+	.soft_reset = amdgpu_pp_soft_reset,
+	.print_status = amdgpu_pp_print_status,
+	.set_clockgating_state = amdgpu_pp_set_clockgating_state,
+	.set_powergating_state = amdgpu_pp_set_powergating_state,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h
new file mode 100644
index 0000000..da5cf47
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h
@@ -0,0 +1,33 @@
+/*
+ *  Copyright 2015 Advanced Micro Devices, 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: AMD
+ *
+ */
+
+#ifndef __AMDGPU_POPWERPLAY_H__
+#define __AMDGPU_POPWERPLAY_H__
+
+#include "amd_shared.h"
+
+extern const struct amd_ip_funcs amdgpu_pp_ip_funcs;
+
+#endif /* __AMDSOC_DM_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index dd005c3..181ce39 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -293,7 +293,8 @@
 		fence = to_amdgpu_fence(sync->sync_to[i]);
 
 		/* check if we really need to sync */
-		if (!amdgpu_fence_need_sync(fence, ring))
+		if (!amdgpu_enable_scheduler &&
+		    !amdgpu_fence_need_sync(fence, ring))
 			continue;
 
 		/* prevent GPU deadlocks */
@@ -303,7 +304,7 @@
 		}
 
 		if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores) {
-			r = fence_wait(&fence->base, true);
+			r = fence_wait(sync->sync_to[i], true);
 			if (r)
 				return r;
 			continue;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index b53d273..aefc668 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -75,50 +75,77 @@
 }
 
 /**
- * amdgpu_vm_get_bos - add the vm BOs to a validation list
+ * amdgpu_vm_get_pd_bo - add the VM PD to a validation list
  *
  * @vm: vm providing the BOs
- * @head: head of validation list
+ * @validated: head of validation list
+ * @entry: entry to add
  *
  * Add the page directory to the list of BOs to
- * validate for command submission (cayman+).
+ * validate for command submission.
  */
-struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
-					  struct amdgpu_vm *vm,
-					  struct list_head *head)
+void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
+			 struct list_head *validated,
+			 struct amdgpu_bo_list_entry *entry)
 {
-	struct amdgpu_bo_list_entry *list;
-	unsigned i, idx;
+	entry->robj = vm->page_directory;
+	entry->prefered_domains = AMDGPU_GEM_DOMAIN_VRAM;
+	entry->allowed_domains = AMDGPU_GEM_DOMAIN_VRAM;
+	entry->priority = 0;
+	entry->tv.bo = &vm->page_directory->tbo;
+	entry->tv.shared = true;
+	list_add(&entry->tv.head, validated);
+}
 
-	list = drm_malloc_ab(vm->max_pde_used + 2,
-			     sizeof(struct amdgpu_bo_list_entry));
-	if (!list) {
-		return NULL;
-	}
+/**
+ * amdgpu_vm_get_bos - add the vm BOs to a duplicates list
+ *
+ * @vm: vm providing the BOs
+ * @duplicates: head of duplicates list
+ *
+ * Add the page directory to the BO duplicates list
+ * for command submission.
+ */
+void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates)
+{
+	unsigned i;
 
 	/* add the vm page table to the list */
-	list[0].robj = vm->page_directory;
-	list[0].prefered_domains = AMDGPU_GEM_DOMAIN_VRAM;
-	list[0].allowed_domains = AMDGPU_GEM_DOMAIN_VRAM;
-	list[0].priority = 0;
-	list[0].tv.bo = &vm->page_directory->tbo;
-	list[0].tv.shared = true;
-	list_add(&list[0].tv.head, head);
+	for (i = 0; i <= vm->max_pde_used; ++i) {
+		struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry;
 
-	for (i = 0, idx = 1; i <= vm->max_pde_used; i++) {
-		if (!vm->page_tables[i].bo)
+		if (!entry->robj)
 			continue;
 
-		list[idx].robj = vm->page_tables[i].bo;
-		list[idx].prefered_domains = AMDGPU_GEM_DOMAIN_VRAM;
-		list[idx].allowed_domains = AMDGPU_GEM_DOMAIN_VRAM;
-		list[idx].priority = 0;
-		list[idx].tv.bo = &list[idx].robj->tbo;
-		list[idx].tv.shared = true;
-		list_add(&list[idx++].tv.head, head);
+		list_add(&entry->tv.head, duplicates);
 	}
 
-	return list;
+}
+
+/**
+ * amdgpu_vm_move_pt_bos_in_lru - move the PT BOs to the LRU tail
+ *
+ * @adev: amdgpu device instance
+ * @vm: vm providing the BOs
+ *
+ * Move the PT BOs to the tail of the LRU.
+ */
+void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
+				  struct amdgpu_vm *vm)
+{
+	struct ttm_bo_global *glob = adev->mman.bdev.glob;
+	unsigned i;
+
+	spin_lock(&glob->lru_lock);
+	for (i = 0; i <= vm->max_pde_used; ++i) {
+		struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry;
+
+		if (!entry->robj)
+			continue;
+
+		ttm_bo_move_to_lru_tail(&entry->robj->tbo);
+	}
+	spin_unlock(&glob->lru_lock);
 }
 
 /**
@@ -461,7 +488,7 @@
 
 	/* walk over the address space and update the page directory */
 	for (pt_idx = 0; pt_idx <= vm->max_pde_used; ++pt_idx) {
-		struct amdgpu_bo *bo = vm->page_tables[pt_idx].bo;
+		struct amdgpu_bo *bo = vm->page_tables[pt_idx].entry.robj;
 		uint64_t pde, pt;
 
 		if (bo == NULL)
@@ -638,7 +665,7 @@
 	/* walk over the address space and update the page tables */
 	for (addr = start; addr < end; ) {
 		uint64_t pt_idx = addr >> amdgpu_vm_block_size;
-		struct amdgpu_bo *pt = vm->page_tables[pt_idx].bo;
+		struct amdgpu_bo *pt = vm->page_tables[pt_idx].entry.robj;
 		unsigned nptes;
 		uint64_t pte;
 		int r;
@@ -1010,13 +1037,13 @@
 		return -EINVAL;
 
 	/* make sure object fit at this offset */
-	eaddr = saddr + size;
+	eaddr = saddr + size - 1;
 	if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo)))
 		return -EINVAL;
 
 	last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE;
-	if (last_pfn > adev->vm_manager.max_pfn) {
-		dev_err(adev->dev, "va above limit (0x%08X > 0x%08X)\n",
+	if (last_pfn >= adev->vm_manager.max_pfn) {
+		dev_err(adev->dev, "va above limit (0x%08X >= 0x%08X)\n",
 			last_pfn, adev->vm_manager.max_pfn);
 		return -EINVAL;
 	}
@@ -1025,7 +1052,7 @@
 	eaddr /= AMDGPU_GPU_PAGE_SIZE;
 
 	spin_lock(&vm->it_lock);
-	it = interval_tree_iter_first(&vm->va, saddr, eaddr - 1);
+	it = interval_tree_iter_first(&vm->va, saddr, eaddr);
 	spin_unlock(&vm->it_lock);
 	if (it) {
 		struct amdgpu_bo_va_mapping *tmp;
@@ -1046,7 +1073,7 @@
 
 	INIT_LIST_HEAD(&mapping->list);
 	mapping->it.start = saddr;
-	mapping->it.last = eaddr - 1;
+	mapping->it.last = eaddr;
 	mapping->offset = offset;
 	mapping->flags = flags;
 
@@ -1070,9 +1097,11 @@
 	/* walk over the address space and allocate the page tables */
 	for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) {
 		struct reservation_object *resv = vm->page_directory->tbo.resv;
+		struct amdgpu_bo_list_entry *entry;
 		struct amdgpu_bo *pt;
 
-		if (vm->page_tables[pt_idx].bo)
+		entry = &vm->page_tables[pt_idx].entry;
+		if (entry->robj)
 			continue;
 
 		r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8,
@@ -1094,8 +1123,13 @@
 			goto error_free;
 		}
 
+		entry->robj = pt;
+		entry->prefered_domains = AMDGPU_GEM_DOMAIN_VRAM;
+		entry->allowed_domains = AMDGPU_GEM_DOMAIN_VRAM;
+		entry->priority = 0;
+		entry->tv.bo = &entry->robj->tbo;
+		entry->tv.shared = true;
 		vm->page_tables[pt_idx].addr = 0;
-		vm->page_tables[pt_idx].bo = pt;
 	}
 
 	return 0;
@@ -1326,7 +1360,7 @@
 	}
 
 	for (i = 0; i < amdgpu_vm_num_pdes(adev); i++)
-		amdgpu_bo_unref(&vm->page_tables[i].bo);
+		amdgpu_bo_unref(&vm->page_tables[i].entry.robj);
 	kfree(vm->page_tables);
 
 	amdgpu_bo_unref(&vm->page_directory);
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c
index 92b6aca..21aacc1 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c
@@ -243,7 +243,7 @@
 
 /* convert bits per color to bits per pixel */
 /* get bpc from the EDID */
-static int amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc)
+static unsigned amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc)
 {
 	if (bpc == 0)
 		return 24;
@@ -251,64 +251,32 @@
 		return bpc * 3;
 }
 
-/* get the max pix clock supported by the link rate and lane num */
-static int amdgpu_atombios_dp_get_max_dp_pix_clock(int link_rate,
-					    int lane_num,
-					    int bpp)
-{
-	return (link_rate * lane_num * 8) / bpp;
-}
-
 /***** amdgpu specific DP functions *****/
 
-/* First get the min lane# when low rate is used according to pixel clock
- * (prefer low rate), second check max lane# supported by DP panel,
- * if the max lane# < low rate lane# then use max lane# instead.
- */
-static int amdgpu_atombios_dp_get_dp_lane_number(struct drm_connector *connector,
+static int amdgpu_atombios_dp_get_dp_link_config(struct drm_connector *connector,
 						 const u8 dpcd[DP_DPCD_SIZE],
-						 int pix_clock)
+						 unsigned pix_clock,
+						 unsigned *dp_lanes, unsigned *dp_rate)
 {
-	int bpp = amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
-	int max_link_rate = drm_dp_max_link_rate(dpcd);
-	int max_lane_num = drm_dp_max_lane_count(dpcd);
-	int lane_num;
-	int max_dp_pix_clock;
+	unsigned bpp =
+		amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
+	static const unsigned link_rates[3] = { 162000, 270000, 540000 };
+	unsigned max_link_rate = drm_dp_max_link_rate(dpcd);
+	unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
+	unsigned lane_num, i, max_pix_clock;
 
-	for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) {
-		max_dp_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp);
-		if (pix_clock <= max_dp_pix_clock)
-			break;
+	for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
+		for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
+			max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
+			if (max_pix_clock >= pix_clock) {
+				*dp_lanes = lane_num;
+				*dp_rate = link_rates[i];
+				return 0;
+			}
+		}
 	}
 
-	return lane_num;
-}
-
-static int amdgpu_atombios_dp_get_dp_link_clock(struct drm_connector *connector,
-						const u8 dpcd[DP_DPCD_SIZE],
-						int pix_clock)
-{
-	int bpp = amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector));
-	int lane_num, max_pix_clock;
-
-	if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) ==
-	    ENCODER_OBJECT_ID_NUTMEG)
-		return 270000;
-
-	lane_num = amdgpu_atombios_dp_get_dp_lane_number(connector, dpcd, pix_clock);
-	max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(162000, lane_num, bpp);
-	if (pix_clock <= max_pix_clock)
-		return 162000;
-	max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(270000, lane_num, bpp);
-	if (pix_clock <= max_pix_clock)
-		return 270000;
-	if (amdgpu_connector_is_dp12_capable(connector)) {
-		max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(540000, lane_num, bpp);
-		if (pix_clock <= max_pix_clock)
-			return 540000;
-	}
-
-	return drm_dp_max_link_rate(dpcd);
+	return -EINVAL;
 }
 
 static u8 amdgpu_atombios_dp_encoder_service(struct amdgpu_device *adev,
@@ -422,6 +390,7 @@
 {
 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 	struct amdgpu_connector_atom_dig *dig_connector;
+	int ret;
 
 	if (!amdgpu_connector->con_priv)
 		return;
@@ -429,10 +398,14 @@
 
 	if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
 	    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
-		dig_connector->dp_clock =
-			amdgpu_atombios_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
-		dig_connector->dp_lane_count =
-			amdgpu_atombios_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock);
+		ret = amdgpu_atombios_dp_get_dp_link_config(connector, dig_connector->dpcd,
+							    mode->clock,
+							    &dig_connector->dp_lane_count,
+							    &dig_connector->dp_clock);
+		if (ret) {
+			dig_connector->dp_clock = 0;
+			dig_connector->dp_lane_count = 0;
+		}
 	}
 }
 
@@ -441,14 +414,17 @@
 {
 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 	struct amdgpu_connector_atom_dig *dig_connector;
-	int dp_clock;
+	unsigned dp_lanes, dp_clock;
+	int ret;
 
 	if (!amdgpu_connector->con_priv)
 		return MODE_CLOCK_HIGH;
 	dig_connector = amdgpu_connector->con_priv;
 
-	dp_clock =
-		amdgpu_atombios_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
+	ret = amdgpu_atombios_dp_get_dp_link_config(connector, dig_connector->dpcd,
+						    mode->clock, &dp_lanes, &dp_clock);
+	if (ret)
+		return MODE_CLOCK_HIGH;
 
 	if ((dp_clock == 540000) &&
 	    (!amdgpu_connector_is_dp12_capable(connector)))
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index 57a2e34..8b4731d 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -1395,7 +1395,6 @@
 		ci_fan_ctrl_set_default_mode(adev);
 }
 
-#if 0
 static int ci_read_smc_soft_register(struct amdgpu_device *adev,
 				     u16 reg_offset, u32 *value)
 {
@@ -1405,7 +1404,6 @@
 				      pi->soft_regs_start + reg_offset,
 				      value, pi->sram_end);
 }
-#endif
 
 static int ci_write_smc_soft_register(struct amdgpu_device *adev,
 				      u16 reg_offset, u32 value)
@@ -6084,11 +6082,23 @@
 	struct amdgpu_ps *rps = &pi->current_rps;
 	u32 sclk = ci_get_average_sclk_freq(adev);
 	u32 mclk = ci_get_average_mclk_freq(adev);
+	u32 activity_percent = 50;
+	int ret;
+
+	ret = ci_read_smc_soft_register(adev, offsetof(SMU7_SoftRegisters, AverageGraphicsA),
+					&activity_percent);
+
+	if (ret == 0) {
+		activity_percent += 0x80;
+		activity_percent >>= 8;
+		activity_percent = activity_percent > 100 ? 100 : activity_percent;
+	}
 
 	seq_printf(m, "uvd %sabled\n", pi->uvd_enabled ? "en" : "dis");
 	seq_printf(m, "vce %sabled\n", rps->vce_active ? "en" : "dis");
 	seq_printf(m, "power level avg    sclk: %u mclk: %u\n",
 		   sclk, mclk);
+	seq_printf(m, "GPU load: %u %%\n", activity_percent);
 }
 
 static void ci_dpm_print_power_state(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index 484710c..fd9c958 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -32,6 +32,7 @@
 #include "amdgpu_vce.h"
 #include "cikd.h"
 #include "atom.h"
+#include "amd_pcie.h"
 
 #include "cik.h"
 #include "gmc_v7_0.h"
@@ -65,6 +66,7 @@
 #include "oss/oss_2_0_sh_mask.h"
 
 #include "amdgpu_amdkfd.h"
+#include "amdgpu_powerplay.h"
 
 /*
  * Indirect registers accessor
@@ -929,6 +931,37 @@
 	return r;
 }
 
+static bool cik_read_bios_from_rom(struct amdgpu_device *adev,
+				   u8 *bios, u32 length_bytes)
+{
+	u32 *dw_ptr;
+	unsigned long flags;
+	u32 i, length_dw;
+
+	if (bios == NULL)
+		return false;
+	if (length_bytes == 0)
+		return false;
+	/* APU vbios image is part of sbios image */
+	if (adev->flags & AMD_IS_APU)
+		return false;
+
+	dw_ptr = (u32 *)bios;
+	length_dw = ALIGN(length_bytes, 4) / 4;
+	/* take the smc lock since we are using the smc index */
+	spin_lock_irqsave(&adev->smc_idx_lock, flags);
+	/* set rom index to 0 */
+	WREG32(mmSMC_IND_INDEX_0, ixROM_INDEX);
+	WREG32(mmSMC_IND_DATA_0, 0);
+	/* set index to data for continous read */
+	WREG32(mmSMC_IND_INDEX_0, ixROM_DATA);
+	for (i = 0; i < length_dw; i++)
+		dw_ptr[i] = RREG32(mmSMC_IND_DATA_0);
+	spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
+
+	return true;
+}
+
 static struct amdgpu_allowed_register_entry cik_allowed_read_registers[] = {
 	{mmGRBM_STATUS, false},
 	{mmGB_ADDR_CONFIG, false},
@@ -1563,8 +1596,8 @@
 {
 	struct pci_dev *root = adev->pdev->bus->self;
 	int bridge_pos, gpu_pos;
-	u32 speed_cntl, mask, current_data_rate;
-	int ret, i;
+	u32 speed_cntl, current_data_rate;
+	int i;
 	u16 tmp16;
 
 	if (pci_is_root_bus(adev->pdev->bus))
@@ -1576,23 +1609,20 @@
 	if (adev->flags & AMD_IS_APU)
 		return;
 
-	ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask);
-	if (ret != 0)
-		return;
-
-	if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80)))
+	if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
+					CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)))
 		return;
 
 	speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL);
 	current_data_rate = (speed_cntl & PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) >>
 		PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
-	if (mask & DRM_PCIE_SPEED_80) {
+	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) {
 		if (current_data_rate == 2) {
 			DRM_INFO("PCIE gen 3 link speeds already enabled\n");
 			return;
 		}
 		DRM_INFO("enabling PCIE gen 3 link speeds, disable with amdgpu.pcie_gen2=0\n");
-	} else if (mask & DRM_PCIE_SPEED_50) {
+	} else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) {
 		if (current_data_rate == 1) {
 			DRM_INFO("PCIE gen 2 link speeds already enabled\n");
 			return;
@@ -1608,7 +1638,7 @@
 	if (!gpu_pos)
 		return;
 
-	if (mask & DRM_PCIE_SPEED_80) {
+	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) {
 		/* re-try equalization if gen3 is not already enabled */
 		if (current_data_rate != 2) {
 			u16 bridge_cfg, gpu_cfg;
@@ -1703,9 +1733,9 @@
 
 	pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16);
 	tmp16 &= ~0xf;
-	if (mask & DRM_PCIE_SPEED_80)
+	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
 		tmp16 |= 3; /* gen3 */
-	else if (mask & DRM_PCIE_SPEED_50)
+	else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
 		tmp16 |= 2; /* gen2 */
 	else
 		tmp16 |= 1; /* gen1 */
@@ -1922,7 +1952,7 @@
 		.major = 7,
 		.minor = 0,
 		.rev = 0,
-		.funcs = &ci_dpm_ip_funcs,
+		.funcs = &amdgpu_pp_ip_funcs,
 	},
 	{
 		.type = AMD_IP_BLOCK_TYPE_DCE,
@@ -1990,7 +2020,7 @@
 		.major = 7,
 		.minor = 0,
 		.rev = 0,
-		.funcs = &ci_dpm_ip_funcs,
+		.funcs = &amdgpu_pp_ip_funcs,
 	},
 	{
 		.type = AMD_IP_BLOCK_TYPE_DCE,
@@ -2058,7 +2088,7 @@
 		.major = 7,
 		.minor = 0,
 		.rev = 0,
-		.funcs = &kv_dpm_ip_funcs,
+		.funcs = &amdgpu_pp_ip_funcs,
 	},
 	{
 		.type = AMD_IP_BLOCK_TYPE_DCE,
@@ -2126,7 +2156,7 @@
 		.major = 7,
 		.minor = 0,
 		.rev = 0,
-		.funcs = &kv_dpm_ip_funcs,
+		.funcs = &amdgpu_pp_ip_funcs,
 	},
 	{
 		.type = AMD_IP_BLOCK_TYPE_DCE,
@@ -2194,7 +2224,7 @@
 		.major = 7,
 		.minor = 0,
 		.rev = 0,
-		.funcs = &kv_dpm_ip_funcs,
+		.funcs = &amdgpu_pp_ip_funcs,
 	},
 	{
 		.type = AMD_IP_BLOCK_TYPE_DCE,
@@ -2267,6 +2297,7 @@
 static const struct amdgpu_asic_funcs cik_asic_funcs =
 {
 	.read_disabled_bios = &cik_read_disabled_bios,
+	.read_bios_from_rom = &cik_read_bios_from_rom,
 	.read_register = &cik_read_register,
 	.reset = &cik_asic_reset,
 	.set_vga_state = &cik_vga_set_state,
@@ -2417,6 +2448,8 @@
 		return -EINVAL;
 	}
 
+	amdgpu_get_pcie_info(adev);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c
index 8993c50..30c9b3be 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c
@@ -274,6 +274,11 @@
 static int cik_ih_early_init(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int ret;
+
+	ret = amdgpu_irq_add_domain(adev);
+	if (ret)
+		return ret;
 
 	cik_ih_set_interrupt_funcs(adev);
 
@@ -300,6 +305,7 @@
 
 	amdgpu_irq_fini(adev);
 	amdgpu_ih_ring_fini(adev);
+	amdgpu_irq_remove_domain(adev);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
index 8035d4d..4dd17f2 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
@@ -1078,6 +1078,37 @@
 	return i;
 }
 
+static uint32_t cz_get_uvd_level(struct amdgpu_device *adev,
+				 uint32_t clock, uint16_t msg)
+{
+	int i = 0;
+	struct amdgpu_uvd_clock_voltage_dependency_table *table =
+		&adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
+
+	switch (msg) {
+	case PPSMC_MSG_SetUvdSoftMin:
+	case PPSMC_MSG_SetUvdHardMin:
+		for (i = 0; i < table->count; i++)
+			if (clock <= table->entries[i].vclk)
+				break;
+		if (i == table->count)
+			i = table->count - 1;
+		break;
+	case PPSMC_MSG_SetUvdSoftMax:
+	case PPSMC_MSG_SetUvdHardMax:
+		for (i = table->count - 1; i >= 0; i--)
+			if (clock >= table->entries[i].vclk)
+				break;
+		if (i < 0)
+			i = 0;
+		break;
+	default:
+		break;
+	}
+
+	return i;
+}
+
 static int cz_program_bootup_state(struct amdgpu_device *adev)
 {
 	struct cz_power_info *pi = cz_get_pi(adev);
@@ -1739,6 +1770,200 @@
 	return 0;
 }
 
+static int cz_dpm_uvd_force_highest(struct amdgpu_device *adev)
+{
+	struct cz_power_info *pi = cz_get_pi(adev);
+	int ret = 0;
+
+	if (pi->uvd_dpm.soft_min_clk != pi->uvd_dpm.soft_max_clk) {
+		pi->uvd_dpm.soft_min_clk =
+			pi->uvd_dpm.soft_max_clk;
+		ret = cz_send_msg_to_smc_with_parameter(adev,
+				PPSMC_MSG_SetUvdSoftMin,
+				cz_get_uvd_level(adev,
+					pi->uvd_dpm.soft_min_clk,
+					PPSMC_MSG_SetUvdSoftMin));
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+static int cz_dpm_uvd_force_lowest(struct amdgpu_device *adev)
+{
+	struct cz_power_info *pi = cz_get_pi(adev);
+	int ret = 0;
+
+	if (pi->uvd_dpm.soft_max_clk != pi->uvd_dpm.soft_min_clk) {
+		pi->uvd_dpm.soft_max_clk = pi->uvd_dpm.soft_min_clk;
+		ret = cz_send_msg_to_smc_with_parameter(adev,
+				PPSMC_MSG_SetUvdSoftMax,
+				cz_get_uvd_level(adev,
+					pi->uvd_dpm.soft_max_clk,
+					PPSMC_MSG_SetUvdSoftMax));
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+static uint32_t cz_dpm_get_max_uvd_level(struct amdgpu_device *adev)
+{
+	struct cz_power_info *pi = cz_get_pi(adev);
+
+	if (!pi->max_uvd_level) {
+		cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxUvdLevel);
+		pi->max_uvd_level = cz_get_argument(adev) + 1;
+	}
+
+	if (pi->max_uvd_level > CZ_MAX_HARDWARE_POWERLEVELS) {
+		DRM_ERROR("Invalid max uvd level!\n");
+		return -EINVAL;
+	}
+
+	return pi->max_uvd_level;
+}
+
+static int cz_dpm_unforce_uvd_dpm_levels(struct amdgpu_device *adev)
+{
+	struct cz_power_info *pi = cz_get_pi(adev);
+	struct amdgpu_uvd_clock_voltage_dependency_table *dep_table =
+		&adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
+	uint32_t level = 0;
+	int ret = 0;
+
+	pi->uvd_dpm.soft_min_clk = dep_table->entries[0].vclk;
+	level = cz_dpm_get_max_uvd_level(adev) - 1;
+	if (level < dep_table->count)
+		pi->uvd_dpm.soft_max_clk = dep_table->entries[level].vclk;
+	else
+		pi->uvd_dpm.soft_max_clk =
+			dep_table->entries[dep_table->count - 1].vclk;
+
+	/* get min/max sclk soft value
+	 * notify SMU to execute */
+	ret = cz_send_msg_to_smc_with_parameter(adev,
+				PPSMC_MSG_SetUvdSoftMin,
+				cz_get_uvd_level(adev,
+					pi->uvd_dpm.soft_min_clk,
+					PPSMC_MSG_SetUvdSoftMin));
+	if (ret)
+		return ret;
+
+	ret = cz_send_msg_to_smc_with_parameter(adev,
+				PPSMC_MSG_SetUvdSoftMax,
+				cz_get_uvd_level(adev,
+					pi->uvd_dpm.soft_max_clk,
+					PPSMC_MSG_SetUvdSoftMax));
+	if (ret)
+		return ret;
+
+	DRM_DEBUG("DPM uvd unforce state min=%d, max=%d.\n",
+		  pi->uvd_dpm.soft_min_clk,
+		  pi->uvd_dpm.soft_max_clk);
+
+	return 0;
+}
+
+static int cz_dpm_vce_force_highest(struct amdgpu_device *adev)
+{
+	struct cz_power_info *pi = cz_get_pi(adev);
+	int ret = 0;
+
+	if (pi->vce_dpm.soft_min_clk != pi->vce_dpm.soft_max_clk) {
+		pi->vce_dpm.soft_min_clk =
+			pi->vce_dpm.soft_max_clk;
+		ret = cz_send_msg_to_smc_with_parameter(adev,
+				PPSMC_MSG_SetEclkSoftMin,
+				cz_get_eclk_level(adev,
+					pi->vce_dpm.soft_min_clk,
+					PPSMC_MSG_SetEclkSoftMin));
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+static int cz_dpm_vce_force_lowest(struct amdgpu_device *adev)
+{
+	struct cz_power_info *pi = cz_get_pi(adev);
+	int ret = 0;
+
+	if (pi->vce_dpm.soft_max_clk != pi->vce_dpm.soft_min_clk) {
+		pi->vce_dpm.soft_max_clk = pi->vce_dpm.soft_min_clk;
+		ret = cz_send_msg_to_smc_with_parameter(adev,
+				PPSMC_MSG_SetEclkSoftMax,
+				cz_get_uvd_level(adev,
+					pi->vce_dpm.soft_max_clk,
+					PPSMC_MSG_SetEclkSoftMax));
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+static uint32_t cz_dpm_get_max_vce_level(struct amdgpu_device *adev)
+{
+	struct cz_power_info *pi = cz_get_pi(adev);
+
+	if (!pi->max_vce_level) {
+		cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxEclkLevel);
+		pi->max_vce_level = cz_get_argument(adev) + 1;
+	}
+
+	if (pi->max_vce_level > CZ_MAX_HARDWARE_POWERLEVELS) {
+		DRM_ERROR("Invalid max vce level!\n");
+		return -EINVAL;
+	}
+
+	return pi->max_vce_level;
+}
+
+static int cz_dpm_unforce_vce_dpm_levels(struct amdgpu_device *adev)
+{
+	struct cz_power_info *pi = cz_get_pi(adev);
+	struct amdgpu_vce_clock_voltage_dependency_table *dep_table =
+		&adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
+	uint32_t level = 0;
+	int ret = 0;
+
+	pi->vce_dpm.soft_min_clk = dep_table->entries[0].ecclk;
+	level = cz_dpm_get_max_vce_level(adev) - 1;
+	if (level < dep_table->count)
+		pi->vce_dpm.soft_max_clk = dep_table->entries[level].ecclk;
+	else
+		pi->vce_dpm.soft_max_clk =
+			dep_table->entries[dep_table->count - 1].ecclk;
+
+	/* get min/max sclk soft value
+	 * notify SMU to execute */
+	ret = cz_send_msg_to_smc_with_parameter(adev,
+				PPSMC_MSG_SetEclkSoftMin,
+				cz_get_eclk_level(adev,
+					pi->vce_dpm.soft_min_clk,
+					PPSMC_MSG_SetEclkSoftMin));
+	if (ret)
+		return ret;
+
+	ret = cz_send_msg_to_smc_with_parameter(adev,
+				PPSMC_MSG_SetEclkSoftMax,
+				cz_get_eclk_level(adev,
+					pi->vce_dpm.soft_max_clk,
+					PPSMC_MSG_SetEclkSoftMax));
+	if (ret)
+		return ret;
+
+	DRM_DEBUG("DPM vce unforce state min=%d, max=%d.\n",
+		  pi->vce_dpm.soft_min_clk,
+		  pi->vce_dpm.soft_max_clk);
+
+	return 0;
+}
+
 static int cz_dpm_force_dpm_level(struct amdgpu_device *adev,
 				  enum amdgpu_dpm_forced_level level)
 {
@@ -1746,25 +1971,70 @@
 
 	switch (level) {
 	case AMDGPU_DPM_FORCED_LEVEL_HIGH:
+		/* sclk */
 		ret = cz_dpm_unforce_dpm_levels(adev);
 		if (ret)
 			return ret;
 		ret = cz_dpm_force_highest(adev);
 		if (ret)
 			return ret;
+
+		/* uvd */
+		ret = cz_dpm_unforce_uvd_dpm_levels(adev);
+		if (ret)
+			return ret;
+		ret = cz_dpm_uvd_force_highest(adev);
+		if (ret)
+			return ret;
+
+		/* vce */
+		ret = cz_dpm_unforce_vce_dpm_levels(adev);
+		if (ret)
+			return ret;
+		ret = cz_dpm_vce_force_highest(adev);
+		if (ret)
+			return ret;
 		break;
 	case AMDGPU_DPM_FORCED_LEVEL_LOW:
+		/* sclk */
 		ret = cz_dpm_unforce_dpm_levels(adev);
 		if (ret)
 			return ret;
 		ret = cz_dpm_force_lowest(adev);
 		if (ret)
 			return ret;
+
+		/* uvd */
+		ret = cz_dpm_unforce_uvd_dpm_levels(adev);
+		if (ret)
+			return ret;
+		ret = cz_dpm_uvd_force_lowest(adev);
+		if (ret)
+			return ret;
+
+		/* vce */
+		ret = cz_dpm_unforce_vce_dpm_levels(adev);
+		if (ret)
+			return ret;
+		ret = cz_dpm_vce_force_lowest(adev);
+		if (ret)
+			return ret;
 		break;
 	case AMDGPU_DPM_FORCED_LEVEL_AUTO:
+		/* sclk */
 		ret = cz_dpm_unforce_dpm_levels(adev);
 		if (ret)
 			return ret;
+
+		/* uvd */
+		ret = cz_dpm_unforce_uvd_dpm_levels(adev);
+		if (ret)
+			return ret;
+
+		/* vce */
+		ret = cz_dpm_unforce_vce_dpm_levels(adev);
+		if (ret)
+			return ret;
 		break;
 	default:
 		break;
@@ -1905,7 +2175,8 @@
 		pi->vce_dpm.hard_min_clk = table->entries[table->count-1].ecclk;
 
 	} else { /* non-stable p-state cases. without vce.Arbiter.EcclkHardMin */
-		pi->vce_dpm.hard_min_clk = table->entries[0].ecclk;
+		/* leave it as set by user */
+		/*pi->vce_dpm.hard_min_clk = table->entries[0].ecclk;*/
 	}
 
 	cz_send_msg_to_smc_with_parameter(adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.h b/drivers/gpu/drm/amd/amdgpu/cz_dpm.h
index 99e1afc..5df8c1f 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.h
@@ -183,6 +183,8 @@
 	uint32_t voltage_drop_threshold;
 	uint32_t gfx_pg_threshold;
 	uint32_t max_sclk_level;
+	uint32_t max_uvd_level;
+	uint32_t max_vce_level;
 	/* flags */
 	bool didt_enabled;
 	bool video_start;
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c
index bc751bf..c79638f 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c
@@ -253,8 +253,14 @@
 static int cz_ih_early_init(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int ret;
+
+	ret = amdgpu_irq_add_domain(adev);
+	if (ret)
+		return ret;
 
 	cz_ih_set_interrupt_funcs(adev);
+
 	return 0;
 }
 
@@ -278,6 +284,7 @@
 
 	amdgpu_irq_fini(adev);
 	amdgpu_ih_ring_fini(adev);
+	amdgpu_irq_remove_domain(adev);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index 8701661..8e67249 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -211,9 +211,9 @@
  */
 static void dce_v11_0_vblank_wait(struct amdgpu_device *adev, int crtc)
 {
-	unsigned i = 0;
+	unsigned i = 100;
 
-	if (crtc >= adev->mode_info.num_crtc)
+	if (crtc < 0 || crtc >= adev->mode_info.num_crtc)
 		return;
 
 	if (!(RREG32(mmCRTC_CONTROL + crtc_offsets[crtc]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK))
@@ -223,14 +223,16 @@
 	 * wait for another frame.
 	 */
 	while (dce_v11_0_is_in_vblank(adev, crtc)) {
-		if (i++ % 100 == 0) {
+		if (i++ == 100) {
+			i = 0;
 			if (!dce_v11_0_is_counter_moving(adev, crtc))
 				break;
 		}
 	}
 
 	while (!dce_v11_0_is_in_vblank(adev, crtc)) {
-		if (i++ % 100 == 0) {
+		if (i++ == 100) {
+			i = 0;
 			if (!dce_v11_0_is_counter_moving(adev, crtc))
 				break;
 		}
@@ -239,7 +241,7 @@
 
 static u32 dce_v11_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
 {
-	if (crtc >= adev->mode_info.num_crtc)
+	if (crtc < 0 || crtc >= adev->mode_info.num_crtc)
 		return 0;
 	else
 		return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
@@ -3384,7 +3386,7 @@
 {
 	u32 tmp;
 
-	if (crtc >= adev->mode_info.num_crtc) {
+	if (crtc < 0 || crtc >= adev->mode_info.num_crtc) {
 		DRM_DEBUG("invalid crtc %d\n", crtc);
 		return;
 	}
@@ -3399,7 +3401,7 @@
 {
 	u32 tmp;
 
-	if (crtc >= adev->mode_info.num_crtc) {
+	if (crtc < 0 || crtc >= adev->mode_info.num_crtc) {
 		DRM_DEBUG("invalid crtc %d\n", crtc);
 		return;
 	}
diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c b/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c
index 8f9845d..4b0e45a 100644
--- a/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c
@@ -24,7 +24,7 @@
 #include <linux/firmware.h>
 #include "drmP.h"
 #include "amdgpu.h"
-#include "fiji_smumgr.h"
+#include "fiji_smum.h"
 
 MODULE_FIRMWARE("amdgpu/fiji_smc.bin");
 
diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h b/drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h
deleted file mode 100644
index 3c48240..0000000
--- a/drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2014 Advanced Micro Devices, 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.
- *
- */
-
-#ifndef FIJI_PP_SMC_H
-#define FIJI_PP_SMC_H
-
-#pragma pack(push, 1)
-
-#define PPSMC_SWSTATE_FLAG_DC                           0x01
-#define PPSMC_SWSTATE_FLAG_UVD                          0x02
-#define PPSMC_SWSTATE_FLAG_VCE                          0x04
-
-#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL             0x00
-#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL             0x01
-#define PPSMC_THERMAL_PROTECT_TYPE_NONE                 0xff
-
-#define PPSMC_SYSTEMFLAG_GPIO_DC                        0x01
-#define PPSMC_SYSTEMFLAG_STEPVDDC                       0x02
-#define PPSMC_SYSTEMFLAG_GDDR5                          0x04
-
-#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP               0x08
-
-#define PPSMC_SYSTEMFLAG_REGULATOR_HOT                  0x10
-#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG           0x20
-
-#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK              0x07
-#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK     0x08
-
-#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE   0x00
-#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE  0x01
-
-#define PPSMC_DPM2FLAGS_TDPCLMP                         0x01
-#define PPSMC_DPM2FLAGS_PWRSHFT                         0x02
-#define PPSMC_DPM2FLAGS_OCP                             0x04
-
-#define PPSMC_DISPLAY_WATERMARK_LOW                     0
-#define PPSMC_DISPLAY_WATERMARK_HIGH                    1
-
-#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP    		0x01
-#define PPSMC_STATEFLAG_POWERBOOST         		0x02
-#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 		0x04
-#define PPSMC_STATEFLAG_POWERSHIFT         		0x08
-#define PPSMC_STATEFLAG_SLOW_READ_MARGIN   		0x10
-#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 		0x20
-#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS   		0x40
-
-#define FDO_MODE_HARDWARE 0
-#define FDO_MODE_PIECE_WISE_LINEAR 1
-
-enum FAN_CONTROL {
-	FAN_CONTROL_FUZZY,
-	FAN_CONTROL_TABLE
-};
-
-//Gemini Modes
-#define PPSMC_GeminiModeNone   0  //Single GPU board
-#define PPSMC_GeminiModeMaster 1  //Master GPU on a Gemini board
-#define PPSMC_GeminiModeSlave  2  //Slave GPU on a Gemini board
-
-#define PPSMC_Result_OK             			((uint16_t)0x01)
-#define PPSMC_Result_NoMore         			((uint16_t)0x02)
-#define PPSMC_Result_NotNow         			((uint16_t)0x03)
-#define PPSMC_Result_Failed         			((uint16_t)0xFF)
-#define PPSMC_Result_UnknownCmd     			((uint16_t)0xFE)
-#define PPSMC_Result_UnknownVT      			((uint16_t)0xFD)
-
-typedef uint16_t PPSMC_Result;
-
-#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x))
-
-#define PPSMC_MSG_Halt                      		((uint16_t)0x10)
-#define PPSMC_MSG_Resume                    		((uint16_t)0x11)
-#define PPSMC_MSG_EnableDPMLevel            		((uint16_t)0x12)
-#define PPSMC_MSG_ZeroLevelsDisabled        		((uint16_t)0x13)
-#define PPSMC_MSG_OneLevelsDisabled         		((uint16_t)0x14)
-#define PPSMC_MSG_TwoLevelsDisabled         		((uint16_t)0x15)
-#define PPSMC_MSG_EnableThermalInterrupt    		((uint16_t)0x16)
-#define PPSMC_MSG_RunningOnAC               		((uint16_t)0x17)
-#define PPSMC_MSG_LevelUp                   		((uint16_t)0x18)
-#define PPSMC_MSG_LevelDown                 		((uint16_t)0x19)
-#define PPSMC_MSG_ResetDPMCounters          		((uint16_t)0x1a)
-#define PPSMC_MSG_SwitchToSwState           		((uint16_t)0x20)
-#define PPSMC_MSG_SwitchToSwStateLast       		((uint16_t)0x3f)
-#define PPSMC_MSG_SwitchToInitialState      		((uint16_t)0x40)
-#define PPSMC_MSG_NoForcedLevel             		((uint16_t)0x41)
-#define PPSMC_MSG_ForceHigh                 		((uint16_t)0x42)
-#define PPSMC_MSG_ForceMediumOrHigh         		((uint16_t)0x43)
-#define PPSMC_MSG_SwitchToMinimumPower      		((uint16_t)0x51)
-#define PPSMC_MSG_ResumeFromMinimumPower    		((uint16_t)0x52)
-#define PPSMC_MSG_EnableCac                 		((uint16_t)0x53)
-#define PPSMC_MSG_DisableCac                		((uint16_t)0x54)
-#define PPSMC_DPMStateHistoryStart          		((uint16_t)0x55)
-#define PPSMC_DPMStateHistoryStop           		((uint16_t)0x56)
-#define PPSMC_CACHistoryStart               		((uint16_t)0x57)
-#define PPSMC_CACHistoryStop                		((uint16_t)0x58)
-#define PPSMC_TDPClampingActive             		((uint16_t)0x59)
-#define PPSMC_TDPClampingInactive           		((uint16_t)0x5A)
-#define PPSMC_StartFanControl               		((uint16_t)0x5B)
-#define PPSMC_StopFanControl                		((uint16_t)0x5C)
-#define PPSMC_NoDisplay                     		((uint16_t)0x5D)
-#define PPSMC_HasDisplay                    		((uint16_t)0x5E)
-#define PPSMC_MSG_UVDPowerOFF               		((uint16_t)0x60)
-#define PPSMC_MSG_UVDPowerON                		((uint16_t)0x61)
-#define PPSMC_MSG_EnableULV                 		((uint16_t)0x62)
-#define PPSMC_MSG_DisableULV                		((uint16_t)0x63)
-#define PPSMC_MSG_EnterULV                  		((uint16_t)0x64)
-#define PPSMC_MSG_ExitULV                   		((uint16_t)0x65)
-#define PPSMC_PowerShiftActive              		((uint16_t)0x6A)
-#define PPSMC_PowerShiftInactive            		((uint16_t)0x6B)
-#define PPSMC_OCPActive                     		((uint16_t)0x6C)
-#define PPSMC_OCPInactive                   		((uint16_t)0x6D)
-#define PPSMC_CACLongTermAvgEnable          		((uint16_t)0x6E)
-#define PPSMC_CACLongTermAvgDisable         		((uint16_t)0x6F)
-#define PPSMC_MSG_InferredStateSweep_Start  		((uint16_t)0x70)
-#define PPSMC_MSG_InferredStateSweep_Stop   		((uint16_t)0x71)
-#define PPSMC_MSG_SwitchToLowestInfState    		((uint16_t)0x72)
-#define PPSMC_MSG_SwitchToNonInfState       		((uint16_t)0x73)
-#define PPSMC_MSG_AllStateSweep_Start       		((uint16_t)0x74)
-#define PPSMC_MSG_AllStateSweep_Stop        		((uint16_t)0x75)
-#define PPSMC_MSG_SwitchNextLowerInfState   		((uint16_t)0x76)
-#define PPSMC_MSG_SwitchNextHigherInfState  		((uint16_t)0x77)
-#define PPSMC_MSG_MclkRetrainingTest        		((uint16_t)0x78)
-#define PPSMC_MSG_ForceTDPClamping          		((uint16_t)0x79)
-#define PPSMC_MSG_CollectCAC_PowerCorreln   		((uint16_t)0x7A)
-#define PPSMC_MSG_CollectCAC_WeightCalib    		((uint16_t)0x7B)
-#define PPSMC_MSG_CollectCAC_SQonly         		((uint16_t)0x7C)
-#define PPSMC_MSG_CollectCAC_TemperaturePwr 		((uint16_t)0x7D)
-#define PPSMC_MSG_ExtremitiesTest_Start     		((uint16_t)0x7E)
-#define PPSMC_MSG_ExtremitiesTest_Stop      		((uint16_t)0x7F)
-#define PPSMC_FlushDataCache                		((uint16_t)0x80)
-#define PPSMC_FlushInstrCache               		((uint16_t)0x81)
-#define PPSMC_MSG_SetEnabledLevels          		((uint16_t)0x82)
-#define PPSMC_MSG_SetForcedLevels           		((uint16_t)0x83)
-#define PPSMC_MSG_ResetToDefaults           		((uint16_t)0x84)
-#define PPSMC_MSG_SetForcedLevelsAndJump    		((uint16_t)0x85)
-#define PPSMC_MSG_SetCACHistoryMode         		((uint16_t)0x86)
-#define PPSMC_MSG_EnableDTE                 		((uint16_t)0x87)
-#define PPSMC_MSG_DisableDTE                		((uint16_t)0x88)
-#define PPSMC_MSG_SmcSpaceSetAddress        		((uint16_t)0x89)
-#define PPSMC_MSG_SmcSpaceWriteDWordInc     		((uint16_t)0x8A)
-#define PPSMC_MSG_SmcSpaceWriteWordInc      		((uint16_t)0x8B)
-#define PPSMC_MSG_SmcSpaceWriteByteInc      		((uint16_t)0x8C)
-
-#define PPSMC_MSG_BREAK                     		((uint16_t)0xF8)
-
-#define PPSMC_MSG_Test                      		((uint16_t)0x100)
-#define PPSMC_MSG_DRV_DRAM_ADDR_HI            		((uint16_t)0x250)
-#define PPSMC_MSG_DRV_DRAM_ADDR_LO            		((uint16_t)0x251)
-#define PPSMC_MSG_SMU_DRAM_ADDR_HI            		((uint16_t)0x252)
-#define PPSMC_MSG_SMU_DRAM_ADDR_LO            		((uint16_t)0x253)
-#define PPSMC_MSG_LoadUcodes                  		((uint16_t)0x254)
-
-typedef uint16_t PPSMC_Msg;
-
-#define PPSMC_EVENT_STATUS_THERMAL          		0x00000001
-#define PPSMC_EVENT_STATUS_REGULATORHOT     		0x00000002
-#define PPSMC_EVENT_STATUS_DC               		0x00000004
-#define PPSMC_EVENT_STATUS_GPIO17           		0x00000008
-
-#pragma pack(pop)
-
-#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_smc.c b/drivers/gpu/drm/amd/amdgpu/fiji_smc.c
index bda1249..e35340a 100644
--- a/drivers/gpu/drm/amd/amdgpu/fiji_smc.c
+++ b/drivers/gpu/drm/amd/amdgpu/fiji_smc.c
@@ -25,7 +25,7 @@
 #include "drmP.h"
 #include "amdgpu.h"
 #include "fiji_ppsmc.h"
-#include "fiji_smumgr.h"
+#include "fiji_smum.h"
 #include "smu_ucode_xfer_vi.h"
 #include "amdgpu_ucode.h"
 
diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_smumgr.h b/drivers/gpu/drm/amd/amdgpu/fiji_smum.h
similarity index 100%
rename from drivers/gpu/drm/amd/amdgpu/fiji_smumgr.h
rename to drivers/gpu/drm/amd/amdgpu/fiji_smum.h
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index e1dcab9..13235d8 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -66,6 +66,27 @@
 #define MACRO_TILE_ASPECT(x)				((x) << GB_MACROTILE_MODE0__MACRO_TILE_ASPECT__SHIFT)
 #define NUM_BANKS(x)					((x) << GB_MACROTILE_MODE0__NUM_BANKS__SHIFT)
 
+#define RLC_CGTT_MGCG_OVERRIDE__CPF_MASK            0x00000001L
+#define RLC_CGTT_MGCG_OVERRIDE__RLC_MASK            0x00000002L
+#define RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK           0x00000004L
+#define RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK           0x00000008L
+#define RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK           0x00000010L
+#define RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK           0x00000020L
+
+/* BPM SERDES CMD */
+#define SET_BPM_SERDES_CMD    1
+#define CLE_BPM_SERDES_CMD    0
+
+/* BPM Register Address*/
+enum {
+	BPM_REG_CGLS_EN = 0,        /* Enable/Disable CGLS */
+	BPM_REG_CGLS_ON,            /* ON/OFF CGLS: shall be controlled by RLC FW */
+	BPM_REG_CGCG_OVERRIDE,      /* Set/Clear CGCG Override */
+	BPM_REG_MGCG_OVERRIDE,      /* Set/Clear MGCG Override */
+	BPM_REG_FGCG_OVERRIDE,      /* Set/Clear FGCG Override */
+	BPM_REG_FGCG_MAX
+};
+
 MODULE_FIRMWARE("amdgpu/carrizo_ce.bin");
 MODULE_FIRMWARE("amdgpu/carrizo_pfp.bin");
 MODULE_FIRMWARE("amdgpu/carrizo_me.bin");
@@ -964,6 +985,322 @@
 	return 0;
 }
 
+static const u32 vgpr_init_compute_shader[] =
+{
+	0x7e000209, 0x7e020208,
+	0x7e040207, 0x7e060206,
+	0x7e080205, 0x7e0a0204,
+	0x7e0c0203, 0x7e0e0202,
+	0x7e100201, 0x7e120200,
+	0x7e140209, 0x7e160208,
+	0x7e180207, 0x7e1a0206,
+	0x7e1c0205, 0x7e1e0204,
+	0x7e200203, 0x7e220202,
+	0x7e240201, 0x7e260200,
+	0x7e280209, 0x7e2a0208,
+	0x7e2c0207, 0x7e2e0206,
+	0x7e300205, 0x7e320204,
+	0x7e340203, 0x7e360202,
+	0x7e380201, 0x7e3a0200,
+	0x7e3c0209, 0x7e3e0208,
+	0x7e400207, 0x7e420206,
+	0x7e440205, 0x7e460204,
+	0x7e480203, 0x7e4a0202,
+	0x7e4c0201, 0x7e4e0200,
+	0x7e500209, 0x7e520208,
+	0x7e540207, 0x7e560206,
+	0x7e580205, 0x7e5a0204,
+	0x7e5c0203, 0x7e5e0202,
+	0x7e600201, 0x7e620200,
+	0x7e640209, 0x7e660208,
+	0x7e680207, 0x7e6a0206,
+	0x7e6c0205, 0x7e6e0204,
+	0x7e700203, 0x7e720202,
+	0x7e740201, 0x7e760200,
+	0x7e780209, 0x7e7a0208,
+	0x7e7c0207, 0x7e7e0206,
+	0xbf8a0000, 0xbf810000,
+};
+
+static const u32 sgpr_init_compute_shader[] =
+{
+	0xbe8a0100, 0xbe8c0102,
+	0xbe8e0104, 0xbe900106,
+	0xbe920108, 0xbe940100,
+	0xbe960102, 0xbe980104,
+	0xbe9a0106, 0xbe9c0108,
+	0xbe9e0100, 0xbea00102,
+	0xbea20104, 0xbea40106,
+	0xbea60108, 0xbea80100,
+	0xbeaa0102, 0xbeac0104,
+	0xbeae0106, 0xbeb00108,
+	0xbeb20100, 0xbeb40102,
+	0xbeb60104, 0xbeb80106,
+	0xbeba0108, 0xbebc0100,
+	0xbebe0102, 0xbec00104,
+	0xbec20106, 0xbec40108,
+	0xbec60100, 0xbec80102,
+	0xbee60004, 0xbee70005,
+	0xbeea0006, 0xbeeb0007,
+	0xbee80008, 0xbee90009,
+	0xbefc0000, 0xbf8a0000,
+	0xbf810000, 0x00000000,
+};
+
+static const u32 vgpr_init_regs[] =
+{
+	mmCOMPUTE_STATIC_THREAD_MGMT_SE0, 0xffffffff,
+	mmCOMPUTE_RESOURCE_LIMITS, 0,
+	mmCOMPUTE_NUM_THREAD_X, 256*4,
+	mmCOMPUTE_NUM_THREAD_Y, 1,
+	mmCOMPUTE_NUM_THREAD_Z, 1,
+	mmCOMPUTE_PGM_RSRC2, 20,
+	mmCOMPUTE_USER_DATA_0, 0xedcedc00,
+	mmCOMPUTE_USER_DATA_1, 0xedcedc01,
+	mmCOMPUTE_USER_DATA_2, 0xedcedc02,
+	mmCOMPUTE_USER_DATA_3, 0xedcedc03,
+	mmCOMPUTE_USER_DATA_4, 0xedcedc04,
+	mmCOMPUTE_USER_DATA_5, 0xedcedc05,
+	mmCOMPUTE_USER_DATA_6, 0xedcedc06,
+	mmCOMPUTE_USER_DATA_7, 0xedcedc07,
+	mmCOMPUTE_USER_DATA_8, 0xedcedc08,
+	mmCOMPUTE_USER_DATA_9, 0xedcedc09,
+};
+
+static const u32 sgpr1_init_regs[] =
+{
+	mmCOMPUTE_STATIC_THREAD_MGMT_SE0, 0x0f,
+	mmCOMPUTE_RESOURCE_LIMITS, 0x1000000,
+	mmCOMPUTE_NUM_THREAD_X, 256*5,
+	mmCOMPUTE_NUM_THREAD_Y, 1,
+	mmCOMPUTE_NUM_THREAD_Z, 1,
+	mmCOMPUTE_PGM_RSRC2, 20,
+	mmCOMPUTE_USER_DATA_0, 0xedcedc00,
+	mmCOMPUTE_USER_DATA_1, 0xedcedc01,
+	mmCOMPUTE_USER_DATA_2, 0xedcedc02,
+	mmCOMPUTE_USER_DATA_3, 0xedcedc03,
+	mmCOMPUTE_USER_DATA_4, 0xedcedc04,
+	mmCOMPUTE_USER_DATA_5, 0xedcedc05,
+	mmCOMPUTE_USER_DATA_6, 0xedcedc06,
+	mmCOMPUTE_USER_DATA_7, 0xedcedc07,
+	mmCOMPUTE_USER_DATA_8, 0xedcedc08,
+	mmCOMPUTE_USER_DATA_9, 0xedcedc09,
+};
+
+static const u32 sgpr2_init_regs[] =
+{
+	mmCOMPUTE_STATIC_THREAD_MGMT_SE0, 0xf0,
+	mmCOMPUTE_RESOURCE_LIMITS, 0x1000000,
+	mmCOMPUTE_NUM_THREAD_X, 256*5,
+	mmCOMPUTE_NUM_THREAD_Y, 1,
+	mmCOMPUTE_NUM_THREAD_Z, 1,
+	mmCOMPUTE_PGM_RSRC2, 20,
+	mmCOMPUTE_USER_DATA_0, 0xedcedc00,
+	mmCOMPUTE_USER_DATA_1, 0xedcedc01,
+	mmCOMPUTE_USER_DATA_2, 0xedcedc02,
+	mmCOMPUTE_USER_DATA_3, 0xedcedc03,
+	mmCOMPUTE_USER_DATA_4, 0xedcedc04,
+	mmCOMPUTE_USER_DATA_5, 0xedcedc05,
+	mmCOMPUTE_USER_DATA_6, 0xedcedc06,
+	mmCOMPUTE_USER_DATA_7, 0xedcedc07,
+	mmCOMPUTE_USER_DATA_8, 0xedcedc08,
+	mmCOMPUTE_USER_DATA_9, 0xedcedc09,
+};
+
+static const u32 sec_ded_counter_registers[] =
+{
+	mmCPC_EDC_ATC_CNT,
+	mmCPC_EDC_SCRATCH_CNT,
+	mmCPC_EDC_UCODE_CNT,
+	mmCPF_EDC_ATC_CNT,
+	mmCPF_EDC_ROQ_CNT,
+	mmCPF_EDC_TAG_CNT,
+	mmCPG_EDC_ATC_CNT,
+	mmCPG_EDC_DMA_CNT,
+	mmCPG_EDC_TAG_CNT,
+	mmDC_EDC_CSINVOC_CNT,
+	mmDC_EDC_RESTORE_CNT,
+	mmDC_EDC_STATE_CNT,
+	mmGDS_EDC_CNT,
+	mmGDS_EDC_GRBM_CNT,
+	mmGDS_EDC_OA_DED,
+	mmSPI_EDC_CNT,
+	mmSQC_ATC_EDC_GATCL1_CNT,
+	mmSQC_EDC_CNT,
+	mmSQ_EDC_DED_CNT,
+	mmSQ_EDC_INFO,
+	mmSQ_EDC_SEC_CNT,
+	mmTCC_EDC_CNT,
+	mmTCP_ATC_EDC_GATCL1_CNT,
+	mmTCP_EDC_CNT,
+	mmTD_EDC_CNT
+};
+
+static int gfx_v8_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
+{
+	struct amdgpu_ring *ring = &adev->gfx.compute_ring[0];
+	struct amdgpu_ib ib;
+	struct fence *f = NULL;
+	int r, i;
+	u32 tmp;
+	unsigned total_size, vgpr_offset, sgpr_offset;
+	u64 gpu_addr;
+
+	/* only supported on CZ */
+	if (adev->asic_type != CHIP_CARRIZO)
+		return 0;
+
+	/* bail if the compute ring is not ready */
+	if (!ring->ready)
+		return 0;
+
+	tmp = RREG32(mmGB_EDC_MODE);
+	WREG32(mmGB_EDC_MODE, 0);
+
+	total_size =
+		(((ARRAY_SIZE(vgpr_init_regs) / 2) * 3) + 4 + 5 + 2) * 4;
+	total_size +=
+		(((ARRAY_SIZE(sgpr1_init_regs) / 2) * 3) + 4 + 5 + 2) * 4;
+	total_size +=
+		(((ARRAY_SIZE(sgpr2_init_regs) / 2) * 3) + 4 + 5 + 2) * 4;
+	total_size = ALIGN(total_size, 256);
+	vgpr_offset = total_size;
+	total_size += ALIGN(sizeof(vgpr_init_compute_shader), 256);
+	sgpr_offset = total_size;
+	total_size += sizeof(sgpr_init_compute_shader);
+
+	/* allocate an indirect buffer to put the commands in */
+	memset(&ib, 0, sizeof(ib));
+	r = amdgpu_ib_get(ring, NULL, total_size, &ib);
+	if (r) {
+		DRM_ERROR("amdgpu: failed to get ib (%d).\n", r);
+		return r;
+	}
+
+	/* load the compute shaders */
+	for (i = 0; i < ARRAY_SIZE(vgpr_init_compute_shader); i++)
+		ib.ptr[i + (vgpr_offset / 4)] = vgpr_init_compute_shader[i];
+
+	for (i = 0; i < ARRAY_SIZE(sgpr_init_compute_shader); i++)
+		ib.ptr[i + (sgpr_offset / 4)] = sgpr_init_compute_shader[i];
+
+	/* init the ib length to 0 */
+	ib.length_dw = 0;
+
+	/* VGPR */
+	/* write the register state for the compute dispatch */
+	for (i = 0; i < ARRAY_SIZE(vgpr_init_regs); i += 2) {
+		ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 1);
+		ib.ptr[ib.length_dw++] = vgpr_init_regs[i] - PACKET3_SET_SH_REG_START;
+		ib.ptr[ib.length_dw++] = vgpr_init_regs[i + 1];
+	}
+	/* write the shader start address: mmCOMPUTE_PGM_LO, mmCOMPUTE_PGM_HI */
+	gpu_addr = (ib.gpu_addr + (u64)vgpr_offset) >> 8;
+	ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 2);
+	ib.ptr[ib.length_dw++] = mmCOMPUTE_PGM_LO - PACKET3_SET_SH_REG_START;
+	ib.ptr[ib.length_dw++] = lower_32_bits(gpu_addr);
+	ib.ptr[ib.length_dw++] = upper_32_bits(gpu_addr);
+
+	/* write dispatch packet */
+	ib.ptr[ib.length_dw++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3);
+	ib.ptr[ib.length_dw++] = 8; /* x */
+	ib.ptr[ib.length_dw++] = 1; /* y */
+	ib.ptr[ib.length_dw++] = 1; /* z */
+	ib.ptr[ib.length_dw++] =
+		REG_SET_FIELD(0, COMPUTE_DISPATCH_INITIATOR, COMPUTE_SHADER_EN, 1);
+
+	/* write CS partial flush packet */
+	ib.ptr[ib.length_dw++] = PACKET3(PACKET3_EVENT_WRITE, 0);
+	ib.ptr[ib.length_dw++] = EVENT_TYPE(7) | EVENT_INDEX(4);
+
+	/* SGPR1 */
+	/* write the register state for the compute dispatch */
+	for (i = 0; i < ARRAY_SIZE(sgpr1_init_regs); i += 2) {
+		ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 1);
+		ib.ptr[ib.length_dw++] = sgpr1_init_regs[i] - PACKET3_SET_SH_REG_START;
+		ib.ptr[ib.length_dw++] = sgpr1_init_regs[i + 1];
+	}
+	/* write the shader start address: mmCOMPUTE_PGM_LO, mmCOMPUTE_PGM_HI */
+	gpu_addr = (ib.gpu_addr + (u64)sgpr_offset) >> 8;
+	ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 2);
+	ib.ptr[ib.length_dw++] = mmCOMPUTE_PGM_LO - PACKET3_SET_SH_REG_START;
+	ib.ptr[ib.length_dw++] = lower_32_bits(gpu_addr);
+	ib.ptr[ib.length_dw++] = upper_32_bits(gpu_addr);
+
+	/* write dispatch packet */
+	ib.ptr[ib.length_dw++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3);
+	ib.ptr[ib.length_dw++] = 8; /* x */
+	ib.ptr[ib.length_dw++] = 1; /* y */
+	ib.ptr[ib.length_dw++] = 1; /* z */
+	ib.ptr[ib.length_dw++] =
+		REG_SET_FIELD(0, COMPUTE_DISPATCH_INITIATOR, COMPUTE_SHADER_EN, 1);
+
+	/* write CS partial flush packet */
+	ib.ptr[ib.length_dw++] = PACKET3(PACKET3_EVENT_WRITE, 0);
+	ib.ptr[ib.length_dw++] = EVENT_TYPE(7) | EVENT_INDEX(4);
+
+	/* SGPR2 */
+	/* write the register state for the compute dispatch */
+	for (i = 0; i < ARRAY_SIZE(sgpr2_init_regs); i += 2) {
+		ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 1);
+		ib.ptr[ib.length_dw++] = sgpr2_init_regs[i] - PACKET3_SET_SH_REG_START;
+		ib.ptr[ib.length_dw++] = sgpr2_init_regs[i + 1];
+	}
+	/* write the shader start address: mmCOMPUTE_PGM_LO, mmCOMPUTE_PGM_HI */
+	gpu_addr = (ib.gpu_addr + (u64)sgpr_offset) >> 8;
+	ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 2);
+	ib.ptr[ib.length_dw++] = mmCOMPUTE_PGM_LO - PACKET3_SET_SH_REG_START;
+	ib.ptr[ib.length_dw++] = lower_32_bits(gpu_addr);
+	ib.ptr[ib.length_dw++] = upper_32_bits(gpu_addr);
+
+	/* write dispatch packet */
+	ib.ptr[ib.length_dw++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3);
+	ib.ptr[ib.length_dw++] = 8; /* x */
+	ib.ptr[ib.length_dw++] = 1; /* y */
+	ib.ptr[ib.length_dw++] = 1; /* z */
+	ib.ptr[ib.length_dw++] =
+		REG_SET_FIELD(0, COMPUTE_DISPATCH_INITIATOR, COMPUTE_SHADER_EN, 1);
+
+	/* write CS partial flush packet */
+	ib.ptr[ib.length_dw++] = PACKET3(PACKET3_EVENT_WRITE, 0);
+	ib.ptr[ib.length_dw++] = EVENT_TYPE(7) | EVENT_INDEX(4);
+
+	/* shedule the ib on the ring */
+	r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, &ib, 1, NULL,
+						 AMDGPU_FENCE_OWNER_UNDEFINED,
+						 &f);
+	if (r) {
+		DRM_ERROR("amdgpu: ib submit failed (%d).\n", r);
+		goto fail;
+	}
+
+	/* wait for the GPU to finish processing the IB */
+	r = fence_wait(f, false);
+	if (r) {
+		DRM_ERROR("amdgpu: fence wait failed (%d).\n", r);
+		goto fail;
+	}
+
+	tmp = REG_SET_FIELD(tmp, GB_EDC_MODE, DED_MODE, 2);
+	tmp = REG_SET_FIELD(tmp, GB_EDC_MODE, PROP_FED, 1);
+	WREG32(mmGB_EDC_MODE, tmp);
+
+	tmp = RREG32(mmCC_GC_EDC_CONFIG);
+	tmp = REG_SET_FIELD(tmp, CC_GC_EDC_CONFIG, DIS_EDC, 0) | 1;
+	WREG32(mmCC_GC_EDC_CONFIG, tmp);
+
+
+	/* read back registers to clear the counters */
+	for (i = 0; i < ARRAY_SIZE(sec_ded_counter_registers); i++)
+		RREG32(sec_ded_counter_registers[i]);
+
+fail:
+	fence_put(f);
+	amdgpu_ib_free(adev, &ib);
+
+	return r;
+}
+
 static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
 {
 	u32 gb_addr_config;
@@ -1323,1418 +1660,923 @@
 
 static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev)
 {
-	const u32 num_tile_mode_states = 32;
-	const u32 num_secondary_tile_mode_states = 16;
-	u32 reg_offset, gb_tile_moden, split_equal_to_row_size;
+	uint32_t *modearray, *mod2array;
+	const u32 num_tile_mode_states = ARRAY_SIZE(adev->gfx.config.tile_mode_array);
+	const u32 num_secondary_tile_mode_states = ARRAY_SIZE(adev->gfx.config.macrotile_mode_array);
+	u32 reg_offset;
 
-	switch (adev->gfx.config.mem_row_size_in_kb) {
-	case 1:
-		split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_1KB;
-		break;
-	case 2:
-	default:
-		split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_2KB;
-		break;
-	case 4:
-		split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_4KB;
-		break;
-	}
+	modearray = adev->gfx.config.tile_mode_array;
+	mod2array = adev->gfx.config.macrotile_mode_array;
+
+	for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
+		modearray[reg_offset] = 0;
+
+	for (reg_offset = 0; reg_offset <  num_secondary_tile_mode_states; reg_offset++)
+		mod2array[reg_offset] = 0;
 
 	switch (adev->asic_type) {
 	case CHIP_TOPAZ:
-		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
-			switch (reg_offset) {
-			case 0:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 1:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 2:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 3:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 4:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 5:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 6:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 8:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
-						PIPE_CONFIG(ADDR_SURF_P2));
-				break;
-			case 9:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 10:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 11:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 13:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 14:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 15:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 16:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 18:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 19:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 20:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 21:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 22:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 24:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 25:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 26:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 27:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 28:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 29:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 7:
-			case 12:
-			case 17:
-			case 23:
-				/* unused idx */
-				continue;
-			default:
-				gb_tile_moden = 0;
-				break;
-			};
-			adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
-		}
-		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
-			switch (reg_offset) {
-			case 0:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 1:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 2:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 3:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 4:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 5:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 6:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 8:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 9:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 10:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 11:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 12:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 13:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 14:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 7:
-				/* unused idx */
-				continue;
-			default:
-				gb_tile_moden = 0;
-				break;
-			};
-			adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
-		}
+		modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+				PIPE_CONFIG(ADDR_SURF_P2));
+		modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+
+		mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				 NUM_BANKS(ADDR_SURF_8_BANK));
+
+		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
+			if (reg_offset != 7 && reg_offset != 12 && reg_offset != 17 &&
+			    reg_offset != 23)
+				WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]);
+
+		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++)
+			if (reg_offset != 7)
+				WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]);
+
+		break;
 	case CHIP_FIJI:
-		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
-			switch (reg_offset) {
-			case 0:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 1:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 2:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 3:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 4:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 5:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 6:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 7:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 8:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16));
-				break;
-			case 9:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 10:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 11:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 12:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 13:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 14:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 15:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 16:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 17:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 18:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 19:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 20:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 21:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 22:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 23:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 24:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 25:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 26:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 27:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 28:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 29:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 30:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			default:
-				gb_tile_moden = 0;
-				break;
-			}
-			adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
-		}
-		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
-			switch (reg_offset) {
-			case 0:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 1:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 2:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 3:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 4:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 5:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 6:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 8:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 9:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 10:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 11:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 12:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 13:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 14:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_4_BANK));
-				break;
-			case 7:
-				/* unused idx */
-				continue;
-			default:
-				gb_tile_moden = 0;
-				break;
-			}
-			adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
-		}
+		modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[7] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+				PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16));
+		modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[12] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[17] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[23] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[30] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+
+		mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				 NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				 NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				 NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				 NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				 NUM_BANKS(ADDR_SURF_4_BANK));
+
+		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
+			WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]);
+
+		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++)
+			if (reg_offset != 7)
+				WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]);
+
 		break;
 	case CHIP_TONGA:
-		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
-			switch (reg_offset) {
-			case 0:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 1:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 2:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 3:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 4:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 5:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 6:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 7:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 8:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16));
-				break;
-			case 9:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 10:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 11:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 12:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 13:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 14:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 15:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 16:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 17:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 18:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 19:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 20:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 21:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 22:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 23:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 24:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 25:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 26:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 27:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 28:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 29:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 30:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P4_16x16) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			default:
-				gb_tile_moden = 0;
-				break;
-			};
-			adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
-		}
-		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
-			switch (reg_offset) {
-			case 0:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 1:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 2:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 3:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 4:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 5:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 6:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 8:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 9:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 10:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 11:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 12:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 13:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_4_BANK));
-				break;
-			case 14:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
-						NUM_BANKS(ADDR_SURF_4_BANK));
-				break;
-			case 7:
-				/* unused idx */
-				continue;
-			default:
-				gb_tile_moden = 0;
-				break;
-			};
-			adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
-		}
+		modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[7] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16));
+		modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[12] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[17] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[23] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[30] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+
+		mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				 NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				 NUM_BANKS(ADDR_SURF_4_BANK));
+		mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				 NUM_BANKS(ADDR_SURF_4_BANK));
+
+		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
+			WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]);
+
+		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++)
+			if (reg_offset != 7)
+				WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]);
+
 		break;
 	case CHIP_STONEY:
-		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
-			switch (reg_offset) {
-			case 0:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 1:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 2:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 3:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 4:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 5:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 6:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 8:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
-						PIPE_CONFIG(ADDR_SURF_P2));
-				break;
-			case 9:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 10:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 11:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 13:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 14:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 15:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 16:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 18:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 19:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 20:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 21:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 22:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 24:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 25:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 26:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 27:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 28:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 29:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 7:
-			case 12:
-			case 17:
-			case 23:
-				/* unused idx */
-				continue;
-			default:
-				gb_tile_moden = 0;
-				break;
-			};
-			adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
-		}
-		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
-			switch (reg_offset) {
-			case 0:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 1:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 2:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 3:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 4:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 5:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 6:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 8:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 9:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 10:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 11:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 12:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 13:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 14:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 7:
-				/* unused idx */
-				continue;
-			default:
-				gb_tile_moden = 0;
-				break;
-			};
-			adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
-		}
+		modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+				PIPE_CONFIG(ADDR_SURF_P2));
+		modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+
+		mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				 NUM_BANKS(ADDR_SURF_8_BANK));
+
+		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
+			if (reg_offset != 7 && reg_offset != 12 && reg_offset != 17 &&
+			    reg_offset != 23)
+				WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]);
+
+		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++)
+			if (reg_offset != 7)
+				WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]);
+
 		break;
-	case CHIP_CARRIZO:
 	default:
-		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
-			switch (reg_offset) {
-			case 0:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 1:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 2:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 3:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 4:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 5:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 6:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
-				break;
-			case 8:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
-						PIPE_CONFIG(ADDR_SURF_P2));
-				break;
-			case 9:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 10:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 11:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 13:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 14:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 15:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 16:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 18:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 19:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 20:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 21:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 22:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 24:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 25:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 26:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
-				break;
-			case 27:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 28:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
-				break;
-			case 29:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
-						PIPE_CONFIG(ADDR_SURF_P2) |
-						MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
-						SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
-				break;
-			case 7:
-			case 12:
-			case 17:
-			case 23:
-				/* unused idx */
-				continue;
-			default:
-				gb_tile_moden = 0;
-				break;
-			};
-			adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
-		}
-		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
-			switch (reg_offset) {
-			case 0:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 1:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 2:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 3:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 4:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 5:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 6:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 8:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 9:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 10:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 11:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 12:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 13:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
-						NUM_BANKS(ADDR_SURF_16_BANK));
-				break;
-			case 14:
-				gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
-						NUM_BANKS(ADDR_SURF_8_BANK));
-				break;
-			case 7:
-				/* unused idx */
-				continue;
-			default:
-				gb_tile_moden = 0;
-				break;
-			};
-			adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
-		}
+		dev_warn(adev->dev,
+			 "Unknown chip type (%d) in function gfx_v8_0_tiling_mode_table_init() falling through to CHIP_CARRIZO\n",
+			 adev->asic_type);
+
+	case CHIP_CARRIZO:
+		modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+				PIPE_CONFIG(ADDR_SURF_P2));
+		modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P2) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				 PIPE_CONFIG(ADDR_SURF_P2) |
+				 MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				 SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+
+		mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+		mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				 NUM_BANKS(ADDR_SURF_16_BANK));
+		mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				 NUM_BANKS(ADDR_SURF_8_BANK));
+
+		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
+			if (reg_offset != 7 && reg_offset != 12 && reg_offset != 17 &&
+			    reg_offset != 23)
+				WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]);
+
+		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++)
+			if (reg_offset != 7)
+				WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]);
+
+		break;
 	}
 }
 
 static u32 gfx_v8_0_create_bitmask(u32 bit_width)
 {
-	u32 i, mask = 0;
-
-	for (i = 0; i < bit_width; i++) {
-		mask <<= 1;
-		mask |= 1;
-	}
-	return mask;
+	return (u32)((1ULL << bit_width) - 1);
 }
 
 void gfx_v8_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num)
@@ -2809,7 +2651,7 @@
 	mutex_lock(&adev->grbm_idx_mutex);
 	for (i = 0; i < se_num; i++) {
 		gfx_v8_0_select_se_sh(adev, i, 0xffffffff);
-		data = 0;
+		data = RREG32(mmPA_SC_RASTER_CONFIG);
 		for (j = 0; j < sh_per_se; j++) {
 			switch (enabled_rbs & 3) {
 			case 0:
@@ -2997,17 +2839,11 @@
 {
 	u32 tmp = RREG32(mmCP_INT_CNTL_RING0);
 
-	if (enable) {
-		tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE, 1);
-		tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE, 1);
-		tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, 1);
-		tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, 1);
-	} else {
-		tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE, 0);
-		tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE, 0);
-		tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, 0);
-		tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, 0);
-	}
+	tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE, enable ? 1 : 0);
+	tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE, enable ? 1 : 0);
+	tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, enable ? 1 : 0);
+	tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, enable ? 1 : 0);
+
 	WREG32(mmCP_INT_CNTL_RING0, tmp);
 }
 
@@ -3087,16 +2923,18 @@
 
 	gfx_v8_0_rlc_reset(adev);
 
-	if (!adev->firmware.smu_load) {
-		/* legacy rlc firmware loading */
-		r = gfx_v8_0_rlc_load_microcode(adev);
-		if (r)
-			return r;
-	} else {
-		r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
-						AMDGPU_UCODE_ID_RLC_G);
-		if (r)
-			return -EINVAL;
+	if (!adev->pp_enabled) {
+		if (!adev->firmware.smu_load) {
+			/* legacy rlc firmware loading */
+			r = gfx_v8_0_rlc_load_microcode(adev);
+			if (r)
+				return r;
+		} else {
+			r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
+							AMDGPU_UCODE_ID_RLC_G);
+			if (r)
+				return -EINVAL;
+		}
 	}
 
 	gfx_v8_0_rlc_start(adev);
@@ -3941,6 +3779,11 @@
 		tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53);
 		WREG32(mmCP_HQD_PERSISTENT_STATE, tmp);
 		mqd->cp_hqd_persistent_state = tmp;
+		if (adev->asic_type == CHIP_STONEY) {
+			tmp = RREG32(mmCP_ME1_PIPE3_INT_CNTL);
+			tmp = REG_SET_FIELD(tmp, CP_ME1_PIPE3_INT_CNTL, GENERIC2_INT_ENABLE, 1);
+			WREG32(mmCP_ME1_PIPE3_INT_CNTL, tmp);
+		}
 
 		/* activate the queue */
 		mqd->cp_hqd_active = 1;
@@ -3982,35 +3825,37 @@
 	if (!(adev->flags & AMD_IS_APU))
 		gfx_v8_0_enable_gui_idle_interrupt(adev, false);
 
-	if (!adev->firmware.smu_load) {
-		/* legacy firmware loading */
-		r = gfx_v8_0_cp_gfx_load_microcode(adev);
-		if (r)
-			return r;
+	if (!adev->pp_enabled) {
+		if (!adev->firmware.smu_load) {
+			/* legacy firmware loading */
+			r = gfx_v8_0_cp_gfx_load_microcode(adev);
+			if (r)
+				return r;
 
-		r = gfx_v8_0_cp_compute_load_microcode(adev);
-		if (r)
-			return r;
-	} else {
-		r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
-						AMDGPU_UCODE_ID_CP_CE);
-		if (r)
-			return -EINVAL;
+			r = gfx_v8_0_cp_compute_load_microcode(adev);
+			if (r)
+				return r;
+		} else {
+			r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
+							AMDGPU_UCODE_ID_CP_CE);
+			if (r)
+				return -EINVAL;
 
-		r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
-						AMDGPU_UCODE_ID_CP_PFP);
-		if (r)
-			return -EINVAL;
+			r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
+							AMDGPU_UCODE_ID_CP_PFP);
+			if (r)
+				return -EINVAL;
 
-		r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
-						AMDGPU_UCODE_ID_CP_ME);
-		if (r)
-			return -EINVAL;
+			r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
+							AMDGPU_UCODE_ID_CP_ME);
+			if (r)
+				return -EINVAL;
 
-		r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
-						AMDGPU_UCODE_ID_CP_MEC1);
-		if (r)
-			return -EINVAL;
+			r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
+							AMDGPU_UCODE_ID_CP_MEC1);
+			if (r)
+				return -EINVAL;
+		}
 	}
 
 	r = gfx_v8_0_cp_gfx_resume(adev);
@@ -4458,15 +4303,261 @@
 	return 0;
 }
 
+static int gfx_v8_0_late_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int r;
+
+	/* requires IBs so do in late init after IB pool is initialized */
+	r = gfx_v8_0_do_edc_gpr_workarounds(adev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
 static int gfx_v8_0_set_powergating_state(void *handle,
 					  enum amd_powergating_state state)
 {
 	return 0;
 }
 
+static void fiji_send_serdes_cmd(struct amdgpu_device *adev,
+		uint32_t reg_addr, uint32_t cmd)
+{
+	uint32_t data;
+
+	gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff);
+
+	WREG32(mmRLC_SERDES_WR_CU_MASTER_MASK, 0xffffffff);
+	WREG32(mmRLC_SERDES_WR_NONCU_MASTER_MASK, 0xffffffff);
+
+	data = RREG32(mmRLC_SERDES_WR_CTRL);
+	data &= ~(RLC_SERDES_WR_CTRL__WRITE_COMMAND_MASK |
+			RLC_SERDES_WR_CTRL__READ_COMMAND_MASK |
+			RLC_SERDES_WR_CTRL__P1_SELECT_MASK |
+			RLC_SERDES_WR_CTRL__P2_SELECT_MASK |
+			RLC_SERDES_WR_CTRL__RDDATA_RESET_MASK |
+			RLC_SERDES_WR_CTRL__POWER_DOWN_MASK |
+			RLC_SERDES_WR_CTRL__POWER_UP_MASK |
+			RLC_SERDES_WR_CTRL__SHORT_FORMAT_MASK |
+			RLC_SERDES_WR_CTRL__BPM_DATA_MASK |
+			RLC_SERDES_WR_CTRL__REG_ADDR_MASK |
+			RLC_SERDES_WR_CTRL__SRBM_OVERRIDE_MASK);
+	data |= (RLC_SERDES_WR_CTRL__RSVD_BPM_ADDR_MASK |
+			(cmd << RLC_SERDES_WR_CTRL__BPM_DATA__SHIFT) |
+			(reg_addr << RLC_SERDES_WR_CTRL__REG_ADDR__SHIFT) |
+			(0xff << RLC_SERDES_WR_CTRL__BPM_ADDR__SHIFT));
+
+	WREG32(mmRLC_SERDES_WR_CTRL, data);
+}
+
+static void fiji_update_medium_grain_clock_gating(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t temp, data;
+
+	/* It is disabled by HW by default */
+	if (enable) {
+		/* 1 - RLC memory Light sleep */
+		temp = data = RREG32(mmRLC_MEM_SLP_CNTL);
+		data |= RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK;
+		if (temp != data)
+			WREG32(mmRLC_MEM_SLP_CNTL, data);
+
+		/* 2 - CP memory Light sleep */
+		temp = data = RREG32(mmCP_MEM_SLP_CNTL);
+		data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
+		if (temp != data)
+			WREG32(mmCP_MEM_SLP_CNTL, data);
+
+		/* 3 - RLC_CGTT_MGCG_OVERRIDE */
+		temp = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
+		data &= ~(RLC_CGTT_MGCG_OVERRIDE__CPF_MASK |
+				RLC_CGTT_MGCG_OVERRIDE__RLC_MASK |
+				RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK |
+				RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK);
+
+		if (temp != data)
+			WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data);
+
+		/* 4 - wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
+		gfx_v8_0_wait_for_rlc_serdes(adev);
+
+		/* 5 - clear mgcg override */
+		fiji_send_serdes_cmd(adev, BPM_REG_MGCG_OVERRIDE, CLE_BPM_SERDES_CMD);
+
+		/* 6 - Enable CGTS(Tree Shade) MGCG /MGLS */
+		temp = data = RREG32(mmCGTS_SM_CTRL_REG);
+		data &= ~(CGTS_SM_CTRL_REG__SM_MODE_MASK);
+		data |= (0x2 << CGTS_SM_CTRL_REG__SM_MODE__SHIFT);
+		data |= CGTS_SM_CTRL_REG__SM_MODE_ENABLE_MASK;
+		data &= ~CGTS_SM_CTRL_REG__OVERRIDE_MASK;
+		data &= ~CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK;
+		data |= CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN_MASK;
+		data |= (0x96 << CGTS_SM_CTRL_REG__ON_MONITOR_ADD__SHIFT);
+		if (temp != data)
+			WREG32(mmCGTS_SM_CTRL_REG, data);
+		udelay(50);
+
+		/* 7 - wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
+		gfx_v8_0_wait_for_rlc_serdes(adev);
+	} else {
+		/* 1 - MGCG_OVERRIDE[0] for CP and MGCG_OVERRIDE[1] for RLC */
+		temp = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
+		data |= (RLC_CGTT_MGCG_OVERRIDE__CPF_MASK |
+				RLC_CGTT_MGCG_OVERRIDE__RLC_MASK |
+				RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK |
+				RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK);
+		if (temp != data)
+			WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data);
+
+		/* 2 - disable MGLS in RLC */
+		data = RREG32(mmRLC_MEM_SLP_CNTL);
+		if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK) {
+			data &= ~RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK;
+			WREG32(mmRLC_MEM_SLP_CNTL, data);
+		}
+
+		/* 3 - disable MGLS in CP */
+		data = RREG32(mmCP_MEM_SLP_CNTL);
+		if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK) {
+			data &= ~CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
+			WREG32(mmCP_MEM_SLP_CNTL, data);
+		}
+
+		/* 4 - Disable CGTS(Tree Shade) MGCG and MGLS */
+		temp = data = RREG32(mmCGTS_SM_CTRL_REG);
+		data |= (CGTS_SM_CTRL_REG__OVERRIDE_MASK |
+				CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK);
+		if (temp != data)
+			WREG32(mmCGTS_SM_CTRL_REG, data);
+
+		/* 5 - wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
+		gfx_v8_0_wait_for_rlc_serdes(adev);
+
+		/* 6 - set mgcg override */
+		fiji_send_serdes_cmd(adev, BPM_REG_MGCG_OVERRIDE, SET_BPM_SERDES_CMD);
+
+		udelay(50);
+
+		/* 7- wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
+		gfx_v8_0_wait_for_rlc_serdes(adev);
+	}
+}
+
+static void fiji_update_coarse_grain_clock_gating(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t temp, temp1, data, data1;
+
+	temp = data = RREG32(mmRLC_CGCG_CGLS_CTRL);
+
+	if (enable) {
+		/* 1 enable cntx_empty_int_enable/cntx_busy_int_enable/
+		 * Cmp_busy/GFX_Idle interrupts
+		 */
+		gfx_v8_0_enable_gui_idle_interrupt(adev, true);
+
+		temp1 = data1 =	RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
+		data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK;
+		if (temp1 != data1)
+			WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1);
+
+		/* 2 wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
+		gfx_v8_0_wait_for_rlc_serdes(adev);
+
+		/* 3 - clear cgcg override */
+		fiji_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, CLE_BPM_SERDES_CMD);
+
+		/* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
+		gfx_v8_0_wait_for_rlc_serdes(adev);
+
+		/* 4 - write cmd to set CGLS */
+		fiji_send_serdes_cmd(adev, BPM_REG_CGLS_EN, SET_BPM_SERDES_CMD);
+
+		/* 5 - enable cgcg */
+		data |= RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
+
+		/* enable cgls*/
+		data |= RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
+
+		temp1 = data1 =	RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
+		data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK;
+
+		if (temp1 != data1)
+			WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1);
+
+		if (temp != data)
+			WREG32(mmRLC_CGCG_CGLS_CTRL, data);
+	} else {
+		/* disable cntx_empty_int_enable & GFX Idle interrupt */
+		gfx_v8_0_enable_gui_idle_interrupt(adev, false);
+
+		/* TEST CGCG */
+		temp1 = data1 =	RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
+		data1 |= (RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK |
+				RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK);
+		if (temp1 != data1)
+			WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1);
+
+		/* read gfx register to wake up cgcg */
+		RREG32(mmCB_CGTT_SCLK_CTRL);
+		RREG32(mmCB_CGTT_SCLK_CTRL);
+		RREG32(mmCB_CGTT_SCLK_CTRL);
+		RREG32(mmCB_CGTT_SCLK_CTRL);
+
+		/* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
+		gfx_v8_0_wait_for_rlc_serdes(adev);
+
+		/* write cmd to Set CGCG Overrride */
+		fiji_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, SET_BPM_SERDES_CMD);
+
+		/* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
+		gfx_v8_0_wait_for_rlc_serdes(adev);
+
+		/* write cmd to Clear CGLS */
+		fiji_send_serdes_cmd(adev, BPM_REG_CGLS_EN, CLE_BPM_SERDES_CMD);
+
+		/* disable cgcg, cgls should be disabled too. */
+		data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK |
+				RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
+		if (temp != data)
+			WREG32(mmRLC_CGCG_CGLS_CTRL, data);
+	}
+}
+static int fiji_update_gfx_clock_gating(struct amdgpu_device *adev,
+		bool enable)
+{
+	if (enable) {
+		/* CGCG/CGLS should be enabled after MGCG/MGLS/TS(CG/LS)
+		 * ===  MGCG + MGLS + TS(CG/LS) ===
+		 */
+		fiji_update_medium_grain_clock_gating(adev, enable);
+		fiji_update_coarse_grain_clock_gating(adev, enable);
+	} else {
+		/* CGCG/CGLS should be disabled before MGCG/MGLS/TS(CG/LS)
+		 * ===  CGCG + CGLS ===
+		 */
+		fiji_update_coarse_grain_clock_gating(adev, enable);
+		fiji_update_medium_grain_clock_gating(adev, enable);
+	}
+	return 0;
+}
+
 static int gfx_v8_0_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	switch (adev->asic_type) {
+	case CHIP_FIJI:
+		fiji_update_gfx_clock_gating(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		break;
+	default:
+		break;
+	}
 	return 0;
 }
 
@@ -4627,7 +4718,7 @@
 				 EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
 				 EVENT_INDEX(5)));
 	amdgpu_ring_write(ring, addr & 0xfffffffc);
-	amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) | 
+	amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) |
 			  DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
 	amdgpu_ring_write(ring, upper_32_bits(seq));
@@ -4995,7 +5086,7 @@
 
 const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
 	.early_init = gfx_v8_0_early_init,
-	.late_init = NULL,
+	.late_init = gfx_v8_0_late_init,
 	.sw_init = gfx_v8_0_sw_init,
 	.sw_fini = gfx_v8_0_sw_fini,
 	.hw_init = gfx_v8_0_hw_init,
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index ed8abb5..3f95606 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -370,6 +370,10 @@
 	adev->mc.real_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL;
 	adev->mc.visible_vram_size = adev->mc.aper_size;
 
+	/* In case the PCI BAR is larger than the actual amount of vram */
+	if (adev->mc.visible_vram_size > adev->mc.real_vram_size)
+		adev->mc.visible_vram_size = adev->mc.real_vram_size;
+
 	/* unless the user had overridden it, set the gart
 	 * size equal to the 1024 or vram, whichever is larger.
 	 */
@@ -1012,7 +1016,6 @@
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
 	if (adev->vm_manager.enabled) {
-		amdgpu_vm_manager_fini(adev);
 		gmc_v7_0_vm_fini(adev);
 		adev->vm_manager.enabled = false;
 	}
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index d390284..c0c9a01 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -476,6 +476,10 @@
 	adev->mc.real_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL;
 	adev->mc.visible_vram_size = adev->mc.aper_size;
 
+	/* In case the PCI BAR is larger than the actual amount of vram */
+	if (adev->mc.visible_vram_size > adev->mc.real_vram_size)
+		adev->mc.visible_vram_size = adev->mc.real_vram_size;
+
 	/* unless the user had overridden it, set the gart
 	 * size equal to the 1024 or vram, whichever is larger.
 	 */
@@ -1033,7 +1037,6 @@
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
 	if (adev->vm_manager.enabled) {
-		amdgpu_vm_manager_fini(adev);
 		gmc_v8_0_vm_fini(adev);
 		adev->vm_manager.enabled = false;
 	}
@@ -1324,9 +1327,181 @@
 	return 0;
 }
 
+static void fiji_update_mc_medium_grain_clock_gating(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t data;
+
+	if (enable) {
+		data = RREG32(mmMC_HUB_MISC_HUB_CG);
+		data |= MC_HUB_MISC_HUB_CG__ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_HUB_CG, data);
+
+		data = RREG32(mmMC_HUB_MISC_SIP_CG);
+		data |= MC_HUB_MISC_SIP_CG__ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_SIP_CG, data);
+
+		data = RREG32(mmMC_HUB_MISC_VM_CG);
+		data |= MC_HUB_MISC_VM_CG__ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_VM_CG, data);
+
+		data = RREG32(mmMC_XPB_CLK_GAT);
+		data |= MC_XPB_CLK_GAT__ENABLE_MASK;
+		WREG32(mmMC_XPB_CLK_GAT, data);
+
+		data = RREG32(mmATC_MISC_CG);
+		data |= ATC_MISC_CG__ENABLE_MASK;
+		WREG32(mmATC_MISC_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_WR_CG);
+		data |= MC_CITF_MISC_WR_CG__ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_WR_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_RD_CG);
+		data |= MC_CITF_MISC_RD_CG__ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_RD_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_VM_CG);
+		data |= MC_CITF_MISC_VM_CG__ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_VM_CG, data);
+
+		data = RREG32(mmVM_L2_CG);
+		data |= VM_L2_CG__ENABLE_MASK;
+		WREG32(mmVM_L2_CG, data);
+	} else {
+		data = RREG32(mmMC_HUB_MISC_HUB_CG);
+		data &= ~MC_HUB_MISC_HUB_CG__ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_HUB_CG, data);
+
+		data = RREG32(mmMC_HUB_MISC_SIP_CG);
+		data &= ~MC_HUB_MISC_SIP_CG__ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_SIP_CG, data);
+
+		data = RREG32(mmMC_HUB_MISC_VM_CG);
+		data &= ~MC_HUB_MISC_VM_CG__ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_VM_CG, data);
+
+		data = RREG32(mmMC_XPB_CLK_GAT);
+		data &= ~MC_XPB_CLK_GAT__ENABLE_MASK;
+		WREG32(mmMC_XPB_CLK_GAT, data);
+
+		data = RREG32(mmATC_MISC_CG);
+		data &= ~ATC_MISC_CG__ENABLE_MASK;
+		WREG32(mmATC_MISC_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_WR_CG);
+		data &= ~MC_CITF_MISC_WR_CG__ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_WR_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_RD_CG);
+		data &= ~MC_CITF_MISC_RD_CG__ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_RD_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_VM_CG);
+		data &= ~MC_CITF_MISC_VM_CG__ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_VM_CG, data);
+
+		data = RREG32(mmVM_L2_CG);
+		data &= ~VM_L2_CG__ENABLE_MASK;
+		WREG32(mmVM_L2_CG, data);
+	}
+}
+
+static void fiji_update_mc_light_sleep(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t data;
+
+	if (enable) {
+		data = RREG32(mmMC_HUB_MISC_HUB_CG);
+		data |= MC_HUB_MISC_HUB_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_HUB_CG, data);
+
+		data = RREG32(mmMC_HUB_MISC_SIP_CG);
+		data |= MC_HUB_MISC_SIP_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_SIP_CG, data);
+
+		data = RREG32(mmMC_HUB_MISC_VM_CG);
+		data |= MC_HUB_MISC_VM_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_VM_CG, data);
+
+		data = RREG32(mmMC_XPB_CLK_GAT);
+		data |= MC_XPB_CLK_GAT__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_XPB_CLK_GAT, data);
+
+		data = RREG32(mmATC_MISC_CG);
+		data |= ATC_MISC_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmATC_MISC_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_WR_CG);
+		data |= MC_CITF_MISC_WR_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_WR_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_RD_CG);
+		data |= MC_CITF_MISC_RD_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_RD_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_VM_CG);
+		data |= MC_CITF_MISC_VM_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_VM_CG, data);
+
+		data = RREG32(mmVM_L2_CG);
+		data |= VM_L2_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmVM_L2_CG, data);
+	} else {
+		data = RREG32(mmMC_HUB_MISC_HUB_CG);
+		data &= ~MC_HUB_MISC_HUB_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_HUB_CG, data);
+
+		data = RREG32(mmMC_HUB_MISC_SIP_CG);
+		data &= ~MC_HUB_MISC_SIP_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_SIP_CG, data);
+
+		data = RREG32(mmMC_HUB_MISC_VM_CG);
+		data &= ~MC_HUB_MISC_VM_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_HUB_MISC_VM_CG, data);
+
+		data = RREG32(mmMC_XPB_CLK_GAT);
+		data &= ~MC_XPB_CLK_GAT__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_XPB_CLK_GAT, data);
+
+		data = RREG32(mmATC_MISC_CG);
+		data &= ~ATC_MISC_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmATC_MISC_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_WR_CG);
+		data &= ~MC_CITF_MISC_WR_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_WR_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_RD_CG);
+		data &= ~MC_CITF_MISC_RD_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_RD_CG, data);
+
+		data = RREG32(mmMC_CITF_MISC_VM_CG);
+		data &= ~MC_CITF_MISC_VM_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmMC_CITF_MISC_VM_CG, data);
+
+		data = RREG32(mmVM_L2_CG);
+		data &= ~VM_L2_CG__MEM_LS_ENABLE_MASK;
+		WREG32(mmVM_L2_CG, data);
+	}
+}
+
 static int gmc_v8_0_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	switch (adev->asic_type) {
+	case CHIP_FIJI:
+		fiji_update_mc_medium_grain_clock_gating(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		fiji_update_mc_light_sleep(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		break;
+	default:
+		break;
+	}
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
index 779532d..679e739 100644
--- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
@@ -253,8 +253,14 @@
 static int iceland_ih_early_init(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int ret;
+
+	ret = amdgpu_irq_add_domain(adev);
+	if (ret)
+		return ret;
 
 	iceland_ih_set_interrupt_funcs(adev);
+
 	return 0;
 }
 
@@ -278,6 +284,7 @@
 
 	amdgpu_irq_fini(adev);
 	amdgpu_ih_ring_fini(adev);
+	amdgpu_irq_remove_domain(adev);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 7253132..ad54c46 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -727,18 +727,20 @@
 {
 	int r, i;
 
-	if (!adev->firmware.smu_load) {
-		r = sdma_v3_0_load_microcode(adev);
-		if (r)
-			return r;
-	} else {
-		for (i = 0; i < adev->sdma.num_instances; i++) {
-			r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
-									 (i == 0) ?
-									 AMDGPU_UCODE_ID_SDMA0 :
-									 AMDGPU_UCODE_ID_SDMA1);
+	if (!adev->pp_enabled) {
+		if (!adev->firmware.smu_load) {
+			r = sdma_v3_0_load_microcode(adev);
 			if (r)
-				return -EINVAL;
+				return r;
+		} else {
+			for (i = 0; i < adev->sdma.num_instances; i++) {
+				r = adev->smu.smumgr_funcs->check_fw_load_finish(adev,
+										 (i == 0) ?
+										 AMDGPU_UCODE_ID_SDMA0 :
+										 AMDGPU_UCODE_ID_SDMA1);
+				if (r)
+					return -EINVAL;
+			}
 		}
 	}
 
@@ -1427,9 +1429,114 @@
 	return 0;
 }
 
+static void fiji_update_sdma_medium_grain_clock_gating(
+		struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t temp, data;
+
+	if (enable) {
+		temp = data = RREG32(mmSDMA0_CLK_CTRL);
+		data &= ~(SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
+		if (data != temp)
+			WREG32(mmSDMA0_CLK_CTRL, data);
+
+		temp = data = RREG32(mmSDMA1_CLK_CTRL);
+		data &= ~(SDMA1_CLK_CTRL__SOFT_OVERRIDE7_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE6_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE5_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE4_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE3_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE2_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE1_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE0_MASK);
+
+		if (data != temp)
+			WREG32(mmSDMA1_CLK_CTRL, data);
+	} else {
+		temp = data = RREG32(mmSDMA0_CLK_CTRL);
+		data |= SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
+				SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK;
+
+		if (data != temp)
+			WREG32(mmSDMA0_CLK_CTRL, data);
+
+		temp = data = RREG32(mmSDMA1_CLK_CTRL);
+		data |= SDMA1_CLK_CTRL__SOFT_OVERRIDE7_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE6_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE5_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE4_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE3_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE2_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE1_MASK |
+				SDMA1_CLK_CTRL__SOFT_OVERRIDE0_MASK;
+
+		if (data != temp)
+			WREG32(mmSDMA1_CLK_CTRL, data);
+	}
+}
+
+static void fiji_update_sdma_medium_grain_light_sleep(
+		struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t temp, data;
+
+	if (enable) {
+		temp = data = RREG32(mmSDMA0_POWER_CNTL);
+		data |= SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+
+		if (temp != data)
+			WREG32(mmSDMA0_POWER_CNTL, data);
+
+		temp = data = RREG32(mmSDMA1_POWER_CNTL);
+		data |= SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+
+		if (temp != data)
+			WREG32(mmSDMA1_POWER_CNTL, data);
+	} else {
+		temp = data = RREG32(mmSDMA0_POWER_CNTL);
+		data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+
+		if (temp != data)
+			WREG32(mmSDMA0_POWER_CNTL, data);
+
+		temp = data = RREG32(mmSDMA1_POWER_CNTL);
+		data &= ~SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+
+		if (temp != data)
+			WREG32(mmSDMA1_POWER_CNTL, data);
+	}
+}
+
 static int sdma_v3_0_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	switch (adev->asic_type) {
+	case CHIP_FIJI:
+		fiji_update_sdma_medium_grain_clock_gating(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		fiji_update_sdma_medium_grain_light_sleep(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		break;
+	default:
+		break;
+	}
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c b/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c
index 2049038..f4a1346 100644
--- a/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c
@@ -24,7 +24,7 @@
 #include <linux/firmware.h>
 #include "drmP.h"
 #include "amdgpu.h"
-#include "tonga_smumgr.h"
+#include "tonga_smum.h"
 
 MODULE_FIRMWARE("amdgpu/tonga_smc.bin");
 
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
index 743c372..b6f7d7b 100644
--- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
@@ -273,8 +273,14 @@
 static int tonga_ih_early_init(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int ret;
+
+	ret = amdgpu_irq_add_domain(adev);
+	if (ret)
+		return ret;
 
 	tonga_ih_set_interrupt_funcs(adev);
+
 	return 0;
 }
 
@@ -301,6 +307,7 @@
 
 	amdgpu_irq_fini(adev);
 	amdgpu_ih_ring_fini(adev);
+	amdgpu_irq_add_domain(adev);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ppsmc.h b/drivers/gpu/drm/amd/amdgpu/tonga_ppsmc.h
deleted file mode 100644
index 811781f..0000000
--- a/drivers/gpu/drm/amd/amdgpu/tonga_ppsmc.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright 2014 Advanced Micro Devices, 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.
- *
- */
-
-#ifndef TONGA_PP_SMC_H
-#define TONGA_PP_SMC_H
-
-#pragma pack(push, 1)
-
-#define PPSMC_SWSTATE_FLAG_DC                           0x01
-#define PPSMC_SWSTATE_FLAG_UVD                          0x02
-#define PPSMC_SWSTATE_FLAG_VCE                          0x04
-#define PPSMC_SWSTATE_FLAG_PCIE_X1                      0x08
-
-#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL             0x00
-#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL             0x01
-#define PPSMC_THERMAL_PROTECT_TYPE_NONE                 0xff 
-
-#define PPSMC_SYSTEMFLAG_GPIO_DC                        0x01 
-#define PPSMC_SYSTEMFLAG_STEPVDDC                       0x02 
-#define PPSMC_SYSTEMFLAG_GDDR5                          0x04 
-
-#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP               0x08 
-
-#define PPSMC_SYSTEMFLAG_REGULATOR_HOT                  0x10 
-#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG           0x20 
-#define PPSMC_SYSTEMFLAG_12CHANNEL                      0x40
-
-#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK              0x07
-#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK     0x08
-
-#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE   0x00
-#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE  0x01
-
-#define PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH      0x10
-#define PPSMC_EXTRAFLAGS_DRIVER_TO_GPIO17               0x20
-#define PPSMC_EXTRAFLAGS_PCC_TO_GPIO17                  0x40
-
-#define PPSMC_DPM2FLAGS_TDPCLMP                         0x01 
-#define PPSMC_DPM2FLAGS_PWRSHFT                         0x02 
-#define PPSMC_DPM2FLAGS_OCP                             0x04 
-
-#define PPSMC_DISPLAY_WATERMARK_LOW                     0
-#define PPSMC_DISPLAY_WATERMARK_HIGH                    1
-
-#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP    		0x01
-#define PPSMC_STATEFLAG_POWERBOOST         		0x02
-#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 		0x04
-#define PPSMC_STATEFLAG_POWERSHIFT         		0x08
-#define PPSMC_STATEFLAG_SLOW_READ_MARGIN   		0x10
-#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 		0x20
-#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS   		0x40
-
-#define FDO_MODE_HARDWARE 0
-#define FDO_MODE_PIECE_WISE_LINEAR 1
-
-enum FAN_CONTROL {
-	FAN_CONTROL_FUZZY,
-	FAN_CONTROL_TABLE
-};
-
-#define PPSMC_Result_OK             			((uint16_t)0x01)
-#define PPSMC_Result_NoMore         			((uint16_t)0x02)
-#define PPSMC_Result_NotNow         			((uint16_t)0x03)
-#define PPSMC_Result_Failed         			((uint16_t)0xFF) 
-#define PPSMC_Result_UnknownCmd     			((uint16_t)0xFE) 
-#define PPSMC_Result_UnknownVT      			((uint16_t)0xFD) 
-
-typedef uint16_t PPSMC_Result;
-
-#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x))
-
-#define PPSMC_MSG_Halt                      		((uint16_t)0x10)
-#define PPSMC_MSG_Resume                    		((uint16_t)0x11)
-#define PPSMC_MSG_EnableDPMLevel            		((uint16_t)0x12)
-#define PPSMC_MSG_ZeroLevelsDisabled        		((uint16_t)0x13)
-#define PPSMC_MSG_OneLevelsDisabled         		((uint16_t)0x14)
-#define PPSMC_MSG_TwoLevelsDisabled         		((uint16_t)0x15)
-#define PPSMC_MSG_EnableThermalInterrupt    		((uint16_t)0x16)
-#define PPSMC_MSG_RunningOnAC               		((uint16_t)0x17)
-#define PPSMC_MSG_LevelUp                   		((uint16_t)0x18)
-#define PPSMC_MSG_LevelDown                 		((uint16_t)0x19)
-#define PPSMC_MSG_ResetDPMCounters          		((uint16_t)0x1a)
-#define PPSMC_MSG_SwitchToSwState           		((uint16_t)0x20)
-#define PPSMC_MSG_SwitchToSwStateLast       		((uint16_t)0x3f)
-#define PPSMC_MSG_SwitchToInitialState      		((uint16_t)0x40)
-#define PPSMC_MSG_NoForcedLevel             		((uint16_t)0x41)
-#define PPSMC_MSG_ForceHigh                 		((uint16_t)0x42)
-#define PPSMC_MSG_ForceMediumOrHigh         		((uint16_t)0x43)
-#define PPSMC_MSG_SwitchToMinimumPower      		((uint16_t)0x51)
-#define PPSMC_MSG_ResumeFromMinimumPower    		((uint16_t)0x52)
-#define PPSMC_MSG_EnableCac                 		((uint16_t)0x53)
-#define PPSMC_MSG_DisableCac                		((uint16_t)0x54)
-#define PPSMC_DPMStateHistoryStart          		((uint16_t)0x55)
-#define PPSMC_DPMStateHistoryStop           		((uint16_t)0x56)
-#define PPSMC_CACHistoryStart               		((uint16_t)0x57)
-#define PPSMC_CACHistoryStop                		((uint16_t)0x58)
-#define PPSMC_TDPClampingActive             		((uint16_t)0x59)
-#define PPSMC_TDPClampingInactive           		((uint16_t)0x5A)
-#define PPSMC_StartFanControl               		((uint16_t)0x5B)
-#define PPSMC_StopFanControl                		((uint16_t)0x5C)
-#define PPSMC_NoDisplay                     		((uint16_t)0x5D)
-#define PPSMC_HasDisplay                    		((uint16_t)0x5E)
-#define PPSMC_MSG_UVDPowerOFF               		((uint16_t)0x60)
-#define PPSMC_MSG_UVDPowerON                		((uint16_t)0x61)
-#define PPSMC_MSG_EnableULV                 		((uint16_t)0x62)
-#define PPSMC_MSG_DisableULV                		((uint16_t)0x63)
-#define PPSMC_MSG_EnterULV                  		((uint16_t)0x64)
-#define PPSMC_MSG_ExitULV                   		((uint16_t)0x65)
-#define PPSMC_PowerShiftActive              		((uint16_t)0x6A)
-#define PPSMC_PowerShiftInactive            		((uint16_t)0x6B)
-#define PPSMC_OCPActive                     		((uint16_t)0x6C)
-#define PPSMC_OCPInactive                   		((uint16_t)0x6D)
-#define PPSMC_CACLongTermAvgEnable          		((uint16_t)0x6E)
-#define PPSMC_CACLongTermAvgDisable         		((uint16_t)0x6F)
-#define PPSMC_MSG_InferredStateSweep_Start  		((uint16_t)0x70)
-#define PPSMC_MSG_InferredStateSweep_Stop   		((uint16_t)0x71)
-#define PPSMC_MSG_SwitchToLowestInfState    		((uint16_t)0x72)
-#define PPSMC_MSG_SwitchToNonInfState       		((uint16_t)0x73)
-#define PPSMC_MSG_AllStateSweep_Start       		((uint16_t)0x74)
-#define PPSMC_MSG_AllStateSweep_Stop        		((uint16_t)0x75)
-#define PPSMC_MSG_SwitchNextLowerInfState   		((uint16_t)0x76)
-#define PPSMC_MSG_SwitchNextHigherInfState  		((uint16_t)0x77)
-#define PPSMC_MSG_MclkRetrainingTest        		((uint16_t)0x78)
-#define PPSMC_MSG_ForceTDPClamping          		((uint16_t)0x79)
-#define PPSMC_MSG_CollectCAC_PowerCorreln   		((uint16_t)0x7A)
-#define PPSMC_MSG_CollectCAC_WeightCalib    		((uint16_t)0x7B)
-#define PPSMC_MSG_CollectCAC_SQonly         		((uint16_t)0x7C)
-#define PPSMC_MSG_CollectCAC_TemperaturePwr 		((uint16_t)0x7D)
-#define PPSMC_MSG_ExtremitiesTest_Start     		((uint16_t)0x7E)
-#define PPSMC_MSG_ExtremitiesTest_Stop      		((uint16_t)0x7F)
-#define PPSMC_FlushDataCache                		((uint16_t)0x80)
-#define PPSMC_FlushInstrCache               		((uint16_t)0x81)
-#define PPSMC_MSG_SetEnabledLevels          		((uint16_t)0x82)
-#define PPSMC_MSG_SetForcedLevels           		((uint16_t)0x83)
-#define PPSMC_MSG_ResetToDefaults           		((uint16_t)0x84)
-#define PPSMC_MSG_SetForcedLevelsAndJump    		((uint16_t)0x85)
-#define PPSMC_MSG_SetCACHistoryMode         		((uint16_t)0x86)
-#define PPSMC_MSG_EnableDTE                 		((uint16_t)0x87)
-#define PPSMC_MSG_DisableDTE                		((uint16_t)0x88)
-#define PPSMC_MSG_SmcSpaceSetAddress        		((uint16_t)0x89)
-#define PPSMC_MSG_SmcSpaceWriteDWordInc     		((uint16_t)0x8A)
-#define PPSMC_MSG_SmcSpaceWriteWordInc      		((uint16_t)0x8B)
-#define PPSMC_MSG_SmcSpaceWriteByteInc      		((uint16_t)0x8C)
-#define PPSMC_MSG_ChangeNearTDPLimit        		((uint16_t)0x90)
-#define PPSMC_MSG_ChangeSafePowerLimit      		((uint16_t)0x91)
-#define PPSMC_MSG_DPMStateSweepStart        		((uint16_t)0x92)
-#define PPSMC_MSG_DPMStateSweepStop         		((uint16_t)0x93)
-#define PPSMC_MSG_OVRDDisableSCLKDS         		((uint16_t)0x94)
-#define PPSMC_MSG_CancelDisableOVRDSCLKDS   		((uint16_t)0x95)
-#define PPSMC_MSG_ThrottleOVRDSCLKDS        		((uint16_t)0x96)
-#define PPSMC_MSG_CancelThrottleOVRDSCLKDS  		((uint16_t)0x97)
-#define PPSMC_MSG_GPIO17                    		((uint16_t)0x98)
-#define PPSMC_MSG_API_SetSvi2Volt_Vddc      		((uint16_t)0x99)
-#define PPSMC_MSG_API_SetSvi2Volt_Vddci     		((uint16_t)0x9A)
-#define PPSMC_MSG_API_SetSvi2Volt_Mvdd      		((uint16_t)0x9B)
-#define PPSMC_MSG_API_GetSvi2Volt_Vddc      		((uint16_t)0x9C)
-#define PPSMC_MSG_API_GetSvi2Volt_Vddci     		((uint16_t)0x9D)
-#define PPSMC_MSG_API_GetSvi2Volt_Mvdd      		((uint16_t)0x9E)
-
-#define PPSMC_MSG_BREAK                     		((uint16_t)0xF8)
-
-#define PPSMC_MSG_Test                      		((uint16_t)0x100)
-#define PPSMC_MSG_DRV_DRAM_ADDR_HI            		((uint16_t)0x250)
-#define PPSMC_MSG_DRV_DRAM_ADDR_LO            		((uint16_t)0x251)
-#define PPSMC_MSG_SMU_DRAM_ADDR_HI            		((uint16_t)0x252)
-#define PPSMC_MSG_SMU_DRAM_ADDR_LO            		((uint16_t)0x253)
-#define PPSMC_MSG_LoadUcodes                  		((uint16_t)0x254)
-
-typedef uint16_t PPSMC_Msg;
-
-#define PPSMC_EVENT_STATUS_THERMAL          		0x00000001
-#define PPSMC_EVENT_STATUS_REGULATORHOT     		0x00000002
-#define PPSMC_EVENT_STATUS_DC               		0x00000004
-#define PPSMC_EVENT_STATUS_GPIO17           		0x00000008
-
-#pragma pack(pop)
-
-#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_smc.c b/drivers/gpu/drm/amd/amdgpu/tonga_smc.c
index 5421309..361c49a 100644
--- a/drivers/gpu/drm/amd/amdgpu/tonga_smc.c
+++ b/drivers/gpu/drm/amd/amdgpu/tonga_smc.c
@@ -25,7 +25,7 @@
 #include "drmP.h"
 #include "amdgpu.h"
 #include "tonga_ppsmc.h"
-#include "tonga_smumgr.h"
+#include "tonga_smum.h"
 #include "smu_ucode_xfer_vi.h"
 #include "amdgpu_ucode.h"
 
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_smumgr.h b/drivers/gpu/drm/amd/amdgpu/tonga_smum.h
similarity index 100%
rename from drivers/gpu/drm/amd/amdgpu/tonga_smumgr.h
rename to drivers/gpu/drm/amd/amdgpu/tonga_smum.h
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
index 121915b..3d591392 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
@@ -279,6 +279,234 @@
 	WREG32(mmUVD_VCPU_CACHE_SIZE2, size);
 }
 
+static void cz_set_uvd_clock_gating_branches(struct amdgpu_device *adev,
+		bool enable)
+{
+	u32 data, data1;
+
+	data = RREG32(mmUVD_CGC_GATE);
+	data1 = RREG32(mmUVD_SUVD_CGC_GATE);
+	if (enable) {
+		data |= UVD_CGC_GATE__SYS_MASK |
+				UVD_CGC_GATE__UDEC_MASK |
+				UVD_CGC_GATE__MPEG2_MASK |
+				UVD_CGC_GATE__RBC_MASK |
+				UVD_CGC_GATE__LMI_MC_MASK |
+				UVD_CGC_GATE__IDCT_MASK |
+				UVD_CGC_GATE__MPRD_MASK |
+				UVD_CGC_GATE__MPC_MASK |
+				UVD_CGC_GATE__LBSI_MASK |
+				UVD_CGC_GATE__LRBBM_MASK |
+				UVD_CGC_GATE__UDEC_RE_MASK |
+				UVD_CGC_GATE__UDEC_CM_MASK |
+				UVD_CGC_GATE__UDEC_IT_MASK |
+				UVD_CGC_GATE__UDEC_DB_MASK |
+				UVD_CGC_GATE__UDEC_MP_MASK |
+				UVD_CGC_GATE__WCB_MASK |
+				UVD_CGC_GATE__VCPU_MASK |
+				UVD_CGC_GATE__SCPU_MASK;
+		data1 |= UVD_SUVD_CGC_GATE__SRE_MASK |
+				UVD_SUVD_CGC_GATE__SIT_MASK |
+				UVD_SUVD_CGC_GATE__SMP_MASK |
+				UVD_SUVD_CGC_GATE__SCM_MASK |
+				UVD_SUVD_CGC_GATE__SDB_MASK |
+				UVD_SUVD_CGC_GATE__SRE_H264_MASK |
+				UVD_SUVD_CGC_GATE__SRE_HEVC_MASK |
+				UVD_SUVD_CGC_GATE__SIT_H264_MASK |
+				UVD_SUVD_CGC_GATE__SIT_HEVC_MASK |
+				UVD_SUVD_CGC_GATE__SCM_H264_MASK |
+				UVD_SUVD_CGC_GATE__SCM_HEVC_MASK |
+				UVD_SUVD_CGC_GATE__SDB_H264_MASK |
+				UVD_SUVD_CGC_GATE__SDB_HEVC_MASK;
+	} else {
+		data &= ~(UVD_CGC_GATE__SYS_MASK |
+				UVD_CGC_GATE__UDEC_MASK |
+				UVD_CGC_GATE__MPEG2_MASK |
+				UVD_CGC_GATE__RBC_MASK |
+				UVD_CGC_GATE__LMI_MC_MASK |
+				UVD_CGC_GATE__LMI_UMC_MASK |
+				UVD_CGC_GATE__IDCT_MASK |
+				UVD_CGC_GATE__MPRD_MASK |
+				UVD_CGC_GATE__MPC_MASK |
+				UVD_CGC_GATE__LBSI_MASK |
+				UVD_CGC_GATE__LRBBM_MASK |
+				UVD_CGC_GATE__UDEC_RE_MASK |
+				UVD_CGC_GATE__UDEC_CM_MASK |
+				UVD_CGC_GATE__UDEC_IT_MASK |
+				UVD_CGC_GATE__UDEC_DB_MASK |
+				UVD_CGC_GATE__UDEC_MP_MASK |
+				UVD_CGC_GATE__WCB_MASK |
+				UVD_CGC_GATE__VCPU_MASK |
+				UVD_CGC_GATE__SCPU_MASK);
+		data1 &= ~(UVD_SUVD_CGC_GATE__SRE_MASK |
+				UVD_SUVD_CGC_GATE__SIT_MASK |
+				UVD_SUVD_CGC_GATE__SMP_MASK |
+				UVD_SUVD_CGC_GATE__SCM_MASK |
+				UVD_SUVD_CGC_GATE__SDB_MASK |
+				UVD_SUVD_CGC_GATE__SRE_H264_MASK |
+				UVD_SUVD_CGC_GATE__SRE_HEVC_MASK |
+				UVD_SUVD_CGC_GATE__SIT_H264_MASK |
+				UVD_SUVD_CGC_GATE__SIT_HEVC_MASK |
+				UVD_SUVD_CGC_GATE__SCM_H264_MASK |
+				UVD_SUVD_CGC_GATE__SCM_HEVC_MASK |
+				UVD_SUVD_CGC_GATE__SDB_H264_MASK |
+				UVD_SUVD_CGC_GATE__SDB_HEVC_MASK);
+	}
+	WREG32(mmUVD_CGC_GATE, data);
+	WREG32(mmUVD_SUVD_CGC_GATE, data1);
+}
+
+static void tonga_set_uvd_clock_gating_branches(struct amdgpu_device *adev,
+		bool enable)
+{
+	u32 data, data1;
+
+	data = RREG32(mmUVD_CGC_GATE);
+	data1 = RREG32(mmUVD_SUVD_CGC_GATE);
+	if (enable) {
+		data |= UVD_CGC_GATE__SYS_MASK |
+				UVD_CGC_GATE__UDEC_MASK |
+				UVD_CGC_GATE__MPEG2_MASK |
+				UVD_CGC_GATE__RBC_MASK |
+				UVD_CGC_GATE__LMI_MC_MASK |
+				UVD_CGC_GATE__IDCT_MASK |
+				UVD_CGC_GATE__MPRD_MASK |
+				UVD_CGC_GATE__MPC_MASK |
+				UVD_CGC_GATE__LBSI_MASK |
+				UVD_CGC_GATE__LRBBM_MASK |
+				UVD_CGC_GATE__UDEC_RE_MASK |
+				UVD_CGC_GATE__UDEC_CM_MASK |
+				UVD_CGC_GATE__UDEC_IT_MASK |
+				UVD_CGC_GATE__UDEC_DB_MASK |
+				UVD_CGC_GATE__UDEC_MP_MASK |
+				UVD_CGC_GATE__WCB_MASK |
+				UVD_CGC_GATE__VCPU_MASK |
+				UVD_CGC_GATE__SCPU_MASK;
+		data1 |= UVD_SUVD_CGC_GATE__SRE_MASK |
+				UVD_SUVD_CGC_GATE__SIT_MASK |
+				UVD_SUVD_CGC_GATE__SMP_MASK |
+				UVD_SUVD_CGC_GATE__SCM_MASK |
+				UVD_SUVD_CGC_GATE__SDB_MASK;
+	} else {
+		data &= ~(UVD_CGC_GATE__SYS_MASK |
+				UVD_CGC_GATE__UDEC_MASK |
+				UVD_CGC_GATE__MPEG2_MASK |
+				UVD_CGC_GATE__RBC_MASK |
+				UVD_CGC_GATE__LMI_MC_MASK |
+				UVD_CGC_GATE__LMI_UMC_MASK |
+				UVD_CGC_GATE__IDCT_MASK |
+				UVD_CGC_GATE__MPRD_MASK |
+				UVD_CGC_GATE__MPC_MASK |
+				UVD_CGC_GATE__LBSI_MASK |
+				UVD_CGC_GATE__LRBBM_MASK |
+				UVD_CGC_GATE__UDEC_RE_MASK |
+				UVD_CGC_GATE__UDEC_CM_MASK |
+				UVD_CGC_GATE__UDEC_IT_MASK |
+				UVD_CGC_GATE__UDEC_DB_MASK |
+				UVD_CGC_GATE__UDEC_MP_MASK |
+				UVD_CGC_GATE__WCB_MASK |
+				UVD_CGC_GATE__VCPU_MASK |
+				UVD_CGC_GATE__SCPU_MASK);
+		data1 &= ~(UVD_SUVD_CGC_GATE__SRE_MASK |
+				UVD_SUVD_CGC_GATE__SIT_MASK |
+				UVD_SUVD_CGC_GATE__SMP_MASK |
+				UVD_SUVD_CGC_GATE__SCM_MASK |
+				UVD_SUVD_CGC_GATE__SDB_MASK);
+	}
+	WREG32(mmUVD_CGC_GATE, data);
+	WREG32(mmUVD_SUVD_CGC_GATE, data1);
+}
+
+static void uvd_v6_0_set_uvd_dynamic_clock_mode(struct amdgpu_device *adev,
+		bool swmode)
+{
+	u32 data, data1 = 0, data2;
+
+	/* Always un-gate UVD REGS bit */
+	data = RREG32(mmUVD_CGC_GATE);
+	data &= ~(UVD_CGC_GATE__REGS_MASK);
+	WREG32(mmUVD_CGC_GATE, data);
+
+	data = RREG32(mmUVD_CGC_CTRL);
+	data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |
+			UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
+	data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |
+			1 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_GATE_DLY_TIMER) |
+			4 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_OFF_DELAY);
+
+	data2 = RREG32(mmUVD_SUVD_CGC_CTRL);
+	if (swmode) {
+		data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK |
+				UVD_CGC_CTRL__UDEC_CM_MODE_MASK |
+				UVD_CGC_CTRL__UDEC_IT_MODE_MASK |
+				UVD_CGC_CTRL__UDEC_DB_MODE_MASK |
+				UVD_CGC_CTRL__UDEC_MP_MODE_MASK |
+				UVD_CGC_CTRL__SYS_MODE_MASK |
+				UVD_CGC_CTRL__UDEC_MODE_MASK |
+				UVD_CGC_CTRL__MPEG2_MODE_MASK |
+				UVD_CGC_CTRL__REGS_MODE_MASK |
+				UVD_CGC_CTRL__RBC_MODE_MASK |
+				UVD_CGC_CTRL__LMI_MC_MODE_MASK |
+				UVD_CGC_CTRL__LMI_UMC_MODE_MASK |
+				UVD_CGC_CTRL__IDCT_MODE_MASK |
+				UVD_CGC_CTRL__MPRD_MODE_MASK |
+				UVD_CGC_CTRL__MPC_MODE_MASK |
+				UVD_CGC_CTRL__LBSI_MODE_MASK |
+				UVD_CGC_CTRL__LRBBM_MODE_MASK |
+				UVD_CGC_CTRL__WCB_MODE_MASK |
+				UVD_CGC_CTRL__VCPU_MODE_MASK |
+				UVD_CGC_CTRL__JPEG_MODE_MASK |
+				UVD_CGC_CTRL__SCPU_MODE_MASK);
+		data1 |= UVD_CGC_CTRL2__DYN_OCLK_RAMP_EN_MASK |
+				UVD_CGC_CTRL2__DYN_RCLK_RAMP_EN_MASK;
+		data1 &= ~UVD_CGC_CTRL2__GATER_DIV_ID_MASK;
+		data1 |= 7 << REG_FIELD_SHIFT(UVD_CGC_CTRL2, GATER_DIV_ID);
+		data2 &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK |
+				UVD_SUVD_CGC_CTRL__SIT_MODE_MASK |
+				UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |
+				UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |
+				UVD_SUVD_CGC_CTRL__SDB_MODE_MASK);
+	} else {
+		data |= UVD_CGC_CTRL__UDEC_RE_MODE_MASK |
+				UVD_CGC_CTRL__UDEC_CM_MODE_MASK |
+				UVD_CGC_CTRL__UDEC_IT_MODE_MASK |
+				UVD_CGC_CTRL__UDEC_DB_MODE_MASK |
+				UVD_CGC_CTRL__UDEC_MP_MODE_MASK |
+				UVD_CGC_CTRL__SYS_MODE_MASK |
+				UVD_CGC_CTRL__UDEC_MODE_MASK |
+				UVD_CGC_CTRL__MPEG2_MODE_MASK |
+				UVD_CGC_CTRL__REGS_MODE_MASK |
+				UVD_CGC_CTRL__RBC_MODE_MASK |
+				UVD_CGC_CTRL__LMI_MC_MODE_MASK |
+				UVD_CGC_CTRL__LMI_UMC_MODE_MASK |
+				UVD_CGC_CTRL__IDCT_MODE_MASK |
+				UVD_CGC_CTRL__MPRD_MODE_MASK |
+				UVD_CGC_CTRL__MPC_MODE_MASK |
+				UVD_CGC_CTRL__LBSI_MODE_MASK |
+				UVD_CGC_CTRL__LRBBM_MODE_MASK |
+				UVD_CGC_CTRL__WCB_MODE_MASK |
+				UVD_CGC_CTRL__VCPU_MODE_MASK |
+				UVD_CGC_CTRL__SCPU_MODE_MASK;
+		data2 |= UVD_SUVD_CGC_CTRL__SRE_MODE_MASK |
+				UVD_SUVD_CGC_CTRL__SIT_MODE_MASK |
+				UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |
+				UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |
+				UVD_SUVD_CGC_CTRL__SDB_MODE_MASK;
+	}
+	WREG32(mmUVD_CGC_CTRL, data);
+	WREG32(mmUVD_SUVD_CGC_CTRL, data2);
+
+	data = RREG32_UVD_CTX(ixUVD_CGC_CTRL2);
+	data &= ~(REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_OCLK_RAMP_EN) |
+			REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_RCLK_RAMP_EN) |
+			REG_FIELD_MASK(UVD_CGC_CTRL2, GATER_DIV_ID));
+	data1 &= (REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_OCLK_RAMP_EN) |
+			REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_RCLK_RAMP_EN) |
+			REG_FIELD_MASK(UVD_CGC_CTRL2, GATER_DIV_ID));
+	data |= data1;
+	WREG32_UVD_CTX(ixUVD_CGC_CTRL2, data);
+}
+
 /**
  * uvd_v6_0_start - start UVD block
  *
@@ -303,8 +531,19 @@
 
 	uvd_v6_0_mc_resume(adev);
 
-	/* disable clock gating */
-	WREG32(mmUVD_CGC_GATE, 0);
+	/* Set dynamic clock gating in S/W control mode */
+	if (adev->cg_flags & AMDGPU_CG_SUPPORT_UVD_MGCG) {
+		if (adev->flags & AMD_IS_APU)
+			cz_set_uvd_clock_gating_branches(adev, false);
+		else
+			tonga_set_uvd_clock_gating_branches(adev, false);
+		uvd_v6_0_set_uvd_dynamic_clock_mode(adev, true);
+	} else {
+		/* disable clock gating */
+		uint32_t data = RREG32(mmUVD_CGC_CTRL);
+		data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+		WREG32(mmUVD_CGC_CTRL, data);
+	}
 
 	/* disable interupt */
 	WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1));
@@ -758,6 +997,24 @@
 static int uvd_v6_0_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
+
+	if (!(adev->cg_flags & AMDGPU_CG_SUPPORT_UVD_MGCG))
+		return 0;
+
+	if (enable) {
+		if (adev->flags & AMD_IS_APU)
+			cz_set_uvd_clock_gating_branches(adev, enable);
+		else
+			tonga_set_uvd_clock_gating_branches(adev, enable);
+		uvd_v6_0_set_uvd_dynamic_clock_mode(adev, true);
+	} else {
+		uint32_t data = RREG32(mmUVD_CGC_CTRL);
+		data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+		WREG32(mmUVD_CGC_CTRL, data);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index 370c6c9..e99af81 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -103,6 +103,108 @@
 		WREG32(mmVCE_RB_WPTR2, ring->wptr);
 }
 
+static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override)
+{
+	u32 tmp, data;
+
+	tmp = data = RREG32(mmVCE_RB_ARB_CTRL);
+	if (override)
+		data |= VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK;
+	else
+		data &= ~VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK;
+
+	if (tmp != data)
+		WREG32(mmVCE_RB_ARB_CTRL, data);
+}
+
+static void vce_v3_0_set_vce_sw_clock_gating(struct amdgpu_device *adev,
+					     bool gated)
+{
+	u32 tmp, data;
+	/* Set Override to disable Clock Gating */
+	vce_v3_0_override_vce_clock_gating(adev, true);
+
+	if (!gated) {
+		/* Force CLOCK ON for VCE_CLOCK_GATING_B,
+		 * {*_FORCE_ON, *_FORCE_OFF} = {1, 0}
+		 * VREG can be FORCE ON or set to Dynamic, but can't be OFF
+		 */
+		tmp = data = RREG32(mmVCE_CLOCK_GATING_B);
+		data |= 0x1ff;
+		data &= ~0xef0000;
+		if (tmp != data)
+			WREG32(mmVCE_CLOCK_GATING_B, data);
+
+		/* Force CLOCK ON for VCE_UENC_CLOCK_GATING,
+		 * {*_FORCE_ON, *_FORCE_OFF} = {1, 0}
+		 */
+		tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING);
+		data |= 0x3ff000;
+		data &= ~0xffc00000;
+		if (tmp != data)
+			WREG32(mmVCE_UENC_CLOCK_GATING, data);
+
+		/* set VCE_UENC_CLOCK_GATING_2 */
+		tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2);
+		data |= 0x2;
+		data &= ~0x2;
+		if (tmp != data)
+			WREG32(mmVCE_UENC_CLOCK_GATING_2, data);
+
+		/* Force CLOCK ON for VCE_UENC_REG_CLOCK_GATING */
+		tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
+		data |= 0x37f;
+		if (tmp != data)
+			WREG32(mmVCE_UENC_REG_CLOCK_GATING, data);
+
+		/* Force VCE_UENC_DMA_DCLK_CTRL Clock ON */
+		tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL);
+		data |= VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK |
+				VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK |
+				VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK  |
+				0x8;
+		if (tmp != data)
+			WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data);
+	} else {
+		/* Force CLOCK OFF for VCE_CLOCK_GATING_B,
+		 * {*, *_FORCE_OFF} = {*, 1}
+		 * set VREG to Dynamic, as it can't be OFF
+		 */
+		tmp = data = RREG32(mmVCE_CLOCK_GATING_B);
+		data &= ~0x80010;
+		data |= 0xe70008;
+		if (tmp != data)
+			WREG32(mmVCE_CLOCK_GATING_B, data);
+		/* Force CLOCK OFF for VCE_UENC_CLOCK_GATING,
+		 * Force ClOCK OFF takes precedent over Force CLOCK ON setting.
+		 * {*_FORCE_ON, *_FORCE_OFF} = {*, 1}
+		 */
+		tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING);
+		data |= 0xffc00000;
+		if (tmp != data)
+			WREG32(mmVCE_UENC_CLOCK_GATING, data);
+		/* Set VCE_UENC_CLOCK_GATING_2 */
+		tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2);
+		data |= 0x10000;
+		if (tmp != data)
+			WREG32(mmVCE_UENC_CLOCK_GATING_2, data);
+		/* Set VCE_UENC_REG_CLOCK_GATING to dynamic */
+		tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
+		data &= ~0xffc00000;
+		if (tmp != data)
+			WREG32(mmVCE_UENC_REG_CLOCK_GATING, data);
+		/* Set VCE_UENC_DMA_DCLK_CTRL CG always in dynamic mode */
+		tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL);
+		data &= ~(VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK |
+				VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK |
+				VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK  |
+				0x8);
+		if (tmp != data)
+			WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data);
+	}
+	vce_v3_0_override_vce_clock_gating(adev, false);
+}
+
 /**
  * vce_v3_0_start - start VCE block
  *
@@ -121,7 +223,7 @@
 		if (adev->vce.harvest_config & (1 << idx))
 			continue;
 
-		if(idx == 0)
+		if (idx == 0)
 			WREG32_P(mmGRBM_GFX_INDEX, 0,
 				~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
 		else
@@ -174,6 +276,10 @@
 		/* clear BUSY flag */
 		WREG32_P(mmVCE_STATUS, 0, ~1);
 
+		/* Set Clock-Gating off */
+		if (adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG)
+			vce_v3_0_set_vce_sw_clock_gating(adev, false);
+
 		if (r) {
 			DRM_ERROR("VCE not responding, giving up!!!\n");
 			mutex_unlock(&adev->grbm_idx_mutex);
@@ -208,14 +314,11 @@
 static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
 {
 	u32 tmp;
-	unsigned ret;
 
 	/* Fiji, Stoney are single pipe */
 	if ((adev->asic_type == CHIP_FIJI) ||
-	    (adev->asic_type == CHIP_STONEY)){
-		ret = AMDGPU_VCE_HARVEST_VCE1;
-		return ret;
-	}
+	    (adev->asic_type == CHIP_STONEY))
+		return AMDGPU_VCE_HARVEST_VCE1;
 
 	/* Tonga and CZ are dual or single pipe */
 	if (adev->flags & AMD_IS_APU)
@@ -229,19 +332,14 @@
 
 	switch (tmp) {
 	case 1:
-		ret = AMDGPU_VCE_HARVEST_VCE0;
-		break;
+		return AMDGPU_VCE_HARVEST_VCE0;
 	case 2:
-		ret = AMDGPU_VCE_HARVEST_VCE1;
-		break;
+		return AMDGPU_VCE_HARVEST_VCE1;
 	case 3:
-		ret = AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
-		break;
+		return AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
 	default:
-		ret = 0;
+		return 0;
 	}
-
-	return ret;
 }
 
 static int vce_v3_0_early_init(void *handle)
@@ -316,28 +414,22 @@
 
 static int vce_v3_0_hw_init(void *handle)
 {
-	struct amdgpu_ring *ring;
-	int r;
+	int r, i;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
 	r = vce_v3_0_start(adev);
 	if (r)
 		return r;
 
-	ring = &adev->vce.ring[0];
-	ring->ready = true;
-	r = amdgpu_ring_test_ring(ring);
-	if (r) {
-		ring->ready = false;
-		return r;
-	}
+	adev->vce.ring[0].ready = false;
+	adev->vce.ring[1].ready = false;
 
-	ring = &adev->vce.ring[1];
-	ring->ready = true;
-	r = amdgpu_ring_test_ring(ring);
-	if (r) {
-		ring->ready = false;
-		return r;
+	for (i = 0; i < 2; i++) {
+		r = amdgpu_ring_test_ring(&adev->vce.ring[i]);
+		if (r)
+			return r;
+		else
+			adev->vce.ring[i].ready = true;
 	}
 
 	DRM_INFO("VCE initialized successfully.\n");
@@ -437,17 +529,9 @@
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	u32 mask = 0;
-	int idx;
 
-	for (idx = 0; idx < 2; ++idx) {
-		if (adev->vce.harvest_config & (1 << idx))
-			continue;
-
-		if (idx == 0)
-			mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
-		else
-			mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
-	}
+	mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_STATUS2__VCE0_BUSY_MASK;
+	mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_STATUS2__VCE1_BUSY_MASK;
 
 	return !(RREG32(mmSRBM_STATUS2) & mask);
 }
@@ -456,23 +540,11 @@
 {
 	unsigned i;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	u32 mask = 0;
-	int idx;
 
-	for (idx = 0; idx < 2; ++idx) {
-		if (adev->vce.harvest_config & (1 << idx))
-			continue;
-
-		if (idx == 0)
-			mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
-		else
-			mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
-	}
-
-	for (i = 0; i < adev->usec_timeout; i++) {
-		if (!(RREG32(mmSRBM_STATUS2) & mask))
+	for (i = 0; i < adev->usec_timeout; i++)
+		if (vce_v3_0_is_idle(handle))
 			return 0;
-	}
+
 	return -ETIMEDOUT;
 }
 
@@ -480,17 +552,10 @@
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	u32 mask = 0;
-	int idx;
 
-	for (idx = 0; idx < 2; ++idx) {
-		if (adev->vce.harvest_config & (1 << idx))
-			continue;
+	mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
+	mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
 
-		if (idx == 0)
-			mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
-		else
-			mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
-	}
 	WREG32_P(mmSRBM_SOFT_RESET, mask,
 		 ~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK |
 		   SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK));
@@ -592,10 +657,8 @@
 
 	switch (entry->src_data) {
 	case 0:
-		amdgpu_fence_process(&adev->vce.ring[0]);
-		break;
 	case 1:
-		amdgpu_fence_process(&adev->vce.ring[1]);
+		amdgpu_fence_process(&adev->vce.ring[entry->src_data]);
 		break;
 	default:
 		DRM_ERROR("Unhandled interrupt: %d %d\n",
@@ -609,6 +672,47 @@
 static int vce_v3_0_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
+	int i;
+
+	if (!(adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG))
+		return 0;
+
+	mutex_lock(&adev->grbm_idx_mutex);
+	for (i = 0; i < 2; i++) {
+		/* Program VCE Instance 0 or 1 if not harvested */
+		if (adev->vce.harvest_config & (1 << i))
+			continue;
+
+		if (i == 0)
+			WREG32_P(mmGRBM_GFX_INDEX, 0,
+					~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
+		else
+			WREG32_P(mmGRBM_GFX_INDEX,
+					GRBM_GFX_INDEX__VCE_INSTANCE_MASK,
+					~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
+
+		if (enable) {
+			/* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */
+			uint32_t data = RREG32(mmVCE_CLOCK_GATING_A);
+			data &= ~(0xf | 0xff0);
+			data |= ((0x0 << 0) | (0x04 << 4));
+			WREG32(mmVCE_CLOCK_GATING_A, data);
+
+			/* initialize VCE_UENC_CLOCK_GATING: Clock ON/OFF delay */
+			data = RREG32(mmVCE_UENC_CLOCK_GATING);
+			data &= ~(0xf | 0xff0);
+			data |= ((0x0 << 0) | (0x04 << 4));
+			WREG32(mmVCE_UENC_CLOCK_GATING, data);
+		}
+
+		vce_v3_0_set_vce_sw_clock_gating(adev, enable);
+	}
+
+	WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
+	mutex_unlock(&adev->grbm_idx_mutex);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 2adc1c8..652e766 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -31,6 +31,7 @@
 #include "amdgpu_vce.h"
 #include "amdgpu_ucode.h"
 #include "atom.h"
+#include "amd_pcie.h"
 
 #include "gmc/gmc_8_1_d.h"
 #include "gmc/gmc_8_1_sh_mask.h"
@@ -71,6 +72,7 @@
 #include "uvd_v5_0.h"
 #include "uvd_v6_0.h"
 #include "vce_v3_0.h"
+#include "amdgpu_powerplay.h"
 
 /*
  * Indirect registers accessor
@@ -376,6 +378,38 @@
 	WREG32_SMC(ixROM_CNTL, rom_cntl);
 	return r;
 }
+
+static bool vi_read_bios_from_rom(struct amdgpu_device *adev,
+				  u8 *bios, u32 length_bytes)
+{
+	u32 *dw_ptr;
+	unsigned long flags;
+	u32 i, length_dw;
+
+	if (bios == NULL)
+		return false;
+	if (length_bytes == 0)
+		return false;
+	/* APU vbios image is part of sbios image */
+	if (adev->flags & AMD_IS_APU)
+		return false;
+
+	dw_ptr = (u32 *)bios;
+	length_dw = ALIGN(length_bytes, 4) / 4;
+	/* take the smc lock since we are using the smc index */
+	spin_lock_irqsave(&adev->smc_idx_lock, flags);
+	/* set rom index to 0 */
+	WREG32(mmSMC_IND_INDEX_0, ixROM_INDEX);
+	WREG32(mmSMC_IND_DATA_0, 0);
+	/* set index to data for continous read */
+	WREG32(mmSMC_IND_INDEX_0, ixROM_DATA);
+	for (i = 0; i < length_dw; i++)
+		dw_ptr[i] = RREG32(mmSMC_IND_DATA_0);
+	spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
+
+	return true;
+}
+
 static struct amdgpu_allowed_register_entry tonga_allowed_read_registers[] = {
 	{mmGB_MACROTILE_MODE7, true},
 };
@@ -1019,9 +1053,6 @@
 
 static void vi_pcie_gen3_enable(struct amdgpu_device *adev)
 {
-	u32 mask;
-	int ret;
-
 	if (pci_is_root_bus(adev->pdev->bus))
 		return;
 
@@ -1031,11 +1062,8 @@
 	if (adev->flags & AMD_IS_APU)
 		return;
 
-	ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask);
-	if (ret != 0)
-		return;
-
-	if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80)))
+	if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
+					CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)))
 		return;
 
 	/* todo */
@@ -1098,7 +1126,7 @@
 		.major = 7,
 		.minor = 1,
 		.rev = 0,
-		.funcs = &iceland_dpm_ip_funcs,
+		.funcs = &amdgpu_pp_ip_funcs,
 	},
 	{
 		.type = AMD_IP_BLOCK_TYPE_GFX,
@@ -1145,7 +1173,7 @@
 		.major = 7,
 		.minor = 1,
 		.rev = 0,
-		.funcs = &tonga_dpm_ip_funcs,
+		.funcs = &amdgpu_pp_ip_funcs,
 	},
 	{
 		.type = AMD_IP_BLOCK_TYPE_DCE,
@@ -1213,7 +1241,7 @@
 		.major = 7,
 		.minor = 1,
 		.rev = 0,
-		.funcs = &fiji_dpm_ip_funcs,
+		.funcs = &amdgpu_pp_ip_funcs,
 	},
 	{
 		.type = AMD_IP_BLOCK_TYPE_DCE,
@@ -1281,7 +1309,7 @@
 		.major = 8,
 		.minor = 0,
 		.rev = 0,
-		.funcs = &cz_dpm_ip_funcs,
+		.funcs = &amdgpu_pp_ip_funcs
 	},
 	{
 		.type = AMD_IP_BLOCK_TYPE_DCE,
@@ -1354,20 +1382,18 @@
 
 static uint32_t vi_get_rev_id(struct amdgpu_device *adev)
 {
-	if (adev->asic_type == CHIP_TOPAZ)
-		return (RREG32(mmPCIE_EFUSE4) & PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID_MASK)
-			>> PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID__SHIFT;
-	else if (adev->flags & AMD_IS_APU)
+	if (adev->flags & AMD_IS_APU)
 		return (RREG32_SMC(ATI_REV_ID_FUSE_MACRO__ADDRESS) & ATI_REV_ID_FUSE_MACRO__MASK)
 			>> ATI_REV_ID_FUSE_MACRO__SHIFT;
 	else
-		return (RREG32(mmCC_DRM_ID_STRAPS) & CC_DRM_ID_STRAPS__ATI_REV_ID_MASK)
-			>> CC_DRM_ID_STRAPS__ATI_REV_ID__SHIFT;
+		return (RREG32(mmPCIE_EFUSE4) & PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID_MASK)
+			>> PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID__SHIFT;
 }
 
 static const struct amdgpu_asic_funcs vi_asic_funcs =
 {
 	.read_disabled_bios = &vi_read_disabled_bios,
+	.read_bios_from_rom = &vi_read_bios_from_rom,
 	.read_register = &vi_read_register,
 	.reset = &vi_asic_reset,
 	.set_vga_state = &vi_vga_set_state,
@@ -1416,7 +1442,8 @@
 		break;
 	case CHIP_FIJI:
 		adev->has_uvd = true;
-		adev->cg_flags = 0;
+		adev->cg_flags = AMDGPU_CG_SUPPORT_UVD_MGCG |
+				AMDGPU_CG_SUPPORT_VCE_MGCG;
 		adev->pg_flags = 0;
 		adev->external_rev_id = adev->rev_id + 0x3c;
 		break;
@@ -1442,6 +1469,8 @@
 	if (amdgpu_smc_load_fw && smc_enabled)
 		adev->firmware.smu_load = true;
 
+	amdgpu_get_pcie_info(adev);
+
 	return 0;
 }
 
@@ -1515,9 +1544,95 @@
 	return 0;
 }
 
+static void fiji_update_bif_medium_grain_light_sleep(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t temp, data;
+
+	temp = data = RREG32_PCIE(ixPCIE_CNTL2);
+
+	if (enable)
+		data |= PCIE_CNTL2__SLV_MEM_LS_EN_MASK |
+				PCIE_CNTL2__MST_MEM_LS_EN_MASK |
+				PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK;
+	else
+		data &= ~(PCIE_CNTL2__SLV_MEM_LS_EN_MASK |
+				PCIE_CNTL2__MST_MEM_LS_EN_MASK |
+				PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK);
+
+	if (temp != data)
+		WREG32_PCIE(ixPCIE_CNTL2, data);
+}
+
+static void fiji_update_hdp_medium_grain_clock_gating(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t temp, data;
+
+	temp = data = RREG32(mmHDP_HOST_PATH_CNTL);
+
+	if (enable)
+		data &= ~HDP_HOST_PATH_CNTL__CLOCK_GATING_DIS_MASK;
+	else
+		data |= HDP_HOST_PATH_CNTL__CLOCK_GATING_DIS_MASK;
+
+	if (temp != data)
+		WREG32(mmHDP_HOST_PATH_CNTL, data);
+}
+
+static void fiji_update_hdp_light_sleep(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t temp, data;
+
+	temp = data = RREG32(mmHDP_MEM_POWER_LS);
+
+	if (enable)
+		data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+	else
+		data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+
+	if (temp != data)
+		WREG32(mmHDP_MEM_POWER_LS, data);
+}
+
+static void fiji_update_rom_medium_grain_clock_gating(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t temp, data;
+
+	temp = data = RREG32_SMC(ixCGTT_ROM_CLK_CTRL0);
+
+	if (enable)
+		data &= ~(CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK |
+				CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK);
+	else
+		data |= CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK |
+				CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK;
+
+	if (temp != data)
+		WREG32_SMC(ixCGTT_ROM_CLK_CTRL0, data);
+}
+
 static int vi_common_set_clockgating_state(void *handle,
 					    enum amd_clockgating_state state)
 {
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	switch (adev->asic_type) {
+	case CHIP_FIJI:
+		fiji_update_bif_medium_grain_light_sleep(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		fiji_update_hdp_medium_grain_clock_gating(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		fiji_update_hdp_light_sleep(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		fiji_update_rom_medium_grain_clock_gating(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		break;
+	default:
+		break;
+	}
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.h b/drivers/gpu/drm/amd/include/amd_acpi.h
similarity index 90%
rename from drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.h
rename to drivers/gpu/drm/amd/include/amd_acpi.h
index 01a29c3..496360e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.h
+++ b/drivers/gpu/drm/amd/include/amd_acpi.h
@@ -21,14 +21,63 @@
  *
  */
 
-#ifndef AMDGPU_ACPI_H
-#define AMDGPU_ACPI_H
+#ifndef AMD_ACPI_H
+#define AMD_ACPI_H
 
-struct amdgpu_device;
-struct acpi_bus_event;
+#define ACPI_AC_CLASS           "ac_adapter"
 
-int amdgpu_atif_handler(struct amdgpu_device *adev,
-		struct acpi_bus_event *event);
+struct atif_verify_interface {
+	u16 size;		/* structure size in bytes (includes size field) */
+	u16 version;		/* version */
+	u32 notification_mask;	/* supported notifications mask */
+	u32 function_bits;	/* supported functions bit vector */
+} __packed;
+
+struct atif_system_params {
+	u16 size;		/* structure size in bytes (includes size field) */
+	u32 valid_mask;		/* valid flags mask */
+	u32 flags;		/* flags */
+	u8 command_code;	/* notify command code */
+} __packed;
+
+struct atif_sbios_requests {
+	u16 size;		/* structure size in bytes (includes size field) */
+	u32 pending;		/* pending sbios requests */
+	u8 panel_exp_mode;	/* panel expansion mode */
+	u8 thermal_gfx;		/* thermal state: target gfx controller */
+	u8 thermal_state;	/* thermal state: state id (0: exit state, non-0: state) */
+	u8 forced_power_gfx;	/* forced power state: target gfx controller */
+	u8 forced_power_state;	/* forced power state: state id */
+	u8 system_power_src;	/* system power source */
+	u8 backlight_level;	/* panel backlight level (0-255) */
+} __packed;
+
+#define ATIF_NOTIFY_MASK	0x3
+#define ATIF_NOTIFY_NONE	0
+#define ATIF_NOTIFY_81		1
+#define ATIF_NOTIFY_N		2
+
+struct atcs_verify_interface {
+	u16 size;		/* structure size in bytes (includes size field) */
+	u16 version;		/* version */
+	u32 function_bits;	/* supported functions bit vector */
+} __packed;
+
+#define ATCS_VALID_FLAGS_MASK	0x3
+
+struct atcs_pref_req_input {
+	u16 size;		/* structure size in bytes (includes size field) */
+	u16 client_id;		/* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */
+	u16 valid_flags_mask;	/* valid flags mask */
+	u16 flags;		/* flags */
+	u8 req_type;		/* request type */
+	u8 perf_req;		/* performance request */
+} __packed;
+
+struct atcs_pref_req_output {
+	u16 size;		/* structure size in bytes (includes size field) */
+	u8 ret_val;		/* return value */
+} __packed;
 
 /* AMD hw uses four ACPI control methods:
  * 1. ATIF
diff --git a/drivers/gpu/drm/amd/include/amd_pcie.h b/drivers/gpu/drm/amd/include/amd_pcie.h
new file mode 100644
index 0000000..7c2a916
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/amd_pcie.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ */
+
+#ifndef __AMD_PCIE_H__
+#define __AMD_PCIE_H__
+
+/* Following flags shows PCIe link speed supported in driver which are decided by chipset and ASIC */
+#define CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1        0x00010000
+#define CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2        0x00020000
+#define CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3        0x00040000
+#define CAIL_PCIE_LINK_SPEED_SUPPORT_MASK        0xFFFF0000
+#define CAIL_PCIE_LINK_SPEED_SUPPORT_SHIFT       16
+
+/* Following flags shows PCIe link speed supported by ASIC H/W.*/
+#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1   0x00000001
+#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2   0x00000002
+#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3   0x00000004
+#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_MASK   0x0000FFFF
+#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_SHIFT  0
+
+/* Following flags shows PCIe lane width switch supported in driver which are decided by chipset and ASIC */
+#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X1          0x00010000
+#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X2          0x00020000
+#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X4          0x00040000
+#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X8          0x00080000
+#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X12         0x00100000
+#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X16         0x00200000
+#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X32         0x00400000
+#define CAIL_PCIE_LINK_WIDTH_SUPPORT_SHIFT       16
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/amd_pcie_helpers.h b/drivers/gpu/drm/amd/include/amd_pcie_helpers.h
new file mode 100644
index 0000000..5725bf8
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/amd_pcie_helpers.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ */
+
+#ifndef __AMD_PCIE_HELPERS_H__
+#define __AMD_PCIE_HELPERS_H__
+
+#include "amd_pcie.h"
+
+static inline bool is_pcie_gen3_supported(uint32_t pcie_link_speed_cap)
+{
+	if (pcie_link_speed_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
+		return true;
+
+	return false;
+}
+
+static inline bool is_pcie_gen2_supported(uint32_t pcie_link_speed_cap)
+{
+	if (pcie_link_speed_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
+		return true;
+
+	return false;
+}
+
+/* Get the new PCIE speed given the ASIC PCIE Cap and the NewState's requested PCIE speed*/
+static inline uint16_t get_pcie_gen_support(uint32_t pcie_link_speed_cap,
+					    uint16_t ns_pcie_gen)
+{
+	uint32_t asic_pcie_link_speed_cap = (pcie_link_speed_cap &
+		CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_MASK);
+	uint32_t sys_pcie_link_speed_cap  = (pcie_link_speed_cap &
+		CAIL_PCIE_LINK_SPEED_SUPPORT_MASK);
+
+	switch (asic_pcie_link_speed_cap) {
+	case CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1:
+		return PP_PCIEGen1;
+
+	case CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2:
+		return PP_PCIEGen2;
+
+	case CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3:
+		return PP_PCIEGen3;
+
+	default:
+		if (is_pcie_gen3_supported(sys_pcie_link_speed_cap) &&
+			(ns_pcie_gen == PP_PCIEGen3)) {
+			return PP_PCIEGen3;
+		} else if (is_pcie_gen2_supported(sys_pcie_link_speed_cap) &&
+			((ns_pcie_gen == PP_PCIEGen3) || (ns_pcie_gen == PP_PCIEGen2))) {
+			return PP_PCIEGen2;
+		}
+	}
+
+	return PP_PCIEGen1;
+}
+
+static inline uint16_t get_pcie_lane_support(uint32_t pcie_lane_width_cap,
+					     uint16_t ns_pcie_lanes)
+{
+	int i, j;
+	uint16_t new_pcie_lanes = ns_pcie_lanes;
+	uint16_t pcie_lanes[7] = {1, 2, 4, 8, 12, 16, 32};
+
+	switch (pcie_lane_width_cap) {
+	case 0:
+		printk(KERN_ERR "No valid PCIE lane width reported");
+		break;
+	case CAIL_PCIE_LINK_WIDTH_SUPPORT_X1:
+		new_pcie_lanes = 1;
+		break;
+	case CAIL_PCIE_LINK_WIDTH_SUPPORT_X2:
+		new_pcie_lanes = 2;
+		break;
+	case CAIL_PCIE_LINK_WIDTH_SUPPORT_X4:
+		new_pcie_lanes = 4;
+		break;
+	case CAIL_PCIE_LINK_WIDTH_SUPPORT_X8:
+		new_pcie_lanes = 8;
+		break;
+	case CAIL_PCIE_LINK_WIDTH_SUPPORT_X12:
+		new_pcie_lanes = 12;
+		break;
+	case CAIL_PCIE_LINK_WIDTH_SUPPORT_X16:
+		new_pcie_lanes = 16;
+		break;
+	case CAIL_PCIE_LINK_WIDTH_SUPPORT_X32:
+		new_pcie_lanes = 32;
+		break;
+	default:
+		for (i = 0; i < 7; i++) {
+			if (ns_pcie_lanes == pcie_lanes[i]) {
+				if (pcie_lane_width_cap & (0x10000 << i)) {
+					break;
+				} else {
+					for (j = i - 1; j >= 0; j--) {
+						if (pcie_lane_width_cap & (0x10000 << j)) {
+							new_pcie_lanes = pcie_lanes[j];
+							break;
+						}
+					}
+
+					if (j < 0) {
+						for (j = i + 1; j < 7; j++) {
+							if (pcie_lane_width_cap & (0x10000 << j)) {
+								new_pcie_lanes = pcie_lanes[j];
+								break;
+							}
+						}
+						if (j > 7)
+							printk(KERN_ERR "Cannot find a valid PCIE lane width!");
+					}
+				}
+				break;
+			}
+		}
+		break;
+	}
+
+	return new_pcie_lanes;
+}
+
+#endif
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
index fe28fb3..1195d06f 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -85,6 +85,27 @@
 	AMD_PG_STATE_UNGATE,
 };
 
+enum amd_pm_state_type {
+	/* not used for dpm */
+	POWER_STATE_TYPE_DEFAULT,
+	POWER_STATE_TYPE_POWERSAVE,
+	/* user selectable states */
+	POWER_STATE_TYPE_BATTERY,
+	POWER_STATE_TYPE_BALANCED,
+	POWER_STATE_TYPE_PERFORMANCE,
+	/* internal states */
+	POWER_STATE_TYPE_INTERNAL_UVD,
+	POWER_STATE_TYPE_INTERNAL_UVD_SD,
+	POWER_STATE_TYPE_INTERNAL_UVD_HD,
+	POWER_STATE_TYPE_INTERNAL_UVD_HD2,
+	POWER_STATE_TYPE_INTERNAL_UVD_MVC,
+	POWER_STATE_TYPE_INTERNAL_BOOT,
+	POWER_STATE_TYPE_INTERNAL_THERMAL,
+	POWER_STATE_TYPE_INTERNAL_ACPI,
+	POWER_STATE_TYPE_INTERNAL_ULV,
+	POWER_STATE_TYPE_INTERNAL_3DPERF,
+};
+
 struct amd_ip_funcs {
 	/* sets up early driver state (pre sw_init), does not configure hw - Optional */
 	int (*early_init)(void *handle);
diff --git a/drivers/gpu/drm/amd/include/asic_reg/bif/bif_5_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/bif/bif_5_0_d.h
index 92b6ba0..2933297 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/bif/bif_5_0_d.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/bif/bif_5_0_d.h
@@ -596,6 +596,7 @@
 #define mmSWRST_EP_CONTROL_0                                                    0x14ac
 #define mmCPM_CONTROL                                                           0x14b8
 #define mmGSKT_CONTROL                                                          0x14bf
+#define ixSWRST_COMMAND_1                                                       0x1400103
 #define ixLM_CONTROL                                                            0x1400120
 #define ixLM_PCIETXMUX0                                                         0x1400121
 #define ixLM_PCIETXMUX1                                                         0x1400122
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h
index daf763b..a9b6923 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h
@@ -2807,5 +2807,18 @@
 #define ixDIDT_DBR_WEIGHT0_3                                                    0x90
 #define ixDIDT_DBR_WEIGHT4_7                                                    0x91
 #define ixDIDT_DBR_WEIGHT8_11                                                   0x92
+#define mmTD_EDC_CNT                                                            0x252e
+#define mmCPF_EDC_TAG_CNT                                                       0x3188
+#define mmCPF_EDC_ROQ_CNT                                                       0x3189
+#define mmCPF_EDC_ATC_CNT                                                       0x318a
+#define mmCPG_EDC_TAG_CNT                                                       0x318b
+#define mmCPG_EDC_ATC_CNT                                                       0x318c
+#define mmCPG_EDC_DMA_CNT                                                       0x318d
+#define mmCPC_EDC_SCRATCH_CNT                                                   0x318e
+#define mmCPC_EDC_UCODE_CNT                                                     0x318f
+#define mmCPC_EDC_ATC_CNT                                                       0x3190
+#define mmDC_EDC_STATE_CNT                                                      0x3191
+#define mmDC_EDC_CSINVOC_CNT                                                    0x3192
+#define mmDC_EDC_RESTORE_CNT                                                    0x3193
 
 #endif /* GFX_8_0_D_H */
diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h
index 5526226..eaf451e 100644
--- a/drivers/gpu/drm/amd/include/atombios.h
+++ b/drivers/gpu/drm/amd/include/atombios.h
@@ -550,6 +550,13 @@
 //MPLL_CNTL_FLAG_BYPASS_AD_PLL has a wrong name, should be BYPASS_DQ_PLL
 #define MPLL_CNTL_FLAG_BYPASS_AD_PLL            0x04
 
+// use for ComputeMemoryClockParamTable
+typedef struct _COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_2
+{
+  COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 ulClock;
+  ULONG ulReserved;
+}COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_2;
+
 typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER
 {
   ATOM_COMPUTE_CLOCK_FREQ ulClock;
@@ -4988,6 +4995,78 @@
   ULONG  ulSDCMargine;
 }ATOM_ASIC_PROFILING_INFO_V3_3;
 
+// for Fiji speed EVV algorithm
+typedef struct  _ATOM_ASIC_PROFILING_INFO_V3_4
+{
+  ATOM_COMMON_TABLE_HEADER         asHeader;
+  ULONG  ulEvvLkgFactor;
+  ULONG  ulBoardCoreTemp;
+  ULONG  ulMaxVddc;
+  ULONG  ulMinVddc;
+  ULONG  ulLoadLineSlop;
+  ULONG  ulLeakageTemp;
+  ULONG  ulLeakageVoltage;
+  EFUSE_LINEAR_FUNC_PARAM sCACm;
+  EFUSE_LINEAR_FUNC_PARAM sCACb;
+  EFUSE_LOGISTIC_FUNC_PARAM sKt_b;
+  EFUSE_LOGISTIC_FUNC_PARAM sKv_m;
+  EFUSE_LOGISTIC_FUNC_PARAM sKv_b;
+  USHORT usLkgEuseIndex;
+  UCHAR  ucLkgEfuseBitLSB;
+  UCHAR  ucLkgEfuseLength;
+  ULONG  ulLkgEncodeLn_MaxDivMin;
+  ULONG  ulLkgEncodeMax;
+  ULONG  ulLkgEncodeMin;
+  ULONG  ulEfuseLogisticAlpha;
+  USHORT usPowerDpm0;
+  USHORT usPowerDpm1;
+  USHORT usPowerDpm2;
+  USHORT usPowerDpm3;
+  USHORT usPowerDpm4;
+  USHORT usPowerDpm5;
+  USHORT usPowerDpm6;
+  USHORT usPowerDpm7;
+  ULONG  ulTdpDerateDPM0;
+  ULONG  ulTdpDerateDPM1;
+  ULONG  ulTdpDerateDPM2;
+  ULONG  ulTdpDerateDPM3;
+  ULONG  ulTdpDerateDPM4;
+  ULONG  ulTdpDerateDPM5;
+  ULONG  ulTdpDerateDPM6;
+  ULONG  ulTdpDerateDPM7;
+  EFUSE_LINEAR_FUNC_PARAM sRoFuse;
+  ULONG  ulEvvDefaultVddc;
+  ULONG  ulEvvNoCalcVddc;
+  USHORT usParamNegFlag;
+  USHORT usSpeed_Model;
+  ULONG  ulSM_A0;
+  ULONG  ulSM_A1;
+  ULONG  ulSM_A2;
+  ULONG  ulSM_A3;
+  ULONG  ulSM_A4;
+  ULONG  ulSM_A5;
+  ULONG  ulSM_A6;
+  ULONG  ulSM_A7;
+  UCHAR  ucSM_A0_sign;
+  UCHAR  ucSM_A1_sign;
+  UCHAR  ucSM_A2_sign;
+  UCHAR  ucSM_A3_sign;
+  UCHAR  ucSM_A4_sign;
+  UCHAR  ucSM_A5_sign;
+  UCHAR  ucSM_A6_sign;
+  UCHAR  ucSM_A7_sign;
+  ULONG ulMargin_RO_a;
+  ULONG ulMargin_RO_b;
+  ULONG ulMargin_RO_c;
+  ULONG ulMargin_fixed;
+  ULONG ulMargin_Fmax_mean;
+  ULONG ulMargin_plat_mean;
+  ULONG ulMargin_Fmax_sigma;
+  ULONG ulMargin_plat_sigma;
+  ULONG ulMargin_DC_sigma;
+  ULONG ulReserved[8];            // Reserved for future ASIC
+}ATOM_ASIC_PROFILING_INFO_V3_4;
+
 typedef struct _ATOM_POWER_SOURCE_OBJECT
 {
    UCHAR  ucPwrSrcId;                                   // Power source
diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h
index 992dcd8..713aec9 100644
--- a/drivers/gpu/drm/amd/include/cgs_common.h
+++ b/drivers/gpu/drm/amd/include/cgs_common.h
@@ -105,6 +105,34 @@
 	CGS_UCODE_ID_MAXIMUM,
 };
 
+enum cgs_system_info_id {
+	CGS_SYSTEM_INFO_ADAPTER_BDF_ID = 1,
+	CGS_SYSTEM_INFO_PCIE_GEN_INFO,
+	CGS_SYSTEM_INFO_PCIE_MLW,
+	CGS_SYSTEM_INFO_ID_MAXIMUM,
+};
+
+struct cgs_system_info {
+	uint64_t       size;
+	uint64_t       info_id;
+	union {
+		void           *ptr;
+		uint64_t        value;
+	};
+	uint64_t               padding[13];
+};
+
+/*
+ * enum cgs_resource_type - GPU resource type
+ */
+enum cgs_resource_type {
+	CGS_RESOURCE_TYPE_MMIO = 0,
+	CGS_RESOURCE_TYPE_FB,
+	CGS_RESOURCE_TYPE_IO,
+	CGS_RESOURCE_TYPE_DOORBELL,
+	CGS_RESOURCE_TYPE_ROM,
+};
+
 /**
  * struct cgs_clock_limits - Clock limits
  *
@@ -127,8 +155,53 @@
 	void			*kptr;
 };
 
+struct cgs_mode_info {
+	uint32_t		refresh_rate;
+	uint32_t		ref_clock;
+	uint32_t		vblank_time_us;
+};
+
+struct cgs_display_info {
+	uint32_t		display_count;
+	uint32_t		active_display_mask;
+	struct cgs_mode_info *mode_info;
+};
+
 typedef unsigned long cgs_handle_t;
 
+#define CGS_ACPI_METHOD_ATCS          0x53435441
+#define CGS_ACPI_METHOD_ATIF          0x46495441
+#define CGS_ACPI_METHOD_ATPX          0x58505441
+#define CGS_ACPI_FIELD_METHOD_NAME                      0x00000001
+#define CGS_ACPI_FIELD_INPUT_ARGUMENT_COUNT             0x00000002
+#define CGS_ACPI_MAX_BUFFER_SIZE     256
+#define CGS_ACPI_TYPE_ANY                      0x00
+#define CGS_ACPI_TYPE_INTEGER               0x01
+#define CGS_ACPI_TYPE_STRING                0x02
+#define CGS_ACPI_TYPE_BUFFER                0x03
+#define CGS_ACPI_TYPE_PACKAGE               0x04
+
+struct cgs_acpi_method_argument {
+	uint32_t type;
+	uint32_t method_length;
+	uint32_t data_length;
+	union{
+		uint32_t value;
+		void *pointer;
+	};
+};
+
+struct cgs_acpi_method_info {
+	uint32_t size;
+	uint32_t field;
+	uint32_t input_count;
+	uint32_t name;
+	struct cgs_acpi_method_argument *pinput_argument;
+	uint32_t output_count;
+	struct cgs_acpi_method_argument *poutput_argument;
+	uint32_t padding[9];
+};
+
 /**
  * cgs_gpu_mem_info() - Return information about memory heaps
  * @cgs_device: opaque device handle
@@ -355,6 +428,23 @@
 typedef void (*cgs_write_pci_config_dword_t)(void *cgs_device, unsigned addr,
 					     uint32_t value);
 
+
+/**
+ * cgs_get_pci_resource() - provide access to a device resource (PCI BAR)
+ * @cgs_device:	opaque device handle
+ * @resource_type:	Type of Resource (MMIO, IO, ROM, FB, DOORBELL)
+ * @size:	size of the region
+ * @offset:	offset from the start of the region
+ * @resource_base:	base address (not including offset) returned
+ *
+ * Return: 0 on success, -errno otherwise
+ */
+typedef int (*cgs_get_pci_resource_t)(void *cgs_device,
+				      enum cgs_resource_type resource_type,
+				      uint64_t size,
+				      uint64_t offset,
+				      uint64_t *resource_base);
+
 /**
  * cgs_atom_get_data_table() - Get a pointer to an ATOM BIOS data table
  * @cgs_device:	opaque device handle
@@ -493,6 +583,21 @@
 				  enum amd_ip_block_type block_type,
 				  enum amd_clockgating_state state);
 
+typedef int(*cgs_get_active_displays_info)(
+					void *cgs_device,
+					struct cgs_display_info *info);
+
+typedef int (*cgs_call_acpi_method)(void *cgs_device,
+					uint32_t acpi_method,
+					uint32_t acpi_function,
+					void *pinput, void *poutput,
+					uint32_t output_count,
+					uint32_t input_size,
+					uint32_t output_size);
+
+typedef int (*cgs_query_system_info)(void *cgs_device,
+				struct cgs_system_info *sys_info);
+
 struct cgs_ops {
 	/* memory management calls (similar to KFD interface) */
 	cgs_gpu_mem_info_t gpu_mem_info;
@@ -516,6 +621,8 @@
 	cgs_write_pci_config_byte_t write_pci_config_byte;
 	cgs_write_pci_config_word_t write_pci_config_word;
 	cgs_write_pci_config_dword_t write_pci_config_dword;
+	/* PCI resources */
+	cgs_get_pci_resource_t get_pci_resource;
 	/* ATOM BIOS */
 	cgs_atom_get_data_table_t atom_get_data_table;
 	cgs_atom_get_cmd_table_revs_t atom_get_cmd_table_revs;
@@ -533,7 +640,12 @@
 	/* cg pg interface*/
 	cgs_set_powergating_state set_powergating_state;
 	cgs_set_clockgating_state set_clockgating_state;
-	/* ACPI (TODO) */
+	/* display manager */
+	cgs_get_active_displays_info get_active_displays_info;
+	/* ACPI */
+	cgs_call_acpi_method call_acpi_method;
+	/* get system info */
+	cgs_query_system_info query_system_info;
 };
 
 struct cgs_os_ops; /* To be define in OS-specific CGS header */
@@ -620,5 +732,15 @@
 	CGS_CALL(set_powergating_state, dev, block_type, state)
 #define cgs_set_clockgating_state(dev, block_type, state)	\
 	CGS_CALL(set_clockgating_state, dev, block_type, state)
+#define cgs_get_active_displays_info(dev, info)	\
+	CGS_CALL(get_active_displays_info, dev, info)
+#define cgs_call_acpi_method(dev, acpi_method, acpi_function, pintput, poutput, output_count, input_size, output_size)	\
+	CGS_CALL(call_acpi_method, dev, acpi_method, acpi_function, pintput, poutput, output_count, input_size, output_size)
+#define cgs_query_system_info(dev, sys_info)	\
+	CGS_CALL(query_system_info, dev, sys_info)
+#define cgs_get_pci_resource(cgs_device, resource_type, size, offset, \
+	resource_base) \
+	CGS_CALL(get_pci_resource, cgs_device, resource_type, size, offset, \
+	resource_base)
 
 #endif /* _CGS_COMMON_H */
diff --git a/drivers/gpu/drm/amd/powerplay/Kconfig b/drivers/gpu/drm/amd/powerplay/Kconfig
new file mode 100644
index 0000000..af38033
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/Kconfig
@@ -0,0 +1,6 @@
+config DRM_AMD_POWERPLAY
+	bool  "Enable AMD powerplay component"
+	depends on DRM_AMDGPU
+	default n
+	help
+	  select this option will enable AMD powerplay component.
diff --git a/drivers/gpu/drm/amd/powerplay/Makefile b/drivers/gpu/drm/amd/powerplay/Makefile
new file mode 100644
index 0000000..e195bf5
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/Makefile
@@ -0,0 +1,22 @@
+
+subdir-ccflags-y += -Iinclude/drm  \
+		-Idrivers/gpu/drm/amd/powerplay/inc/  \
+		-Idrivers/gpu/drm/amd/include/asic_reg  \
+		-Idrivers/gpu/drm/amd/include  \
+		-Idrivers/gpu/drm/amd/powerplay/smumgr\
+		-Idrivers/gpu/drm/amd/powerplay/hwmgr \
+		-Idrivers/gpu/drm/amd/powerplay/eventmgr
+
+AMD_PP_PATH = ../powerplay
+
+PP_LIBS = smumgr hwmgr eventmgr
+
+AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix drivers/gpu/drm/amd/powerplay/,$(PP_LIBS)))
+
+include $(AMD_POWERPLAY)
+
+POWER_MGR = amd_powerplay.o
+
+AMD_PP_POWER = $(addprefix $(AMD_PP_PATH)/,$(POWER_MGR))
+
+AMD_POWERPLAY_FILES += $(AMD_PP_POWER)
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
new file mode 100644
index 0000000..8f5d5ed
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -0,0 +1,660 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include "amd_shared.h"
+#include "amd_powerplay.h"
+#include "pp_instance.h"
+#include "power_state.h"
+#include "eventmanager.h"
+
+#define PP_CHECK(handle)						\
+	do {								\
+		if ((handle) == NULL || (handle)->pp_valid != PP_VALID)	\
+			return -EINVAL;					\
+	} while (0)
+
+static int pp_early_init(void *handle)
+{
+	return 0;
+}
+
+static int pp_sw_init(void *handle)
+{
+	struct pp_instance *pp_handle;
+	struct pp_hwmgr  *hwmgr;
+	int ret = 0;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	pp_handle = (struct pp_instance *)handle;
+	hwmgr = pp_handle->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->pptable_func == NULL ||
+	    hwmgr->hwmgr_func == NULL ||
+	    hwmgr->pptable_func->pptable_init == NULL ||
+	    hwmgr->hwmgr_func->backend_init == NULL)
+		return -EINVAL;
+
+	ret = hwmgr->pptable_func->pptable_init(hwmgr);
+
+	if (ret == 0)
+		ret = hwmgr->hwmgr_func->backend_init(hwmgr);
+
+	return ret;
+}
+
+static int pp_sw_fini(void *handle)
+{
+	struct pp_instance *pp_handle;
+	struct pp_hwmgr  *hwmgr;
+	int ret = 0;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	pp_handle = (struct pp_instance *)handle;
+	hwmgr = pp_handle->hwmgr;
+
+	if (hwmgr != NULL || hwmgr->hwmgr_func != NULL ||
+	    hwmgr->hwmgr_func->backend_fini != NULL)
+		ret = hwmgr->hwmgr_func->backend_fini(hwmgr);
+
+	return ret;
+}
+
+static int pp_hw_init(void *handle)
+{
+	struct pp_instance *pp_handle;
+	struct pp_smumgr *smumgr;
+	struct pp_eventmgr *eventmgr;
+	int ret = 0;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	pp_handle = (struct pp_instance *)handle;
+	smumgr = pp_handle->smu_mgr;
+
+	if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
+		smumgr->smumgr_funcs->smu_init == NULL ||
+		smumgr->smumgr_funcs->start_smu == NULL)
+		return -EINVAL;
+
+	ret = smumgr->smumgr_funcs->smu_init(smumgr);
+	if (ret) {
+		printk(KERN_ERR "[ powerplay ] smc initialization failed\n");
+		return ret;
+	}
+
+	ret = smumgr->smumgr_funcs->start_smu(smumgr);
+	if (ret) {
+		printk(KERN_ERR "[ powerplay ] smc start failed\n");
+		smumgr->smumgr_funcs->smu_fini(smumgr);
+		return ret;
+	}
+
+	hw_init_power_state_table(pp_handle->hwmgr);
+	eventmgr = pp_handle->eventmgr;
+
+	if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
+		return -EINVAL;
+
+	ret = eventmgr->pp_eventmgr_init(eventmgr);
+	return 0;
+}
+
+static int pp_hw_fini(void *handle)
+{
+	struct pp_instance *pp_handle;
+	struct pp_smumgr *smumgr;
+	struct pp_eventmgr *eventmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	pp_handle = (struct pp_instance *)handle;
+	eventmgr = pp_handle->eventmgr;
+
+	if (eventmgr != NULL || eventmgr->pp_eventmgr_fini != NULL)
+		eventmgr->pp_eventmgr_fini(eventmgr);
+
+	smumgr = pp_handle->smu_mgr;
+
+	if (smumgr != NULL || smumgr->smumgr_funcs != NULL ||
+		smumgr->smumgr_funcs->smu_fini != NULL)
+		smumgr->smumgr_funcs->smu_fini(smumgr);
+
+	return 0;
+}
+
+static bool pp_is_idle(void *handle)
+{
+	return 0;
+}
+
+static int pp_wait_for_idle(void *handle)
+{
+	return 0;
+}
+
+static int pp_sw_reset(void *handle)
+{
+	return 0;
+}
+
+static void pp_print_status(void *handle)
+{
+
+}
+
+static int pp_set_clockgating_state(void *handle,
+				    enum amd_clockgating_state state)
+{
+	return 0;
+}
+
+static int pp_set_powergating_state(void *handle,
+				    enum amd_powergating_state state)
+{
+	return 0;
+}
+
+static int pp_suspend(void *handle)
+{
+	struct pp_instance *pp_handle;
+	struct pp_eventmgr *eventmgr;
+	struct pem_event_data event_data = { {0} };
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	pp_handle = (struct pp_instance *)handle;
+	eventmgr = pp_handle->eventmgr;
+	pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
+	return 0;
+}
+
+static int pp_resume(void *handle)
+{
+	struct pp_instance *pp_handle;
+	struct pp_eventmgr *eventmgr;
+	struct pem_event_data event_data = { {0} };
+	struct pp_smumgr *smumgr;
+	int ret;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	pp_handle = (struct pp_instance *)handle;
+	smumgr = pp_handle->smu_mgr;
+
+	if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
+		smumgr->smumgr_funcs->start_smu == NULL)
+		return -EINVAL;
+
+	ret = smumgr->smumgr_funcs->start_smu(smumgr);
+	if (ret) {
+		printk(KERN_ERR "[ powerplay ] smc start failed\n");
+		smumgr->smumgr_funcs->smu_fini(smumgr);
+		return ret;
+	}
+
+	eventmgr = pp_handle->eventmgr;
+	pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
+
+	return 0;
+}
+
+const struct amd_ip_funcs pp_ip_funcs = {
+	.early_init = pp_early_init,
+	.late_init = NULL,
+	.sw_init = pp_sw_init,
+	.sw_fini = pp_sw_fini,
+	.hw_init = pp_hw_init,
+	.hw_fini = pp_hw_fini,
+	.suspend = pp_suspend,
+	.resume = pp_resume,
+	.is_idle = pp_is_idle,
+	.wait_for_idle = pp_wait_for_idle,
+	.soft_reset = pp_sw_reset,
+	.print_status = pp_print_status,
+	.set_clockgating_state = pp_set_clockgating_state,
+	.set_powergating_state = pp_set_powergating_state,
+};
+
+static int pp_dpm_load_fw(void *handle)
+{
+	return 0;
+}
+
+static int pp_dpm_fw_loading_complete(void *handle)
+{
+	return 0;
+}
+
+static int pp_dpm_force_performance_level(void *handle,
+					enum amd_dpm_forced_level level)
+{
+	struct pp_instance *pp_handle;
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	pp_handle = (struct pp_instance *)handle;
+
+	hwmgr = pp_handle->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	    hwmgr->hwmgr_func->force_dpm_level == NULL)
+		return -EINVAL;
+
+	hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
+
+	return 0;
+}
+
+static enum amd_dpm_forced_level pp_dpm_get_performance_level(
+								void *handle)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL)
+		return -EINVAL;
+
+	return (((struct pp_instance *)handle)->hwmgr->dpm_level);
+}
+
+static int pp_dpm_get_sclk(void *handle, bool low)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	    hwmgr->hwmgr_func->get_sclk == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->get_sclk(hwmgr, low);
+}
+
+static int pp_dpm_get_mclk(void *handle, bool low)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	    hwmgr->hwmgr_func->get_mclk == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->get_mclk(hwmgr, low);
+}
+
+static int pp_dpm_powergate_vce(void *handle, bool gate)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	    hwmgr->hwmgr_func->powergate_vce == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
+}
+
+static int pp_dpm_powergate_uvd(void *handle, bool gate)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	    hwmgr->hwmgr_func->powergate_uvd == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
+}
+
+static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type  state)
+{
+	switch (state) {
+	case POWER_STATE_TYPE_BATTERY:
+		return PP_StateUILabel_Battery;
+	case POWER_STATE_TYPE_BALANCED:
+		return PP_StateUILabel_Balanced;
+	case POWER_STATE_TYPE_PERFORMANCE:
+		return PP_StateUILabel_Performance;
+	default:
+		return PP_StateUILabel_None;
+	}
+}
+
+int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, void *output)
+{
+	int ret = 0;
+	struct pp_instance *pp_handle;
+	struct pem_event_data data = { {0} };
+
+	pp_handle = (struct pp_instance *)handle;
+
+	if (pp_handle == NULL)
+		return -EINVAL;
+
+	switch (event_id) {
+	case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
+		ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
+		break;
+	case AMD_PP_EVENT_ENABLE_USER_STATE:
+	{
+		enum amd_pm_state_type  ps;
+
+		if (input == NULL)
+			return -EINVAL;
+		ps = *(unsigned long *)input;
+
+		data.requested_ui_label = power_state_convert(ps);
+		ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
+	}
+	break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
+{
+	struct pp_hwmgr *hwmgr;
+	struct pp_power_state *state;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->current_ps == NULL)
+		return -EINVAL;
+
+	state = hwmgr->current_ps;
+
+	switch (state->classification.ui_label) {
+	case PP_StateUILabel_Battery:
+		return POWER_STATE_TYPE_BATTERY;
+	case PP_StateUILabel_Balanced:
+		return POWER_STATE_TYPE_BALANCED;
+	case PP_StateUILabel_Performance:
+		return POWER_STATE_TYPE_PERFORMANCE;
+	default:
+		return POWER_STATE_TYPE_DEFAULT;
+	}
+}
+
+static void
+pp_debugfs_print_current_performance_level(void *handle,
+					       struct seq_file *m)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	  hwmgr->hwmgr_func->print_current_perforce_level == NULL)
+		return;
+
+	hwmgr->hwmgr_func->print_current_perforce_level(hwmgr, m);
+}
+
+static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	  hwmgr->hwmgr_func->set_fan_control_mode == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
+}
+
+static int pp_dpm_get_fan_control_mode(void *handle)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	  hwmgr->hwmgr_func->get_fan_control_mode == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
+}
+
+static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	  hwmgr->hwmgr_func->set_fan_speed_percent == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
+}
+
+static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	  hwmgr->hwmgr_func->get_fan_speed_percent == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
+}
+
+static int pp_dpm_get_temperature(void *handle)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
+	  hwmgr->hwmgr_func->get_temperature == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->get_temperature(hwmgr);
+}
+
+const struct amd_powerplay_funcs pp_dpm_funcs = {
+	.get_temperature = pp_dpm_get_temperature,
+	.load_firmware = pp_dpm_load_fw,
+	.wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
+	.force_performance_level = pp_dpm_force_performance_level,
+	.get_performance_level = pp_dpm_get_performance_level,
+	.get_current_power_state = pp_dpm_get_current_power_state,
+	.get_sclk = pp_dpm_get_sclk,
+	.get_mclk = pp_dpm_get_mclk,
+	.powergate_vce = pp_dpm_powergate_vce,
+	.powergate_uvd = pp_dpm_powergate_uvd,
+	.dispatch_tasks = pp_dpm_dispatch_tasks,
+	.print_current_performance_level = pp_debugfs_print_current_performance_level,
+	.set_fan_control_mode = pp_dpm_set_fan_control_mode,
+	.get_fan_control_mode = pp_dpm_get_fan_control_mode,
+	.set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
+	.get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
+};
+
+static int amd_pp_instance_init(struct amd_pp_init *pp_init,
+				struct amd_powerplay *amd_pp)
+{
+	int ret;
+	struct pp_instance *handle;
+
+	handle = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
+	if (handle == NULL)
+		return -ENOMEM;
+
+	handle->pp_valid = PP_VALID;
+
+	ret = smum_init(pp_init, handle);
+	if (ret)
+		goto fail_smum;
+
+	ret = hwmgr_init(pp_init, handle);
+	if (ret)
+		goto fail_hwmgr;
+
+	ret = eventmgr_init(handle);
+	if (ret)
+		goto fail_eventmgr;
+
+	amd_pp->pp_handle = handle;
+	return 0;
+
+fail_eventmgr:
+	hwmgr_fini(handle->hwmgr);
+fail_hwmgr:
+	smum_fini(handle->smu_mgr);
+fail_smum:
+	kfree(handle);
+	return ret;
+}
+
+static int amd_pp_instance_fini(void *handle)
+{
+	struct pp_instance *instance = (struct pp_instance *)handle;
+
+	if (instance == NULL)
+		return -EINVAL;
+
+	eventmgr_fini(instance->eventmgr);
+
+	hwmgr_fini(instance->hwmgr);
+
+	smum_fini(instance->smu_mgr);
+
+	kfree(handle);
+	return 0;
+}
+
+int amd_powerplay_init(struct amd_pp_init *pp_init,
+		       struct amd_powerplay *amd_pp)
+{
+	int ret;
+
+	if (pp_init == NULL || amd_pp == NULL)
+		return -EINVAL;
+
+	ret = amd_pp_instance_init(pp_init, amd_pp);
+
+	if (ret)
+		return ret;
+
+	amd_pp->ip_funcs = &pp_ip_funcs;
+	amd_pp->pp_funcs = &pp_dpm_funcs;
+
+	return 0;
+}
+
+int amd_powerplay_fini(void *handle)
+{
+	amd_pp_instance_fini(handle);
+
+	return 0;
+}
+
+/* export this function to DAL */
+
+int amd_powerplay_display_configuration_change(void *handle, const void *input)
+{
+	struct pp_hwmgr  *hwmgr;
+	const struct amd_pp_display_configuration *display_config = input;
+
+	PP_CHECK((struct pp_instance *)handle);
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	phm_store_dal_configuration_data(hwmgr, display_config);
+
+	return 0;
+}
+
+int amd_powerplay_get_display_power_level(void *handle,
+		struct amd_pp_dal_clock_info *output)
+{
+	struct pp_hwmgr  *hwmgr;
+
+	PP_CHECK((struct pp_instance *)handle);
+
+	if (output == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	return phm_get_dal_power_level(hwmgr, output);
+}
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/Makefile b/drivers/gpu/drm/amd/powerplay/eventmgr/Makefile
new file mode 100644
index 0000000..7509e38
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the 'event manager' sub-component of powerplay.
+# It provides the event management services for the driver.
+
+EVENT_MGR = eventmgr.o eventinit.o eventmanagement.o  \
+		eventactionchains.o eventsubchains.o eventtasks.o psm.o
+
+AMD_PP_EVENT = $(addprefix $(AMD_PP_PATH)/eventmgr/,$(EVENT_MGR))
+
+AMD_POWERPLAY_FILES += $(AMD_PP_EVENT)
+
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c
new file mode 100644
index 0000000..83be3cf
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include "eventmgr.h"
+#include "eventactionchains.h"
+#include "eventsubchains.h"
+
+static const pem_event_action *initialize_event[] = {
+	block_adjust_power_state_tasks,
+	power_budget_tasks,
+	system_config_tasks,
+	setup_asic_tasks,
+	enable_dynamic_state_management_tasks,
+	enable_clock_power_gatings_tasks,
+	get_2d_performance_state_tasks,
+	set_performance_state_tasks,
+	initialize_thermal_controller_tasks,
+	conditionally_force_3d_performance_state_tasks,
+	process_vbios_eventinfo_tasks,
+	broadcast_power_policy_tasks,
+	NULL
+};
+
+const struct action_chain initialize_action_chain = {
+	"Initialize",
+	initialize_event
+};
+
+static const pem_event_action *uninitialize_event[] = {
+	ungate_all_display_phys_tasks,
+	uninitialize_display_phy_access_tasks,
+	disable_gfx_voltage_island_power_gating_tasks,
+	disable_gfx_clock_gating_tasks,
+	set_boot_state_tasks,
+	adjust_power_state_tasks,
+	disable_dynamic_state_management_tasks,
+	disable_clock_power_gatings_tasks,
+	cleanup_asic_tasks,
+	prepare_for_pnp_stop_tasks,
+	NULL
+};
+
+const struct action_chain uninitialize_action_chain = {
+	"Uninitialize",
+	uninitialize_event
+};
+
+static const pem_event_action *power_source_change_event_pp_enabled[] = {
+	set_power_source_tasks,
+	set_power_saving_state_tasks,
+	adjust_power_state_tasks,
+	enable_disable_fps_tasks,
+	set_nbmcu_state_tasks,
+	broadcast_power_policy_tasks,
+	NULL
+};
+
+const struct action_chain power_source_change_action_chain_pp_enabled = {
+	"Power source change - PowerPlay enabled",
+	power_source_change_event_pp_enabled
+};
+
+static const pem_event_action *power_source_change_event_pp_disabled[] = {
+	set_power_source_tasks,
+	set_nbmcu_state_tasks,
+	NULL
+};
+
+const struct action_chain power_source_changes_action_chain_pp_disabled = {
+	"Power source change - PowerPlay disabled",
+	power_source_change_event_pp_disabled
+};
+
+static const pem_event_action *power_source_change_event_hardware_dc[] = {
+	set_power_source_tasks,
+	set_power_saving_state_tasks,
+	adjust_power_state_tasks,
+	enable_disable_fps_tasks,
+	reset_hardware_dc_notification_tasks,
+	set_nbmcu_state_tasks,
+	broadcast_power_policy_tasks,
+	NULL
+};
+
+const struct action_chain power_source_change_action_chain_hardware_dc = {
+	"Power source change - with Hardware DC switching",
+	power_source_change_event_hardware_dc
+};
+
+static const pem_event_action *suspend_event[] = {
+	reset_display_phy_access_tasks,
+	unregister_interrupt_tasks,
+	disable_gfx_voltage_island_power_gating_tasks,
+	disable_gfx_clock_gating_tasks,
+	notify_smu_suspend_tasks,
+	disable_smc_firmware_ctf_tasks,
+	set_boot_state_tasks,
+	adjust_power_state_tasks,
+	disable_fps_tasks,
+	vari_bright_suspend_tasks,
+	reset_fan_speed_to_default_tasks,
+	power_down_asic_tasks,
+	disable_stutter_mode_tasks,
+	set_connected_standby_tasks,
+	block_hw_access_tasks,
+	NULL
+};
+
+const struct action_chain suspend_action_chain = {
+	"Suspend",
+	suspend_event
+};
+
+static const pem_event_action *resume_event[] = {
+	unblock_hw_access_tasks,
+	resume_connected_standby_tasks,
+	notify_smu_resume_tasks,
+	reset_display_configCounter_tasks,
+	update_dal_configuration_tasks,
+	vari_bright_resume_tasks,
+	block_adjust_power_state_tasks,
+	setup_asic_tasks,
+	enable_stutter_mode_tasks, /*must do this in boot state and before SMC is started */
+	enable_dynamic_state_management_tasks,
+	enable_clock_power_gatings_tasks,
+	enable_disable_bapm_tasks,
+	initialize_thermal_controller_tasks,
+	reset_boot_state_tasks,
+	adjust_power_state_tasks,
+	enable_disable_fps_tasks,
+	notify_hw_power_source_tasks,
+	process_vbios_event_info_tasks,
+	enable_gfx_clock_gating_tasks,
+	enable_gfx_voltage_island_power_gating_tasks,
+	reset_clock_gating_tasks,
+	notify_smu_vpu_recovery_end_tasks,
+	disable_vpu_cap_tasks,
+	execute_escape_sequence_tasks,
+	NULL
+};
+
+
+const struct action_chain resume_action_chain = {
+	"resume",
+	resume_event
+};
+
+static const pem_event_action *complete_init_event[] = {
+	adjust_power_state_tasks,
+	enable_gfx_clock_gating_tasks,
+	enable_gfx_voltage_island_power_gating_tasks,
+	notify_power_state_change_tasks,
+	NULL
+};
+
+const struct action_chain complete_init_action_chain = {
+	"complete init",
+	complete_init_event
+};
+
+static const pem_event_action *enable_gfx_clock_gating_event[] = {
+	enable_gfx_clock_gating_tasks,
+	NULL
+};
+
+const struct action_chain enable_gfx_clock_gating_action_chain = {
+	"enable gfx clock gate",
+	enable_gfx_clock_gating_event
+};
+
+static const pem_event_action *disable_gfx_clock_gating_event[] = {
+	disable_gfx_clock_gating_tasks,
+	NULL
+};
+
+const struct action_chain disable_gfx_clock_gating_action_chain = {
+	"disable gfx clock gate",
+	disable_gfx_clock_gating_event
+};
+
+static const pem_event_action *enable_cgpg_event[] = {
+	enable_cgpg_tasks,
+	NULL
+};
+
+const struct action_chain enable_cgpg_action_chain = {
+	"eable cg pg",
+	enable_cgpg_event
+};
+
+static const pem_event_action *disable_cgpg_event[] = {
+	disable_cgpg_tasks,
+	NULL
+};
+
+const struct action_chain disable_cgpg_action_chain = {
+	"disable cg pg",
+	disable_cgpg_event
+};
+
+
+/* Enable user _2d performance and activate */
+
+static const pem_event_action *enable_user_state_event[] = {
+	create_new_user_performance_state_tasks,
+	adjust_power_state_tasks,
+	NULL
+};
+
+const struct action_chain enable_user_state_action_chain = {
+	"Enable user state",
+	enable_user_state_event
+};
+
+static const pem_event_action *enable_user_2d_performance_event[] = {
+	enable_user_2d_performance_tasks,
+	add_user_2d_performance_state_tasks,
+	set_performance_state_tasks,
+	adjust_power_state_tasks,
+	delete_user_2d_performance_state_tasks,
+	NULL
+};
+
+const struct action_chain enable_user_2d_performance_action_chain = {
+	"enable_user_2d_performance_event_activate",
+	enable_user_2d_performance_event
+};
+
+
+static const pem_event_action *disable_user_2d_performance_event[] = {
+	disable_user_2d_performance_tasks,
+	delete_user_2d_performance_state_tasks,
+	NULL
+};
+
+const struct action_chain disable_user_2d_performance_action_chain = {
+	"disable_user_2d_performance_event",
+	disable_user_2d_performance_event
+};
+
+
+static const pem_event_action *display_config_change_event[] = {
+	/* countDisplayConfigurationChangeEventTasks, */
+	unblock_adjust_power_state_tasks,
+	set_cpu_power_state,
+	notify_hw_power_source_tasks,
+	/* updateDALConfigurationTasks,
+	variBrightDisplayConfigurationChangeTasks, */
+	adjust_power_state_tasks,
+	/*enableDisableFPSTasks,
+	setNBMCUStateTasks,
+	notifyPCIEDeviceReadyTasks,*/
+	NULL
+};
+
+const struct action_chain display_config_change_action_chain = {
+	"Display configuration change",
+	display_config_change_event
+};
+
+static const pem_event_action *readjust_power_state_event[] = {
+	adjust_power_state_tasks,
+	NULL
+};
+
+const struct action_chain readjust_power_state_action_chain = {
+	"re-adjust power state",
+	readjust_power_state_event
+};
+
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.h
new file mode 100644
index 0000000..f181e53
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _EVENT_ACTION_CHAINS_H_
+#define _EVENT_ACTION_CHAINS_H_
+#include "eventmgr.h"
+
+extern const struct action_chain initialize_action_chain;
+
+extern const struct action_chain uninitialize_action_chain;
+
+extern const struct action_chain power_source_change_action_chain_pp_enabled;
+
+extern const struct action_chain power_source_changes_action_chain_pp_disabled;
+
+extern const struct action_chain power_source_change_action_chain_hardware_dc;
+
+extern const struct action_chain suspend_action_chain;
+
+extern const struct action_chain resume_action_chain;
+
+extern const struct action_chain complete_init_action_chain;
+
+extern const struct action_chain enable_gfx_clock_gating_action_chain;
+
+extern const struct action_chain disable_gfx_clock_gating_action_chain;
+
+extern const struct action_chain enable_cgpg_action_chain;
+
+extern const struct action_chain disable_cgpg_action_chain;
+
+extern const struct action_chain enable_user_2d_performance_action_chain;
+
+extern const struct action_chain disable_user_2d_performance_action_chain;
+
+extern const struct action_chain enable_user_state_action_chain;
+
+extern const struct action_chain readjust_power_state_action_chain;
+
+extern const struct action_chain display_config_change_action_chain;
+
+#endif /*_EVENT_ACTION_CHAINS_H_*/
+
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.c
new file mode 100644
index 0000000..d5ec8cc
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include "eventmgr.h"
+#include "eventinit.h"
+#include "ppinterrupt.h"
+#include "hardwaremanager.h"
+
+void pem_init_feature_info(struct pp_eventmgr *eventmgr)
+{
+
+	/* PowerPlay info */
+	eventmgr->ui_state_info[PP_PowerSource_AC].default_ui_lable =
+					    PP_StateUILabel_Performance;
+
+	eventmgr->ui_state_info[PP_PowerSource_AC].current_ui_label =
+					    PP_StateUILabel_Performance;
+
+	eventmgr->ui_state_info[PP_PowerSource_DC].default_ui_lable =
+						  PP_StateUILabel_Battery;
+
+	eventmgr->ui_state_info[PP_PowerSource_DC].current_ui_label =
+						  PP_StateUILabel_Battery;
+
+	if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_PowerPlaySupport)) {
+		eventmgr->features[PP_Feature_PowerPlay].supported = true;
+		eventmgr->features[PP_Feature_PowerPlay].version = PEM_CURRENT_POWERPLAY_FEATURE_VERSION;
+		eventmgr->features[PP_Feature_PowerPlay].enabled_default = true;
+		eventmgr->features[PP_Feature_PowerPlay].enabled = true;
+	} else {
+		eventmgr->features[PP_Feature_PowerPlay].supported = false;
+		eventmgr->features[PP_Feature_PowerPlay].enabled = false;
+		eventmgr->features[PP_Feature_PowerPlay].enabled_default = false;
+	}
+
+	eventmgr->features[PP_Feature_Force3DClock].supported = true;
+	eventmgr->features[PP_Feature_Force3DClock].enabled = false;
+	eventmgr->features[PP_Feature_Force3DClock].enabled_default = false;
+	eventmgr->features[PP_Feature_Force3DClock].version = 1;
+
+	/* over drive*/
+	eventmgr->features[PP_Feature_User2DPerformance].version = 4;
+	eventmgr->features[PP_Feature_User3DPerformance].version = 4;
+	eventmgr->features[PP_Feature_OverdriveTest].version = 4;
+
+	eventmgr->features[PP_Feature_OverDrive].version = 4;
+	eventmgr->features[PP_Feature_OverDrive].enabled = false;
+	eventmgr->features[PP_Feature_OverDrive].enabled_default = false;
+
+	eventmgr->features[PP_Feature_User2DPerformance].supported = false;
+	eventmgr->features[PP_Feature_User2DPerformance].enabled = false;
+	eventmgr->features[PP_Feature_User2DPerformance].enabled_default = false;
+
+	eventmgr->features[PP_Feature_User3DPerformance].supported = false;
+	eventmgr->features[PP_Feature_User3DPerformance].enabled = false;
+	eventmgr->features[PP_Feature_User3DPerformance].enabled_default = false;
+
+	eventmgr->features[PP_Feature_OverdriveTest].supported = false;
+	eventmgr->features[PP_Feature_OverdriveTest].enabled = false;
+	eventmgr->features[PP_Feature_OverdriveTest].enabled_default = false;
+
+	eventmgr->features[PP_Feature_OverDrive].supported = false;
+
+	eventmgr->features[PP_Feature_PowerBudgetWaiver].enabled_default = false;
+	eventmgr->features[PP_Feature_PowerBudgetWaiver].version = 1;
+	eventmgr->features[PP_Feature_PowerBudgetWaiver].supported = false;
+	eventmgr->features[PP_Feature_PowerBudgetWaiver].enabled = false;
+
+	/* Multi UVD States support */
+	eventmgr->features[PP_Feature_MultiUVDState].supported = false;
+	eventmgr->features[PP_Feature_MultiUVDState].enabled = false;
+	eventmgr->features[PP_Feature_MultiUVDState].enabled_default = false;
+
+	/* Dynamic UVD States support */
+	eventmgr->features[PP_Feature_DynamicUVDState].supported = false;
+	eventmgr->features[PP_Feature_DynamicUVDState].enabled = false;
+	eventmgr->features[PP_Feature_DynamicUVDState].enabled_default = false;
+
+	/* VCE DPM support */
+	eventmgr->features[PP_Feature_VCEDPM].supported = false;
+	eventmgr->features[PP_Feature_VCEDPM].enabled = false;
+	eventmgr->features[PP_Feature_VCEDPM].enabled_default = false;
+
+	/* ACP PowerGating support */
+	eventmgr->features[PP_Feature_ACP_POWERGATING].supported = false;
+	eventmgr->features[PP_Feature_ACP_POWERGATING].enabled = false;
+	eventmgr->features[PP_Feature_ACP_POWERGATING].enabled_default = false;
+
+	/* PPM support */
+	eventmgr->features[PP_Feature_PPM].version = 1;
+	eventmgr->features[PP_Feature_PPM].supported = false;
+	eventmgr->features[PP_Feature_PPM].enabled = false;
+
+	/* FFC support (enables fan and temp settings, Gemini needs temp settings) */
+	if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_ODFuzzyFanControlSupport) ||
+	    phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_GeminiRegulatorFanControlSupport)) {
+		eventmgr->features[PP_Feature_FFC].version = 1;
+		eventmgr->features[PP_Feature_FFC].supported = true;
+		eventmgr->features[PP_Feature_FFC].enabled = true;
+		eventmgr->features[PP_Feature_FFC].enabled_default = true;
+	} else {
+		eventmgr->features[PP_Feature_FFC].supported = false;
+		eventmgr->features[PP_Feature_FFC].enabled = false;
+		eventmgr->features[PP_Feature_FFC].enabled_default = false;
+	}
+
+	eventmgr->features[PP_Feature_VariBright].supported = false;
+	eventmgr->features[PP_Feature_VariBright].enabled = false;
+	eventmgr->features[PP_Feature_VariBright].enabled_default = false;
+
+	eventmgr->features[PP_Feature_BACO].supported = false;
+	eventmgr->features[PP_Feature_BACO].supported = false;
+	eventmgr->features[PP_Feature_BACO].enabled_default = false;
+
+	/* PowerDown feature support */
+	eventmgr->features[PP_Feature_PowerDown].supported = false;
+	eventmgr->features[PP_Feature_PowerDown].enabled = false;
+	eventmgr->features[PP_Feature_PowerDown].enabled_default = false;
+
+	eventmgr->features[PP_Feature_FPS].version = 1;
+	eventmgr->features[PP_Feature_FPS].supported = false;
+	eventmgr->features[PP_Feature_FPS].enabled_default = false;
+	eventmgr->features[PP_Feature_FPS].enabled = false;
+
+	eventmgr->features[PP_Feature_ViPG].version = 1;
+	eventmgr->features[PP_Feature_ViPG].supported = false;
+	eventmgr->features[PP_Feature_ViPG].enabled_default = false;
+	eventmgr->features[PP_Feature_ViPG].enabled = false;
+}
+
+static int thermal_interrupt_callback(void *private_data,
+				      unsigned src_id, const uint32_t *iv_entry)
+{
+	/* TO DO hanle PEM_Event_ThermalNotification (struct pp_eventmgr *)private_data*/
+	printk("current thermal is out of range \n");
+	return 0;
+}
+
+int pem_register_interrupts(struct pp_eventmgr *eventmgr)
+{
+	int result = 0;
+	struct pp_interrupt_registration_info info;
+
+	info.call_back = thermal_interrupt_callback;
+	info.context = eventmgr;
+
+	result = phm_register_thermal_interrupt(eventmgr->hwmgr, &info);
+
+	/* TODO:
+	 * 2. Register CTF event interrupt
+	 * 3. Register for vbios events interrupt
+	 * 4. Register External Throttle Interrupt
+	 * 5. Register Smc To Host Interrupt
+	 * */
+	return result;
+}
+
+
+int pem_unregister_interrupts(struct pp_eventmgr *eventmgr)
+{
+	return 0;
+}
+
+
+void pem_uninit_featureInfo(struct pp_eventmgr *eventmgr)
+{
+	eventmgr->features[PP_Feature_MultiUVDState].supported = false;
+	eventmgr->features[PP_Feature_VariBright].supported = false;
+	eventmgr->features[PP_Feature_PowerBudgetWaiver].supported = false;
+	eventmgr->features[PP_Feature_OverDrive].supported = false;
+	eventmgr->features[PP_Feature_OverdriveTest].supported = false;
+	eventmgr->features[PP_Feature_User3DPerformance].supported = false;
+	eventmgr->features[PP_Feature_User2DPerformance].supported = false;
+	eventmgr->features[PP_Feature_PowerPlay].supported = false;
+	eventmgr->features[PP_Feature_Force3DClock].supported = false;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.h
new file mode 100644
index 0000000..9ef96aa
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _EVENTINIT_H_
+#define _EVENTINIT_H_
+
+#define PEM_CURRENT_POWERPLAY_FEATURE_VERSION 4
+
+void pem_init_feature_info(struct pp_eventmgr *eventmgr);
+void pem_uninit_featureInfo(struct pp_eventmgr *eventmgr);
+int pem_register_interrupts(struct pp_eventmgr *eventmgr);
+int pem_unregister_interrupts(struct pp_eventmgr *eventmgr);
+
+#endif /* _EVENTINIT_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c
new file mode 100644
index 0000000..1e2ad56
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include "eventmanagement.h"
+#include "eventmgr.h"
+#include "eventactionchains.h"
+
+int pem_init_event_action_chains(struct pp_eventmgr *eventmgr)
+{
+	int i;
+
+	for (i = 0; i < AMD_PP_EVENT_MAX; i++)
+		eventmgr->event_chain[i] = NULL;
+
+	eventmgr->event_chain[AMD_PP_EVENT_SUSPEND] = pem_get_suspend_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_INITIALIZE] = pem_get_initialize_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_UNINITIALIZE] = pem_get_uninitialize_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_POWER_SOURCE_CHANGE] = pem_get_power_source_change_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_HIBERNATE] = pem_get_hibernate_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_RESUME] = pem_get_resume_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_THERMAL_NOTIFICATION] = pem_get_thermal_notification_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_VBIOS_NOTIFICATION] = pem_get_vbios_notification_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_ENTER_THERMAL_STATE] = pem_get_enter_thermal_state_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_EXIT_THERMAL_STATE] = pem_get_exit_thermal_state_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_ENABLE_POWER_PLAY] = pem_get_enable_powerplay_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_DISABLE_POWER_PLAY] = pem_get_disable_powerplay_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_ENABLE_OVER_DRIVE_TEST] = pem_get_enable_overdrive_test_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_DISABLE_OVER_DRIVE_TEST] = pem_get_disable_overdrive_test_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_ENABLE_GFX_CLOCK_GATING] = pem_get_enable_gfx_clock_gating_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_DISABLE_GFX_CLOCK_GATING] = pem_get_disable_gfx_clock_gating_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_ENABLE_CGPG] = pem_get_enable_cgpg_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_DISABLE_CGPG] = pem_get_disable_cgpg_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_COMPLETE_INIT] = pem_get_complete_init_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_SCREEN_ON] = pem_get_screen_on_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_SCREEN_OFF] = pem_get_screen_off_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_PRE_SUSPEND] = pem_get_pre_suspend_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_PRE_RESUME] = pem_get_pre_resume_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_ENABLE_USER_STATE] = pem_enable_user_state_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_READJUST_POWER_STATE] = pem_readjust_power_state_action_chain(eventmgr);
+	eventmgr->event_chain[AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE] = pem_display_config_change_action_chain(eventmgr);
+	return 0;
+}
+
+int pem_excute_event_chain(struct pp_eventmgr *eventmgr, const struct action_chain *event_chain, struct pem_event_data *event_data)
+{
+	const pem_event_action **paction_chain;
+	const pem_event_action *psub_chain;
+	int tmp_result = 0;
+	int result = 0;
+
+	if (eventmgr == NULL || event_chain == NULL || event_data == NULL)
+		return -EINVAL;
+
+	for (paction_chain = event_chain->action_chain; NULL != *paction_chain; paction_chain++) {
+		if (0 != result)
+			return result;
+
+		for (psub_chain = *paction_chain; NULL != *psub_chain; psub_chain++) {
+			tmp_result = (*psub_chain)(eventmgr, event_data);
+			if (0 == result)
+				result = tmp_result;
+		}
+	}
+
+	return result;
+}
+
+const struct action_chain *pem_get_suspend_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &suspend_action_chain;
+}
+
+const struct action_chain *pem_get_initialize_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &initialize_action_chain;
+}
+
+const struct action_chain *pem_get_uninitialize_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &uninitialize_action_chain;
+}
+
+const struct action_chain *pem_get_power_source_change_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &power_source_change_action_chain_pp_enabled;  /* other case base on feature info*/
+}
+
+const struct action_chain *pem_get_resume_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &resume_action_chain;
+}
+
+const struct action_chain *pem_get_hibernate_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_thermal_notification_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_vbios_notification_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_enter_thermal_state_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_exit_thermal_state_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_enable_powerplay_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_disable_powerplay_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_enable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_disable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_enable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &enable_gfx_clock_gating_action_chain;
+}
+
+const struct action_chain *pem_get_disable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &disable_gfx_clock_gating_action_chain;
+}
+
+const struct action_chain *pem_get_enable_cgpg_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &enable_cgpg_action_chain;
+}
+
+const struct action_chain *pem_get_disable_cgpg_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &disable_cgpg_action_chain;
+}
+
+const struct action_chain *pem_get_complete_init_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &complete_init_action_chain;
+}
+
+const struct action_chain *pem_get_screen_on_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_screen_off_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_pre_suspend_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_get_pre_resume_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return NULL;
+}
+
+const struct action_chain *pem_enable_user_state_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &enable_user_state_action_chain;
+}
+
+const struct action_chain *pem_readjust_power_state_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &readjust_power_state_action_chain;
+}
+
+const struct action_chain *pem_display_config_change_action_chain(struct pp_eventmgr *eventmgr)
+{
+	return &display_config_change_action_chain;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.h
new file mode 100644
index 0000000..383d4b2
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _EVENT_MANAGEMENT_H_
+#define _EVENT_MANAGEMENT_H_
+
+#include "eventmgr.h"
+
+int pem_init_event_action_chains(struct pp_eventmgr *eventmgr);
+int pem_excute_event_chain(struct pp_eventmgr *eventmgr, const struct action_chain *event_chain, struct pem_event_data *event_data);
+const struct action_chain *pem_get_suspend_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_initialize_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_uninitialize_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_power_source_change_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_resume_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_hibernate_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_thermal_notification_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_vbios_notification_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_enter_thermal_state_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_exit_thermal_state_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_enable_powerplay_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_disable_powerplay_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_enable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_disable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_enable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_disable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_enable_cgpg_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_disable_cgpg_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_complete_init_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_screen_on_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_screen_off_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_pre_suspend_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_get_pre_resume_action_chain(struct pp_eventmgr *eventmgr);
+
+extern const struct action_chain *pem_enable_user_state_action_chain(struct pp_eventmgr *eventmgr);
+extern const struct action_chain *pem_readjust_power_state_action_chain(struct pp_eventmgr *eventmgr);
+const struct action_chain *pem_display_config_change_action_chain(struct pp_eventmgr *eventmgr);
+
+
+#endif /* _EVENT_MANAGEMENT_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c
new file mode 100644
index 0000000..52a3efc
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include "eventmgr.h"
+#include "hwmgr.h"
+#include "eventinit.h"
+#include "eventmanagement.h"
+
+static int pem_init(struct pp_eventmgr *eventmgr)
+{
+	int result = 0;
+	struct pem_event_data event_data;
+
+	/* Initialize PowerPlay feature info */
+	pem_init_feature_info(eventmgr);
+
+	/* Initialize event action chains */
+	pem_init_event_action_chains(eventmgr);
+
+	/* Call initialization event */
+	result = pem_handle_event(eventmgr, AMD_PP_EVENT_INITIALIZE, &event_data);
+
+	if (0 != result)
+		return result;
+
+	/* Register interrupt callback functions */
+	result = pem_register_interrupts(eventmgr);
+	return 0;
+}
+
+static void pem_fini(struct pp_eventmgr *eventmgr)
+{
+	struct pem_event_data event_data;
+
+	pem_uninit_featureInfo(eventmgr);
+	pem_unregister_interrupts(eventmgr);
+
+	pem_handle_event(eventmgr, AMD_PP_EVENT_UNINITIALIZE, &event_data);
+
+	if (eventmgr != NULL)
+		kfree(eventmgr);
+}
+
+int eventmgr_init(struct pp_instance *handle)
+{
+	int result = 0;
+	struct pp_eventmgr *eventmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	eventmgr = kzalloc(sizeof(struct pp_eventmgr), GFP_KERNEL);
+	if (eventmgr == NULL)
+		return -ENOMEM;
+
+	eventmgr->hwmgr = handle->hwmgr;
+	handle->eventmgr = eventmgr;
+
+	eventmgr->platform_descriptor = &(eventmgr->hwmgr->platform_descriptor);
+	eventmgr->pp_eventmgr_init = pem_init;
+	eventmgr->pp_eventmgr_fini = pem_fini;
+
+	return result;
+}
+
+int eventmgr_fini(struct pp_eventmgr *eventmgr)
+{
+	kfree(eventmgr);
+	return 0;
+}
+
+static int pem_handle_event_unlocked(struct pp_eventmgr *eventmgr, enum amd_pp_event event, struct pem_event_data *data)
+{
+	if (eventmgr == NULL || event >= AMD_PP_EVENT_MAX || data == NULL)
+		return -EINVAL;
+
+	return pem_excute_event_chain(eventmgr, eventmgr->event_chain[event], data);
+}
+
+int pem_handle_event(struct pp_eventmgr *eventmgr, enum amd_pp_event event, struct pem_event_data *event_data)
+{
+	int r = 0;
+
+	r = pem_handle_event_unlocked(eventmgr, event, event_data);
+
+	return r;
+}
+
+bool pem_is_hw_access_blocked(struct pp_eventmgr *eventmgr)
+{
+	return (eventmgr->block_adjust_power_state || phm_is_hw_access_blocked(eventmgr->hwmgr));
+}
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c
new file mode 100644
index 0000000..9ef2d90
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#include "eventmgr.h"
+#include "eventsubchains.h"
+#include "eventtasks.h"
+#include "hardwaremanager.h"
+
+const pem_event_action reset_display_phy_access_tasks[] = {
+	pem_task_reset_display_phys_access,
+	NULL
+};
+
+const pem_event_action broadcast_power_policy_tasks[] = {
+	/* PEM_Task_BroadcastPowerPolicyChange, */
+	NULL
+};
+
+const pem_event_action unregister_interrupt_tasks[] = {
+	pem_task_unregister_interrupts,
+	NULL
+};
+
+/* Disable GFX Voltage Islands Power Gating */
+const pem_event_action disable_gfx_voltage_island_powergating_tasks[] = {
+	pem_task_disable_voltage_island_power_gating,
+	NULL
+};
+
+const pem_event_action disable_gfx_clockgating_tasks[] = {
+	pem_task_disable_gfx_clock_gating,
+	NULL
+};
+
+const pem_event_action block_adjust_power_state_tasks[] = {
+	pem_task_block_adjust_power_state,
+	NULL
+};
+
+
+const pem_event_action unblock_adjust_power_state_tasks[] = {
+	pem_task_unblock_adjust_power_state,
+	NULL
+};
+
+const pem_event_action set_performance_state_tasks[] = {
+	pem_task_set_performance_state,
+	NULL
+};
+
+const pem_event_action get_2d_performance_state_tasks[] = {
+	pem_task_get_2D_performance_state_id,
+	NULL
+};
+
+const pem_event_action conditionally_force3D_performance_state_tasks[] = {
+	pem_task_conditionally_force_3d_performance_state,
+	NULL
+};
+
+const pem_event_action process_vbios_eventinfo_tasks[] = {
+	/* PEM_Task_ProcessVbiosEventInfo,*/
+	NULL
+};
+
+const pem_event_action enable_dynamic_state_management_tasks[] = {
+	/* PEM_Task_ResetBAPMPolicyChangedFlag,*/
+	pem_task_get_boot_state_id,
+	pem_task_enable_dynamic_state_management,
+	pem_task_register_interrupts,
+	NULL
+};
+
+const pem_event_action enable_clock_power_gatings_tasks[] = {
+	pem_task_enable_clock_power_gatings_tasks,
+	pem_task_powerdown_uvd_tasks,
+	pem_task_powerdown_vce_tasks,
+	NULL
+};
+
+const pem_event_action setup_asic_tasks[] = {
+	pem_task_setup_asic,
+	NULL
+};
+
+const pem_event_action power_budget_tasks[] = {
+	/* TODO
+	 * PEM_Task_PowerBudgetWaiverAvailable,
+	 * PEM_Task_PowerBudgetWarningMessage,
+	 * PEM_Task_PruneStatesBasedOnPowerBudget,
+	*/
+	NULL
+};
+
+const pem_event_action system_config_tasks[] = {
+	/* PEM_Task_PruneStatesBasedOnSystemConfig,*/
+	NULL
+};
+
+
+const pem_event_action conditionally_force_3d_performance_state_tasks[] = {
+	pem_task_conditionally_force_3d_performance_state,
+	NULL
+};
+
+const pem_event_action ungate_all_display_phys_tasks[] = {
+	/* PEM_Task_GetDisplayPhyAccessInfo */
+	NULL
+};
+
+const pem_event_action uninitialize_display_phy_access_tasks[] = {
+	/* PEM_Task_UninitializeDisplayPhysAccess, */
+	NULL
+};
+
+const pem_event_action disable_gfx_voltage_island_power_gating_tasks[] = {
+	/* PEM_Task_DisableVoltageIslandPowerGating, */
+	NULL
+};
+
+const pem_event_action disable_gfx_clock_gating_tasks[] = {
+	pem_task_disable_gfx_clock_gating,
+	NULL
+};
+
+const pem_event_action set_boot_state_tasks[] = {
+	pem_task_get_boot_state_id,
+	pem_task_set_boot_state,
+	NULL
+};
+
+const pem_event_action adjust_power_state_tasks[] = {
+	pem_task_notify_hw_mgr_display_configuration_change,
+	pem_task_adjust_power_state,
+	pem_task_notify_smc_display_config_after_power_state_adjustment,
+	pem_task_update_allowed_performance_levels,
+	/* to do pem_task_Enable_disable_bapm, */
+	NULL
+};
+
+const pem_event_action disable_dynamic_state_management_tasks[] = {
+	pem_task_unregister_interrupts,
+	pem_task_get_boot_state_id,
+	pem_task_disable_dynamic_state_management,
+	NULL
+};
+
+const pem_event_action disable_clock_power_gatings_tasks[] = {
+	pem_task_disable_clock_power_gatings_tasks,
+	NULL
+};
+
+const pem_event_action cleanup_asic_tasks[] = {
+	/* PEM_Task_DisableFPS,*/
+	pem_task_cleanup_asic,
+	NULL
+};
+
+const pem_event_action prepare_for_pnp_stop_tasks[] = {
+	/* PEM_Task_PrepareForPnpStop,*/
+	NULL
+};
+
+const pem_event_action set_power_source_tasks[] = {
+	pem_task_set_power_source,
+	pem_task_notify_hw_of_power_source,
+	NULL
+};
+
+const pem_event_action set_power_saving_state_tasks[] = {
+	pem_task_reset_power_saving_state,
+	pem_task_get_power_saving_state,
+	pem_task_set_power_saving_state,
+	/* PEM_Task_ResetODDCState,
+	 * PEM_Task_GetODDCState,
+	 * PEM_Task_SetODDCState,*/
+	NULL
+};
+
+const pem_event_action enable_disable_fps_tasks[] = {
+	/* PEM_Task_EnableDisableFPS,*/
+	NULL
+};
+
+const pem_event_action set_nbmcu_state_tasks[] = {
+	/* PEM_Task_NBMCUStateChange,*/
+	NULL
+};
+
+const pem_event_action reset_hardware_dc_notification_tasks[] = {
+	/* PEM_Task_ResetHardwareDCNotification,*/
+	NULL
+};
+
+
+const pem_event_action notify_smu_suspend_tasks[] = {
+	/* PEM_Task_NotifySMUSuspend,*/
+	NULL
+};
+
+const pem_event_action disable_smc_firmware_ctf_tasks[] = {
+	/* PEM_Task_DisableSMCFirmwareCTF,*/
+	NULL
+};
+
+const pem_event_action disable_fps_tasks[] = {
+	/* PEM_Task_DisableFPS,*/
+	NULL
+};
+
+const pem_event_action vari_bright_suspend_tasks[] = {
+	/* PEM_Task_VariBright_Suspend,*/
+	NULL
+};
+
+const pem_event_action reset_fan_speed_to_default_tasks[] = {
+	/* PEM_Task_ResetFanSpeedToDefault,*/
+	NULL
+};
+
+const pem_event_action power_down_asic_tasks[] = {
+	/* PEM_Task_DisableFPS,*/
+	pem_task_power_down_asic,
+	NULL
+};
+
+const pem_event_action disable_stutter_mode_tasks[] = {
+	/* PEM_Task_DisableStutterMode,*/
+	NULL
+};
+
+const pem_event_action set_connected_standby_tasks[] = {
+	/* PEM_Task_SetConnectedStandby,*/
+	NULL
+};
+
+const pem_event_action block_hw_access_tasks[] = {
+	pem_task_block_hw_access,
+	NULL
+};
+
+const pem_event_action unblock_hw_access_tasks[] = {
+	pem_task_un_block_hw_access,
+	NULL
+};
+
+const pem_event_action resume_connected_standby_tasks[] = {
+	/* PEM_Task_ResumeConnectedStandby,*/
+	NULL
+};
+
+const pem_event_action notify_smu_resume_tasks[] = {
+	/* PEM_Task_NotifySMUResume,*/
+	NULL
+};
+
+const pem_event_action reset_display_configCounter_tasks[] = {
+	pem_task_reset_display_phys_access,
+	NULL
+};
+
+const pem_event_action update_dal_configuration_tasks[] = {
+	/* PEM_Task_CheckVBlankTime,*/
+	NULL
+};
+
+const pem_event_action vari_bright_resume_tasks[] = {
+	/* PEM_Task_VariBright_Resume,*/
+	NULL
+};
+
+const pem_event_action notify_hw_power_source_tasks[] = {
+	pem_task_notify_hw_of_power_source,
+	NULL
+};
+
+const pem_event_action process_vbios_event_info_tasks[] = {
+	/* PEM_Task_ProcessVbiosEventInfo,*/
+	NULL
+};
+
+const pem_event_action enable_gfx_clock_gating_tasks[] = {
+	pem_task_enable_gfx_clock_gating,
+	NULL
+};
+
+const pem_event_action enable_gfx_voltage_island_power_gating_tasks[] = {
+	pem_task_enable_voltage_island_power_gating,
+	NULL
+};
+
+const pem_event_action reset_clock_gating_tasks[] = {
+	/* PEM_Task_ResetClockGating*/
+	NULL
+};
+
+const pem_event_action notify_smu_vpu_recovery_end_tasks[] = {
+	/* PEM_Task_NotifySmuVPURecoveryEnd,*/
+	NULL
+};
+
+const pem_event_action disable_vpu_cap_tasks[] = {
+	/* PEM_Task_DisableVPUCap,*/
+	NULL
+};
+
+const pem_event_action execute_escape_sequence_tasks[] = {
+	/* PEM_Task_ExecuteEscapesequence,*/
+	NULL
+};
+
+const pem_event_action notify_power_state_change_tasks[] = {
+	pem_task_notify_power_state_change,
+	NULL
+};
+
+const pem_event_action enable_cgpg_tasks[] = {
+	pem_task_enable_cgpg,
+	NULL
+};
+
+const pem_event_action disable_cgpg_tasks[] = {
+	pem_task_disable_cgpg,
+	NULL
+};
+
+const pem_event_action enable_user_2d_performance_tasks[] = {
+	/* PEM_Task_SetUser2DPerformanceFlag,*/
+	/* PEM_Task_UpdateUser2DPerformanceEnableEvents,*/
+	NULL
+};
+
+const pem_event_action add_user_2d_performance_state_tasks[] = {
+	/* PEM_Task_Get2DPerformanceTemplate,*/
+	/* PEM_Task_AllocateNewPowerStateMemory,*/
+	/* PEM_Task_CopyNewPowerStateInfo,*/
+	/* PEM_Task_UpdateNewPowerStateClocks,*/
+	/* PEM_Task_UpdateNewPowerStateUser2DPerformanceFlag,*/
+	/* PEM_Task_AddPowerState,*/
+	/* PEM_Task_ReleaseNewPowerStateMemory,*/
+	NULL
+};
+
+const pem_event_action delete_user_2d_performance_state_tasks[] = {
+	/* PEM_Task_GetCurrentUser2DPerformanceStateID,*/
+	/* PEM_Task_DeletePowerState,*/
+	/* PEM_Task_SetCurrentUser2DPerformanceStateID,*/
+	NULL
+};
+
+const pem_event_action disable_user_2d_performance_tasks[] = {
+	/* PEM_Task_ResetUser2DPerformanceFlag,*/
+	/* PEM_Task_UpdateUser2DPerformanceDisableEvents,*/
+	NULL
+};
+
+const pem_event_action enable_stutter_mode_tasks[] = {
+	pem_task_enable_stutter_mode,
+	NULL
+};
+
+const pem_event_action enable_disable_bapm_tasks[] = {
+	/*PEM_Task_EnableDisableBAPM,*/
+	NULL
+};
+
+const pem_event_action reset_boot_state_tasks[] = {
+	pem_task_reset_boot_state,
+	NULL
+};
+
+const pem_event_action create_new_user_performance_state_tasks[] = {
+	pem_task_create_user_performance_state,
+	NULL
+};
+
+const pem_event_action initialize_thermal_controller_tasks[] = {
+	pem_task_initialize_thermal_controller,
+	NULL
+};
+
+const pem_event_action uninitialize_thermal_controller_tasks[] = {
+	pem_task_uninitialize_thermal_controller,
+	NULL
+};
+
+const pem_event_action set_cpu_power_state[] = {
+	pem_task_set_cpu_power_state,
+	NULL
+};
\ No newline at end of file
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.h
new file mode 100644
index 0000000..7714cb92
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _EVENT_SUB_CHAINS_H_
+#define _EVENT_SUB_CHAINS_H_
+
+#include "eventmgr.h"
+
+extern const pem_event_action reset_display_phy_access_tasks[];
+extern const pem_event_action broadcast_power_policy_tasks[];
+extern const pem_event_action unregister_interrupt_tasks[];
+extern const pem_event_action disable_GFX_voltage_island_powergating_tasks[];
+extern const pem_event_action disable_GFX_clockgating_tasks[];
+extern const pem_event_action block_adjust_power_state_tasks[];
+extern const pem_event_action unblock_adjust_power_state_tasks[];
+extern const pem_event_action set_performance_state_tasks[];
+extern const pem_event_action get_2D_performance_state_tasks[];
+extern const pem_event_action conditionally_force3D_performance_state_tasks[];
+extern const pem_event_action process_vbios_eventinfo_tasks[];
+extern const pem_event_action enable_dynamic_state_management_tasks[];
+extern const pem_event_action enable_clock_power_gatings_tasks[];
+extern const pem_event_action conditionally_force3D_performance_state_tasks[];
+extern const pem_event_action setup_asic_tasks[];
+extern const pem_event_action power_budget_tasks[];
+extern const pem_event_action system_config_tasks[];
+extern const pem_event_action get_2d_performance_state_tasks[];
+extern const pem_event_action conditionally_force_3d_performance_state_tasks[];
+extern const pem_event_action ungate_all_display_phys_tasks[];
+extern const pem_event_action uninitialize_display_phy_access_tasks[];
+extern const pem_event_action disable_gfx_voltage_island_power_gating_tasks[];
+extern const pem_event_action disable_gfx_clock_gating_tasks[];
+extern const pem_event_action set_boot_state_tasks[];
+extern const pem_event_action adjust_power_state_tasks[];
+extern const pem_event_action disable_dynamic_state_management_tasks[];
+extern const pem_event_action disable_clock_power_gatings_tasks[];
+extern const pem_event_action cleanup_asic_tasks[];
+extern const pem_event_action prepare_for_pnp_stop_tasks[];
+extern const pem_event_action set_power_source_tasks[];
+extern const pem_event_action set_power_saving_state_tasks[];
+extern const pem_event_action enable_disable_fps_tasks[];
+extern const pem_event_action set_nbmcu_state_tasks[];
+extern const pem_event_action reset_hardware_dc_notification_tasks[];
+extern const pem_event_action notify_smu_suspend_tasks[];
+extern const pem_event_action disable_smc_firmware_ctf_tasks[];
+extern const pem_event_action disable_fps_tasks[];
+extern const pem_event_action vari_bright_suspend_tasks[];
+extern const pem_event_action reset_fan_speed_to_default_tasks[];
+extern const pem_event_action power_down_asic_tasks[];
+extern const pem_event_action disable_stutter_mode_tasks[];
+extern const pem_event_action set_connected_standby_tasks[];
+extern const pem_event_action block_hw_access_tasks[];
+extern const pem_event_action unblock_hw_access_tasks[];
+extern const pem_event_action resume_connected_standby_tasks[];
+extern const pem_event_action notify_smu_resume_tasks[];
+extern const pem_event_action reset_display_configCounter_tasks[];
+extern const pem_event_action update_dal_configuration_tasks[];
+extern const pem_event_action vari_bright_resume_tasks[];
+extern const pem_event_action notify_hw_power_source_tasks[];
+extern const pem_event_action process_vbios_event_info_tasks[];
+extern const pem_event_action enable_gfx_clock_gating_tasks[];
+extern const pem_event_action enable_gfx_voltage_island_power_gating_tasks[];
+extern const pem_event_action reset_clock_gating_tasks[];
+extern const pem_event_action notify_smu_vpu_recovery_end_tasks[];
+extern const pem_event_action disable_vpu_cap_tasks[];
+extern const pem_event_action execute_escape_sequence_tasks[];
+extern const pem_event_action notify_power_state_change_tasks[];
+extern const pem_event_action enable_cgpg_tasks[];
+extern const pem_event_action disable_cgpg_tasks[];
+extern const pem_event_action enable_user_2d_performance_tasks[];
+extern const pem_event_action add_user_2d_performance_state_tasks[];
+extern const pem_event_action delete_user_2d_performance_state_tasks[];
+extern const pem_event_action disable_user_2d_performance_tasks[];
+extern const pem_event_action enable_stutter_mode_tasks[];
+extern const pem_event_action enable_disable_bapm_tasks[];
+extern const pem_event_action reset_boot_state_tasks[];
+extern const pem_event_action create_new_user_performance_state_tasks[];
+extern const pem_event_action initialize_thermal_controller_tasks[];
+extern const pem_event_action uninitialize_thermal_controller_tasks[];
+extern const pem_event_action set_cpu_power_state[];
+#endif /* _EVENT_SUB_CHAINS_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c
new file mode 100644
index 0000000..5cd1234
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#include "eventmgr.h"
+#include "eventinit.h"
+#include "eventmanagement.h"
+#include "eventmanager.h"
+#include "hardwaremanager.h"
+#include "eventtasks.h"
+#include "power_state.h"
+#include "hwmgr.h"
+#include "amd_powerplay.h"
+#include "psm.h"
+
+#define TEMP_RANGE_MIN (90 * 1000)
+#define TEMP_RANGE_MAX (120 * 1000)
+
+int pem_task_update_allowed_performance_levels(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+
+	if (pem_is_hw_access_blocked(eventmgr))
+		return 0;
+
+	phm_force_dpm_levels(eventmgr->hwmgr, AMD_DPM_FORCED_LEVEL_AUTO);
+
+	return 0;
+}
+
+/* eventtasks_generic.c */
+int pem_task_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	struct pp_hwmgr *hwmgr;
+
+	if (pem_is_hw_access_blocked(eventmgr))
+		return 0;
+
+	hwmgr = eventmgr->hwmgr;
+	if (event_data->pnew_power_state != NULL)
+		hwmgr->request_ps = event_data->pnew_power_state;
+
+	if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
+		psm_adjust_power_state_dynamic(eventmgr, event_data->skip_state_adjust_rules);
+	else
+		psm_adjust_power_state_static(eventmgr, event_data->skip_state_adjust_rules);
+
+	return 0;
+}
+
+int pem_task_power_down_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	return phm_power_down_asic(eventmgr->hwmgr);
+}
+
+int pem_task_set_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	if (pem_is_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID))
+		return psm_set_states(eventmgr, &(event_data->requested_state_id));
+
+	return 0;
+}
+
+int pem_task_reset_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_update_new_power_state_clocks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_system_shutdown(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_register_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_unregister_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	return pem_unregister_interrupts(eventmgr);
+}
+
+int pem_task_get_boot_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	int result;
+
+	result = psm_get_state_by_classification(eventmgr,
+		PP_StateClassificationFlag_Boot,
+		&(event_data->requested_state_id)
+	);
+
+	if (0 == result)
+		pem_set_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID);
+	else
+		pem_unset_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID);
+
+	return result;
+}
+
+int pem_task_enable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	return phm_enable_dynamic_state_management(eventmgr->hwmgr);
+}
+
+int pem_task_disable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_enable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	return phm_enable_clock_power_gatings(eventmgr->hwmgr);
+}
+
+int pem_task_powerdown_uvd_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	return phm_powerdown_uvd(eventmgr->hwmgr);
+}
+
+int pem_task_powerdown_vce_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	phm_powergate_uvd(eventmgr->hwmgr, true);
+	phm_powergate_vce(eventmgr->hwmgr, true);
+	return 0;
+}
+
+int pem_task_disable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_start_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_stop_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_setup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	return phm_setup_asic(eventmgr->hwmgr);
+}
+
+int pem_task_cleanup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_store_dal_configuration(struct pp_eventmgr *eventmgr, const struct amd_display_configuration *display_config)
+{
+	/* TODO */
+	return 0;
+	/*phm_store_dal_configuration_data(eventmgr->hwmgr, display_config) */
+}
+
+int pem_task_notify_hw_mgr_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	if (pem_is_hw_access_blocked(eventmgr))
+		return 0;
+
+	return phm_display_configuration_changed(eventmgr->hwmgr);
+}
+
+int pem_task_notify_hw_mgr_pre_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	return 0;
+}
+
+int pem_task_notify_smc_display_config_after_power_state_adjustment(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	if (pem_is_hw_access_blocked(eventmgr))
+		return 0;
+
+	return phm_notify_smc_display_config_after_ps_adjustment(eventmgr->hwmgr);
+}
+
+int pem_task_block_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	eventmgr->block_adjust_power_state = true;
+	/* to do PHM_ResetIPSCounter(pEventMgr->pHwMgr);*/
+	return 0;
+}
+
+int pem_task_unblock_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	eventmgr->block_adjust_power_state = false;
+	return 0;
+}
+
+int pem_task_notify_power_state_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_un_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_reset_display_phys_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_set_cpu_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	return phm_set_cpu_power_state(eventmgr->hwmgr);
+}
+
+/*powersaving*/
+
+int pem_task_set_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_notify_hw_of_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_get_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_reset_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_set_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_set_screen_state_on(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_set_screen_state_off(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_enable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_disable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_enable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_disable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_enable_clock_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+
+int pem_task_enable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_disable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+
+/* performance */
+int pem_task_set_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	if (pem_is_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID))
+		return psm_set_states(eventmgr, &(event_data->requested_state_id));
+
+	return 0;
+}
+
+int pem_task_conditionally_force_3d_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_enable_stutter_mode(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	/* TODO */
+	return 0;
+}
+
+int pem_task_get_2D_performance_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	int result;
+
+	if (eventmgr->features[PP_Feature_PowerPlay].supported &&
+		!(eventmgr->features[PP_Feature_PowerPlay].enabled))
+			result = psm_get_state_by_classification(eventmgr,
+					PP_StateClassificationFlag_Boot,
+					&(event_data->requested_state_id));
+	else if (eventmgr->features[PP_Feature_User2DPerformance].enabled)
+			result = psm_get_state_by_classification(eventmgr,
+				   PP_StateClassificationFlag_User2DPerformance,
+					&(event_data->requested_state_id));
+	else
+		result = psm_get_ui_state(eventmgr, PP_StateUILabel_Performance,
+					&(event_data->requested_state_id));
+
+	if (0 == result)
+		pem_set_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID);
+	else
+		pem_unset_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID);
+
+	return result;
+}
+
+int pem_task_create_user_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	struct pp_power_state *state;
+	int table_entries;
+	struct pp_hwmgr *hwmgr = eventmgr->hwmgr;
+	int i;
+
+	table_entries = hwmgr->num_ps;
+	state = hwmgr->ps;
+
+restart_search:
+	for (i = 0; i < table_entries; i++) {
+		if (state->classification.ui_label & event_data->requested_ui_label) {
+			event_data->pnew_power_state = state;
+			return 0;
+		}
+		state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
+	}
+
+	switch (event_data->requested_ui_label) {
+	case PP_StateUILabel_Battery:
+	case PP_StateUILabel_Balanced:
+		event_data->requested_ui_label = PP_StateUILabel_Performance;
+		goto restart_search;
+	default:
+		break;
+	}
+	return -1;
+}
+
+int pem_task_initialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	struct PP_TemperatureRange range;
+
+	range.max = TEMP_RANGE_MAX;
+	range.min = TEMP_RANGE_MIN;
+
+	if (eventmgr == NULL || eventmgr->platform_descriptor == NULL)
+		return -EINVAL;
+
+	if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_ThermalController))
+		return phm_start_thermal_controller(eventmgr->hwmgr, &range);
+
+	return 0;
+}
+
+int pem_task_uninitialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+	return phm_stop_thermal_controller(eventmgr->hwmgr);
+}
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h
new file mode 100644
index 0000000..6c6297e
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _EVENT_TASKS_H_
+#define _EVENT_TASKS_H_
+#include "eventmgr.h"
+
+struct amd_display_configuration;
+
+/* eventtasks_generic.c */
+int pem_task_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_power_down_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_get_boot_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_set_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_reset_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_update_new_power_state_clocks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_system_shutdown(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_register_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_unregister_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_enable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_disable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_enable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_powerdown_uvd_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_powerdown_vce_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_disable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_start_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_stop_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_setup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_cleanup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_store_dal_configuration (struct pp_eventmgr *eventmgr, const struct amd_display_configuration *display_config);
+int pem_task_notify_hw_mgr_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_notify_hw_mgr_pre_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_block_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_unblock_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_notify_power_state_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_un_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_reset_display_phys_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_set_cpu_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_notify_smc_display_config_after_power_state_adjustment(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+/*powersaving*/
+
+int pem_task_set_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_notify_hw_of_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_get_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_reset_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_set_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_set_screen_state_on(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_set_screen_state_off(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_enable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_disable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_enable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_disable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_enable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_disable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_enable_stutter_mode(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+
+/* performance */
+int pem_task_set_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_conditionally_force_3d_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_get_2D_performance_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_create_user_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_update_allowed_performance_levels(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+/*thermal */
+int pem_task_initialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_uninitialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+
+#endif /* _EVENT_TASKS_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c
new file mode 100644
index 0000000..a46225c
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include "psm.h"
+
+int psm_get_ui_state(struct pp_eventmgr *eventmgr, enum PP_StateUILabel ui_label, unsigned long *state_id)
+{
+	struct pp_power_state *state;
+	int table_entries;
+	struct pp_hwmgr *hwmgr = eventmgr->hwmgr;
+	int i;
+
+	table_entries = hwmgr->num_ps;
+	state = hwmgr->ps;
+
+	for (i = 0; i < table_entries; i++) {
+		if (state->classification.ui_label & ui_label) {
+			*state_id = state->id;
+			return 0;
+		}
+		state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
+	}
+	return -1;
+}
+
+int psm_get_state_by_classification(struct pp_eventmgr *eventmgr, enum PP_StateClassificationFlag flag, unsigned long *state_id)
+{
+	struct pp_power_state *state;
+	int table_entries;
+	struct pp_hwmgr *hwmgr = eventmgr->hwmgr;
+	int i;
+
+	table_entries = hwmgr->num_ps;
+	state = hwmgr->ps;
+
+	for (i = 0; i < table_entries; i++) {
+		if (state->classification.flags & flag) {
+			*state_id = state->id;
+			return 0;
+		}
+		state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
+	}
+	return -1;
+}
+
+int psm_set_states(struct pp_eventmgr *eventmgr, unsigned long *state_id)
+{
+	struct pp_power_state *state;
+	int table_entries;
+	struct pp_hwmgr *hwmgr = eventmgr->hwmgr;
+	int i;
+
+	table_entries = hwmgr->num_ps;
+	state = hwmgr->ps;
+
+	for (i = 0; i < table_entries; i++) {
+		if (state->id == *state_id) {
+			hwmgr->request_ps = state;
+			return 0;
+		}
+		state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
+	}
+	return -1;
+}
+
+int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip)
+{
+
+	struct pp_power_state *pcurrent;
+	struct pp_power_state *requested;
+	struct pp_hwmgr *hwmgr;
+	bool equal;
+
+	if (skip)
+		return 0;
+
+	hwmgr = eventmgr->hwmgr;
+	pcurrent = hwmgr->current_ps;
+	requested = hwmgr->request_ps;
+
+	if (requested == NULL)
+		return 0;
+
+	if (pcurrent == NULL || (0 != phm_check_states_equal(hwmgr, &pcurrent->hardware, &requested->hardware, &equal)))
+		equal = false;
+
+	if (!equal || phm_check_smc_update_required_for_display_configuration(hwmgr)) {
+		phm_apply_state_adjust_rules(hwmgr, requested, pcurrent);
+		phm_set_power_state(hwmgr, &pcurrent->hardware, &requested->hardware);
+		hwmgr->current_ps = requested;
+	}
+	return 0;
+}
+
+int psm_adjust_power_state_static(struct pp_eventmgr *eventmgr, bool skip)
+{
+	return 0;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/psm.h b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.h
new file mode 100644
index 0000000..fbdff3e
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include "eventmgr.h"
+#include "eventinit.h"
+#include "eventmanagement.h"
+#include "eventmanager.h"
+#include "power_state.h"
+#include "hardwaremanager.h"
+
+int psm_get_ui_state(struct pp_eventmgr *eventmgr, enum PP_StateUILabel ui_label, unsigned long *state_id);
+
+int psm_get_state_by_classification(struct pp_eventmgr *eventmgr, enum PP_StateClassificationFlag flag, unsigned long *state_id);
+
+int psm_set_states(struct pp_eventmgr *eventmgr, unsigned long *state_id);
+
+int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip);
+
+int psm_adjust_power_state_static(struct pp_eventmgr *eventmgr, bool skip);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
new file mode 100644
index 0000000..b664e34
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the 'hw manager' sub-component of powerplay.
+# It provides the hardware management services for the driver.
+
+HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \
+	       hardwaremanager.o pp_acpi.o cz_hwmgr.o \
+               cz_clockpowergating.o \
+	       tonga_processpptables.o ppatomctrl.o \
+               tonga_hwmgr.o pppcielanes.o  tonga_thermal.o\
+               fiji_powertune.o fiji_hwmgr.o tonga_clockpowergating.o \
+               fiji_clockpowergating.o fiji_thermal.o
+
+AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
+
+AMD_POWERPLAY_FILES += $(AMD_PP_HWMGR)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
new file mode 100644
index 0000000..ad77008
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#include "hwmgr.h"
+#include "cz_clockpowergating.h"
+#include "cz_ppsmc.h"
+
+/* PhyID -> Status Mapping in DDI_PHY_GEN_STATUS
+    0    GFX0L (3:0),                  (27:24),
+    1    GFX0H (7:4),                  (31:28),
+    2    GFX1L (3:0),                  (19:16),
+    3    GFX1H (7:4),                  (23:20),
+    4    DDIL   (3:0),                   (11: 8),
+    5    DDIH  (7:4),                   (15:12),
+    6    DDI2L (3:0),                   ( 3: 0),
+    7    DDI2H (7:4),                   ( 7: 4),
+*/
+#define DDI_PHY_GEN_STATUS_VAL(phyID)   (1 << ((3 - ((phyID & 0x07)/2))*8 + (phyID & 0x01)*4))
+#define IS_PHY_ID_USED_BY_PLL(PhyID)    (((0xF3 & (1 << PhyID)) & 0xFF) ? true : false)
+
+
+int cz_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating)
+{
+	int ret = 0;
+
+	switch (block) {
+	case PHM_AsicBlock_UVD_MVC:
+	case PHM_AsicBlock_UVD:
+	case PHM_AsicBlock_UVD_HD:
+	case PHM_AsicBlock_UVD_SD:
+		if (gating == PHM_ClockGateSetting_StaticOff)
+			ret = cz_dpm_powerdown_uvd(hwmgr);
+		else
+			ret = cz_dpm_powerup_uvd(hwmgr);
+		break;
+	case PHM_AsicBlock_GFX:
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+
+bool cz_phm_is_safe_for_asic_block(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, enum PHM_AsicBlock block)
+{
+	return true;
+}
+
+
+int cz_phm_enable_disable_gfx_power_gating(struct pp_hwmgr *hwmgr, bool enable)
+{
+	return 0;
+}
+
+int cz_phm_smu_power_up_down_pcie(struct pp_hwmgr *hwmgr, uint32_t target, bool up, uint32_t args)
+{
+	/* TODO */
+	return 0;
+}
+
+int cz_phm_initialize_display_phy_access(struct pp_hwmgr *hwmgr, bool initialize, bool accesshw)
+{
+	/* TODO */
+	return 0;
+}
+
+int cz_phm_get_display_phy_access_info(struct pp_hwmgr *hwmgr)
+{
+	/* TODO */
+	return 0;
+}
+
+int cz_phm_gate_unused_display_phys(struct pp_hwmgr *hwmgr)
+{
+	/* TODO */
+	return 0;
+}
+
+int cz_phm_ungate_all_display_phys(struct pp_hwmgr *hwmgr)
+{
+	/* TODO */
+	return 0;
+}
+
+static int cz_tf_uvd_power_gating_initialize(struct pp_hwmgr *hwmgr, void *pInput, void *pOutput, void *pStorage, int Result)
+{
+	return 0;
+}
+
+static int cz_tf_vce_power_gating_initialize(struct pp_hwmgr *hwmgr, void *pInput, void *pOutput, void *pStorage, int Result)
+{
+	return 0;
+}
+
+int cz_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	uint32_t dpm_features = 0;
+
+	if (enable &&
+		phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				  PHM_PlatformCaps_UVDDPM)) {
+		cz_hwmgr->dpm_flags |= DPMFlags_UVD_Enabled;
+		dpm_features |= UVD_DPM_MASK;
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+			    PPSMC_MSG_EnableAllSmuFeatures, dpm_features);
+	} else {
+		dpm_features |= UVD_DPM_MASK;
+		cz_hwmgr->dpm_flags &= ~DPMFlags_UVD_Enabled;
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+			   PPSMC_MSG_DisableAllSmuFeatures, dpm_features);
+	}
+	return 0;
+}
+
+int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	uint32_t dpm_features = 0;
+
+	if (enable && phm_cap_enabled(
+				hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_VCEDPM)) {
+		cz_hwmgr->dpm_flags |= DPMFlags_VCE_Enabled;
+		dpm_features |= VCE_DPM_MASK;
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+			    PPSMC_MSG_EnableAllSmuFeatures, dpm_features);
+	} else {
+		dpm_features |= VCE_DPM_MASK;
+		cz_hwmgr->dpm_flags &= ~DPMFlags_VCE_Enabled;
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+			   PPSMC_MSG_DisableAllSmuFeatures, dpm_features);
+	}
+
+	return 0;
+}
+
+
+int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	if (cz_hwmgr->uvd_power_gated == bgate)
+		return 0;
+
+	cz_hwmgr->uvd_power_gated = bgate;
+
+	if (bgate) {
+		cgs_set_clockgating_state(hwmgr->device,
+						AMD_IP_BLOCK_TYPE_UVD,
+						AMD_CG_STATE_UNGATE);
+		cgs_set_powergating_state(hwmgr->device,
+						AMD_IP_BLOCK_TYPE_UVD,
+						AMD_PG_STATE_GATE);
+		cz_dpm_update_uvd_dpm(hwmgr, true);
+		cz_dpm_powerdown_uvd(hwmgr);
+	} else {
+		cz_dpm_powerup_uvd(hwmgr);
+		cgs_set_clockgating_state(hwmgr->device,
+						AMD_IP_BLOCK_TYPE_UVD,
+						AMD_PG_STATE_GATE);
+		cgs_set_powergating_state(hwmgr->device,
+						AMD_IP_BLOCK_TYPE_UVD,
+						AMD_CG_STATE_UNGATE);
+		cz_dpm_update_uvd_dpm(hwmgr, false);
+	}
+
+	return 0;
+}
+
+int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_VCEPowerGating)) {
+		if (cz_hwmgr->vce_power_gated != bgate) {
+			if (bgate) {
+				cgs_set_clockgating_state(
+							hwmgr->device,
+							AMD_IP_BLOCK_TYPE_VCE,
+							AMD_CG_STATE_UNGATE);
+				cgs_set_powergating_state(
+							hwmgr->device,
+							AMD_IP_BLOCK_TYPE_VCE,
+							AMD_PG_STATE_GATE);
+				cz_enable_disable_vce_dpm(hwmgr, false);
+			/* TODO: to figure out why vce can't be poweroff*/
+				cz_hwmgr->vce_power_gated = true;
+			} else {
+				cz_dpm_powerup_vce(hwmgr);
+				cz_hwmgr->vce_power_gated = false;
+				cgs_set_clockgating_state(
+							hwmgr->device,
+							AMD_IP_BLOCK_TYPE_VCE,
+							AMD_PG_STATE_GATE);
+				cgs_set_powergating_state(
+							hwmgr->device,
+							AMD_IP_BLOCK_TYPE_VCE,
+							AMD_CG_STATE_UNGATE);
+				cz_dpm_update_vce_dpm(hwmgr);
+				cz_enable_disable_vce_dpm(hwmgr, true);
+				return 0;
+			}
+		}
+	} else {
+		cz_dpm_update_vce_dpm(hwmgr);
+		cz_enable_disable_vce_dpm(hwmgr, true);
+		return 0;
+	}
+
+	if (!cz_hwmgr->vce_power_gated)
+		cz_dpm_update_vce_dpm(hwmgr);
+
+	return 0;
+}
+
+
+static struct phm_master_table_item cz_enable_clock_power_gatings_list[] = {
+	/*we don't need an exit table here, because there is only D3 cold on Kv*/
+	{ phm_cf_want_uvd_power_gating, cz_tf_uvd_power_gating_initialize },
+	{ phm_cf_want_vce_power_gating, cz_tf_vce_power_gating_initialize },
+	/* to do { NULL, cz_tf_xdma_power_gating_enable }, */
+	{ NULL, NULL }
+};
+
+struct phm_master_table_header cz_phm_enable_clock_power_gatings_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	cz_enable_clock_power_gatings_list
+};
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h
new file mode 100644
index 0000000..bbbc057
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _CZ_CLOCK_POWER_GATING_H_
+#define _CZ_CLOCK_POWER_GATING_H_
+
+#include "cz_hwmgr.h"
+#include "pp_asicblocks.h"
+
+extern int cz_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating);
+extern struct phm_master_table_header cz_phm_enable_clock_power_gatings_master;
+extern struct phm_master_table_header cz_phm_disable_clock_power_gatings_master;
+extern int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate);
+extern int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate);
+extern int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable);
+extern int cz_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable);
+#endif /* _CZ_CLOCK_POWER_GATING_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
new file mode 100644
index 0000000..0874ab4
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
@@ -0,0 +1,1737 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include "atom-types.h"
+#include "atombios.h"
+#include "processpptables.h"
+#include "pp_debug.h"
+#include "cgs_common.h"
+#include "smu/smu_8_0_d.h"
+#include "smu8_fusion.h"
+#include "smu/smu_8_0_sh_mask.h"
+#include "smumgr.h"
+#include "hwmgr.h"
+#include "hardwaremanager.h"
+#include "cz_ppsmc.h"
+#include "cz_hwmgr.h"
+#include "power_state.h"
+#include "cz_clockpowergating.h"
+#include "pp_debug.h"
+
+#define ixSMUSVI_NB_CURRENTVID 0xD8230044
+#define CURRENT_NB_VID_MASK 0xff000000
+#define CURRENT_NB_VID__SHIFT 24
+#define ixSMUSVI_GFX_CURRENTVID  0xD8230048
+#define CURRENT_GFX_VID_MASK 0xff000000
+#define CURRENT_GFX_VID__SHIFT 24
+
+static const unsigned long PhwCz_Magic = (unsigned long) PHM_Cz_Magic;
+
+static struct cz_power_state *cast_PhwCzPowerState(struct pp_hw_power_state *hw_ps)
+{
+	if (PhwCz_Magic != hw_ps->magic)
+		return NULL;
+
+	return (struct cz_power_state *)hw_ps;
+}
+
+static const struct cz_power_state *cast_const_PhwCzPowerState(
+				const struct pp_hw_power_state *hw_ps)
+{
+	if (PhwCz_Magic != hw_ps->magic)
+		return NULL;
+
+	return (struct cz_power_state *)hw_ps;
+}
+
+uint32_t cz_get_eclk_level(struct pp_hwmgr *hwmgr,
+					uint32_t clock, uint32_t msg)
+{
+	int i = 0;
+	struct phm_vce_clock_voltage_dependency_table *ptable =
+		hwmgr->dyn_state.vce_clock_voltage_dependency_table;
+
+	switch (msg) {
+	case PPSMC_MSG_SetEclkSoftMin:
+	case PPSMC_MSG_SetEclkHardMin:
+		for (i = 0; i < (int)ptable->count; i++) {
+			if (clock <= ptable->entries[i].ecclk)
+				break;
+		}
+		break;
+
+	case PPSMC_MSG_SetEclkSoftMax:
+	case PPSMC_MSG_SetEclkHardMax:
+		for (i = ptable->count - 1; i >= 0; i--) {
+			if (clock >= ptable->entries[i].ecclk)
+				break;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return i;
+}
+
+static uint32_t cz_get_sclk_level(struct pp_hwmgr *hwmgr,
+				uint32_t clock, uint32_t msg)
+{
+	int i = 0;
+	struct phm_clock_voltage_dependency_table *table =
+				hwmgr->dyn_state.vddc_dependency_on_sclk;
+
+	switch (msg) {
+	case PPSMC_MSG_SetSclkSoftMin:
+	case PPSMC_MSG_SetSclkHardMin:
+		for (i = 0; i < (int)table->count; i++) {
+			if (clock <= table->entries[i].clk)
+				break;
+		}
+		break;
+
+	case PPSMC_MSG_SetSclkSoftMax:
+	case PPSMC_MSG_SetSclkHardMax:
+		for (i = table->count - 1; i >= 0; i--) {
+			if (clock >= table->entries[i].clk)
+				break;
+		}
+		break;
+
+	default:
+		break;
+	}
+	return i;
+}
+
+static uint32_t cz_get_uvd_level(struct pp_hwmgr *hwmgr,
+					uint32_t clock, uint32_t msg)
+{
+	int i = 0;
+	struct phm_uvd_clock_voltage_dependency_table *ptable =
+		hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
+
+	switch (msg) {
+	case PPSMC_MSG_SetUvdSoftMin:
+	case PPSMC_MSG_SetUvdHardMin:
+		for (i = 0; i < (int)ptable->count; i++) {
+			if (clock <= ptable->entries[i].vclk)
+				break;
+		}
+		break;
+
+	case PPSMC_MSG_SetUvdSoftMax:
+	case PPSMC_MSG_SetUvdHardMax:
+		for (i = ptable->count - 1; i >= 0; i--) {
+			if (clock >= ptable->entries[i].vclk)
+				break;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return i;
+}
+
+static uint32_t cz_get_max_sclk_level(struct pp_hwmgr *hwmgr)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	if (cz_hwmgr->max_sclk_level == 0) {
+		smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxSclkLevel);
+		cz_hwmgr->max_sclk_level = smum_get_argument(hwmgr->smumgr) + 1;
+	}
+
+	return cz_hwmgr->max_sclk_level;
+}
+
+static int cz_initialize_dpm_defaults(struct pp_hwmgr *hwmgr)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	uint32_t i;
+
+	cz_hwmgr->gfx_ramp_step = 256*25/100;
+
+	cz_hwmgr->gfx_ramp_delay = 1; /* by default, we delay 1us */
+
+	for (i = 0; i < CZ_MAX_HARDWARE_POWERLEVELS; i++)
+		cz_hwmgr->activity_target[i] = CZ_AT_DFLT;
+
+	cz_hwmgr->mgcg_cgtt_local0 = 0x00000000;
+	cz_hwmgr->mgcg_cgtt_local1 = 0x00000000;
+
+	cz_hwmgr->clock_slow_down_freq = 25000;
+
+	cz_hwmgr->skip_clock_slow_down = 1;
+
+	cz_hwmgr->enable_nb_ps_policy = 1; /* disable until UNB is ready, Enabled */
+
+	cz_hwmgr->voltage_drop_in_dce_power_gating = 0; /* disable until fully verified */
+
+	cz_hwmgr->voting_rights_clients = 0x00C00033;
+
+	cz_hwmgr->static_screen_threshold = 8;
+
+	cz_hwmgr->ddi_power_gating_disabled = 0;
+
+	cz_hwmgr->bapm_enabled = 1;
+
+	cz_hwmgr->voltage_drop_threshold = 0;
+
+	cz_hwmgr->gfx_power_gating_threshold = 500;
+
+	cz_hwmgr->vce_slow_sclk_threshold = 20000;
+
+	cz_hwmgr->dce_slow_sclk_threshold = 30000;
+
+	cz_hwmgr->disable_driver_thermal_policy = 1;
+
+	cz_hwmgr->disable_nb_ps3_in_battery = 0;
+
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+							PHM_PlatformCaps_ABM);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				    PHM_PlatformCaps_NonABMSupportInPPLib);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					   PHM_PlatformCaps_SclkDeepSleep);
+
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_DynamicM3Arbiter);
+
+	cz_hwmgr->override_dynamic_mgpg = 1;
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				  PHM_PlatformCaps_DynamicPatchPowerState);
+
+	cz_hwmgr->thermal_auto_throttling_treshold = 0;
+
+	cz_hwmgr->tdr_clock = 0;
+
+	cz_hwmgr->disable_gfx_power_gating_in_uvd = 0;
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_DynamicUVDState);
+
+	cz_hwmgr->cc6_settings.cpu_cc6_disable = false;
+	cz_hwmgr->cc6_settings.cpu_pstate_disable = false;
+	cz_hwmgr->cc6_settings.nb_pstate_switch_disable = false;
+	cz_hwmgr->cc6_settings.cpu_pstate_separation_time = 0;
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				   PHM_PlatformCaps_DisableVoltageIsland);
+
+	return 0;
+}
+
+static uint32_t cz_convert_8Bit_index_to_voltage(
+			struct pp_hwmgr *hwmgr, uint16_t voltage)
+{
+	return 6200 - (voltage * 25);
+}
+
+static int cz_construct_max_power_limits_table(struct pp_hwmgr *hwmgr,
+			struct phm_clock_and_voltage_limits *table)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)hwmgr->backend;
+	struct cz_sys_info *sys_info = &cz_hwmgr->sys_info;
+	struct phm_clock_voltage_dependency_table *dep_table =
+				hwmgr->dyn_state.vddc_dependency_on_sclk;
+
+	if (dep_table->count > 0) {
+		table->sclk = dep_table->entries[dep_table->count-1].clk;
+		table->vddc = cz_convert_8Bit_index_to_voltage(hwmgr,
+		   (uint16_t)dep_table->entries[dep_table->count-1].v);
+	}
+	table->mclk = sys_info->nbp_memory_clock[0];
+	return 0;
+}
+
+static int cz_init_dynamic_state_adjustment_rule_settings(
+			struct pp_hwmgr *hwmgr,
+			ATOM_CLK_VOLT_CAPABILITY *disp_voltage_table)
+{
+	uint32_t table_size =
+		sizeof(struct phm_clock_voltage_dependency_table) +
+		(7 * sizeof(struct phm_clock_voltage_dependency_record));
+
+	struct phm_clock_voltage_dependency_table *table_clk_vlt =
+					kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == table_clk_vlt) {
+		printk(KERN_ERR "[ powerplay ] Can not allocate memory!\n");
+		return -ENOMEM;
+	}
+
+	table_clk_vlt->count = 8;
+	table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0;
+	table_clk_vlt->entries[0].v = 0;
+	table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1;
+	table_clk_vlt->entries[1].v = 1;
+	table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2;
+	table_clk_vlt->entries[2].v = 2;
+	table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3;
+	table_clk_vlt->entries[3].v = 3;
+	table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4;
+	table_clk_vlt->entries[4].v = 4;
+	table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5;
+	table_clk_vlt->entries[5].v = 5;
+	table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6;
+	table_clk_vlt->entries[6].v = 6;
+	table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7;
+	table_clk_vlt->entries[7].v = 7;
+	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
+
+	return 0;
+}
+
+static int cz_get_system_info_data(struct pp_hwmgr *hwmgr)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)hwmgr->backend;
+	ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info = NULL;
+	uint32_t i;
+	int result = 0;
+	uint8_t frev, crev;
+	uint16_t size;
+
+	info = (ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *) cgs_atom_get_data_table(
+			hwmgr->device,
+			GetIndexIntoMasterTable(DATA, IntegratedSystemInfo),
+			&size, &frev, &crev);
+
+	if (crev != 9) {
+		printk(KERN_ERR "[ powerplay ] Unsupported IGP table: %d %d\n", frev, crev);
+		return -EINVAL;
+	}
+
+	if (info == NULL) {
+		printk(KERN_ERR "[ powerplay ] Could not retrieve the Integrated System Info Table!\n");
+		return -EINVAL;
+	}
+
+	cz_hwmgr->sys_info.bootup_uma_clock =
+				   le32_to_cpu(info->ulBootUpUMAClock);
+
+	cz_hwmgr->sys_info.bootup_engine_clock =
+				le32_to_cpu(info->ulBootUpEngineClock);
+
+	cz_hwmgr->sys_info.dentist_vco_freq =
+				   le32_to_cpu(info->ulDentistVCOFreq);
+
+	cz_hwmgr->sys_info.system_config =
+				     le32_to_cpu(info->ulSystemConfig);
+
+	cz_hwmgr->sys_info.bootup_nb_voltage_index =
+				  le16_to_cpu(info->usBootUpNBVoltage);
+
+	cz_hwmgr->sys_info.htc_hyst_lmt =
+			(info->ucHtcHystLmt == 0) ? 5 : info->ucHtcHystLmt;
+
+	cz_hwmgr->sys_info.htc_tmp_lmt =
+			(info->ucHtcTmpLmt == 0) ? 203 : info->ucHtcTmpLmt;
+
+	if (cz_hwmgr->sys_info.htc_tmp_lmt <=
+			cz_hwmgr->sys_info.htc_hyst_lmt) {
+		printk(KERN_ERR "[ powerplay ] The htcTmpLmt should be larger than htcHystLmt.\n");
+		return -EINVAL;
+	}
+
+	cz_hwmgr->sys_info.nb_dpm_enable =
+				cz_hwmgr->enable_nb_ps_policy &&
+				(le32_to_cpu(info->ulSystemConfig) >> 3 & 0x1);
+
+	for (i = 0; i < CZ_NUM_NBPSTATES; i++) {
+		if (i < CZ_NUM_NBPMEMORYCLOCK) {
+			cz_hwmgr->sys_info.nbp_memory_clock[i] =
+			  le32_to_cpu(info->ulNbpStateMemclkFreq[i]);
+		}
+		cz_hwmgr->sys_info.nbp_n_clock[i] =
+			    le32_to_cpu(info->ulNbpStateNClkFreq[i]);
+	}
+
+	for (i = 0; i < MAX_DISPLAY_CLOCK_LEVEL; i++) {
+		cz_hwmgr->sys_info.display_clock[i] =
+					le32_to_cpu(info->sDispClkVoltageMapping[i].ulMaximumSupportedCLK);
+	}
+
+	/* Here use 4 levels, make sure not exceed */
+	for (i = 0; i < CZ_NUM_NBPSTATES; i++) {
+		cz_hwmgr->sys_info.nbp_voltage_index[i] =
+			     le16_to_cpu(info->usNBPStateVoltage[i]);
+	}
+
+	if (!cz_hwmgr->sys_info.nb_dpm_enable) {
+		for (i = 1; i < CZ_NUM_NBPSTATES; i++) {
+			if (i < CZ_NUM_NBPMEMORYCLOCK) {
+				cz_hwmgr->sys_info.nbp_memory_clock[i] =
+				    cz_hwmgr->sys_info.nbp_memory_clock[0];
+			}
+			cz_hwmgr->sys_info.nbp_n_clock[i] =
+				    cz_hwmgr->sys_info.nbp_n_clock[0];
+			cz_hwmgr->sys_info.nbp_voltage_index[i] =
+				    cz_hwmgr->sys_info.nbp_voltage_index[0];
+		}
+	}
+
+	if (le32_to_cpu(info->ulGPUCapInfo) &
+		SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS) {
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				    PHM_PlatformCaps_EnableDFSBypass);
+	}
+
+	cz_hwmgr->sys_info.uma_channel_number = info->ucUMAChannelNumber;
+
+	cz_construct_max_power_limits_table (hwmgr,
+				    &hwmgr->dyn_state.max_clock_voltage_on_ac);
+
+	cz_init_dynamic_state_adjustment_rule_settings(hwmgr,
+				    &info->sDISPCLK_Voltage[0]);
+
+	return result;
+}
+
+static int cz_construct_boot_state(struct pp_hwmgr *hwmgr)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	cz_hwmgr->boot_power_level.engineClock =
+				cz_hwmgr->sys_info.bootup_engine_clock;
+
+	cz_hwmgr->boot_power_level.vddcIndex =
+			(uint8_t)cz_hwmgr->sys_info.bootup_nb_voltage_index;
+
+	cz_hwmgr->boot_power_level.dsDividerIndex = 0;
+
+	cz_hwmgr->boot_power_level.ssDividerIndex = 0;
+
+	cz_hwmgr->boot_power_level.allowGnbSlow = 1;
+
+	cz_hwmgr->boot_power_level.forceNBPstate = 0;
+
+	cz_hwmgr->boot_power_level.hysteresis_up = 0;
+
+	cz_hwmgr->boot_power_level.numSIMDToPowerDown = 0;
+
+	cz_hwmgr->boot_power_level.display_wm = 0;
+
+	cz_hwmgr->boot_power_level.vce_wm = 0;
+
+	return 0;
+}
+
+static int cz_tf_reset_active_process_mask(struct pp_hwmgr *hwmgr, void *input,
+					void *output, void *storage, int result)
+{
+	return 0;
+}
+
+static int cz_tf_upload_pptable_to_smu(struct pp_hwmgr *hwmgr, void *input,
+				       void *output, void *storage, int result)
+{
+	struct SMU8_Fusion_ClkTable *clock_table;
+	int ret;
+	uint32_t i;
+	void *table = NULL;
+	pp_atomctrl_clock_dividers_kong dividers;
+
+	struct phm_clock_voltage_dependency_table *vddc_table =
+		hwmgr->dyn_state.vddc_dependency_on_sclk;
+	struct phm_clock_voltage_dependency_table *vdd_gfx_table =
+		hwmgr->dyn_state.vdd_gfx_dependency_on_sclk;
+	struct phm_acp_clock_voltage_dependency_table *acp_table =
+		hwmgr->dyn_state.acp_clock_voltage_dependency_table;
+	struct phm_uvd_clock_voltage_dependency_table *uvd_table =
+		hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
+	struct phm_vce_clock_voltage_dependency_table *vce_table =
+		hwmgr->dyn_state.vce_clock_voltage_dependency_table;
+
+	if (!hwmgr->need_pp_table_upload)
+		return 0;
+
+	ret = smum_download_powerplay_table(hwmgr->smumgr, &table);
+
+	PP_ASSERT_WITH_CODE((0 == ret && NULL != table),
+			    "Fail to get clock table from SMU!", return -EINVAL;);
+
+	clock_table = (struct SMU8_Fusion_ClkTable *)table;
+
+	/* patch clock table */
+	PP_ASSERT_WITH_CODE((vddc_table->count <= CZ_MAX_HARDWARE_POWERLEVELS),
+			    "Dependency table entry exceeds max limit!", return -EINVAL;);
+	PP_ASSERT_WITH_CODE((vdd_gfx_table->count <= CZ_MAX_HARDWARE_POWERLEVELS),
+			    "Dependency table entry exceeds max limit!", return -EINVAL;);
+	PP_ASSERT_WITH_CODE((acp_table->count <= CZ_MAX_HARDWARE_POWERLEVELS),
+			    "Dependency table entry exceeds max limit!", return -EINVAL;);
+	PP_ASSERT_WITH_CODE((uvd_table->count <= CZ_MAX_HARDWARE_POWERLEVELS),
+			    "Dependency table entry exceeds max limit!", return -EINVAL;);
+	PP_ASSERT_WITH_CODE((vce_table->count <= CZ_MAX_HARDWARE_POWERLEVELS),
+			    "Dependency table entry exceeds max limit!", return -EINVAL;);
+
+	for (i = 0; i < CZ_MAX_HARDWARE_POWERLEVELS; i++) {
+
+		/* vddc_sclk */
+		clock_table->SclkBreakdownTable.ClkLevel[i].GnbVid =
+			(i < vddc_table->count) ? (uint8_t)vddc_table->entries[i].v : 0;
+		clock_table->SclkBreakdownTable.ClkLevel[i].Frequency =
+			(i < vddc_table->count) ? vddc_table->entries[i].clk : 0;
+
+		atomctrl_get_engine_pll_dividers_kong(hwmgr,
+						      clock_table->SclkBreakdownTable.ClkLevel[i].Frequency,
+						      &dividers);
+
+		clock_table->SclkBreakdownTable.ClkLevel[i].DfsDid =
+			(uint8_t)dividers.pll_post_divider;
+
+		/* vddgfx_sclk */
+		clock_table->SclkBreakdownTable.ClkLevel[i].GfxVid =
+			(i < vdd_gfx_table->count) ? (uint8_t)vdd_gfx_table->entries[i].v : 0;
+
+		/* acp breakdown */
+		clock_table->AclkBreakdownTable.ClkLevel[i].GfxVid =
+			(i < acp_table->count) ? (uint8_t)acp_table->entries[i].v : 0;
+		clock_table->AclkBreakdownTable.ClkLevel[i].Frequency =
+			(i < acp_table->count) ? acp_table->entries[i].acpclk : 0;
+
+		atomctrl_get_engine_pll_dividers_kong(hwmgr,
+						      clock_table->AclkBreakdownTable.ClkLevel[i].Frequency,
+						      &dividers);
+
+		clock_table->AclkBreakdownTable.ClkLevel[i].DfsDid =
+			(uint8_t)dividers.pll_post_divider;
+
+
+		/* uvd breakdown */
+		clock_table->VclkBreakdownTable.ClkLevel[i].GfxVid =
+			(i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0;
+		clock_table->VclkBreakdownTable.ClkLevel[i].Frequency =
+			(i < uvd_table->count) ? uvd_table->entries[i].vclk : 0;
+
+		atomctrl_get_engine_pll_dividers_kong(hwmgr,
+						      clock_table->VclkBreakdownTable.ClkLevel[i].Frequency,
+						      &dividers);
+
+		clock_table->VclkBreakdownTable.ClkLevel[i].DfsDid =
+			(uint8_t)dividers.pll_post_divider;
+
+		clock_table->DclkBreakdownTable.ClkLevel[i].GfxVid =
+			(i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0;
+		clock_table->DclkBreakdownTable.ClkLevel[i].Frequency =
+			(i < uvd_table->count) ? uvd_table->entries[i].dclk : 0;
+
+		atomctrl_get_engine_pll_dividers_kong(hwmgr,
+						      clock_table->DclkBreakdownTable.ClkLevel[i].Frequency,
+						      &dividers);
+
+		clock_table->DclkBreakdownTable.ClkLevel[i].DfsDid =
+			(uint8_t)dividers.pll_post_divider;
+
+		/* vce breakdown */
+		clock_table->EclkBreakdownTable.ClkLevel[i].GfxVid =
+			(i < vce_table->count) ? (uint8_t)vce_table->entries[i].v : 0;
+		clock_table->EclkBreakdownTable.ClkLevel[i].Frequency =
+			(i < vce_table->count) ? vce_table->entries[i].ecclk : 0;
+
+
+		atomctrl_get_engine_pll_dividers_kong(hwmgr,
+						      clock_table->EclkBreakdownTable.ClkLevel[i].Frequency,
+						      &dividers);
+
+		clock_table->EclkBreakdownTable.ClkLevel[i].DfsDid =
+			(uint8_t)dividers.pll_post_divider;
+
+	}
+	ret = smum_upload_powerplay_table(hwmgr->smumgr);
+
+	return ret;
+}
+
+static int cz_tf_init_sclk_limit(struct pp_hwmgr *hwmgr, void *input,
+				 void *output, void *storage, int result)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	struct phm_clock_voltage_dependency_table *table =
+					hwmgr->dyn_state.vddc_dependency_on_sclk;
+	unsigned long clock = 0, level;
+
+	if (NULL == table || table->count <= 0)
+		return -EINVAL;
+
+	cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk;
+	cz_hwmgr->sclk_dpm.hard_min_clk = table->entries[0].clk;
+
+	level = cz_get_max_sclk_level(hwmgr) - 1;
+
+	if (level < table->count)
+		clock = table->entries[level].clk;
+	else
+		clock = table->entries[table->count - 1].clk;
+
+	cz_hwmgr->sclk_dpm.soft_max_clk = clock;
+	cz_hwmgr->sclk_dpm.hard_max_clk = clock;
+
+	return 0;
+}
+
+static int cz_tf_init_uvd_limit(struct pp_hwmgr *hwmgr, void *input,
+				void *output, void *storage, int result)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	struct phm_uvd_clock_voltage_dependency_table *table =
+				hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
+	unsigned long clock = 0, level;
+
+	if (NULL == table || table->count <= 0)
+		return -EINVAL;
+
+	cz_hwmgr->uvd_dpm.soft_min_clk = 0;
+	cz_hwmgr->uvd_dpm.hard_min_clk = 0;
+
+	smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxUvdLevel);
+	level = smum_get_argument(hwmgr->smumgr);
+
+	if (level < table->count)
+		clock = table->entries[level].vclk;
+	else
+		clock = table->entries[table->count - 1].vclk;
+
+	cz_hwmgr->uvd_dpm.soft_max_clk = clock;
+	cz_hwmgr->uvd_dpm.hard_max_clk = clock;
+
+	return 0;
+}
+
+static int cz_tf_init_vce_limit(struct pp_hwmgr *hwmgr, void *input,
+				void *output, void *storage, int result)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	struct phm_vce_clock_voltage_dependency_table *table =
+				hwmgr->dyn_state.vce_clock_voltage_dependency_table;
+	unsigned long clock = 0, level;
+
+	if (NULL == table || table->count <= 0)
+		return -EINVAL;
+
+	cz_hwmgr->vce_dpm.soft_min_clk = 0;
+	cz_hwmgr->vce_dpm.hard_min_clk = 0;
+
+	smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxEclkLevel);
+	level = smum_get_argument(hwmgr->smumgr);
+
+	if (level < table->count)
+		clock = table->entries[level].ecclk;
+	else
+		clock = table->entries[table->count - 1].ecclk;
+
+	cz_hwmgr->vce_dpm.soft_max_clk = clock;
+	cz_hwmgr->vce_dpm.hard_max_clk = clock;
+
+	return 0;
+}
+
+static int cz_tf_init_acp_limit(struct pp_hwmgr *hwmgr, void *input,
+				void *output, void *storage, int result)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	struct phm_acp_clock_voltage_dependency_table *table =
+				hwmgr->dyn_state.acp_clock_voltage_dependency_table;
+	unsigned long clock = 0, level;
+
+	if (NULL == table || table->count <= 0)
+		return -EINVAL;
+
+	cz_hwmgr->acp_dpm.soft_min_clk = 0;
+	cz_hwmgr->acp_dpm.hard_min_clk = 0;
+
+	smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxAclkLevel);
+	level = smum_get_argument(hwmgr->smumgr);
+
+	if (level < table->count)
+		clock = table->entries[level].acpclk;
+	else
+		clock = table->entries[table->count - 1].acpclk;
+
+	cz_hwmgr->acp_dpm.soft_max_clk = clock;
+	cz_hwmgr->acp_dpm.hard_max_clk = clock;
+	return 0;
+}
+
+static int cz_tf_init_power_gate_state(struct pp_hwmgr *hwmgr, void *input,
+				void *output, void *storage, int result)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	cz_hwmgr->uvd_power_gated = false;
+	cz_hwmgr->vce_power_gated = false;
+	cz_hwmgr->samu_power_gated = false;
+	cz_hwmgr->acp_power_gated = false;
+	cz_hwmgr->pgacpinit = true;
+
+	return 0;
+}
+
+static int cz_tf_init_sclk_threshold(struct pp_hwmgr *hwmgr, void *input,
+				void *output, void *storage, int result)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	cz_hwmgr->low_sclk_interrupt_threshold = 0;
+
+	return 0;
+}
+static int cz_tf_update_sclk_limit(struct pp_hwmgr *hwmgr,
+					void *input, void *output,
+					void *storage, int result)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	struct phm_clock_voltage_dependency_table *table =
+					hwmgr->dyn_state.vddc_dependency_on_sclk;
+
+	unsigned long clock = 0;
+	unsigned long level;
+	unsigned long stable_pstate_sclk;
+	struct PP_Clocks clocks;
+	unsigned long percentage;
+
+	cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk;
+	level = cz_get_max_sclk_level(hwmgr) - 1;
+
+	if (level < table->count)
+		cz_hwmgr->sclk_dpm.soft_max_clk  = table->entries[level].clk;
+	else
+		cz_hwmgr->sclk_dpm.soft_max_clk  = table->entries[table->count - 1].clk;
+
+	/*PECI_GetMinClockSettings(pHwMgr->pPECI, &clocks);*/
+	clock = clocks.engineClock;
+
+	if (cz_hwmgr->sclk_dpm.hard_min_clk != clock) {
+		cz_hwmgr->sclk_dpm.hard_min_clk = clock;
+
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_SetSclkHardMin,
+						 cz_get_sclk_level(hwmgr,
+					cz_hwmgr->sclk_dpm.hard_min_clk,
+					     PPSMC_MSG_SetSclkHardMin));
+	}
+
+	clock = cz_hwmgr->sclk_dpm.soft_min_clk;
+
+	/* update minimum clocks for Stable P-State feature */
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				     PHM_PlatformCaps_StablePState)) {
+		percentage = 75;
+		/*Sclk - calculate sclk value based on percentage and find FLOOR sclk from VddcDependencyOnSCLK table  */
+		stable_pstate_sclk = (hwmgr->dyn_state.max_clock_voltage_on_ac.mclk *
+					percentage) / 100;
+
+		if (clock < stable_pstate_sclk)
+			clock = stable_pstate_sclk;
+	} else {
+		if (clock < hwmgr->gfx_arbiter.sclk)
+			clock = hwmgr->gfx_arbiter.sclk;
+	}
+
+	if (cz_hwmgr->sclk_dpm.soft_min_clk != clock) {
+		cz_hwmgr->sclk_dpm.soft_min_clk = clock;
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_SetSclkSoftMin,
+						cz_get_sclk_level(hwmgr,
+					cz_hwmgr->sclk_dpm.soft_min_clk,
+					     PPSMC_MSG_SetSclkSoftMin));
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				    PHM_PlatformCaps_StablePState) &&
+			 cz_hwmgr->sclk_dpm.soft_max_clk != clock) {
+		cz_hwmgr->sclk_dpm.soft_max_clk = clock;
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_SetSclkSoftMax,
+						cz_get_sclk_level(hwmgr,
+					cz_hwmgr->sclk_dpm.soft_max_clk,
+					PPSMC_MSG_SetSclkSoftMax));
+	}
+
+	return 0;
+}
+
+static int cz_tf_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr,
+					void *input, void *output,
+					void *storage, int result)
+{
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_SclkDeepSleep)) {
+		uint32_t clks = hwmgr->display_config.min_core_set_clock_in_sr;
+		if (clks == 0)
+			clks = CZ_MIN_DEEP_SLEEP_SCLK;
+
+		PP_DBG_LOG("Setting Deep Sleep Clock: %d\n", clks);
+
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetMinDeepSleepSclk,
+				clks);
+	}
+
+	return 0;
+}
+
+static int cz_tf_set_watermark_threshold(struct pp_hwmgr *hwmgr,
+					void *input, void *output,
+					void *storage, int result)
+{
+	struct cz_hwmgr *cz_hwmgr =
+				  (struct cz_hwmgr *)(hwmgr->backend);
+
+	smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_SetWatermarkFrequency,
+				      cz_hwmgr->sclk_dpm.soft_max_clk);
+
+	return 0;
+}
+
+static int cz_tf_set_enabled_levels(struct pp_hwmgr *hwmgr,
+					void *input, void *output,
+					void *storage, int result)
+{
+	return 0;
+}
+
+
+static int cz_tf_enable_nb_dpm(struct pp_hwmgr *hwmgr,
+					void *input, void *output,
+					void *storage, int result)
+{
+	int ret = 0;
+
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	unsigned long dpm_features = 0;
+
+	if (!cz_hwmgr->is_nb_dpm_enabled) {
+		PP_DBG_LOG("enabling ALL SMU features.\n");
+		dpm_features |= NB_DPM_MASK;
+		ret = smum_send_msg_to_smc_with_parameter(
+							     hwmgr->smumgr,
+					 PPSMC_MSG_EnableAllSmuFeatures,
+							     dpm_features);
+		if (ret == 0)
+			cz_hwmgr->is_nb_dpm_enabled = true;
+	}
+
+	return ret;
+}
+
+static int cz_nbdpm_pstate_enable_disable(struct pp_hwmgr *hwmgr, bool enable, bool lock)
+{
+	struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
+
+	if (hw_data->is_nb_dpm_enabled) {
+		if (enable) {
+			PP_DBG_LOG("enable Low Memory PState.\n");
+
+			return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_EnableLowMemoryPstate,
+						(lock ? 1 : 0));
+		} else {
+			PP_DBG_LOG("disable Low Memory PState.\n");
+
+			return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_DisableLowMemoryPstate,
+						(lock ? 1 : 0));
+		}
+	}
+
+	return 0;
+}
+
+static int cz_tf_update_low_mem_pstate(struct pp_hwmgr *hwmgr,
+					void *input, void *output,
+					void *storage, int result)
+{
+	bool disable_switch;
+	bool enable_low_mem_state;
+	struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
+	const struct phm_set_power_state_input *states = (struct phm_set_power_state_input *)input;
+	const struct cz_power_state *pnew_state = cast_const_PhwCzPowerState(states->pnew_state);
+
+	if (hw_data->sys_info.nb_dpm_enable) {
+		disable_switch = hw_data->cc6_settings.nb_pstate_switch_disable ? true : false;
+		enable_low_mem_state = hw_data->cc6_settings.nb_pstate_switch_disable ? false : true;
+
+		if (pnew_state->action == FORCE_HIGH)
+			cz_nbdpm_pstate_enable_disable(hwmgr, false, disable_switch);
+		else if(pnew_state->action == CANCEL_FORCE_HIGH)
+			cz_nbdpm_pstate_enable_disable(hwmgr, false, disable_switch);
+		else 
+			cz_nbdpm_pstate_enable_disable(hwmgr, enable_low_mem_state, disable_switch);
+	}
+	return 0;
+}
+
+static struct phm_master_table_item cz_set_power_state_list[] = {
+	{NULL, cz_tf_update_sclk_limit},
+	{NULL, cz_tf_set_deep_sleep_sclk_threshold},
+	{NULL, cz_tf_set_watermark_threshold},
+	{NULL, cz_tf_set_enabled_levels},
+	{NULL, cz_tf_enable_nb_dpm},
+	{NULL, cz_tf_update_low_mem_pstate},
+	{NULL, NULL}
+};
+
+static struct phm_master_table_header cz_set_power_state_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	cz_set_power_state_list
+};
+
+static struct phm_master_table_item cz_setup_asic_list[] = {
+	{NULL, cz_tf_reset_active_process_mask},
+	{NULL, cz_tf_upload_pptable_to_smu},
+	{NULL, cz_tf_init_sclk_limit},
+	{NULL, cz_tf_init_uvd_limit},
+	{NULL, cz_tf_init_vce_limit},
+	{NULL, cz_tf_init_acp_limit},
+	{NULL, cz_tf_init_power_gate_state},
+	{NULL, cz_tf_init_sclk_threshold},
+	{NULL, NULL}
+};
+
+static struct phm_master_table_header cz_setup_asic_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	cz_setup_asic_list
+};
+
+static int cz_tf_power_up_display_clock_sys_pll(struct pp_hwmgr *hwmgr,
+					void *input, void *output,
+					void *storage, int result)
+{
+	struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
+	hw_data->disp_clk_bypass_pending = false;
+	hw_data->disp_clk_bypass = false;
+
+	return 0;
+}
+
+static int cz_tf_clear_nb_dpm_flag(struct pp_hwmgr *hwmgr,
+					void *input, void *output,
+					void *storage, int result)
+{
+	struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
+	hw_data->is_nb_dpm_enabled = false;
+
+	return 0;
+}
+
+static int cz_tf_reset_cc6_data(struct pp_hwmgr *hwmgr,
+					void *input, void *output,
+					void *storage, int result)
+{
+	struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
+
+	hw_data->cc6_settings.cc6_setting_changed = false;
+	hw_data->cc6_settings.cpu_pstate_separation_time = 0;
+	hw_data->cc6_settings.cpu_cc6_disable = false;
+	hw_data->cc6_settings.cpu_pstate_disable = false;
+
+	return 0;
+}
+
+static struct phm_master_table_item cz_power_down_asic_list[] = {
+	{NULL, cz_tf_power_up_display_clock_sys_pll},
+	{NULL, cz_tf_clear_nb_dpm_flag},
+	{NULL, cz_tf_reset_cc6_data},
+	{NULL, NULL}
+};
+
+static struct phm_master_table_header cz_power_down_asic_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	cz_power_down_asic_list
+};
+
+static int cz_tf_program_voting_clients(struct pp_hwmgr *hwmgr, void *input,
+				void *output, void *storage, int result)
+{
+	PHMCZ_WRITE_SMC_REGISTER(hwmgr->device, CG_FREQ_TRAN_VOTING_0,
+				PPCZ_VOTINGRIGHTSCLIENTS_DFLT0);
+	return 0;
+}
+
+static int cz_tf_start_dpm(struct pp_hwmgr *hwmgr, void *input, void *output,
+			   void *storage, int result)
+{
+	int res = 0xff;
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	unsigned long dpm_features = 0;
+
+	cz_hwmgr->dpm_flags |= DPMFlags_SCLK_Enabled;
+	dpm_features |= SCLK_DPM_MASK;
+
+	res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_EnableAllSmuFeatures,
+				dpm_features);
+
+	return res;
+}
+
+static int cz_tf_program_bootup_state(struct pp_hwmgr *hwmgr, void *input,
+				void *output, void *storage, int result)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	cz_hwmgr->sclk_dpm.soft_min_clk = cz_hwmgr->sys_info.bootup_engine_clock;
+	cz_hwmgr->sclk_dpm.soft_max_clk = cz_hwmgr->sys_info.bootup_engine_clock;
+
+	smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetSclkSoftMin,
+				cz_get_sclk_level(hwmgr,
+				cz_hwmgr->sclk_dpm.soft_min_clk,
+				PPSMC_MSG_SetSclkSoftMin));
+
+	smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetSclkSoftMax,
+				cz_get_sclk_level(hwmgr,
+				cz_hwmgr->sclk_dpm.soft_max_clk,
+				PPSMC_MSG_SetSclkSoftMax));
+
+	return 0;
+}
+
+int cz_tf_reset_acp_boot_level(struct pp_hwmgr *hwmgr, void *input,
+				void *output, void *storage, int result)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	cz_hwmgr->acp_boot_level = 0xff;
+	return 0;
+}
+
+static bool cz_dpm_check_smu_features(struct pp_hwmgr *hwmgr,
+				unsigned long check_feature)
+{
+	int result;
+	unsigned long features;
+
+	result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_GetFeatureStatus, 0);
+	if (result == 0) {
+		features = smum_get_argument(hwmgr->smumgr);
+		if (features & check_feature)
+			return true;
+	}
+
+	return result;
+}
+
+static int cz_tf_check_for_dpm_disabled(struct pp_hwmgr *hwmgr, void *input,
+				void *output, void *storage, int result)
+{
+	if (cz_dpm_check_smu_features(hwmgr, SMU_EnabledFeatureScoreboard_SclkDpmOn))
+		return PP_Result_TableImmediateExit;
+	return 0;
+}
+
+static int cz_tf_enable_didt(struct pp_hwmgr *hwmgr, void *input,
+				void *output, void *storage, int result)
+{
+	/* TO DO */
+	return 0;
+}
+
+static int cz_tf_check_for_dpm_enabled(struct pp_hwmgr *hwmgr,
+						void *input, void *output,
+						void *storage, int result)
+{
+	if (!cz_dpm_check_smu_features(hwmgr,
+			     SMU_EnabledFeatureScoreboard_SclkDpmOn))
+		return PP_Result_TableImmediateExit;
+	return 0;
+}
+
+static struct phm_master_table_item cz_disable_dpm_list[] = {
+	{ NULL, cz_tf_check_for_dpm_enabled},
+	{NULL, NULL},
+};
+
+
+static struct phm_master_table_header cz_disable_dpm_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	cz_disable_dpm_list
+};
+
+static struct phm_master_table_item cz_enable_dpm_list[] = {
+	{ NULL, cz_tf_check_for_dpm_disabled },
+	{ NULL, cz_tf_program_voting_clients },
+	{ NULL, cz_tf_start_dpm},
+	{ NULL, cz_tf_program_bootup_state},
+	{ NULL, cz_tf_enable_didt },
+	{ NULL, cz_tf_reset_acp_boot_level },
+	{NULL, NULL},
+};
+
+static struct phm_master_table_header cz_enable_dpm_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	cz_enable_dpm_list
+};
+
+static int cz_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+				struct pp_power_state  *prequest_ps,
+			const struct pp_power_state *pcurrent_ps)
+{
+	struct cz_power_state *cz_ps =
+				cast_PhwCzPowerState(&prequest_ps->hardware);
+
+	const struct cz_power_state *cz_current_ps =
+				cast_const_PhwCzPowerState(&pcurrent_ps->hardware);
+
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	struct PP_Clocks clocks;
+	bool force_high;
+	unsigned long  num_of_active_displays = 4;
+
+	cz_ps->evclk = hwmgr->vce_arbiter.evclk;
+	cz_ps->ecclk = hwmgr->vce_arbiter.ecclk;
+
+	cz_ps->need_dfs_bypass = true;
+
+	cz_hwmgr->video_start = (hwmgr->uvd_arbiter.vclk != 0 || hwmgr->uvd_arbiter.dclk != 0 ||
+				hwmgr->vce_arbiter.evclk != 0 || hwmgr->vce_arbiter.ecclk != 0);
+
+	cz_hwmgr->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label);
+
+	/* to do PECI_GetMinClockSettings(pHwMgr->pPECI, &clocks); */
+	/* PECI_GetNumberOfActiveDisplays(pHwMgr->pPECI, &numOfActiveDisplays); */
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
+		clocks.memoryClock = hwmgr->dyn_state.max_clock_voltage_on_ac.mclk;
+	else
+		clocks.memoryClock = 0;
+
+	if (clocks.memoryClock < hwmgr->gfx_arbiter.mclk)
+		clocks.memoryClock = hwmgr->gfx_arbiter.mclk;
+
+	force_high = (clocks.memoryClock > cz_hwmgr->sys_info.nbp_memory_clock[CZ_NUM_NBPMEMORYCLOCK - 1])
+			|| (num_of_active_displays >= 3);
+
+	cz_ps->action = cz_current_ps->action;
+
+	if ((force_high == false) && (cz_ps->action == FORCE_HIGH))
+		cz_ps->action = CANCEL_FORCE_HIGH;
+	else if ((force_high == true) && (cz_ps->action != FORCE_HIGH))
+		cz_ps->action = FORCE_HIGH;
+	else
+		cz_ps->action = DO_NOTHING;
+
+	return 0;
+}
+
+static int cz_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+{
+	int result = 0;
+
+	result = cz_initialize_dpm_defaults(hwmgr);
+	if (result != 0) {
+		printk(KERN_ERR "[ powerplay ] cz_initialize_dpm_defaults failed\n");
+		return result;
+	}
+
+	result = cz_get_system_info_data(hwmgr);
+	if (result != 0) {
+		printk(KERN_ERR "[ powerplay ] cz_get_system_info_data failed\n");
+		return result;
+	}
+
+	cz_construct_boot_state(hwmgr);
+
+	result = phm_construct_table(hwmgr, &cz_setup_asic_master,
+				&(hwmgr->setup_asic));
+	if (result != 0) {
+		printk(KERN_ERR "[ powerplay ] Fail to construct setup ASIC\n");
+		return result;
+	}
+
+	result = phm_construct_table(hwmgr, &cz_power_down_asic_master,
+				&(hwmgr->power_down_asic));
+	if (result != 0) {
+		printk(KERN_ERR "[ powerplay ] Fail to construct power down ASIC\n");
+		return result;
+	}
+
+	result = phm_construct_table(hwmgr, &cz_disable_dpm_master,
+				&(hwmgr->disable_dynamic_state_management));
+	if (result != 0) {
+		printk(KERN_ERR "[ powerplay ] Fail to disable_dynamic_state\n");
+		return result;
+	}
+	result = phm_construct_table(hwmgr, &cz_enable_dpm_master,
+				&(hwmgr->enable_dynamic_state_management));
+	if (result != 0) {
+		printk(KERN_ERR "[ powerplay ] Fail to enable_dynamic_state\n");
+		return result;
+	}
+	result = phm_construct_table(hwmgr, &cz_set_power_state_master,
+				&(hwmgr->set_power_state));
+	if (result != 0) {
+		printk(KERN_ERR "[ powerplay ] Fail to construct set_power_state\n");
+		return result;
+	}
+
+	result = phm_construct_table(hwmgr, &cz_phm_enable_clock_power_gatings_master, &(hwmgr->enable_clock_power_gatings));
+	if (result != 0) {
+		printk(KERN_ERR "[ powerplay ] Fail to construct enable_clock_power_gatings\n");
+		return result;
+	}
+	return result;
+}
+
+static int cz_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
+{
+	if (hwmgr != NULL || hwmgr->backend != NULL) {
+		kfree(hwmgr->backend);
+		kfree(hwmgr);
+	}
+	return 0;
+}
+
+int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	if (cz_hwmgr->sclk_dpm.soft_min_clk !=
+				cz_hwmgr->sclk_dpm.soft_max_clk)
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_SetSclkSoftMin,
+						cz_get_sclk_level(hwmgr,
+						cz_hwmgr->sclk_dpm.soft_max_clk,
+						PPSMC_MSG_SetSclkSoftMin));
+	return 0;
+}
+
+int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	struct phm_clock_voltage_dependency_table *table =
+				hwmgr->dyn_state.vddc_dependency_on_sclk;
+	unsigned long clock = 0, level;
+
+	if (NULL == table || table->count <= 0)
+		return -EINVAL;
+
+	cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk;
+	cz_hwmgr->sclk_dpm.hard_min_clk = table->entries[0].clk;
+
+	level = cz_get_max_sclk_level(hwmgr) - 1;
+
+	if (level < table->count)
+		clock = table->entries[level].clk;
+	else
+		clock = table->entries[table->count - 1].clk;
+
+	cz_hwmgr->sclk_dpm.soft_max_clk = clock;
+	cz_hwmgr->sclk_dpm.hard_max_clk = clock;
+
+	smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetSclkSoftMin,
+				cz_get_sclk_level(hwmgr,
+				cz_hwmgr->sclk_dpm.soft_min_clk,
+				PPSMC_MSG_SetSclkSoftMin));
+
+	smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetSclkSoftMax,
+				cz_get_sclk_level(hwmgr,
+				cz_hwmgr->sclk_dpm.soft_max_clk,
+				PPSMC_MSG_SetSclkSoftMax));
+
+	return 0;
+}
+
+int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	if (cz_hwmgr->sclk_dpm.soft_min_clk !=
+				cz_hwmgr->sclk_dpm.soft_max_clk) {
+		cz_hwmgr->sclk_dpm.soft_max_clk =
+			cz_hwmgr->sclk_dpm.soft_min_clk;
+
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetSclkSoftMax,
+				cz_get_sclk_level(hwmgr,
+				cz_hwmgr->sclk_dpm.soft_max_clk,
+				PPSMC_MSG_SetSclkSoftMax));
+	}
+
+	return 0;
+}
+
+static int cz_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
+				enum amd_dpm_forced_level level)
+{
+	int ret = 0;
+
+	switch (level) {
+	case AMD_DPM_FORCED_LEVEL_HIGH:
+		ret = cz_phm_force_dpm_highest(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	case AMD_DPM_FORCED_LEVEL_LOW:
+		ret = cz_phm_force_dpm_lowest(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	case AMD_DPM_FORCED_LEVEL_AUTO:
+		ret = cz_phm_unforce_dpm_levels(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	default:
+		break;
+	}
+
+	hwmgr->dpm_level = level;
+
+	return ret;
+}
+
+int cz_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					 PHM_PlatformCaps_UVDPowerGating))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+						     PPSMC_MSG_UVDPowerOFF);
+	return 0;
+}
+
+int cz_dpm_powerup_uvd(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					 PHM_PlatformCaps_UVDPowerGating)) {
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				  PHM_PlatformCaps_UVDDynamicPowerGating)) {
+			return smum_send_msg_to_smc_with_parameter(
+								hwmgr->smumgr,
+						   PPSMC_MSG_UVDPowerON, 1);
+		} else {
+			return smum_send_msg_to_smc_with_parameter(
+								hwmgr->smumgr,
+						   PPSMC_MSG_UVDPowerON, 0);
+		}
+	}
+
+	return 0;
+}
+
+int cz_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	struct phm_uvd_clock_voltage_dependency_table *ptable =
+		hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
+
+	if (!bgate) {
+		/* Stable Pstate is enabled and we need to set the UVD DPM to highest level */
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					 PHM_PlatformCaps_StablePState)) {
+			cz_hwmgr->uvd_dpm.hard_min_clk =
+				   ptable->entries[ptable->count - 1].vclk;
+
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						     PPSMC_MSG_SetUvdHardMin,
+						      cz_get_uvd_level(hwmgr,
+					     cz_hwmgr->uvd_dpm.hard_min_clk,
+						   PPSMC_MSG_SetUvdHardMin));
+
+			cz_enable_disable_uvd_dpm(hwmgr, true);
+		} else
+			cz_enable_disable_uvd_dpm(hwmgr, true);
+	} else
+		cz_enable_disable_uvd_dpm(hwmgr, false);
+
+	return 0;
+}
+
+int  cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	struct phm_vce_clock_voltage_dependency_table *ptable =
+		hwmgr->dyn_state.vce_clock_voltage_dependency_table;
+
+	/* Stable Pstate is enabled and we need to set the VCE DPM to highest level */
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					 PHM_PlatformCaps_StablePState)) {
+		cz_hwmgr->vce_dpm.hard_min_clk =
+				  ptable->entries[ptable->count - 1].ecclk;
+
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_SetEclkHardMin,
+					cz_get_eclk_level(hwmgr,
+					     cz_hwmgr->vce_dpm.hard_min_clk,
+						PPSMC_MSG_SetEclkHardMin));
+	} else {
+		/*EPR# 419220 -HW limitation to to */
+		cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					    PPSMC_MSG_SetEclkHardMin,
+					    cz_get_eclk_level(hwmgr,
+				     cz_hwmgr->vce_dpm.hard_min_clk,
+					  PPSMC_MSG_SetEclkHardMin));
+
+	}
+	return 0;
+}
+
+int cz_dpm_powerdown_vce(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					 PHM_PlatformCaps_VCEPowerGating))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+						     PPSMC_MSG_VCEPowerOFF);
+	return 0;
+}
+
+int cz_dpm_powerup_vce(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					 PHM_PlatformCaps_VCEPowerGating))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+						     PPSMC_MSG_VCEPowerON);
+	return 0;
+}
+
+static int cz_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	return cz_hwmgr->sys_info.bootup_uma_clock;
+}
+
+static int cz_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
+{
+	struct pp_power_state  *ps;
+	struct cz_power_state  *cz_ps;
+
+	if (hwmgr == NULL)
+		return -EINVAL;
+
+	ps = hwmgr->request_ps;
+
+	if (ps == NULL)
+		return -EINVAL;
+
+	cz_ps = cast_PhwCzPowerState(&ps->hardware);
+
+	if (low)
+		return cz_ps->levels[0].engineClock;
+	else
+		return cz_ps->levels[cz_ps->level-1].engineClock;
+}
+
+static int cz_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
+					struct pp_hw_power_state *hw_ps)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+	struct cz_power_state *cz_ps = cast_PhwCzPowerState(hw_ps);
+
+	cz_ps->level = 1;
+	cz_ps->nbps_flags = 0;
+	cz_ps->bapm_flags = 0;
+	cz_ps->levels[0] = cz_hwmgr->boot_power_level;
+
+	return 0;
+}
+
+static int cz_dpm_get_pp_table_entry_callback(
+						     struct pp_hwmgr *hwmgr,
+					   struct pp_hw_power_state *hw_ps,
+							  unsigned int index,
+						     const void *clock_info)
+{
+	struct cz_power_state *cz_ps = cast_PhwCzPowerState(hw_ps);
+
+	const ATOM_PPLIB_CZ_CLOCK_INFO *cz_clock_info = clock_info;
+
+	struct phm_clock_voltage_dependency_table *table =
+				    hwmgr->dyn_state.vddc_dependency_on_sclk;
+	uint8_t clock_info_index = cz_clock_info->index;
+
+	if (clock_info_index > (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1))
+		clock_info_index = (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1);
+
+	cz_ps->levels[index].engineClock = table->entries[clock_info_index].clk;
+	cz_ps->levels[index].vddcIndex = (uint8_t)table->entries[clock_info_index].v;
+
+	cz_ps->level = index + 1;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
+		cz_ps->levels[index].dsDividerIndex = 5;
+		cz_ps->levels[index].ssDividerIndex = 5;
+	}
+
+	return 0;
+}
+
+static int cz_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr)
+{
+	int result;
+	unsigned long ret = 0;
+
+	result = pp_tables_get_num_of_entries(hwmgr, &ret);
+
+	return result ? 0 : ret;
+}
+
+static int cz_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr,
+		    unsigned long entry, struct pp_power_state *ps)
+{
+	int result;
+	struct cz_power_state *cz_ps;
+
+	ps->hardware.magic = PhwCz_Magic;
+
+	cz_ps = cast_PhwCzPowerState(&(ps->hardware));
+
+	result = pp_tables_get_entry(hwmgr, entry, ps,
+			cz_dpm_get_pp_table_entry_callback);
+
+	cz_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK;
+	cz_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK;
+
+	return result;
+}
+
+int cz_get_power_state_size(struct pp_hwmgr *hwmgr)
+{
+	return sizeof(struct cz_power_state);
+}
+
+static void
+cz_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m)
+{
+	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
+
+	struct phm_clock_voltage_dependency_table *table =
+				hwmgr->dyn_state.vddc_dependency_on_sclk;
+
+	struct phm_vce_clock_voltage_dependency_table *vce_table =
+		hwmgr->dyn_state.vce_clock_voltage_dependency_table;
+
+	struct phm_uvd_clock_voltage_dependency_table *uvd_table =
+		hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
+
+	uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX),
+					TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX);
+	uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
+					TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX);
+	uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
+					TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX);
+
+	uint32_t sclk, vclk, dclk, ecclk, tmp, activity_percent;
+	uint16_t vddnb, vddgfx;
+	int result;
+
+	if (sclk_index >= NUM_SCLK_LEVELS) {
+		seq_printf(m, "\n invalid sclk dpm profile %d\n", sclk_index);
+	} else {
+		sclk = table->entries[sclk_index].clk;
+		seq_printf(m, "\n index: %u sclk: %u MHz\n", sclk_index, sclk/100);
+	}
+
+	tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) &
+		CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT;
+	vddnb = cz_convert_8Bit_index_to_voltage(hwmgr, tmp);
+	tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) &
+		CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT;
+	vddgfx = cz_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp);
+	seq_printf(m, "\n vddnb: %u vddgfx: %u\n", vddnb, vddgfx);
+
+	seq_printf(m, "\n uvd    %sabled\n", cz_hwmgr->uvd_power_gated ? "dis" : "en");
+	if (!cz_hwmgr->uvd_power_gated) {
+		if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
+			seq_printf(m, "\n invalid uvd dpm level %d\n", uvd_index);
+		} else {
+			vclk = uvd_table->entries[uvd_index].vclk;
+			dclk = uvd_table->entries[uvd_index].dclk;
+			seq_printf(m, "\n index: %u uvd vclk: %u MHz dclk: %u MHz\n", uvd_index, vclk/100, dclk/100);
+		}
+	}
+
+	seq_printf(m, "\n vce    %sabled\n", cz_hwmgr->vce_power_gated ? "dis" : "en");
+	if (!cz_hwmgr->vce_power_gated) {
+		if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
+			seq_printf(m, "\n invalid vce dpm level %d\n", vce_index);
+		} else {
+			ecclk = vce_table->entries[vce_index].ecclk;
+			seq_printf(m, "\n index: %u vce ecclk: %u MHz\n", vce_index, ecclk/100);
+		}
+	}
+
+	result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetAverageGraphicsActivity);
+	if (0 == result) {
+		activity_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0);
+		activity_percent = activity_percent > 100 ? 100 : activity_percent;
+	} else {
+		activity_percent = 50;
+	}
+
+	seq_printf(m, "\n [GPU load]: %u %%\n\n", activity_percent);
+}
+
+static void cz_hw_print_display_cfg(
+	const struct cc6_settings *cc6_settings)
+{
+	PP_DBG_LOG("New Display Configuration:\n");
+
+	PP_DBG_LOG("   cpu_cc6_disable: %d\n",
+			cc6_settings->cpu_cc6_disable);
+	PP_DBG_LOG("   cpu_pstate_disable: %d\n",
+			cc6_settings->cpu_pstate_disable);
+	PP_DBG_LOG("   nb_pstate_switch_disable: %d\n",
+			cc6_settings->nb_pstate_switch_disable);
+	PP_DBG_LOG("   cpu_pstate_separation_time: %d\n\n",
+			cc6_settings->cpu_pstate_separation_time);
+}
+
+ static int cz_set_cpu_power_state(struct pp_hwmgr *hwmgr)
+{
+	struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
+	uint32_t data = 0;
+
+	if (hw_data->cc6_settings.cc6_setting_changed == true) {
+
+		hw_data->cc6_settings.cc6_setting_changed = false;
+
+		cz_hw_print_display_cfg(&hw_data->cc6_settings);
+
+		data |= (hw_data->cc6_settings.cpu_pstate_separation_time
+			& PWRMGT_SEPARATION_TIME_MASK)
+			<< PWRMGT_SEPARATION_TIME_SHIFT;
+
+		data|= (hw_data->cc6_settings.cpu_cc6_disable ? 0x1 : 0x0)
+			<< PWRMGT_DISABLE_CPU_CSTATES_SHIFT;
+
+		data|= (hw_data->cc6_settings.cpu_pstate_disable ? 0x1 : 0x0)
+			<< PWRMGT_DISABLE_CPU_PSTATES_SHIFT;
+
+		PP_DBG_LOG("SetDisplaySizePowerParams data: 0x%X\n",
+			data);
+
+		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_SetDisplaySizePowerParams,
+						data);
+	}
+
+	return 0;
+}
+
+
+ static int cz_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time,
+			bool cc6_disable, bool pstate_disable, bool pstate_switch_disable)
+ {
+	struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
+
+	if (separation_time !=
+		hw_data->cc6_settings.cpu_pstate_separation_time
+		|| cc6_disable !=
+		hw_data->cc6_settings.cpu_cc6_disable
+		|| pstate_disable !=
+		hw_data->cc6_settings.cpu_pstate_disable
+		|| pstate_switch_disable !=
+		hw_data->cc6_settings.nb_pstate_switch_disable) {
+
+		hw_data->cc6_settings.cc6_setting_changed = true;
+
+		hw_data->cc6_settings.cpu_pstate_separation_time =
+			separation_time;
+		hw_data->cc6_settings.cpu_cc6_disable =
+			cc6_disable;
+		hw_data->cc6_settings.cpu_pstate_disable =
+			pstate_disable;
+		hw_data->cc6_settings.nb_pstate_switch_disable =
+			pstate_switch_disable;
+
+	}
+
+	return 0;
+}
+
+ static int cz_get_dal_power_level(struct pp_hwmgr *hwmgr,
+		struct amd_pp_dal_clock_info*info)
+{
+	uint32_t i;
+	const struct phm_clock_voltage_dependency_table * table =
+			hwmgr->dyn_state.vddc_dep_on_dal_pwrl;
+	const struct phm_clock_and_voltage_limits* limits =
+			&hwmgr->dyn_state.max_clock_voltage_on_ac;
+
+	info->engine_max_clock = limits->sclk;
+	info->memory_max_clock = limits->mclk;
+
+	for (i = table->count - 1; i > 0; i--) {
+
+		if (limits->vddc >= table->entries[i].v) {
+			info->level = table->entries[i].clk;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static const struct pp_hwmgr_func cz_hwmgr_funcs = {
+	.backend_init = cz_hwmgr_backend_init,
+	.backend_fini = cz_hwmgr_backend_fini,
+	.asic_setup = NULL,
+	.apply_state_adjust_rules = cz_apply_state_adjust_rules,
+	.force_dpm_level = cz_dpm_force_dpm_level,
+	.get_power_state_size = cz_get_power_state_size,
+	.powerdown_uvd = cz_dpm_powerdown_uvd,
+	.powergate_uvd = cz_dpm_powergate_uvd,
+	.powergate_vce = cz_dpm_powergate_vce,
+	.get_mclk = cz_dpm_get_mclk,
+	.get_sclk = cz_dpm_get_sclk,
+	.patch_boot_state = cz_dpm_patch_boot_state,
+	.get_pp_table_entry = cz_dpm_get_pp_table_entry,
+	.get_num_of_pp_table_entries = cz_dpm_get_num_of_pp_table_entries,
+	.print_current_perforce_level = cz_print_current_perforce_level,
+	.set_cpu_power_state = cz_set_cpu_power_state,
+	.store_cc6_data = cz_store_cc6_data,
+	.get_dal_power_level= cz_get_dal_power_level,
+};
+
+int cz_hwmgr_init(struct pp_hwmgr *hwmgr)
+{
+	struct cz_hwmgr *cz_hwmgr;
+	int ret = 0;
+
+	cz_hwmgr = kzalloc(sizeof(struct cz_hwmgr), GFP_KERNEL);
+	if (cz_hwmgr == NULL)
+		return -ENOMEM;
+
+	hwmgr->backend = cz_hwmgr;
+	hwmgr->hwmgr_func = &cz_hwmgr_funcs;
+	hwmgr->pptable_func = &pptable_funcs;
+	return ret;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h
new file mode 100644
index 0000000..c477f1c
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _CZ_HWMGR_H_
+#define _CZ_HWMGR_H_
+
+#include "cgs_common.h"
+#include "ppatomctrl.h"
+
+#define CZ_NUM_NBPSTATES               4
+#define CZ_NUM_NBPMEMORYCLOCK          2
+#define MAX_DISPLAY_CLOCK_LEVEL        8
+#define CZ_AT_DFLT                     30
+#define CZ_MAX_HARDWARE_POWERLEVELS    8
+#define PPCZ_VOTINGRIGHTSCLIENTS_DFLT0   0x3FFFC102
+#define CZ_MIN_DEEP_SLEEP_SCLK         800
+
+/* Carrizo device IDs */
+#define DEVICE_ID_CZ_9870             0x9870
+#define DEVICE_ID_CZ_9874             0x9874
+#define DEVICE_ID_CZ_9875             0x9875
+#define DEVICE_ID_CZ_9876             0x9876
+#define DEVICE_ID_CZ_9877             0x9877
+
+#define PHMCZ_WRITE_SMC_REGISTER(device, reg, value)                            \
+		cgs_write_ind_register(device, CGS_IND_REG__SMC, ix##reg, value)
+
+struct cz_dpm_entry {
+	uint32_t soft_min_clk;
+	uint32_t hard_min_clk;
+	uint32_t soft_max_clk;
+	uint32_t hard_max_clk;
+};
+
+struct cz_sys_info {
+	uint32_t bootup_uma_clock;
+	uint32_t bootup_engine_clock;
+	uint32_t dentist_vco_freq;
+	uint32_t nb_dpm_enable;
+	uint32_t nbp_memory_clock[CZ_NUM_NBPMEMORYCLOCK];
+	uint32_t nbp_n_clock[CZ_NUM_NBPSTATES];
+	uint16_t nbp_voltage_index[CZ_NUM_NBPSTATES];
+	uint32_t display_clock[MAX_DISPLAY_CLOCK_LEVEL];
+	uint16_t bootup_nb_voltage_index;
+	uint8_t htc_tmp_lmt;
+	uint8_t htc_hyst_lmt;
+	uint32_t system_config;
+	uint32_t uma_channel_number;
+};
+
+#define MAX_DISPLAYPHY_IDS			0x8
+#define DISPLAYPHY_LANEMASK			0xF
+#define UNKNOWN_TRANSMITTER_PHY_ID		(-1)
+
+#define DISPLAYPHY_PHYID_SHIFT			24
+#define DISPLAYPHY_LANESELECT_SHIFT		16
+
+#define DISPLAYPHY_RX_SELECT			0x1
+#define DISPLAYPHY_TX_SELECT			0x2
+#define DISPLAYPHY_CORE_SELECT			0x4
+
+#define DDI_POWERGATING_ARG(phyID, lanemask, rx, tx, core) \
+		(((uint32_t)(phyID))<<DISPLAYPHY_PHYID_SHIFT | \
+		((uint32_t)(lanemask))<<DISPLAYPHY_LANESELECT_SHIFT | \
+		((rx) ? DISPLAYPHY_RX_SELECT : 0) | \
+		((tx) ? DISPLAYPHY_TX_SELECT : 0) | \
+		((core) ? DISPLAYPHY_CORE_SELECT : 0))
+
+struct cz_display_phy_info_entry {
+	uint8_t phy_present;
+	uint8_t active_lane_mapping;
+	uint8_t display_config_type;
+	uint8_t active_number_of_lanes;
+};
+
+#define CZ_MAX_DISPLAYPHY_IDS			10
+
+struct cz_display_phy_info {
+	bool display_phy_access_initialized;
+	struct cz_display_phy_info_entry entries[CZ_MAX_DISPLAYPHY_IDS];
+};
+
+struct cz_power_level {
+	uint32_t engineClock;
+	uint8_t vddcIndex;
+	uint8_t dsDividerIndex;
+	uint8_t ssDividerIndex;
+	uint8_t allowGnbSlow;
+	uint8_t forceNBPstate;
+	uint8_t display_wm;
+	uint8_t vce_wm;
+	uint8_t numSIMDToPowerDown;
+	uint8_t hysteresis_up;
+	uint8_t rsv[3];
+};
+
+struct cz_uvd_clocks {
+	uint32_t vclk;
+	uint32_t dclk;
+	uint32_t vclk_low_divider;
+	uint32_t vclk_high_divider;
+	uint32_t dclk_low_divider;
+	uint32_t dclk_high_divider;
+};
+
+enum cz_pstate_previous_action {
+	DO_NOTHING = 1,
+	FORCE_HIGH,
+	CANCEL_FORCE_HIGH
+};
+
+struct pp_disable_nb_ps_flags {
+	union {
+		struct {
+			uint32_t entry : 1;
+			uint32_t display : 1;
+			uint32_t driver: 1;
+			uint32_t vce : 1;
+			uint32_t uvd : 1;
+			uint32_t acp : 1;
+			uint32_t reserved: 26;
+		} bits;
+		uint32_t u32All;
+	};
+};
+
+struct cz_power_state {
+	unsigned int magic;
+	uint32_t level;
+	struct cz_uvd_clocks uvd_clocks;
+	uint32_t evclk;
+	uint32_t ecclk;
+	uint32_t samclk;
+	uint32_t acpclk;
+	bool need_dfs_bypass;
+	uint32_t nbps_flags;
+	uint32_t bapm_flags;
+	uint8_t dpm_0_pg_nb_ps_low;
+	uint8_t dpm_0_pg_nb_ps_high;
+	uint8_t dpm_x_nb_ps_low;
+	uint8_t dpm_x_nb_ps_high;
+	enum cz_pstate_previous_action action;
+	struct cz_power_level levels[CZ_MAX_HARDWARE_POWERLEVELS];
+	struct pp_disable_nb_ps_flags disable_nb_ps_flag;
+};
+
+#define DPMFlags_SCLK_Enabled			0x00000001
+#define DPMFlags_UVD_Enabled			0x00000002
+#define DPMFlags_VCE_Enabled			0x00000004
+#define DPMFlags_ACP_Enabled			0x00000008
+#define DPMFlags_ForceHighestValid		0x40000000
+#define DPMFlags_Debug				0x80000000
+
+#define SMU_EnabledFeatureScoreboard_AcpDpmOn   0x00000001 /* bit 0 */
+#define SMU_EnabledFeatureScoreboard_SclkDpmOn    0x00200000
+#define SMU_EnabledFeatureScoreboard_UvdDpmOn   0x00800000 /* bit 23 */
+#define SMU_EnabledFeatureScoreboard_VceDpmOn   0x01000000 /* bit 24 */
+
+struct cc6_settings {
+	bool cc6_setting_changed;
+	bool nb_pstate_switch_disable;/* controls NB PState switch */
+	bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */
+	bool cpu_pstate_disable;
+	uint32_t cpu_pstate_separation_time;
+};
+
+struct cz_hwmgr {
+	uint32_t activity_target[CZ_MAX_HARDWARE_POWERLEVELS];
+	uint32_t dpm_interval;
+
+	uint32_t voltage_drop_threshold;
+
+	uint32_t voting_rights_clients;
+
+	uint32_t disable_driver_thermal_policy;
+
+	uint32_t static_screen_threshold;
+
+	uint32_t gfx_power_gating_threshold;
+
+	uint32_t activity_hysteresis;
+	uint32_t bootup_sclk_divider;
+	uint32_t gfx_ramp_step;
+	uint32_t gfx_ramp_delay; /* in micro-seconds */
+
+	uint32_t thermal_auto_throttling_treshold;
+
+	struct cz_sys_info sys_info;
+
+	struct cz_power_level boot_power_level;
+	struct cz_power_state *cz_current_ps;
+	struct cz_power_state *cz_requested_ps;
+
+	uint32_t mgcg_cgtt_local0;
+	uint32_t mgcg_cgtt_local1;
+
+	uint32_t tdr_clock; /* in 10khz unit */
+
+	uint32_t ddi_power_gating_disabled;
+	uint32_t disable_gfx_power_gating_in_uvd;
+	uint32_t disable_nb_ps3_in_battery;
+
+	uint32_t lock_nb_ps_in_uvd_play_back;
+
+	struct cz_display_phy_info display_phy_info;
+	uint32_t vce_slow_sclk_threshold; /* default 200mhz */
+	uint32_t dce_slow_sclk_threshold; /* default 300mhz */
+	uint32_t min_sclk_did;  /* minimum sclk divider */
+
+	bool disp_clk_bypass;
+	bool disp_clk_bypass_pending;
+	uint32_t bapm_enabled;
+	uint32_t clock_slow_down_freq;
+	uint32_t skip_clock_slow_down;
+	uint32_t enable_nb_ps_policy;
+	uint32_t voltage_drop_in_dce_power_gating;
+	uint32_t uvd_dpm_interval;
+	uint32_t override_dynamic_mgpg;
+	uint32_t lclk_deep_enabled;
+
+	uint32_t uvd_performance;
+
+	bool video_start;
+	bool battery_state;
+	uint32_t lowest_valid;
+	uint32_t highest_valid;
+	uint32_t high_voltage_threshold;
+	uint32_t is_nb_dpm_enabled;
+	struct cc6_settings cc6_settings;
+	uint32_t is_voltage_island_enabled;
+
+	bool pgacpinit;
+
+	uint8_t disp_config;
+
+	/* PowerTune */
+	uint32_t power_containment_features;
+	bool cac_enabled;
+	bool disable_uvd_power_tune_feature;
+	bool enable_ba_pm_feature;
+	bool enable_tdc_limit_feature;
+
+	uint32_t sram_end;
+	uint32_t dpm_table_start;
+	uint32_t soft_regs_start;
+
+	uint8_t uvd_level_count;
+	uint8_t vce_level_count;
+
+	uint8_t acp_level_count;
+	uint8_t samu_level_count;
+	uint32_t fps_high_threshold;
+	uint32_t fps_low_threshold;
+
+	uint32_t dpm_flags;
+	struct cz_dpm_entry sclk_dpm;
+	struct cz_dpm_entry uvd_dpm;
+	struct cz_dpm_entry vce_dpm;
+	struct cz_dpm_entry acp_dpm;
+
+	uint8_t uvd_boot_level;
+	uint8_t vce_boot_level;
+	uint8_t acp_boot_level;
+	uint8_t samu_boot_level;
+	uint8_t uvd_interval;
+	uint8_t vce_interval;
+	uint8_t acp_interval;
+	uint8_t samu_interval;
+
+	uint8_t graphics_interval;
+	uint8_t graphics_therm_throttle_enable;
+	uint8_t graphics_voltage_change_enable;
+
+	uint8_t graphics_clk_slow_enable;
+	uint8_t graphics_clk_slow_divider;
+
+	uint32_t display_cac;
+	uint32_t low_sclk_interrupt_threshold;
+
+	uint32_t dram_log_addr_h;
+	uint32_t dram_log_addr_l;
+	uint32_t dram_log_phy_addr_h;
+	uint32_t dram_log_phy_addr_l;
+	uint32_t dram_log_buff_size;
+
+	bool uvd_power_gated;
+	bool vce_power_gated;
+	bool samu_power_gated;
+	bool acp_power_gated;
+	bool acp_power_up_no_dsp;
+	uint32_t active_process_mask;
+
+	uint32_t max_sclk_level;
+	uint32_t num_of_clk_entries;
+};
+
+struct pp_hwmgr;
+
+int cz_hwmgr_init(struct pp_hwmgr *hwmgr);
+int cz_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr);
+int cz_dpm_powerup_uvd(struct pp_hwmgr *hwmgr);
+int cz_dpm_powerdown_vce(struct pp_hwmgr *hwmgr);
+int cz_dpm_powerup_vce(struct pp_hwmgr *hwmgr);
+int cz_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate);
+int  cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr);
+#endif /* _CZ_HWMGR_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.c
new file mode 100644
index 0000000..e68edf0
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#include "hwmgr.h"
+#include "fiji_clockpowergating.h"
+#include "fiji_ppsmc.h"
+#include "fiji_hwmgr.h"
+
+int fiji_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	data->uvd_power_gated = false;
+	data->vce_power_gated = false;
+	data->samu_power_gated = false;
+	data->acp_power_gated = false;
+
+	return 0;
+}
+
+int fiji_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if (data->uvd_power_gated == bgate)
+		return 0;
+
+	data->uvd_power_gated = bgate;
+
+	if (bgate)
+		fiji_update_uvd_dpm(hwmgr, true);
+	else
+		fiji_update_uvd_dpm(hwmgr, false);
+
+	return 0;
+}
+
+int fiji_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_set_power_state_input states;
+	const struct pp_power_state  *pcurrent;
+	struct pp_power_state  *requested;
+
+	if (data->vce_power_gated == bgate)
+		return 0;
+
+	data->vce_power_gated = bgate;
+
+	pcurrent = hwmgr->current_ps;
+	requested = hwmgr->request_ps;
+
+	states.pcurrent_state = &(pcurrent->hardware);
+	states.pnew_state = &(requested->hardware);
+
+	fiji_update_vce_dpm(hwmgr, &states);
+	fiji_enable_disable_vce_dpm(hwmgr, !bgate);
+
+	return 0;
+}
+
+int fiji_phm_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if (data->samu_power_gated == bgate)
+		return 0;
+
+	data->samu_power_gated = bgate;
+
+	if (bgate)
+		fiji_update_samu_dpm(hwmgr, true);
+	else
+		fiji_update_samu_dpm(hwmgr, false);
+
+	return 0;
+}
+
+int fiji_phm_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if (data->acp_power_gated == bgate)
+		return 0;
+
+	data->acp_power_gated = bgate;
+
+	if (bgate)
+		fiji_update_acp_dpm(hwmgr, true);
+	else
+		fiji_update_acp_dpm(hwmgr, false);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.h
new file mode 100644
index 0000000..33af5f5
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _FIJI_CLOCK_POWER_GATING_H_
+#define _FIJI_CLOCK_POWER_GATING_H_
+
+#include "fiji_hwmgr.h"
+#include "pp_asicblocks.h"
+
+extern int fiji_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate);
+extern int fiji_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate);
+extern int fiji_phm_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate);
+extern int fiji_phm_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate);
+extern int fiji_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr);
+#endif /* _TONGA_CLOCK_POWER_GATING_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_dyn_defaults.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_dyn_defaults.h
new file mode 100644
index 0000000..32d43e8
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_dyn_defaults.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef FIJI_DYN_DEFAULTS_H
+#define FIJI_DYN_DEFAULTS_H
+
+/** \file
+* Volcanic Islands Dynamic default parameters.
+*/
+
+enum FIJIdpm_TrendDetection
+{
+    FIJIAdpm_TrendDetection_AUTO,
+    FIJIAdpm_TrendDetection_UP,
+    FIJIAdpm_TrendDetection_DOWN
+};
+typedef enum FIJIdpm_TrendDetection FIJIdpm_TrendDetection;
+
+/* We need to fill in the default values!!!!!!!!!!!!!!!!!!!!!!! */
+
+/* Bit vector representing same fields as hardware register. */
+#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT0    0x3FFFC102  /* CP_Gfx_busy ????
+                                                         * HDP_busy
+                                                         * IH_busy
+                                                         * UVD_busy
+                                                         * VCE_busy
+                                                         * ACP_busy
+                                                         * SAMU_busy
+                                                         * SDMA enabled */
+#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT1    0x000400  /* FE_Gfx_busy  - Intended for primary usage.   Rest are for flexibility. ????
+                                                       * SH_Gfx_busy
+                                                       * RB_Gfx_busy
+                                                       * VCE_busy */
+
+#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT2    0xC00080  /* SH_Gfx_busy - Intended for primary usage.   Rest are for flexibility.
+                                                       * FE_Gfx_busy
+                                                       * RB_Gfx_busy
+                                                       * ACP_busy */
+
+#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT3    0xC00200  /* RB_Gfx_busy - Intended for primary usage.   Rest are for flexibility.
+                                                       * FE_Gfx_busy
+                                                       * SH_Gfx_busy
+                                                       * UVD_busy */
+
+#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT4    0xC01680  /* UVD_busy
+                                                       * VCE_busy
+                                                       * ACP_busy
+                                                       * SAMU_busy */
+
+#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT5    0xC00033  /* GFX, HDP */
+#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT6    0xC00033  /* GFX, HDP */
+#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT7    0x3FFFC000  /* GFX, HDP */
+
+
+/* thermal protection counter (units). */
+#define PPFIJI_THERMALPROTECTCOUNTER_DFLT            0x200 /* ~19us */
+
+/* static screen threshold unit */
+#define PPFIJI_STATICSCREENTHRESHOLDUNIT_DFLT    0
+
+/* static screen threshold */
+#define PPFIJI_STATICSCREENTHRESHOLD_DFLT        0x00C8
+
+/* gfx idle clock stop threshold */
+#define PPFIJI_GFXIDLECLOCKSTOPTHRESHOLD_DFLT        0x200 /* ~19us with static screen threshold unit of 0 */
+
+/* Fixed reference divider to use when building baby stepping tables. */
+#define PPFIJI_REFERENCEDIVIDER_DFLT                  4
+
+/* ULV voltage change delay time
+ * Used to be delay_vreg in N.I. split for S.I.
+ * Using N.I. delay_vreg value as default
+ * ReferenceClock = 2700
+ * VoltageResponseTime = 1000
+ * VDDCDelayTime = (VoltageResponseTime * ReferenceClock) / 1600 = 1687
+ */
+#define PPFIJI_ULVVOLTAGECHANGEDELAY_DFLT             1687
+
+#define PPFIJI_CGULVPARAMETER_DFLT			0x00040035
+#define PPFIJI_CGULVCONTROL_DFLT			0x00007450
+#define PPFIJI_TARGETACTIVITY_DFLT			30 /* 30%*/
+#define PPFIJI_MCLK_TARGETACTIVITY_DFLT		10 /* 10% */
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
new file mode 100644
index 0000000..28031a7
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
@@ -0,0 +1,5127 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include "linux/delay.h"
+
+#include "hwmgr.h"
+#include "fiji_smumgr.h"
+#include "atombios.h"
+#include "hardwaremanager.h"
+#include "ppatomctrl.h"
+#include "atombios.h"
+#include "cgs_common.h"
+#include "fiji_dyn_defaults.h"
+#include "fiji_powertune.h"
+#include "smu73.h"
+#include "smu/smu_7_1_3_d.h"
+#include "smu/smu_7_1_3_sh_mask.h"
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+#include "bif/bif_5_0_d.h"
+#include "bif/bif_5_0_sh_mask.h"
+#include "dce/dce_10_0_d.h"
+#include "dce/dce_10_0_sh_mask.h"
+#include "pppcielanes.h"
+#include "fiji_hwmgr.h"
+#include "tonga_processpptables.h"
+#include "tonga_pptable.h"
+#include "pp_debug.h"
+#include "pp_acpi.h"
+#include "amd_pcie_helpers.h"
+#include "cgs_linux.h"
+#include "ppinterrupt.h"
+
+#include "fiji_clockpowergating.h"
+#include "fiji_thermal.h"
+
+#define VOLTAGE_SCALE	4
+#define SMC_RAM_END		0x40000
+#define VDDC_VDDCI_DELTA	300
+
+#define MC_SEQ_MISC0_GDDR5_SHIFT 28
+#define MC_SEQ_MISC0_GDDR5_MASK  0xf0000000
+#define MC_SEQ_MISC0_GDDR5_VALUE 5
+
+#define MC_CG_ARB_FREQ_F0           0x0a /* boot-up default */
+#define MC_CG_ARB_FREQ_F1           0x0b
+#define MC_CG_ARB_FREQ_F2           0x0c
+#define MC_CG_ARB_FREQ_F3           0x0d
+
+/* From smc_reg.h */
+#define SMC_CG_IND_START            0xc0030000
+#define SMC_CG_IND_END              0xc0040000  /* First byte after SMC_CG_IND */
+
+#define VOLTAGE_SCALE               4
+#define VOLTAGE_VID_OFFSET_SCALE1   625
+#define VOLTAGE_VID_OFFSET_SCALE2   100
+
+#define VDDC_VDDCI_DELTA            300
+
+#define ixSWRST_COMMAND_1           0x1400103
+#define MC_SEQ_CNTL__CAC_EN_MASK    0x40000000
+
+/** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */
+enum DPM_EVENT_SRC {
+    DPM_EVENT_SRC_ANALOG = 0,               /* Internal analog trip point */
+    DPM_EVENT_SRC_EXTERNAL = 1,             /* External (GPIO 17) signal */
+    DPM_EVENT_SRC_DIGITAL = 2,              /* Internal digital trip point (DIG_THERM_DPM) */
+    DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,   /* Internal analog or external */
+    DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4   /* Internal digital or external */
+};
+
+
+/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs
+ * not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ]
+ */
+uint16_t fiji_clock_stretcher_lookup_table[2][4] = { {600, 1050, 3, 0},
+                                                {600, 1050, 6, 1} };
+
+/* [FF, SS] type, [] 4 voltage ranges, and
+ * [Floor Freq, Boundary Freq, VID min , VID max]
+ */
+uint32_t fiji_clock_stretcher_ddt_table[2][4][4] =
+{ { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
+  { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } };
+
+/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%]
+ * (coming from PWR_CKS_CNTL.stretch_amount reg spec)
+ */
+uint8_t fiji_clock_stretch_amount_conversion[2][6] = { {0, 1, 3, 2, 4, 5},
+                                                  {0, 2, 4, 5, 6, 5} };
+
+const unsigned long PhwFiji_Magic = (unsigned long)(PHM_VIslands_Magic);
+
+struct fiji_power_state *cast_phw_fiji_power_state(
+				  struct pp_hw_power_state *hw_ps)
+{
+	PP_ASSERT_WITH_CODE((PhwFiji_Magic == hw_ps->magic),
+				"Invalid Powerstate Type!",
+				 return NULL;);
+
+	return (struct fiji_power_state *)hw_ps;
+}
+
+const struct fiji_power_state *cast_const_phw_fiji_power_state(
+				 const struct pp_hw_power_state *hw_ps)
+{
+	PP_ASSERT_WITH_CODE((PhwFiji_Magic == hw_ps->magic),
+				"Invalid Powerstate Type!",
+				 return NULL;);
+
+	return (const struct fiji_power_state *)hw_ps;
+}
+
+static bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr)
+{
+	return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device,
+			CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON))
+			? true : false;
+}
+
+static void fiji_init_dpm_defaults(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_ulv_parm *ulv = &data->ulv;
+
+	ulv->cg_ulv_parameter = PPFIJI_CGULVPARAMETER_DFLT;
+	data->voting_rights_clients0 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT0;
+	data->voting_rights_clients1 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT1;
+	data->voting_rights_clients2 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT2;
+	data->voting_rights_clients3 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT3;
+	data->voting_rights_clients4 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT4;
+	data->voting_rights_clients5 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT5;
+	data->voting_rights_clients6 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT6;
+	data->voting_rights_clients7 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT7;
+
+	data->static_screen_threshold_unit =
+			PPFIJI_STATICSCREENTHRESHOLDUNIT_DFLT;
+	data->static_screen_threshold =
+			PPFIJI_STATICSCREENTHRESHOLD_DFLT;
+
+	/* Unset ABM cap as it moved to DAL.
+	 * Add PHM_PlatformCaps_NonABMSupportInPPLib
+	 * for re-direct ABM related request to DAL
+	 */
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ABM);
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_NonABMSupportInPPLib);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_DynamicACTiming);
+
+	fiji_initialize_power_tune_defaults(hwmgr);
+
+	data->mclk_stutter_mode_threshold = 60000;
+	data->pcie_gen_performance.max = PP_PCIEGen1;
+	data->pcie_gen_performance.min = PP_PCIEGen3;
+	data->pcie_gen_power_saving.max = PP_PCIEGen1;
+	data->pcie_gen_power_saving.min = PP_PCIEGen3;
+	data->pcie_lane_performance.max = 0;
+	data->pcie_lane_performance.min = 16;
+	data->pcie_lane_power_saving.max = 0;
+	data->pcie_lane_power_saving.min = 16;
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_DynamicUVDState);
+}
+
+static int fiji_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
+	phm_ppt_v1_voltage_lookup_table *lookup_table,
+	uint16_t virtual_voltage_id, int32_t *sclk)
+{
+	uint8_t entryId;
+	uint8_t voltageId;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL);
+
+	/* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */
+	for (entryId = 0; entryId < table_info->vdd_dep_on_sclk->count; entryId++) {
+		voltageId = table_info->vdd_dep_on_sclk->entries[entryId].vddInd;
+		if (lookup_table->entries[voltageId].us_vdd == virtual_voltage_id)
+			break;
+	}
+
+	PP_ASSERT_WITH_CODE(entryId < table_info->vdd_dep_on_sclk->count,
+			"Can't find requested voltage id in vdd_dep_on_sclk table!",
+			return -EINVAL;
+			);
+
+	*sclk = table_info->vdd_dep_on_sclk->entries[entryId].clk;
+
+	return 0;
+}
+
+/**
+* Get Leakage VDDC based on leakage ID.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int fiji_get_evv_voltages(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint16_t    vv_id;
+	uint16_t    vddc = 0;
+	uint16_t    evv_default = 1150;
+	uint16_t    i, j;
+	uint32_t  sclk = 0;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)hwmgr->pptable;
+	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
+			table_info->vdd_dep_on_sclk;
+	int result;
+
+	for (i = 0; i < FIJI_MAX_LEAKAGE_COUNT; i++) {
+		vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
+		if (!fiji_get_sclk_for_voltage_evv(hwmgr,
+				table_info->vddc_lookup_table, vv_id, &sclk)) {
+			if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_ClockStretcher)) {
+				for (j = 1; j < sclk_table->count; j++) {
+					if (sclk_table->entries[j].clk == sclk &&
+							sclk_table->entries[j].cks_enable == 0) {
+						sclk += 5000;
+						break;
+					}
+				}
+			}
+
+			if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_EnableDriverEVV))
+				result = atomctrl_calculate_voltage_evv_on_sclk(hwmgr,
+						VOLTAGE_TYPE_VDDC, sclk, vv_id, &vddc, i, true);
+			else
+				result = -EINVAL;
+
+			if (result)
+				result = atomctrl_get_voltage_evv_on_sclk(hwmgr,
+						VOLTAGE_TYPE_VDDC, sclk,vv_id, &vddc);
+
+			/* need to make sure vddc is less than 2v or else, it could burn the ASIC. */
+			PP_ASSERT_WITH_CODE((vddc < 2000),
+					"Invalid VDDC value, greater than 2v!", result = -EINVAL;);
+
+			if (result)
+				/* 1.15V is the default safe value for Fiji */
+				vddc = evv_default;
+
+			/* the voltage should not be zero nor equal to leakage ID */
+			if (vddc != 0 && vddc != vv_id) {
+				data->vddc_leakage.actual_voltage
+				[data->vddc_leakage.count] = vddc;
+				data->vddc_leakage.leakage_id
+				[data->vddc_leakage.count] = vv_id;
+				data->vddc_leakage.count++;
+			}
+		}
+	}
+	return 0;
+}
+
+/**
+ * Change virtual leakage voltage to actual value.
+ *
+ * @param     hwmgr  the address of the powerplay hardware manager.
+ * @param     pointer to changing voltage
+ * @param     pointer to leakage table
+ */
+static void fiji_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr,
+		uint16_t *voltage, struct fiji_leakage_voltage *leakage_table)
+{
+	uint32_t index;
+
+	/* search for leakage voltage ID 0xff01 ~ 0xff08 */
+	for (index = 0; index < leakage_table->count; index++) {
+		/* if this voltage matches a leakage voltage ID */
+		/* patch with actual leakage voltage */
+		if (leakage_table->leakage_id[index] == *voltage) {
+			*voltage = leakage_table->actual_voltage[index];
+			break;
+		}
+	}
+
+	if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
+		printk(KERN_ERR "Voltage value looks like a Leakage ID but it's not patched \n");
+}
+
+/**
+* Patch voltage lookup table by EVV leakages.
+*
+* @param     hwmgr  the address of the powerplay hardware manager.
+* @param     pointer to voltage lookup table
+* @param     pointer to leakage table
+* @return     always 0
+*/
+static int fiji_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_voltage_lookup_table *lookup_table,
+		struct fiji_leakage_voltage *leakage_table)
+{
+	uint32_t i;
+
+	for (i = 0; i < lookup_table->count; i++)
+		fiji_patch_with_vdd_leakage(hwmgr,
+				&lookup_table->entries[i].us_vdd, leakage_table);
+
+	return 0;
+}
+
+static int fiji_patch_clock_voltage_limits_with_vddc_leakage(
+		struct pp_hwmgr *hwmgr, struct fiji_leakage_voltage *leakage_table,
+		uint16_t *vddc)
+{
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	fiji_patch_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table);
+	hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
+			table_info->max_clock_voltage_on_dc.vddc;
+	return 0;
+}
+
+static int fiji_patch_voltage_dependency_tables_with_lookup_table(
+		struct pp_hwmgr *hwmgr)
+{
+	uint8_t entryId;
+	uint8_t voltageId;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
+			table_info->vdd_dep_on_sclk;
+	struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table =
+			table_info->vdd_dep_on_mclk;
+	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
+			table_info->mm_dep_table;
+
+	for (entryId = 0; entryId < sclk_table->count; ++entryId) {
+		voltageId = sclk_table->entries[entryId].vddInd;
+		sclk_table->entries[entryId].vddc =
+				table_info->vddc_lookup_table->entries[voltageId].us_vdd;
+	}
+
+	for (entryId = 0; entryId < mclk_table->count; ++entryId) {
+		voltageId = mclk_table->entries[entryId].vddInd;
+		mclk_table->entries[entryId].vddc =
+			table_info->vddc_lookup_table->entries[voltageId].us_vdd;
+	}
+
+	for (entryId = 0; entryId < mm_table->count; ++entryId) {
+		voltageId = mm_table->entries[entryId].vddcInd;
+		mm_table->entries[entryId].vddc =
+			table_info->vddc_lookup_table->entries[voltageId].us_vdd;
+	}
+
+	return 0;
+
+}
+
+static int fiji_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr)
+{
+	/* Need to determine if we need calculated voltage. */
+	return 0;
+}
+
+static int fiji_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr)
+{
+	/* Need to determine if we need calculated voltage from mm table. */
+	return 0;
+}
+
+static int fiji_sort_lookup_table(struct pp_hwmgr *hwmgr,
+		struct phm_ppt_v1_voltage_lookup_table *lookup_table)
+{
+	uint32_t table_size, i, j;
+	struct phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record;
+	table_size = lookup_table->count;
+
+	PP_ASSERT_WITH_CODE(0 != lookup_table->count,
+		"Lookup table is empty", return -EINVAL);
+
+	/* Sorting voltages */
+	for (i = 0; i < table_size - 1; i++) {
+		for (j = i + 1; j > 0; j--) {
+			if (lookup_table->entries[j].us_vdd <
+					lookup_table->entries[j - 1].us_vdd) {
+				tmp_voltage_lookup_record = lookup_table->entries[j - 1];
+				lookup_table->entries[j - 1] = lookup_table->entries[j];
+				lookup_table->entries[j] = tmp_voltage_lookup_record;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int fiji_complete_dependency_tables(struct pp_hwmgr *hwmgr)
+{
+	int result = 0;
+	int tmp_result;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	tmp_result = fiji_patch_lookup_table_with_leakage(hwmgr,
+			table_info->vddc_lookup_table, &(data->vddc_leakage));
+	if (tmp_result)
+		result = tmp_result;
+
+	tmp_result = fiji_patch_clock_voltage_limits_with_vddc_leakage(hwmgr,
+			&(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc);
+	if (tmp_result)
+		result = tmp_result;
+
+	tmp_result = fiji_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
+	if (tmp_result)
+		result = tmp_result;
+
+	tmp_result = fiji_calc_voltage_dependency_tables(hwmgr);
+	if (tmp_result)
+		result = tmp_result;
+
+	tmp_result = fiji_calc_mm_voltage_dependency_table(hwmgr);
+	if (tmp_result)
+		result = tmp_result;
+
+	tmp_result = fiji_sort_lookup_table(hwmgr, table_info->vddc_lookup_table);
+	if(tmp_result)
+		result = tmp_result;
+
+	return result;
+}
+
+static int fiji_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
+			table_info->vdd_dep_on_sclk;
+	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
+			table_info->vdd_dep_on_mclk;
+
+	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL,
+		"VDD dependency on SCLK table is missing. 	\
+		This table is mandatory", return -EINVAL);
+	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
+		"VDD dependency on SCLK table has to have is missing. 	\
+		This table is mandatory", return -EINVAL);
+
+	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL,
+		"VDD dependency on MCLK table is missing. 	\
+		This table is mandatory", return -EINVAL);
+	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
+		"VDD dependency on MCLK table has to have is missing.	 \
+		This table is mandatory", return -EINVAL);
+
+	data->min_vddc_in_pptable = (uint16_t)allowed_sclk_vdd_table->entries[0].vddc;
+	data->max_vddc_in_pptable =	(uint16_t)allowed_sclk_vdd_table->
+			entries[allowed_sclk_vdd_table->count - 1].vddc;
+
+	table_info->max_clock_voltage_on_ac.sclk =
+		allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
+	table_info->max_clock_voltage_on_ac.mclk =
+		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
+	table_info->max_clock_voltage_on_ac.vddc =
+		allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
+	table_info->max_clock_voltage_on_ac.vddci =
+		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
+
+	hwmgr->dyn_state.max_clock_voltage_on_ac.sclk =
+		table_info->max_clock_voltage_on_ac.sclk;
+	hwmgr->dyn_state.max_clock_voltage_on_ac.mclk =
+		table_info->max_clock_voltage_on_ac.mclk;
+	hwmgr->dyn_state.max_clock_voltage_on_ac.vddc =
+		table_info->max_clock_voltage_on_ac.vddc;
+	hwmgr->dyn_state.max_clock_voltage_on_ac.vddci =
+		table_info->max_clock_voltage_on_ac.vddci;
+
+	return 0;
+}
+
+static uint16_t fiji_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
+{
+	uint32_t speedCntl = 0;
+
+	/* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
+	speedCntl = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__PCIE,
+			ixPCIE_LC_SPEED_CNTL);
+	return((uint16_t)PHM_GET_FIELD(speedCntl,
+			PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE));
+}
+
+static int fiji_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
+{
+	uint32_t link_width;
+
+	/* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
+	link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
+			PCIE_LC_LINK_WIDTH_CNTL, LC_LINK_WIDTH_RD);
+
+	PP_ASSERT_WITH_CODE((7 >= link_width),
+			"Invalid PCIe lane width!", return 0);
+
+	return decode_pcie_lane_width(link_width);
+}
+
+/** Patch the Boot State to match VBIOS boot clocks and voltage.
+*
+* @param hwmgr Pointer to the hardware manager.
+* @param pPowerState The address of the PowerState instance being created.
+*
+*/
+static int fiji_patch_boot_state(struct pp_hwmgr *hwmgr,
+		struct pp_hw_power_state *hw_ps)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_power_state *ps = (struct fiji_power_state *)hw_ps;
+	ATOM_FIRMWARE_INFO_V2_2 *fw_info;
+	uint16_t size;
+	uint8_t frev, crev;
+	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+
+	/* First retrieve the Boot clocks and VDDC from the firmware info table.
+	 * We assume here that fw_info is unchanged if this call fails.
+	 */
+	fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)cgs_atom_get_data_table(
+			hwmgr->device, index,
+			&size, &frev, &crev);
+	if (!fw_info)
+		/* During a test, there is no firmware info table. */
+		return 0;
+
+	/* Patch the state. */
+	data->vbios_boot_state.sclk_bootup_value =
+			le32_to_cpu(fw_info->ulDefaultEngineClock);
+	data->vbios_boot_state.mclk_bootup_value =
+			le32_to_cpu(fw_info->ulDefaultMemoryClock);
+	data->vbios_boot_state.mvdd_bootup_value =
+			le16_to_cpu(fw_info->usBootUpMVDDCVoltage);
+	data->vbios_boot_state.vddc_bootup_value =
+			le16_to_cpu(fw_info->usBootUpVDDCVoltage);
+	data->vbios_boot_state.vddci_bootup_value =
+			le16_to_cpu(fw_info->usBootUpVDDCIVoltage);
+	data->vbios_boot_state.pcie_gen_bootup_value =
+			fiji_get_current_pcie_speed(hwmgr);
+	data->vbios_boot_state.pcie_lane_bootup_value =
+			(uint16_t)fiji_get_current_pcie_lane_number(hwmgr);
+
+	/* set boot power state */
+	ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value;
+	ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value;
+	ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value;
+	ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value;
+
+	return 0;
+}
+
+static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t i;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	bool stay_in_boot;
+	int result;
+
+	data->dll_default_on = false;
+	data->sram_end = SMC_RAM_END;
+
+	for (i = 0; i < SMU73_MAX_LEVELS_GRAPHICS; i++)
+		data->activity_target[i] = FIJI_AT_DFLT;
+
+	data->vddc_vddci_delta = VDDC_VDDCI_DELTA;
+
+	data->mclk_activity_target = PPFIJI_MCLK_TARGETACTIVITY_DFLT;
+	data->mclk_dpm0_activity_target = 0xa;
+
+	data->sclk_dpm_key_disabled = 0;
+	data->mclk_dpm_key_disabled = 0;
+	data->pcie_dpm_key_disabled = 0;
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_UnTabledHardwareInterface);
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_TablelessHardwareInterface);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SclkDeepSleep);
+
+	data->gpio_debug = 0;
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_DynamicPatchPowerState);
+
+	/* need to set voltage control types before EVV patching */
+	data->voltage_control = FIJI_VOLTAGE_CONTROL_NONE;
+	data->vddci_control = FIJI_VOLTAGE_CONTROL_NONE;
+	data->mvdd_control = FIJI_VOLTAGE_CONTROL_NONE;
+
+	if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+			VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
+		data->voltage_control = FIJI_VOLTAGE_CONTROL_BY_SVID2;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_EnableMVDDControl))
+		if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT))
+			data->mvdd_control = FIJI_VOLTAGE_CONTROL_BY_GPIO;
+
+	if (data->mvdd_control == FIJI_VOLTAGE_CONTROL_NONE)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_EnableMVDDControl);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ControlVDDCI)) {
+		if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
+			data->vddci_control = FIJI_VOLTAGE_CONTROL_BY_GPIO;
+		else if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2))
+			data->vddci_control = FIJI_VOLTAGE_CONTROL_BY_SVID2;
+	}
+
+	if (data->vddci_control == FIJI_VOLTAGE_CONTROL_NONE)
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_ControlVDDCI);
+
+	if (table_info && table_info->cac_dtp_table->usClockStretchAmount)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_ClockStretcher);
+
+	fiji_init_dpm_defaults(hwmgr);
+
+	/* Get leakage voltage based on leakage ID. */
+	fiji_get_evv_voltages(hwmgr);
+
+	/* Patch our voltage dependency table with actual leakage voltage
+	 * We need to perform leakage translation before it's used by other functions
+	 */
+	fiji_complete_dependency_tables(hwmgr);
+
+	/* Parse pptable data read from VBIOS */
+	fiji_set_private_data_based_on_pptable(hwmgr);
+
+	/* ULV Support */
+	data->ulv.ulv_supported = true; /* ULV feature is enabled by default */
+
+	/* Initalize Dynamic State Adjustment Rule Settings */
+	result = tonga_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
+
+	if (!result) {
+		data->uvd_enabled = false;
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_EnableSMU7ThermalManagement);
+		data->vddc_phase_shed_control = false;
+	}
+
+	stay_in_boot = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_StayInBootState);
+
+	if (0 == result) {
+		struct cgs_system_info sys_info = {0};
+
+		data->is_tlu_enabled = 0;
+		hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
+				FIJI_MAX_HARDWARE_POWERLEVELS;
+		hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
+		hwmgr->platform_descriptor.minimumClocksReductionPercentage  = 50;
+
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_FanSpeedInTableIsRPM);
+
+		if (table_info->cac_dtp_table->usDefaultTargetOperatingTemp &&
+				hwmgr->thermal_controller.
+				advanceFanControlParameters.ucFanControlMode) {
+			hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM =
+					hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM;
+			hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM =
+					hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM;
+			hwmgr->dyn_state.cac_dtp_table->usOperatingTempMinLimit =
+					table_info->cac_dtp_table->usOperatingTempMinLimit;
+			hwmgr->dyn_state.cac_dtp_table->usOperatingTempMaxLimit =
+					table_info->cac_dtp_table->usOperatingTempMaxLimit;
+			hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
+					table_info->cac_dtp_table->usDefaultTargetOperatingTemp;
+			hwmgr->dyn_state.cac_dtp_table->usOperatingTempStep =
+					table_info->cac_dtp_table->usOperatingTempStep;
+			hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp =
+					table_info->cac_dtp_table->usTargetOperatingTemp;
+
+			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_ODFuzzyFanControlSupport);
+		}
+
+		sys_info.size = sizeof(struct cgs_system_info);
+		sys_info.info_id = CGS_SYSTEM_INFO_PCIE_GEN_INFO;
+		result = cgs_query_system_info(hwmgr->device, &sys_info);
+		if (result)
+			data->pcie_gen_cap = 0x30007;
+		else
+			data->pcie_gen_cap = (uint32_t)sys_info.value;
+		if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
+			data->pcie_spc_cap = 20;
+		sys_info.size = sizeof(struct cgs_system_info);
+		sys_info.info_id = CGS_SYSTEM_INFO_PCIE_MLW;
+		result = cgs_query_system_info(hwmgr->device, &sys_info);
+		if (result)
+			data->pcie_lane_cap = 0x2f0000;
+		else
+			data->pcie_lane_cap = (uint32_t)sys_info.value;
+	} else {
+		/* Ignore return value in here, we are cleaning up a mess. */
+		tonga_hwmgr_backend_fini(hwmgr);
+	}
+
+	return 0;
+}
+
+/**
+ * Read clock related registers.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+static int fiji_read_clock_registers(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	data->clock_registers.vCG_SPLL_FUNC_CNTL =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixCG_SPLL_FUNC_CNTL);
+	data->clock_registers.vCG_SPLL_FUNC_CNTL_2 =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixCG_SPLL_FUNC_CNTL_2);
+	data->clock_registers.vCG_SPLL_FUNC_CNTL_3 =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixCG_SPLL_FUNC_CNTL_3);
+	data->clock_registers.vCG_SPLL_FUNC_CNTL_4 =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixCG_SPLL_FUNC_CNTL_4);
+	data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixCG_SPLL_SPREAD_SPECTRUM);
+	data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixCG_SPLL_SPREAD_SPECTRUM_2);
+
+	return 0;
+}
+
+/**
+ * Find out if memory is GDDR5.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+static int fiji_get_memory_type(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t temp;
+
+	temp = cgs_read_register(hwmgr->device, mmMC_SEQ_MISC0);
+
+	data->is_memory_gddr5 = (MC_SEQ_MISC0_GDDR5_VALUE ==
+			((temp & MC_SEQ_MISC0_GDDR5_MASK) >>
+			 MC_SEQ_MISC0_GDDR5_SHIFT));
+
+	return 0;
+}
+
+/**
+ * Enables Dynamic Power Management by SMC
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+static int fiji_enable_acpi_power_management(struct pp_hwmgr *hwmgr)
+{
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			GENERAL_PWRMGT, STATIC_PM_EN, 1);
+
+	return 0;
+}
+
+/**
+ * Initialize PowerGating States for different engines
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+static int fiji_init_power_gate_state(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	data->uvd_power_gated = false;
+	data->vce_power_gated = false;
+	data->samu_power_gated = false;
+	data->acp_power_gated = false;
+	data->pg_acp_init = true;
+
+	return 0;
+}
+
+static int fiji_init_sclk_threshold(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	data->low_sclk_interrupt_threshold = 0;
+
+	return 0;
+}
+
+static int fiji_setup_asic_task(struct pp_hwmgr *hwmgr)
+{
+	int tmp_result, result = 0;
+
+	tmp_result = fiji_read_clock_registers(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to read clock registers!", result = tmp_result);
+
+	tmp_result = fiji_get_memory_type(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to get memory type!", result = tmp_result);
+
+	tmp_result = fiji_enable_acpi_power_management(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable ACPI power management!", result = tmp_result);
+
+	tmp_result = fiji_init_power_gate_state(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to init power gate state!", result = tmp_result);
+
+	tmp_result = tonga_get_mc_microcode_version(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to get MC microcode version!", result = tmp_result);
+
+	tmp_result = fiji_init_sclk_threshold(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to init sclk threshold!", result = tmp_result);
+
+	return result;
+}
+
+/**
+* Checks if we want to support voltage control
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+*/
+static bool fiji_voltage_control(const struct pp_hwmgr *hwmgr)
+{
+	const struct fiji_hwmgr *data =
+			(const struct fiji_hwmgr *)(hwmgr->backend);
+
+	return (FIJI_VOLTAGE_CONTROL_NONE != data->voltage_control);
+}
+
+/**
+* Enable voltage control
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int fiji_enable_voltage_control(struct pp_hwmgr *hwmgr)
+{
+	/* enable voltage control */
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1);
+
+	return 0;
+}
+
+/**
+* Remove repeated voltage values and create table with unique values.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    vol_table  the pointer to changing voltage table
+* @return    0 in success
+*/
+
+static int fiji_trim_voltage_table(struct pp_hwmgr *hwmgr,
+		struct pp_atomctrl_voltage_table *vol_table)
+{
+	uint32_t i, j;
+	uint16_t vvalue;
+	bool found = false;
+	struct pp_atomctrl_voltage_table *table;
+
+	PP_ASSERT_WITH_CODE((NULL != vol_table),
+			"Voltage Table empty.", return -EINVAL);
+	table = kzalloc(sizeof(struct pp_atomctrl_voltage_table),
+			GFP_KERNEL);
+
+	if (NULL == table)
+		return -ENOMEM;
+
+	table->mask_low = vol_table->mask_low;
+	table->phase_delay = vol_table->phase_delay;
+
+	for (i = 0; i < vol_table->count; i++) {
+		vvalue = vol_table->entries[i].value;
+		found = false;
+
+		for (j = 0; j < table->count; j++) {
+			if (vvalue == table->entries[j].value) {
+				found = true;
+				break;
+			}
+		}
+
+		if (!found) {
+			table->entries[table->count].value = vvalue;
+			table->entries[table->count].smio_low =
+					vol_table->entries[i].smio_low;
+			table->count++;
+		}
+	}
+
+	memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table));
+	kfree(table);
+
+	return 0;
+}
+
+static int fiji_get_svi2_mvdd_voltage_table(struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_clock_voltage_dependency_table *dep_table)
+{
+	uint32_t i;
+	int result;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct pp_atomctrl_voltage_table *vol_table = &(data->mvdd_voltage_table);
+
+	PP_ASSERT_WITH_CODE((0 != dep_table->count),
+			"Voltage Dependency Table empty.", return -EINVAL);
+
+	vol_table->mask_low = 0;
+	vol_table->phase_delay = 0;
+	vol_table->count = dep_table->count;
+
+	for (i = 0; i < dep_table->count; i++) {
+		vol_table->entries[i].value = dep_table->entries[i].mvdd;
+		vol_table->entries[i].smio_low = 0;
+	}
+
+	result = fiji_trim_voltage_table(hwmgr, vol_table);
+	PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to trim MVDD table.", return result);
+
+	return 0;
+}
+
+static int fiji_get_svi2_vddci_voltage_table(struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_clock_voltage_dependency_table *dep_table)
+{
+	uint32_t i;
+	int result;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct pp_atomctrl_voltage_table *vol_table = &(data->vddci_voltage_table);
+
+	PP_ASSERT_WITH_CODE((0 != dep_table->count),
+			"Voltage Dependency Table empty.", return -EINVAL);
+
+	vol_table->mask_low = 0;
+	vol_table->phase_delay = 0;
+	vol_table->count = dep_table->count;
+
+	for (i = 0; i < dep_table->count; i++) {
+		vol_table->entries[i].value = dep_table->entries[i].vddci;
+		vol_table->entries[i].smio_low = 0;
+	}
+
+	result = fiji_trim_voltage_table(hwmgr, vol_table);
+	PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to trim VDDCI table.", return result);
+
+	return 0;
+}
+
+static int fiji_get_svi2_vdd_voltage_table(struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_voltage_lookup_table *lookup_table)
+{
+	int i = 0;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct pp_atomctrl_voltage_table *vol_table = &(data->vddc_voltage_table);
+
+	PP_ASSERT_WITH_CODE((0 != lookup_table->count),
+			"Voltage Lookup Table empty.", return -EINVAL);
+
+	vol_table->mask_low = 0;
+	vol_table->phase_delay = 0;
+
+	vol_table->count = lookup_table->count;
+
+	for (i = 0; i < vol_table->count; i++) {
+		vol_table->entries[i].value = lookup_table->entries[i].us_vdd;
+		vol_table->entries[i].smio_low = 0;
+	}
+
+	return 0;
+}
+
+/* ---- Voltage Tables ----
+ * If the voltage table would be bigger than
+ * what will fit into the state table on
+ * the SMC keep only the higher entries.
+ */
+static void fiji_trim_voltage_table_to_fit_state_table(struct pp_hwmgr *hwmgr,
+		uint32_t max_vol_steps, struct pp_atomctrl_voltage_table *vol_table)
+{
+	unsigned int i, diff;
+
+	if (vol_table->count <= max_vol_steps)
+		return;
+
+	diff = vol_table->count - max_vol_steps;
+
+	for (i = 0; i < max_vol_steps; i++)
+		vol_table->entries[i] = vol_table->entries[i + diff];
+
+	vol_table->count = max_vol_steps;
+
+	return;
+}
+
+/**
+* Create Voltage Tables.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int fiji_construct_voltage_tables(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)hwmgr->pptable;
+	int result;
+
+	if (FIJI_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
+		result = atomctrl_get_voltage_table_v3(hwmgr,
+				VOLTAGE_TYPE_MVDDC,	VOLTAGE_OBJ_GPIO_LUT,
+				&(data->mvdd_voltage_table));
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to retrieve MVDD table.",
+				return result);
+	} else if (FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) {
+		result = fiji_get_svi2_mvdd_voltage_table(hwmgr,
+				table_info->vdd_dep_on_mclk);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to retrieve SVI2 MVDD table from dependancy table.",
+				return result;);
+	}
+
+	if (FIJI_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
+		result = atomctrl_get_voltage_table_v3(hwmgr,
+				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT,
+				&(data->vddci_voltage_table));
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to retrieve VDDCI table.",
+				return result);
+	} else if (FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
+		result = fiji_get_svi2_vddci_voltage_table(hwmgr,
+				table_info->vdd_dep_on_mclk);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to retrieve SVI2 VDDCI table from dependancy table.",
+				return result);
+	}
+
+	if(FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
+		result = fiji_get_svi2_vdd_voltage_table(hwmgr,
+				table_info->vddc_lookup_table);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to retrieve SVI2 VDDC table from lookup table.",
+				return result);
+	}
+
+	PP_ASSERT_WITH_CODE(
+			(data->vddc_voltage_table.count <= (SMU73_MAX_LEVELS_VDDC)),
+			"Too many voltage values for VDDC. Trimming to fit state table.",
+			fiji_trim_voltage_table_to_fit_state_table(hwmgr,
+					SMU73_MAX_LEVELS_VDDC, &(data->vddc_voltage_table)));
+
+	PP_ASSERT_WITH_CODE(
+			(data->vddci_voltage_table.count <= (SMU73_MAX_LEVELS_VDDCI)),
+			"Too many voltage values for VDDCI. Trimming to fit state table.",
+			fiji_trim_voltage_table_to_fit_state_table(hwmgr,
+					SMU73_MAX_LEVELS_VDDCI, &(data->vddci_voltage_table)));
+
+	PP_ASSERT_WITH_CODE(
+			(data->mvdd_voltage_table.count <= (SMU73_MAX_LEVELS_MVDD)),
+			"Too many voltage values for MVDD. Trimming to fit state table.",
+			fiji_trim_voltage_table_to_fit_state_table(hwmgr,
+					SMU73_MAX_LEVELS_MVDD, &(data->mvdd_voltage_table)));
+
+	return 0;
+}
+
+static int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
+{
+	/* Program additional LP registers
+	 * that are no longer programmed by VBIOS
+	 */
+	cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP,
+			cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP,
+			cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP,
+			cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP,
+			cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP,
+			cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP,
+			cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP,
+			cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING));
+
+	return 0;
+}
+
+/**
+* Programs static screed detection parameters
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int fiji_program_static_screen_threshold_parameters(
+		struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	/* Set static screen threshold unit */
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT,
+			data->static_screen_threshold_unit);
+	/* Set static screen threshold */
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD,
+			data->static_screen_threshold);
+
+	return 0;
+}
+
+/**
+* Setup display gap for glitch free memory clock switching.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always  0
+*/
+static int fiji_enable_display_gap(struct pp_hwmgr *hwmgr)
+{
+	uint32_t displayGap =
+			cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixCG_DISPLAY_GAP_CNTL);
+
+	displayGap = PHM_SET_FIELD(displayGap, CG_DISPLAY_GAP_CNTL,
+			DISP_GAP, DISPLAY_GAP_IGNORE);
+
+	displayGap = PHM_SET_FIELD(displayGap, CG_DISPLAY_GAP_CNTL,
+			DISP_GAP_MCHG, DISPLAY_GAP_VBLANK);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_DISPLAY_GAP_CNTL, displayGap);
+
+	return 0;
+}
+
+/**
+* Programs activity state transition voting clients
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always  0
+*/
+static int fiji_program_voting_clients(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	/* Clear reset for voting clients before enabling DPM */
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0);
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_0, data->voting_rights_clients0);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_1, data->voting_rights_clients1);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_2, data->voting_rights_clients2);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_3, data->voting_rights_clients3);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_4, data->voting_rights_clients4);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_5, data->voting_rights_clients5);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_6, data->voting_rights_clients6);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_7, data->voting_rights_clients7);
+
+	return 0;
+}
+
+/**
+* Get the location of various tables inside the FW image.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always  0
+*/
+static int fiji_process_firmware_header(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend);
+	uint32_t tmp;
+	int result;
+	bool error = false;
+
+	result = fiji_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU73_Firmware_Header, DpmTable),
+			&tmp, data->sram_end);
+
+	if (0 == result)
+		data->dpm_table_start = tmp;
+
+	error |= (0 != result);
+
+	result = fiji_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU73_Firmware_Header, SoftRegisters),
+			&tmp, data->sram_end);
+
+	if (!result) {
+		data->soft_regs_start = tmp;
+		smu_data->soft_regs_start = tmp;
+	}
+
+	error |= (0 != result);
+
+	result = fiji_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU73_Firmware_Header, mcRegisterTable),
+			&tmp, data->sram_end);
+
+	if (!result)
+		data->mc_reg_table_start = tmp;
+
+	result = fiji_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU73_Firmware_Header, FanTable),
+			&tmp, data->sram_end);
+
+	if (!result)
+		data->fan_table_start = tmp;
+
+	error |= (0 != result);
+
+	result = fiji_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU73_Firmware_Header, mcArbDramTimingTable),
+			&tmp, data->sram_end);
+
+	if (!result)
+		data->arb_table_start = tmp;
+
+	error |= (0 != result);
+
+	result = fiji_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU73_Firmware_Header, Version),
+			&tmp, data->sram_end);
+
+	if (!result)
+		hwmgr->microcode_version_info.SMC = tmp;
+
+	error |= (0 != result);
+
+	return error ? -1 : 0;
+}
+
+/* Copy one arb setting to another and then switch the active set.
+ * arb_src and arb_dest is one of the MC_CG_ARB_FREQ_Fx constants.
+ */
+static int fiji_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr,
+		uint32_t arb_src, uint32_t arb_dest)
+{
+	uint32_t mc_arb_dram_timing;
+	uint32_t mc_arb_dram_timing2;
+	uint32_t burst_time;
+	uint32_t mc_cg_config;
+
+	switch (arb_src) {
+	case MC_CG_ARB_FREQ_F0:
+		mc_arb_dram_timing  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
+		mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
+		burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
+		break;
+	case MC_CG_ARB_FREQ_F1:
+		mc_arb_dram_timing  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1);
+		mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1);
+		burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (arb_dest) {
+	case MC_CG_ARB_FREQ_F0:
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing);
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
+		PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time);
+		break;
+	case MC_CG_ARB_FREQ_F1:
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
+		PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG);
+	mc_cg_config |= 0x0000000F;
+	cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config);
+	PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest);
+
+	return 0;
+}
+
+/**
+* Initial switch from ARB F0->F1
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+* This function is to be called from the SetPowerState table.
+*/
+static int fiji_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr)
+{
+	return fiji_copy_and_switch_arb_sets(hwmgr,
+			MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
+}
+
+static int fiji_reset_single_dpm_table(struct pp_hwmgr *hwmgr,
+		struct fiji_single_dpm_table *dpm_table, uint32_t count)
+{
+	int i;
+	PP_ASSERT_WITH_CODE(count <= MAX_REGULAR_DPM_NUMBER,
+			"Fatal error, can not set up single DPM table entries "
+			"to exceed max number!",);
+
+	dpm_table->count = count;
+	for (i = 0; i < MAX_REGULAR_DPM_NUMBER; i++)
+		dpm_table->dpm_levels[i].enabled = false;
+
+	return 0;
+}
+
+static void fiji_setup_pcie_table_entry(
+	struct fiji_single_dpm_table *dpm_table,
+	uint32_t index, uint32_t pcie_gen,
+	uint32_t pcie_lanes)
+{
+	dpm_table->dpm_levels[index].value = pcie_gen;
+	dpm_table->dpm_levels[index].param1 = pcie_lanes;
+	dpm_table->dpm_levels[index].enabled = 1;
+}
+
+static int fiji_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table;
+	uint32_t i, max_entry;
+
+	PP_ASSERT_WITH_CODE((data->use_pcie_performance_levels ||
+			data->use_pcie_power_saving_levels), "No pcie performance levels!",
+			return -EINVAL);
+
+	if (data->use_pcie_performance_levels &&
+			!data->use_pcie_power_saving_levels) {
+		data->pcie_gen_power_saving = data->pcie_gen_performance;
+		data->pcie_lane_power_saving = data->pcie_lane_performance;
+	} else if (!data->use_pcie_performance_levels &&
+			data->use_pcie_power_saving_levels) {
+		data->pcie_gen_performance = data->pcie_gen_power_saving;
+		data->pcie_lane_performance = data->pcie_lane_power_saving;
+	}
+
+	fiji_reset_single_dpm_table(hwmgr,
+			&data->dpm_table.pcie_speed_table, SMU73_MAX_LEVELS_LINK);
+
+	if (pcie_table != NULL) {
+		/* max_entry is used to make sure we reserve one PCIE level
+		 * for boot level (fix for A+A PSPP issue).
+		 * If PCIE table from PPTable have ULV entry + 8 entries,
+		 * then ignore the last entry.*/
+		max_entry = (SMU73_MAX_LEVELS_LINK < pcie_table->count) ?
+				SMU73_MAX_LEVELS_LINK : pcie_table->count;
+		for (i = 1; i < max_entry; i++) {
+			fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i - 1,
+					get_pcie_gen_support(data->pcie_gen_cap,
+							pcie_table->entries[i].gen_speed),
+					get_pcie_lane_support(data->pcie_lane_cap,
+							pcie_table->entries[i].lane_width));
+		}
+		data->dpm_table.pcie_speed_table.count = max_entry - 1;
+	} else {
+		/* Hardcode Pcie Table */
+		fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Min_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+		fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Min_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+		fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Max_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+		fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Max_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+		fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Max_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+		fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Max_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+
+		data->dpm_table.pcie_speed_table.count = 6;
+	}
+	/* Populate last level for boot PCIE level, but do not increment count. */
+	fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table,
+			data->dpm_table.pcie_speed_table.count,
+			get_pcie_gen_support(data->pcie_gen_cap,
+					PP_Min_PCIEGen),
+			get_pcie_lane_support(data->pcie_lane_cap,
+					PP_Max_PCIELane));
+
+	return 0;
+}
+
+/*
+ * This function is to initalize all DPM state tables
+ * for SMU7 based on the dependency table.
+ * Dynamic state patching function will then trim these
+ * state tables to the allowed range based
+ * on the power policy or external client requests,
+ * such as UVD request, etc.
+ */
+static int fiji_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint32_t i;
+
+	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table =
+			table_info->vdd_dep_on_sclk;
+	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
+			table_info->vdd_dep_on_mclk;
+
+	PP_ASSERT_WITH_CODE(dep_sclk_table != NULL,
+			"SCLK dependency table is missing. This table is mandatory",
+			return -EINVAL);
+	PP_ASSERT_WITH_CODE(dep_sclk_table->count >= 1,
+			"SCLK dependency table has to have is missing. "
+			"This table is mandatory",
+			return -EINVAL);
+
+	PP_ASSERT_WITH_CODE(dep_mclk_table != NULL,
+			"MCLK dependency table is missing. This table is mandatory",
+			return -EINVAL);
+	PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1,
+			"MCLK dependency table has to have is missing. "
+			"This table is mandatory",
+			return -EINVAL);
+
+	/* clear the state table to reset everything to default */
+	fiji_reset_single_dpm_table(hwmgr,
+			&data->dpm_table.sclk_table, SMU73_MAX_LEVELS_GRAPHICS);
+	fiji_reset_single_dpm_table(hwmgr,
+			&data->dpm_table.mclk_table, SMU73_MAX_LEVELS_MEMORY);
+
+	/* Initialize Sclk DPM table based on allow Sclk values */
+	data->dpm_table.sclk_table.count = 0;
+	for (i = 0; i < dep_sclk_table->count; i++) {
+		if (i == 0 || data->dpm_table.sclk_table.dpm_levels
+				[data->dpm_table.sclk_table.count - 1].value !=
+						dep_sclk_table->entries[i].clk) {
+			data->dpm_table.sclk_table.dpm_levels
+			[data->dpm_table.sclk_table.count].value =
+					dep_sclk_table->entries[i].clk;
+			data->dpm_table.sclk_table.dpm_levels
+			[data->dpm_table.sclk_table.count].enabled =
+					(i == 0) ? true : false;
+			data->dpm_table.sclk_table.count++;
+		}
+	}
+
+	/* Initialize Mclk DPM table based on allow Mclk values */
+	data->dpm_table.mclk_table.count = 0;
+	for (i=0; i<dep_mclk_table->count; i++) {
+		if ( i==0 || data->dpm_table.mclk_table.dpm_levels
+				[data->dpm_table.mclk_table.count - 1].value !=
+						dep_mclk_table->entries[i].clk) {
+			data->dpm_table.mclk_table.dpm_levels
+			[data->dpm_table.mclk_table.count].value =
+					dep_mclk_table->entries[i].clk;
+			data->dpm_table.mclk_table.dpm_levels
+			[data->dpm_table.mclk_table.count].enabled =
+					(i == 0) ? true : false;
+			data->dpm_table.mclk_table.count++;
+		}
+	}
+
+	/* setup PCIE gen speed levels */
+	fiji_setup_default_pcie_table(hwmgr);
+
+	/* save a copy of the default DPM table */
+	memcpy(&(data->golden_dpm_table), &(data->dpm_table),
+			sizeof(struct fiji_dpm_table));
+
+	return 0;
+}
+
+/**
+ * @brief PhwFiji_GetVoltageOrder
+ *  Returns index of requested voltage record in lookup(table)
+ * @param lookup_table - lookup list to search in
+ * @param voltage - voltage to look for
+ * @return 0 on success
+ */
+uint8_t fiji_get_voltage_index(
+		struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage)
+{
+	uint8_t count = (uint8_t) (lookup_table->count);
+	uint8_t i;
+
+	PP_ASSERT_WITH_CODE((NULL != lookup_table),
+			"Lookup Table empty.", return 0);
+	PP_ASSERT_WITH_CODE((0 != count),
+			"Lookup Table empty.", return 0);
+
+	for (i = 0; i < lookup_table->count; i++) {
+		/* find first voltage equal or bigger than requested */
+		if (lookup_table->entries[i].us_vdd >= voltage)
+			return i;
+	}
+	/* voltage is bigger than max voltage in the table */
+	return i - 1;
+}
+
+/**
+* Preparation of vddc and vddgfx CAC tables for SMC.
+*
+* @param    hwmgr  the address of the hardware manager
+* @param    table  the SMC DPM table structure to be populated
+* @return   always 0
+*/
+static int fiji_populate_cac_table(struct pp_hwmgr *hwmgr,
+		struct SMU73_Discrete_DpmTable *table)
+{
+	uint32_t count;
+	uint8_t index;
+	int result = 0;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_voltage_lookup_table *lookup_table =
+			table_info->vddc_lookup_table;
+	/* tables is already swapped, so in order to use the value from it,
+	 * we need to swap it back.
+	 * We are populating vddc CAC data to BapmVddc table
+	 * in split and merged mode
+	 */
+	for( count = 0; count<lookup_table->count; count++) {
+		index = fiji_get_voltage_index(lookup_table,
+				data->vddc_voltage_table.entries[count].value);
+		table->BapmVddcVidLoSidd[count] = (uint8_t) ((6200 -
+				(lookup_table->entries[index].us_cac_low *
+						VOLTAGE_SCALE)) / 25);
+		table->BapmVddcVidHiSidd[count] = (uint8_t) ((6200 -
+				(lookup_table->entries[index].us_cac_high *
+						VOLTAGE_SCALE)) / 25);
+	}
+
+	return result;
+}
+
+/**
+* Preparation of voltage tables for SMC.
+*
+* @param    hwmgr   the address of the hardware manager
+* @param    table   the SMC DPM table structure to be populated
+* @return   always  0
+*/
+
+int fiji_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
+		struct SMU73_Discrete_DpmTable *table)
+{
+	int result;
+
+	result = fiji_populate_cac_table(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"can not populate CAC voltage tables to SMC",
+			return -EINVAL);
+
+	return 0;
+}
+
+static int fiji_populate_ulv_level(struct pp_hwmgr *hwmgr,
+		struct SMU73_Discrete_Ulv *state)
+{
+	int result = 0;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	state->CcPwrDynRm = 0;
+	state->CcPwrDynRm1 = 0;
+
+	state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset;
+	state->VddcOffsetVid = (uint8_t)( table_info->us_ulv_voltage_offset *
+			VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1 );
+
+	state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1;
+
+	if (!result) {
+		CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm);
+		CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1);
+		CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset);
+	}
+	return result;
+}
+
+static int fiji_populate_ulv_state(struct pp_hwmgr *hwmgr,
+		struct SMU73_Discrete_DpmTable *table)
+{
+	return fiji_populate_ulv_level(hwmgr, &table->Ulv);
+}
+
+static int32_t fiji_get_dpm_level_enable_mask_value(
+		struct fiji_single_dpm_table* dpm_table)
+{
+	int32_t i;
+	int32_t mask = 0;
+
+	for (i = dpm_table->count; i > 0; i--) {
+		mask = mask << 1;
+		if (dpm_table->dpm_levels[i - 1].enabled)
+			mask |= 0x1;
+		else
+			mask &= 0xFFFFFFFE;
+	}
+	return mask;
+}
+
+static int fiji_populate_smc_link_level(struct pp_hwmgr *hwmgr,
+		struct SMU73_Discrete_DpmTable *table)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_dpm_table *dpm_table = &data->dpm_table;
+	int i;
+
+	/* Index (dpm_table->pcie_speed_table.count)
+	 * is reserved for PCIE boot level. */
+	for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
+		table->LinkLevel[i].PcieGenSpeed  =
+				(uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
+		table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width(
+				dpm_table->pcie_speed_table.dpm_levels[i].param1);
+		table->LinkLevel[i].EnabledForActivity = 1;
+		table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff);
+		table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5);
+		table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30);
+	}
+
+	data->smc_state_table.LinkLevelCount =
+			(uint8_t)dpm_table->pcie_speed_table.count;
+	data->dpm_level_enable_mask.pcie_dpm_enable_mask =
+			fiji_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
+
+	return 0;
+}
+
+/**
+* Calculates the SCLK dividers using the provided engine clock
+*
+* @param    hwmgr  the address of the hardware manager
+* @param    clock  the engine clock to use to populate the structure
+* @param    sclk   the SMC SCLK structure to be populated
+*/
+static int fiji_calculate_sclk_params(struct pp_hwmgr *hwmgr,
+		uint32_t clock, struct SMU73_Discrete_GraphicsLevel *sclk)
+{
+	const struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct pp_atomctrl_clock_dividers_vi dividers;
+	uint32_t spll_func_cntl            = data->clock_registers.vCG_SPLL_FUNC_CNTL;
+	uint32_t spll_func_cntl_3          = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
+	uint32_t spll_func_cntl_4          = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
+	uint32_t cg_spll_spread_spectrum   = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
+	uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
+	uint32_t ref_clock;
+	uint32_t ref_divider;
+	uint32_t fbdiv;
+	int result;
+
+	/* get the engine clock dividers for this clock value */
+	result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock,  &dividers);
+
+	PP_ASSERT_WITH_CODE(result == 0,
+			"Error retrieving Engine Clock dividers from VBIOS.",
+			return result);
+
+	/* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */
+	ref_clock = atomctrl_get_reference_clock(hwmgr);
+	ref_divider = 1 + dividers.uc_pll_ref_div;
+
+	/* low 14 bits is fraction and high 12 bits is divider */
+	fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF;
+
+	/* SPLL_FUNC_CNTL setup */
+	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
+			SPLL_REF_DIV, dividers.uc_pll_ref_div);
+	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
+			SPLL_PDIV_A,  dividers.uc_pll_post_div);
+
+	/* SPLL_FUNC_CNTL_3 setup*/
+	spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3,
+			SPLL_FB_DIV, fbdiv);
+
+	/* set to use fractional accumulation*/
+	spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3,
+			SPLL_DITHEN, 1);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_EngineSpreadSpectrumSupport)) {
+		struct pp_atomctrl_internal_ss_info ssInfo;
+
+		uint32_t vco_freq = clock * dividers.uc_pll_post_div;
+		if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr,
+				vco_freq, &ssInfo)) {
+			/*
+			 * ss_info.speed_spectrum_percentage -- in unit of 0.01%
+			 * ss_info.speed_spectrum_rate -- in unit of khz
+			 *
+			 * clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2
+			 */
+			uint32_t clk_s = ref_clock * 5 /
+					(ref_divider * ssInfo.speed_spectrum_rate);
+			/* clkv = 2 * D * fbdiv / NS */
+			uint32_t clk_v = 4 * ssInfo.speed_spectrum_percentage *
+					fbdiv / (clk_s * 10000);
+
+			cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum,
+					CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s);
+			cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum,
+					CG_SPLL_SPREAD_SPECTRUM, SSEN, 1);
+			cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2,
+					CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v);
+		}
+	}
+
+	sclk->SclkFrequency        = clock;
+	sclk->CgSpllFuncCntl3      = spll_func_cntl_3;
+	sclk->CgSpllFuncCntl4      = spll_func_cntl_4;
+	sclk->SpllSpreadSpectrum   = cg_spll_spread_spectrum;
+	sclk->SpllSpreadSpectrum2  = cg_spll_spread_spectrum_2;
+	sclk->SclkDid              = (uint8_t)dividers.pll_post_divider;
+
+	return 0;
+}
+
+static uint16_t fiji_find_closest_vddci(struct pp_hwmgr *hwmgr, uint16_t vddci)
+{
+	uint32_t  i;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct pp_atomctrl_voltage_table *vddci_table =
+			&(data->vddci_voltage_table);
+
+	for (i = 0; i < vddci_table->count; i++) {
+		if (vddci_table->entries[i].value >= vddci)
+			return vddci_table->entries[i].value;
+	}
+
+	PP_ASSERT_WITH_CODE(false,
+			"VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
+			return vddci_table->entries[i].value);
+}
+
+static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
+		struct phm_ppt_v1_clock_voltage_dependency_table* dep_table,
+		uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd)
+{
+	uint32_t i;
+	uint16_t vddci;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	*voltage = *mvdd = 0;
+
+	/* clock - voltage dependency table is empty table */
+	if (dep_table->count == 0)
+		return -EINVAL;
+
+	for (i = 0; i < dep_table->count; i++) {
+		/* find first sclk bigger than request */
+		if (dep_table->entries[i].clk >= clock) {
+			*voltage |= (dep_table->entries[i].vddc *
+					VOLTAGE_SCALE) << VDDC_SHIFT;
+			if (FIJI_VOLTAGE_CONTROL_NONE == data->vddci_control)
+				*voltage |= (data->vbios_boot_state.vddci_bootup_value *
+						VOLTAGE_SCALE) << VDDCI_SHIFT;
+			else if (dep_table->entries[i].vddci)
+				*voltage |= (dep_table->entries[i].vddci *
+						VOLTAGE_SCALE) << VDDCI_SHIFT;
+			else {
+				vddci = fiji_find_closest_vddci(hwmgr,
+						(dep_table->entries[i].vddc -
+								(uint16_t)data->vddc_vddci_delta));
+				*voltage |= (vddci * VOLTAGE_SCALE) <<	VDDCI_SHIFT;
+			}
+
+			if (FIJI_VOLTAGE_CONTROL_NONE == data->mvdd_control)
+				*mvdd = data->vbios_boot_state.mvdd_bootup_value *
+					VOLTAGE_SCALE;
+			else if (dep_table->entries[i].mvdd)
+				*mvdd = (uint32_t) dep_table->entries[i].mvdd *
+					VOLTAGE_SCALE;
+
+			*voltage |= 1 << PHASES_SHIFT;
+			return 0;
+		}
+	}
+
+	/* sclk is bigger than max sclk in the dependence table */
+	*voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
+
+	if (FIJI_VOLTAGE_CONTROL_NONE == data->vddci_control)
+		*voltage |= (data->vbios_boot_state.vddci_bootup_value *
+				VOLTAGE_SCALE) << VDDCI_SHIFT;
+	else if (dep_table->entries[i-1].vddci) {
+		vddci = fiji_find_closest_vddci(hwmgr,
+				(dep_table->entries[i].vddc -
+						(uint16_t)data->vddc_vddci_delta));
+		*voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
+	}
+
+	if (FIJI_VOLTAGE_CONTROL_NONE == data->mvdd_control)
+		*mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE;
+	else if (dep_table->entries[i].mvdd)
+		*mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE;
+
+	return 0;
+}
+/**
+* Populates single SMC SCLK structure using the provided engine clock
+*
+* @param    hwmgr      the address of the hardware manager
+* @param    clock the engine clock to use to populate the structure
+* @param    sclk        the SMC SCLK structure to be populated
+*/
+
+static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
+		uint32_t clock, uint16_t sclk_al_threshold,
+		struct SMU73_Discrete_GraphicsLevel *level)
+{
+	int result;
+	/* PP_Clocks minClocks; */
+	uint32_t threshold, mvdd;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	result = fiji_calculate_sclk_params(hwmgr, clock, level);
+
+	/* populate graphics levels */
+	result = fiji_get_dependency_volt_by_clk(hwmgr,
+			table_info->vdd_dep_on_sclk, clock,
+			&level->MinVoltage, &mvdd);
+	PP_ASSERT_WITH_CODE((0 == result),
+			"can not find VDDC voltage value for "
+			"VDDC engine clock dependency table",
+			return result);
+
+	level->SclkFrequency = clock;
+	level->ActivityLevel = sclk_al_threshold;
+	level->CcPwrDynRm = 0;
+	level->CcPwrDynRm1 = 0;
+	level->EnabledForActivity = 0;
+	level->EnabledForThrottle = 1;
+	level->UpHyst = 10;
+	level->DownHyst = 0;
+	level->VoltageDownHyst = 0;
+	level->PowerThrottle = 0;
+
+	threshold = clock * data->fast_watermark_threshold / 100;
+
+	/*
+	* TODO: get minimum clocks from dal configaration
+	* PECI_GetMinClockSettings(hwmgr->pPECI, &minClocks);
+	*/
+	/* data->DisplayTiming.minClockInSR = minClocks.engineClockInSR; */
+
+	/* get level->DeepSleepDivId
+	if (phm_cap_enabled(hwmgr->platformDescriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
+	{
+	level->DeepSleepDivId = PhwFiji_GetSleepDividerIdFromClock(hwmgr, clock, minClocks.engineClockInSR);
+	} */
+
+	/* Default to slow, highest DPM level will be
+	 * set to PPSMC_DISPLAY_WATERMARK_LOW later.
+	 */
+	level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
+
+	CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage);
+	CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency);
+	CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel);
+	CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3);
+	CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4);
+	CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum);
+	CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2);
+	CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm);
+	CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1);
+
+	return 0;
+}
+/**
+* Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
+*
+* @param    hwmgr      the address of the hardware manager
+*/
+static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_dpm_table *dpm_table = &data->dpm_table;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table;
+	uint8_t pcie_entry_cnt = (uint8_t) data->dpm_table.pcie_speed_table.count;
+	int result = 0;
+	uint32_t array = data->dpm_table_start +
+			offsetof(SMU73_Discrete_DpmTable, GraphicsLevel);
+	uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) *
+			SMU73_MAX_LEVELS_GRAPHICS;
+	struct SMU73_Discrete_GraphicsLevel *levels =
+			data->smc_state_table.GraphicsLevel;
+	uint32_t i, max_entry;
+	uint8_t hightest_pcie_level_enabled = 0,
+			lowest_pcie_level_enabled = 0,
+			mid_pcie_level_enabled = 0,
+			count = 0;
+
+	for (i = 0; i < dpm_table->sclk_table.count; i++) {
+		result = fiji_populate_single_graphic_level(hwmgr,
+				dpm_table->sclk_table.dpm_levels[i].value,
+				(uint16_t)data->activity_target[i],
+				&levels[i]);
+		if (result)
+			return result;
+
+		/* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
+		if (i > 1)
+			levels[i].DeepSleepDivId = 0;
+	}
+
+	/* Only enable level 0 for now.*/
+	levels[0].EnabledForActivity = 1;
+
+	/* set highest level watermark to high */
+	levels[dpm_table->sclk_table.count - 1].DisplayWatermark =
+			PPSMC_DISPLAY_WATERMARK_HIGH;
+
+	data->smc_state_table.GraphicsDpmLevelCount =
+			(uint8_t)dpm_table->sclk_table.count;
+	data->dpm_level_enable_mask.sclk_dpm_enable_mask =
+			fiji_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
+
+	if (pcie_table != NULL) {
+		PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt),
+				"There must be 1 or more PCIE levels defined in PPTable.",
+				return -EINVAL);
+		max_entry = pcie_entry_cnt - 1;
+		for (i = 0; i < dpm_table->sclk_table.count; i++)
+			levels[i].pcieDpmLevel =
+					(uint8_t) ((i < max_entry)? i : max_entry);
+	} else {
+		while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
+				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
+						(1 << (hightest_pcie_level_enabled + 1))) != 0 ))
+			hightest_pcie_level_enabled++;
+
+		while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
+				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
+						(1 << lowest_pcie_level_enabled)) == 0 ))
+			lowest_pcie_level_enabled++;
+
+		while ((count < hightest_pcie_level_enabled) &&
+				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
+						(1 << (lowest_pcie_level_enabled + 1 + count))) == 0 ))
+			count++;
+
+		mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1+ count) <
+				hightest_pcie_level_enabled?
+						(lowest_pcie_level_enabled + 1 + count) :
+						hightest_pcie_level_enabled;
+
+		/* set pcieDpmLevel to hightest_pcie_level_enabled */
+		for(i = 2; i < dpm_table->sclk_table.count; i++)
+			levels[i].pcieDpmLevel = hightest_pcie_level_enabled;
+
+		/* set pcieDpmLevel to lowest_pcie_level_enabled */
+		levels[0].pcieDpmLevel = lowest_pcie_level_enabled;
+
+		/* set pcieDpmLevel to mid_pcie_level_enabled */
+		levels[1].pcieDpmLevel = mid_pcie_level_enabled;
+	}
+	/* level count will send to smc once at init smc table and never change */
+	result = fiji_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels,
+			(uint32_t)array_size, data->sram_end);
+
+	return result;
+}
+
+/**
+ * MCLK Frequency Ratio
+ * SEQ_CG_RESP  Bit[31:24] - 0x0
+ * Bit[27:24] \96 DDR3 Frequency ratio
+ * 0x0 <= 100MHz,       450 < 0x8 <= 500MHz
+ * 100 < 0x1 <= 150MHz,       500 < 0x9 <= 550MHz
+ * 150 < 0x2 <= 200MHz,       550 < 0xA <= 600MHz
+ * 200 < 0x3 <= 250MHz,       600 < 0xB <= 650MHz
+ * 250 < 0x4 <= 300MHz,       650 < 0xC <= 700MHz
+ * 300 < 0x5 <= 350MHz,       700 < 0xD <= 750MHz
+ * 350 < 0x6 <= 400MHz,       750 < 0xE <= 800MHz
+ * 400 < 0x7 <= 450MHz,       800 < 0xF
+ */
+static uint8_t fiji_get_mclk_frequency_ratio(uint32_t mem_clock)
+{
+	if (mem_clock <= 10000) return 0x0;
+	if (mem_clock <= 15000) return 0x1;
+	if (mem_clock <= 20000) return 0x2;
+	if (mem_clock <= 25000) return 0x3;
+	if (mem_clock <= 30000) return 0x4;
+	if (mem_clock <= 35000) return 0x5;
+	if (mem_clock <= 40000) return 0x6;
+	if (mem_clock <= 45000) return 0x7;
+	if (mem_clock <= 50000) return 0x8;
+	if (mem_clock <= 55000) return 0x9;
+	if (mem_clock <= 60000) return 0xa;
+	if (mem_clock <= 65000) return 0xb;
+	if (mem_clock <= 70000) return 0xc;
+	if (mem_clock <= 75000) return 0xd;
+	if (mem_clock <= 80000) return 0xe;
+	/* mem_clock > 800MHz */
+	return 0xf;
+}
+
+/**
+* Populates the SMC MCLK structure using the provided memory clock
+*
+* @param    hwmgr   the address of the hardware manager
+* @param    clock   the memory clock to use to populate the structure
+* @param    sclk    the SMC SCLK structure to be populated
+*/
+static int fiji_calculate_mclk_params(struct pp_hwmgr *hwmgr,
+    uint32_t clock, struct SMU73_Discrete_MemoryLevel *mclk)
+{
+	struct pp_atomctrl_memory_clock_param mem_param;
+	int result;
+
+	result = atomctrl_get_memory_pll_dividers_vi(hwmgr, clock, &mem_param);
+	PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to get Memory PLL Dividers.",);
+
+	/* Save the result data to outpupt memory level structure */
+	mclk->MclkFrequency   = clock;
+	mclk->MclkDivider     = (uint8_t)mem_param.mpll_post_divider;
+	mclk->FreqRange       = fiji_get_mclk_frequency_ratio(clock);
+
+	return result;
+}
+
+static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr,
+		uint32_t clock, struct SMU73_Discrete_MemoryLevel *mem_level)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	int result = 0;
+
+	if (table_info->vdd_dep_on_mclk) {
+		result = fiji_get_dependency_volt_by_clk(hwmgr,
+				table_info->vdd_dep_on_mclk, clock,
+				&mem_level->MinVoltage, &mem_level->MinMvdd);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find MinVddc voltage value from memory "
+				"VDDC voltage dependency table", return result);
+	}
+
+	mem_level->EnabledForThrottle = 1;
+	mem_level->EnabledForActivity = 0;
+	mem_level->UpHyst = 0;
+	mem_level->DownHyst = 100;
+	mem_level->VoltageDownHyst = 0;
+	mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
+	mem_level->StutterEnable = false;
+
+	mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
+
+	/* enable stutter mode if all the follow condition applied
+	 * PECI_GetNumberOfActiveDisplays(hwmgr->pPECI,
+	 * &(data->DisplayTiming.numExistingDisplays));
+	 */
+	data->display_timing.num_existing_displays = 1;
+
+	if ((data->mclk_stutter_mode_threshold) &&
+		(clock <= data->mclk_stutter_mode_threshold) &&
+		(!data->is_uvd_enabled) &&
+		(PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL,
+				STUTTER_ENABLE) & 0x1))
+		mem_level->StutterEnable = true;
+
+	result = fiji_calculate_mclk_params(hwmgr, clock, mem_level);
+	if (!result) {
+		CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd);
+		CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency);
+		CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel);
+		CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage);
+	}
+	return result;
+}
+
+/**
+* Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states
+*
+* @param    hwmgr      the address of the hardware manager
+*/
+static int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_dpm_table *dpm_table = &data->dpm_table;
+	int result;
+	/* populate MCLK dpm table to SMU7 */
+	uint32_t array = data->dpm_table_start +
+			offsetof(SMU73_Discrete_DpmTable, MemoryLevel);
+	uint32_t array_size = sizeof(SMU73_Discrete_MemoryLevel) *
+			SMU73_MAX_LEVELS_MEMORY;
+	struct SMU73_Discrete_MemoryLevel *levels =
+			data->smc_state_table.MemoryLevel;
+	uint32_t i;
+
+	for (i = 0; i < dpm_table->mclk_table.count; i++) {
+		PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
+				"can not populate memory level as memory clock is zero",
+				return -EINVAL);
+		result = fiji_populate_single_memory_level(hwmgr,
+				dpm_table->mclk_table.dpm_levels[i].value,
+				&levels[i]);
+		if (result)
+			return result;
+	}
+
+	/* Only enable level 0 for now. */
+	levels[0].EnabledForActivity = 1;
+
+	/* in order to prevent MC activity from stutter mode to push DPM up.
+	 * the UVD change complements this by putting the MCLK in
+	 * a higher state by default such that we are not effected by
+	 * up threshold or and MCLK DPM latency.
+	 */
+	levels[0].ActivityLevel = (uint16_t)data->mclk_dpm0_activity_target;
+	CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel);
+
+	data->smc_state_table.MemoryDpmLevelCount =
+			(uint8_t)dpm_table->mclk_table.count;
+	data->dpm_level_enable_mask.mclk_dpm_enable_mask =
+			fiji_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
+	/* set highest level watermark to high */
+	levels[dpm_table->mclk_table.count - 1].DisplayWatermark =
+			PPSMC_DISPLAY_WATERMARK_HIGH;
+
+	/* level count will send to smc once at init smc table and never change */
+	result = fiji_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels,
+			(uint32_t)array_size, data->sram_end);
+
+	return result;
+}
+
+/**
+* Populates the SMC MVDD structure using the provided memory clock.
+*
+* @param    hwmgr      the address of the hardware manager
+* @param    mclk        the MCLK value to be used in the decision if MVDD should be high or low.
+* @param    voltage     the SMC VOLTAGE structure to be populated
+*/
+int fiji_populate_mvdd_value(struct pp_hwmgr *hwmgr,
+		uint32_t mclk, SMIO_Pattern *smio_pat)
+{
+	const struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint32_t i = 0;
+
+	if (FIJI_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
+		/* find mvdd value which clock is more than request */
+		for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) {
+			if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) {
+				smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value;
+				break;
+			}
+		}
+		PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count,
+				"MVDD Voltage is outside the supported range.",
+				return -EINVAL);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
+		SMU73_Discrete_DpmTable *table)
+{
+	int result = 0;
+	const struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct pp_atomctrl_clock_dividers_vi dividers;
+	SMIO_Pattern vol_level;
+	uint32_t mvdd;
+	uint16_t us_mvdd;
+	uint32_t spll_func_cntl    = data->clock_registers.vCG_SPLL_FUNC_CNTL;
+	uint32_t spll_func_cntl_2  = data->clock_registers.vCG_SPLL_FUNC_CNTL_2;
+
+	table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
+
+	if (!data->sclk_dpm_key_disabled) {
+		/* Get MinVoltage and Frequency from DPM0,
+		 * already converted to SMC_UL */
+		table->ACPILevel.SclkFrequency =
+				data->dpm_table.sclk_table.dpm_levels[0].value;
+		result = fiji_get_dependency_volt_by_clk(hwmgr,
+				table_info->vdd_dep_on_sclk,
+				table->ACPILevel.SclkFrequency,
+				&table->ACPILevel.MinVoltage, &mvdd);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Cannot find ACPI VDDC voltage value "
+				"in Clock Dependency Table",);
+	} else {
+		table->ACPILevel.SclkFrequency =
+				data->vbios_boot_state.sclk_bootup_value;
+		table->ACPILevel.MinVoltage =
+				data->vbios_boot_state.vddc_bootup_value * VOLTAGE_SCALE;
+	}
+
+	/* get the engine clock dividers for this clock value */
+	result = atomctrl_get_engine_pll_dividers_vi(hwmgr,
+			table->ACPILevel.SclkFrequency,  &dividers);
+	PP_ASSERT_WITH_CODE(result == 0,
+			"Error retrieving Engine Clock dividers from VBIOS.",
+			return result);
+
+	table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider;
+	table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
+	table->ACPILevel.DeepSleepDivId = 0;
+
+	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
+			SPLL_PWRON, 0);
+	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
+			SPLL_RESET, 1);
+	spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2,
+			SCLK_MUX_SEL, 4);
+
+	table->ACPILevel.CgSpllFuncCntl = spll_func_cntl;
+	table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2;
+	table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
+	table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
+	table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
+	table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
+	table->ACPILevel.CcPwrDynRm = 0;
+	table->ACPILevel.CcPwrDynRm1 = 0;
+
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
+
+	if (!data->mclk_dpm_key_disabled) {
+		/* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */
+		table->MemoryACPILevel.MclkFrequency =
+				data->dpm_table.mclk_table.dpm_levels[0].value;
+		result = fiji_get_dependency_volt_by_clk(hwmgr,
+				table_info->vdd_dep_on_mclk,
+				table->MemoryACPILevel.MclkFrequency,
+				&table->MemoryACPILevel.MinVoltage, &mvdd);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Cannot find ACPI VDDCI voltage value "
+				"in Clock Dependency Table",);
+	} else {
+		table->MemoryACPILevel.MclkFrequency =
+				data->vbios_boot_state.mclk_bootup_value;
+		table->MemoryACPILevel.MinVoltage =
+				data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE;
+	}
+
+	us_mvdd = 0;
+	if ((FIJI_VOLTAGE_CONTROL_NONE == data->mvdd_control) ||
+			(data->mclk_dpm_key_disabled))
+		us_mvdd = data->vbios_boot_state.mvdd_bootup_value;
+	else {
+		if (!fiji_populate_mvdd_value(hwmgr,
+				data->dpm_table.mclk_table.dpm_levels[0].value,
+				&vol_level))
+			us_mvdd = vol_level.Voltage;
+	}
+
+	table->MemoryACPILevel.MinMvdd =
+			PP_HOST_TO_SMC_UL(us_mvdd * VOLTAGE_SCALE);
+
+	table->MemoryACPILevel.EnabledForThrottle = 0;
+	table->MemoryACPILevel.EnabledForActivity = 0;
+	table->MemoryACPILevel.UpHyst = 0;
+	table->MemoryACPILevel.DownHyst = 100;
+	table->MemoryACPILevel.VoltageDownHyst = 0;
+	table->MemoryACPILevel.ActivityLevel =
+			PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
+
+	table->MemoryACPILevel.StutterEnable = false;
+	CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);
+
+	return result;
+}
+
+static int fiji_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
+		SMU73_Discrete_DpmTable *table)
+{
+	int result = -EINVAL;
+	uint8_t count;
+	struct pp_atomctrl_clock_dividers_vi dividers;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
+			table_info->mm_dep_table;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	table->VceLevelCount = (uint8_t)(mm_table->count);
+	table->VceBootLevel = 0;
+
+	for(count = 0; count < table->VceLevelCount; count++) {
+		table->VceLevel[count].Frequency = mm_table->entries[count].eclk;
+		table->VceLevel[count].MinVoltage |=
+				(mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
+		table->VceLevel[count].MinVoltage |=
+				((mm_table->entries[count].vddc - data->vddc_vddci_delta) *
+						VOLTAGE_SCALE) << VDDCI_SHIFT;
+		table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
+
+		/*retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+				table->VceLevel[count].Frequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find divide id for VCE engine clock",
+				return result);
+
+		table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
+		CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage);
+	}
+	return result;
+}
+
+static int fiji_populate_smc_acp_level(struct pp_hwmgr *hwmgr,
+		SMU73_Discrete_DpmTable *table)
+{
+	int result = -EINVAL;
+	uint8_t count;
+	struct pp_atomctrl_clock_dividers_vi dividers;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
+			table_info->mm_dep_table;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	table->AcpLevelCount = (uint8_t)(mm_table->count);
+	table->AcpBootLevel = 0;
+
+	for (count = 0; count < table->AcpLevelCount; count++) {
+		table->AcpLevel[count].Frequency = mm_table->entries[count].aclk;
+		table->AcpLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
+				VOLTAGE_SCALE) << VDDC_SHIFT;
+		table->AcpLevel[count].MinVoltage |= ((mm_table->entries[count].vddc -
+				data->vddc_vddci_delta) * VOLTAGE_SCALE) << VDDCI_SHIFT;
+		table->AcpLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
+
+		/* retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+				table->AcpLevel[count].Frequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find divide id for engine clock", return result);
+
+		table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency);
+		CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].MinVoltage);
+	}
+	return result;
+}
+
+static int fiji_populate_smc_samu_level(struct pp_hwmgr *hwmgr,
+		SMU73_Discrete_DpmTable *table)
+{
+	int result = -EINVAL;
+	uint8_t count;
+	struct pp_atomctrl_clock_dividers_vi dividers;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
+			table_info->mm_dep_table;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	table->SamuBootLevel = 0;
+	table->SamuLevelCount = (uint8_t)(mm_table->count);
+
+	for (count = 0; count < table->SamuLevelCount; count++) {
+		/* not sure whether we need evclk or not */
+		table->SamuLevel[count].Frequency = mm_table->entries[count].samclock;
+		table->SamuLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
+				VOLTAGE_SCALE) << VDDC_SHIFT;
+		table->SamuLevel[count].MinVoltage |= ((mm_table->entries[count].vddc -
+				data->vddc_vddci_delta) * VOLTAGE_SCALE) << VDDCI_SHIFT;
+		table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
+
+		/* retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+				table->SamuLevel[count].Frequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find divide id for samu clock", return result);
+
+		table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency);
+		CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage);
+	}
+	return result;
+}
+
+static int fiji_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr,
+		int32_t eng_clock, int32_t mem_clock,
+		struct SMU73_Discrete_MCArbDramTimingTableEntry *arb_regs)
+{
+	uint32_t dram_timing;
+	uint32_t dram_timing2;
+	uint32_t burstTime;
+	ULONG state, trrds, trrdl;
+	int result;
+
+	result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
+			eng_clock, mem_clock);
+	PP_ASSERT_WITH_CODE(result == 0,
+			"Error calling VBIOS to set DRAM_TIMING.", return result);
+
+	dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
+	dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
+	burstTime = cgs_read_register(hwmgr->device, mmMC_ARB_BURST_TIME);
+
+	state = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, STATE0);
+	trrds = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDS0);
+	trrdl = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDL0);
+
+	arb_regs->McArbDramTiming  = PP_HOST_TO_SMC_UL(dram_timing);
+	arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2);
+	arb_regs->McArbBurstTime   = (uint8_t)burstTime;
+	arb_regs->TRRDS            = (uint8_t)trrds;
+	arb_regs->TRRDL            = (uint8_t)trrdl;
+
+	return 0;
+}
+
+static int fiji_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct SMU73_Discrete_MCArbDramTimingTable arb_regs;
+	uint32_t i, j;
+	int result = 0;
+
+	for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
+		for (j = 0; j < data->dpm_table.mclk_table.count; j++) {
+			result = fiji_populate_memory_timing_parameters(hwmgr,
+					data->dpm_table.sclk_table.dpm_levels[i].value,
+					data->dpm_table.mclk_table.dpm_levels[j].value,
+					&arb_regs.entries[i][j]);
+			if (result)
+				break;
+		}
+	}
+
+	if (!result)
+		result = fiji_copy_bytes_to_smc(
+				hwmgr->smumgr,
+				data->arb_table_start,
+				(uint8_t *)&arb_regs,
+				sizeof(SMU73_Discrete_MCArbDramTimingTable),
+				data->sram_end);
+	return result;
+}
+
+static int fiji_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
+		struct SMU73_Discrete_DpmTable *table)
+{
+	int result = -EINVAL;
+	uint8_t count;
+	struct pp_atomctrl_clock_dividers_vi dividers;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
+			table_info->mm_dep_table;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	table->UvdLevelCount = (uint8_t)(mm_table->count);
+	table->UvdBootLevel = 0;
+
+	for (count = 0; count < table->UvdLevelCount; count++) {
+		table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk;
+		table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk;
+		table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
+				VOLTAGE_SCALE) << VDDC_SHIFT;
+		table->UvdLevel[count].MinVoltage |= ((mm_table->entries[count].vddc -
+				data->vddc_vddci_delta) * VOLTAGE_SCALE) << VDDCI_SHIFT;
+		table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
+
+		/* retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+				table->UvdLevel[count].VclkFrequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find divide id for Vclk clock", return result);
+
+		table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider;
+
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+				table->UvdLevel[count].DclkFrequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find divide id for Dclk clock", return result);
+
+		table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
+		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
+		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage);
+
+	}
+	return result;
+}
+
+static int fiji_find_boot_level(struct fiji_single_dpm_table *table,
+		uint32_t value, uint32_t *boot_level)
+{
+	int result = -EINVAL;
+	uint32_t i;
+
+	for (i = 0; i < table->count; i++) {
+		if (value == table->dpm_levels[i].value) {
+			*boot_level = i;
+			result = 0;
+		}
+	}
+	return result;
+}
+
+static int fiji_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
+		struct SMU73_Discrete_DpmTable *table)
+{
+	int result = 0;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	table->GraphicsBootLevel = 0;
+	table->MemoryBootLevel = 0;
+
+	/* find boot level from dpm table */
+	result = fiji_find_boot_level(&(data->dpm_table.sclk_table),
+			data->vbios_boot_state.sclk_bootup_value,
+			(uint32_t *)&(table->GraphicsBootLevel));
+
+	result = fiji_find_boot_level(&(data->dpm_table.mclk_table),
+			data->vbios_boot_state.mclk_bootup_value,
+			(uint32_t *)&(table->MemoryBootLevel));
+
+	table->BootVddc  = data->vbios_boot_state.vddc_bootup_value *
+			VOLTAGE_SCALE;
+	table->BootVddci = data->vbios_boot_state.vddci_bootup_value *
+			VOLTAGE_SCALE;
+	table->BootMVdd  = data->vbios_boot_state.mvdd_bootup_value *
+			VOLTAGE_SCALE;
+
+	CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc);
+	CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci);
+	CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd);
+
+	return 0;
+}
+
+static int fiji_populate_smc_initailial_state(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint8_t count, level;
+
+	count = (uint8_t)(table_info->vdd_dep_on_sclk->count);
+	for (level = 0; level < count; level++) {
+		if(table_info->vdd_dep_on_sclk->entries[level].clk >=
+				data->vbios_boot_state.sclk_bootup_value) {
+			data->smc_state_table.GraphicsBootLevel = level;
+			break;
+		}
+	}
+
+	count = (uint8_t)(table_info->vdd_dep_on_mclk->count);
+	for (level = 0; level < count; level++) {
+		if(table_info->vdd_dep_on_mclk->entries[level].clk >=
+				data->vbios_boot_state.mclk_bootup_value) {
+			data->smc_state_table.MemoryBootLevel = level;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
+{
+	uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks,
+			volt_with_cks, value;
+	uint16_t clock_freq_u16;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2,
+			volt_offset = 0;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
+			table_info->vdd_dep_on_sclk;
+
+	stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount;
+
+	/* Read SMU_Eefuse to read and calculate RO and determine
+	 * if the part is SS or FF. if RO >= 1660MHz, part is FF.
+	 */
+	efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixSMU_EFUSE_0 + (146 * 4));
+	efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixSMU_EFUSE_0 + (148 * 4));
+	efuse &= 0xFF000000;
+	efuse = efuse >> 24;
+	efuse2 &= 0xF;
+
+	if (efuse2 == 1)
+		ro = (2300 - 1350) * efuse / 255 + 1350;
+	else
+		ro = (2500 - 1000) * efuse / 255 + 1000;
+
+	if (ro >= 1660)
+		type = 0;
+	else
+		type = 1;
+
+	/* Populate Stretch amount */
+	data->smc_state_table.ClockStretcherAmount = stretch_amount;
+
+	/* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
+	for (i = 0; i < sclk_table->count; i++) {
+		data->smc_state_table.Sclk_CKS_masterEn0_7 |=
+				sclk_table->entries[i].cks_enable << i;
+		volt_without_cks = (uint32_t)((14041 *
+			(sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 /
+			(4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000)));
+		volt_with_cks = (uint32_t)((13946 *
+			(sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 /
+			(3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000)));
+		if (volt_without_cks >= volt_with_cks)
+			volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks +
+					sclk_table->entries[i].cks_voffset) * 100 / 625) + 1);
+		data->smc_state_table.Sclk_voltageOffset[i] = volt_offset;
+	}
+
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
+			STRETCH_ENABLE, 0x0);
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
+			masterReset, 0x1);
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
+			staticEnable, 0x1);
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
+			masterReset, 0x0);
+
+	/* Populate CKS Lookup Table */
+	if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5)
+		stretch_amount2 = 0;
+	else if (stretch_amount == 3 || stretch_amount == 4)
+		stretch_amount2 = 1;
+	else {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_ClockStretcher);
+		PP_ASSERT_WITH_CODE(false,
+				"Stretch Amount in PPTable not supported\n",
+				return -EINVAL);
+	}
+
+	value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixPWR_CKS_CNTL);
+	value &= 0xFFC2FF87;
+	data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq =
+			fiji_clock_stretcher_lookup_table[stretch_amount2][0];
+	data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq =
+			fiji_clock_stretcher_lookup_table[stretch_amount2][1];
+	clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(data->smc_state_table.
+			GraphicsLevel[data->smc_state_table.GraphicsDpmLevelCount - 1].
+			SclkFrequency) / 100);
+	if (fiji_clock_stretcher_lookup_table[stretch_amount2][0] <
+			clock_freq_u16 &&
+	    fiji_clock_stretcher_lookup_table[stretch_amount2][1] >
+			clock_freq_u16) {
+		/* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
+		value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 16;
+		/* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
+		value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][2]) << 18;
+		/* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
+		value |= (fiji_clock_stretch_amount_conversion
+				[fiji_clock_stretcher_lookup_table[stretch_amount2][3]]
+				 [stretch_amount]) << 3;
+	}
+	CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.CKS_LOOKUPTable.
+			CKS_LOOKUPTableEntry[0].minFreq);
+	CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.CKS_LOOKUPTable.
+			CKS_LOOKUPTableEntry[0].maxFreq);
+	data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting =
+			fiji_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F;
+	data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |=
+			(fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 7;
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixPWR_CKS_CNTL, value);
+
+	/* Populate DDT Lookup Table */
+	for (i = 0; i < 4; i++) {
+		/* Assign the minimum and maximum VID stored
+		 * in the last row of Clock Stretcher Voltage Table.
+		 */
+		data->smc_state_table.ClockStretcherDataTable.
+		ClockStretcherDataTableEntry[i].minVID =
+				(uint8_t) fiji_clock_stretcher_ddt_table[type][i][2];
+		data->smc_state_table.ClockStretcherDataTable.
+		ClockStretcherDataTableEntry[i].maxVID =
+				(uint8_t) fiji_clock_stretcher_ddt_table[type][i][3];
+		/* Loop through each SCLK and check the frequency
+		 * to see if it lies within the frequency for clock stretcher.
+		 */
+		for (j = 0; j < data->smc_state_table.GraphicsDpmLevelCount; j++) {
+			cks_setting = 0;
+			clock_freq = PP_SMC_TO_HOST_UL(
+					data->smc_state_table.GraphicsLevel[j].SclkFrequency);
+			/* Check the allowed frequency against the sclk level[j].
+			 *  Sclk's endianness has already been converted,
+			 *  and it's in 10Khz unit,
+			 *  as opposed to Data table, which is in Mhz unit.
+			 */
+			if (clock_freq >=
+					(fiji_clock_stretcher_ddt_table[type][i][0]) * 100) {
+				cks_setting |= 0x2;
+				if (clock_freq <
+						(fiji_clock_stretcher_ddt_table[type][i][1]) * 100)
+					cks_setting |= 0x1;
+			}
+			data->smc_state_table.ClockStretcherDataTable.
+			ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2);
+		}
+		CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.
+				ClockStretcherDataTable.
+				ClockStretcherDataTableEntry[i].setting);
+	}
+
+	value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL);
+	value &= 0xFFFFFFFE;
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value);
+
+	return 0;
+}
+
+/**
+* Populates the SMC VRConfig field in DPM table.
+*
+* @param    hwmgr   the address of the hardware manager
+* @param    table   the SMC DPM table structure to be populated
+* @return   always 0
+*/
+static int fiji_populate_vr_config(struct pp_hwmgr *hwmgr,
+		struct SMU73_Discrete_DpmTable *table)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint16_t config;
+
+	config = VR_MERGED_WITH_VDDC;
+	table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT);
+
+	/* Set Vddc Voltage Controller */
+	if(FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
+		config = VR_SVI2_PLANE_1;
+		table->VRConfig |= config;
+	} else {
+		PP_ASSERT_WITH_CODE(false,
+				"VDDC should be on SVI2 control in merged mode!",);
+	}
+	/* Set Vddci Voltage Controller */
+	if(FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
+		config = VR_SVI2_PLANE_2;  /* only in merged mode */
+		table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
+	} else if (FIJI_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
+		config = VR_SMIO_PATTERN_1;
+		table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
+	} else {
+		config = VR_STATIC_VOLTAGE;
+		table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
+	}
+	/* Set Mvdd Voltage Controller */
+	if(FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) {
+		config = VR_SVI2_PLANE_2;
+		table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
+	} else if(FIJI_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
+		config = VR_SMIO_PATTERN_2;
+		table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
+	} else {
+		config = VR_STATIC_VOLTAGE;
+		table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
+	}
+
+	return 0;
+}
+
+/**
+* Initializes the SMC table and uploads it
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput  the pointer to input data (PowerState)
+* @return   always 0
+*/
+static int fiji_init_smc_table(struct pp_hwmgr *hwmgr)
+{
+	int result;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct SMU73_Discrete_DpmTable *table = &(data->smc_state_table);
+	const struct fiji_ulv_parm *ulv = &(data->ulv);
+	uint8_t i;
+	struct pp_atomctrl_gpio_pin_assignment gpio_pin;
+
+	result = fiji_setup_default_dpm_tables(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to setup default DPM tables!", return result);
+
+	if(FIJI_VOLTAGE_CONTROL_NONE != data->voltage_control)
+		fiji_populate_smc_voltage_tables(hwmgr, table);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_AutomaticDCTransition))
+		table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_StepVddc))
+		table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
+
+	if (data->is_memory_gddr5)
+		table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
+
+	if (ulv->ulv_supported && table_info->us_ulv_voltage_offset) {
+		result = fiji_populate_ulv_state(hwmgr, table);
+		PP_ASSERT_WITH_CODE(0 == result,
+				"Failed to initialize ULV state!", return result);
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixCG_ULV_PARAMETER, ulv->cg_ulv_parameter);
+	}
+
+	result = fiji_populate_smc_link_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize Link Level!", return result);
+
+	result = fiji_populate_all_graphic_levels(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize Graphics Level!", return result);
+
+	result = fiji_populate_all_memory_levels(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize Memory Level!", return result);
+
+	result = fiji_populate_smc_acpi_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize ACPI Level!", return result);
+
+	result = fiji_populate_smc_vce_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize VCE Level!", return result);
+
+	result = fiji_populate_smc_acp_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize ACP Level!", return result);
+
+	result = fiji_populate_smc_samu_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize SAMU Level!", return result);
+
+	/* Since only the initial state is completely set up at this point
+	 * (the other states are just copies of the boot state) we only
+	 * need to populate the  ARB settings for the initial state.
+	 */
+	result = fiji_program_memory_timing_parameters(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to Write ARB settings for the initial state.", return result);
+
+	result = fiji_populate_smc_uvd_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize UVD Level!", return result);
+
+	result = fiji_populate_smc_boot_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize Boot Level!", return result);
+
+	result = fiji_populate_smc_initailial_state(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize Boot State!", return result);
+
+	result = fiji_populate_bapm_parameters_in_dpm_table(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to populate BAPM Parameters!", return result);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ClockStretcher)) {
+		result = fiji_populate_clock_stretcher_data_table(hwmgr);
+		PP_ASSERT_WITH_CODE(0 == result,
+				"Failed to populate Clock Stretcher Data Table!",
+				return result);
+	}
+
+	table->GraphicsVoltageChangeEnable  = 1;
+	table->GraphicsThermThrottleEnable  = 1;
+	table->GraphicsInterval = 1;
+	table->VoltageInterval  = 1;
+	table->ThermalInterval  = 1;
+	table->TemperatureLimitHigh =
+			table_info->cac_dtp_table->usTargetOperatingTemp *
+			FIJI_Q88_FORMAT_CONVERSION_UNIT;
+	table->TemperatureLimitLow  =
+			(table_info->cac_dtp_table->usTargetOperatingTemp - 1) *
+			FIJI_Q88_FORMAT_CONVERSION_UNIT;
+	table->MemoryVoltageChangeEnable = 1;
+	table->MemoryInterval = 1;
+	table->VoltageResponseTime = 0;
+	table->PhaseResponseTime = 0;
+	table->MemoryThermThrottleEnable = 1;
+	table->PCIeBootLinkLevel = 0;      /* 0:Gen1 1:Gen2 2:Gen3*/
+	table->PCIeGenInterval = 1;
+
+	result = fiji_populate_vr_config(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to populate VRConfig setting!", return result);
+
+	table->ThermGpio = 17;
+	table->SclkStepSize = 0x4000;
+
+	if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) {
+		table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift;
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_RegulatorHot);
+	} else {
+		table->VRHotGpio = FIJI_UNUSED_GPIO_PIN;
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_RegulatorHot);
+	}
+
+	if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID,
+			&gpio_pin)) {
+		table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift;
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_AutomaticDCTransition);
+	} else {
+		table->AcDcGpio = FIJI_UNUSED_GPIO_PIN;
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_AutomaticDCTransition);
+	}
+
+	/* Thermal Output GPIO */
+	if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID,
+			&gpio_pin)) {
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_ThermalOutGPIO);
+
+		table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift;
+
+		/* For porlarity read GPIOPAD_A with assigned Gpio pin
+		 * since VBIOS will program this register to set 'inactive state',
+		 * driver can then determine 'active state' from this and
+		 * program SMU with correct polarity
+		 */
+		table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) &
+				(1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0;
+		table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY;
+
+		/* if required, combine VRHot/PCC with thermal out GPIO */
+		if(phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_RegulatorHot) &&
+			phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_CombinePCCWithThermalSignal))
+			table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT;
+	} else {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_ThermalOutGPIO);
+		table->ThermOutGpio = 17;
+		table->ThermOutPolarity = 1;
+		table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE;
+	}
+
+	for (i = 0; i < SMU73_MAX_ENTRIES_SMIO; i++)
+		table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
+
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
+	CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
+	CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
+	CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
+	CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
+
+	/* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
+	result = fiji_copy_bytes_to_smc(hwmgr->smumgr,
+			data->dpm_table_start +
+			offsetof(SMU73_Discrete_DpmTable, SystemFlags),
+			(uint8_t *)&(table->SystemFlags),
+			sizeof(SMU73_Discrete_DpmTable) - 3 * sizeof(SMU73_PIDController),
+			data->sram_end);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to upload dpm data to SMC memory!", return result);
+
+	return 0;
+}
+
+/**
+* Initialize the ARB DRAM timing table's index field.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr)
+{
+	const struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t tmp;
+	int result;
+
+	/* This is a read-modify-write on the first byte of the ARB table.
+	 * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure
+	 * is the field 'current'.
+	 * This solution is ugly, but we never write the whole table only
+	 * individual fields in it.
+	 * In reality this field should not be in that structure
+	 * but in a soft register.
+	 */
+	result = fiji_read_smc_sram_dword(hwmgr->smumgr,
+			data->arb_table_start, &tmp, data->sram_end);
+
+	if (result)
+		return result;
+
+	tmp &= 0x00FFFFFF;
+	tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24;
+
+	return fiji_write_smc_sram_dword(hwmgr->smumgr,
+			data->arb_table_start,  tmp, data->sram_end);
+}
+
+static int fiji_enable_vrhot_gpio_interrupt(struct pp_hwmgr *hwmgr)
+{
+	if(phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_RegulatorHot))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_EnableVRHotGPIOInterrupt);
+
+	return 0;
+}
+
+static int fiji_enable_sclk_control(struct pp_hwmgr *hwmgr)
+{
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,
+			SCLK_PWRMGT_OFF, 0);
+	return 0;
+}
+
+static int fiji_enable_ulv(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_ulv_parm *ulv = &(data->ulv);
+
+	if (ulv->ulv_supported)
+		return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_EnableULV);
+
+	return 0;
+}
+
+static int fiji_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SclkDeepSleep)) {
+		if (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_MASTER_DeepSleep_ON))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to enable Master Deep Sleep switch failed!",
+					return -1);
+	} else {
+		if (smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_MASTER_DeepSleep_OFF)) {
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to disable Master Deep Sleep switch failed!",
+					return -1);
+		}
+	}
+
+	return 0;
+}
+
+static int fiji_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t   val, val0, val2;
+	uint32_t   i, cpl_cntl, cpl_threshold, mc_threshold;
+
+	/* enable SCLK dpm */
+	if(!data->sclk_dpm_key_disabled)
+		PP_ASSERT_WITH_CODE(
+		(0 == smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DPM_Enable)),
+		"Failed to enable SCLK DPM during DPM Start Function!",
+		return -1);
+
+	/* enable MCLK dpm */
+	if(0 == data->mclk_dpm_key_disabled) {
+		cpl_threshold = 0;
+		mc_threshold = 0;
+
+		/* Read per MCD tile (0 - 7) */
+		for (i = 0; i < 8; i++) {
+			PHM_WRITE_FIELD(hwmgr->device, MC_CONFIG_MCD, MC_RD_ENABLE, i);
+			val = cgs_read_register(hwmgr->device, mmMC_SEQ_RESERVE_0_S) & 0xf0000000;
+			if (0xf0000000 != val) {
+				/* count number of MCQ that has channel(s) enabled */
+				cpl_threshold++;
+				/* only harvest 3 or full 4 supported */
+				mc_threshold = val ? 3 : 4;
+			}
+		}
+		PP_ASSERT_WITH_CODE(0 != cpl_threshold,
+				"Number of MCQ is zero!", return -EINVAL;);
+
+		mc_threshold = ((mc_threshold & LCAC_MC0_CNTL__MC0_THRESHOLD_MASK) <<
+				LCAC_MC0_CNTL__MC0_THRESHOLD__SHIFT) |
+						LCAC_MC0_CNTL__MC0_ENABLE_MASK;
+		cpl_cntl = ((cpl_threshold & LCAC_CPL_CNTL__CPL_THRESHOLD_MASK) <<
+				LCAC_CPL_CNTL__CPL_THRESHOLD__SHIFT) |
+						LCAC_CPL_CNTL__CPL_ENABLE_MASK;
+		cpl_cntl = (cpl_cntl | (8 << LCAC_CPL_CNTL__CPL_BLOCK_ID__SHIFT));
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixLCAC_MC0_CNTL, mc_threshold);
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixLCAC_MC1_CNTL, mc_threshold);
+		if (8 == cpl_threshold) {
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC2_CNTL, mc_threshold);
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC3_CNTL, mc_threshold);
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC4_CNTL, mc_threshold);
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC5_CNTL, mc_threshold);
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC6_CNTL, mc_threshold);
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC7_CNTL, mc_threshold);
+		}
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixLCAC_CPL_CNTL, cpl_cntl);
+
+		udelay(5);
+
+		mc_threshold = mc_threshold |
+				(1 << LCAC_MC0_CNTL__MC0_SIGNAL_ID__SHIFT);
+		cpl_cntl = cpl_cntl | (1 << LCAC_CPL_CNTL__CPL_SIGNAL_ID__SHIFT);
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixLCAC_MC0_CNTL, mc_threshold);
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixLCAC_MC1_CNTL, mc_threshold);
+		if (8 == cpl_threshold) {
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC2_CNTL, mc_threshold);
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC3_CNTL, mc_threshold);
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC4_CNTL, mc_threshold);
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC5_CNTL, mc_threshold);
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC6_CNTL, mc_threshold);
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixLCAC_MC7_CNTL, mc_threshold);
+		}
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixLCAC_CPL_CNTL, cpl_cntl);
+
+		/* Program CAC_EN per MCD (0-7) Tile */
+		val0 = val = cgs_read_register(hwmgr->device, mmMC_CONFIG_MCD);
+		val &= ~(MC_CONFIG_MCD__MCD0_WR_ENABLE_MASK |
+				MC_CONFIG_MCD__MCD1_WR_ENABLE_MASK |
+				MC_CONFIG_MCD__MCD2_WR_ENABLE_MASK |
+				MC_CONFIG_MCD__MCD3_WR_ENABLE_MASK |
+				MC_CONFIG_MCD__MCD4_WR_ENABLE_MASK |
+				MC_CONFIG_MCD__MCD5_WR_ENABLE_MASK |
+				MC_CONFIG_MCD__MCD6_WR_ENABLE_MASK |
+				MC_CONFIG_MCD__MCD7_WR_ENABLE_MASK |
+				MC_CONFIG_MCD__MC_RD_ENABLE_MASK);
+
+		for (i = 0; i < 8; i++) {
+			/* Enable MCD i Tile read & write */
+			val2  = (val | (i << MC_CONFIG_MCD__MC_RD_ENABLE__SHIFT) |
+					(1 << i));
+			cgs_write_register(hwmgr->device, mmMC_CONFIG_MCD, val2);
+			/* Enbale CAC_ON MCD i Tile */
+			val2 = cgs_read_register(hwmgr->device, mmMC_SEQ_CNTL);
+			val2 |= MC_SEQ_CNTL__CAC_EN_MASK;
+			cgs_write_register(hwmgr->device, mmMC_SEQ_CNTL, val2);
+		}
+		/* Set MC_CONFIG_MCD back to its default setting val0 */
+		cgs_write_register(hwmgr->device, mmMC_CONFIG_MCD, val0);
+
+		PP_ASSERT_WITH_CODE(
+				(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+						PPSMC_MSG_MCLKDPM_Enable)),
+				"Failed to enable MCLK DPM during DPM Start Function!",
+				return -1);
+	}
+	return 0;
+}
+
+static int fiji_start_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	/*enable general power management */
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
+			GLOBAL_PWRMGT_EN, 1);
+	/* enable sclk deep sleep */
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,
+			DYNAMIC_PM_EN, 1);
+	/* prepare for PCIE DPM */
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			data->soft_regs_start + offsetof(SMU73_SoftRegisters,
+					VoltageChangeTimeout), 0x1000);
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
+			SWRST_COMMAND_1, RESETLC, 0x0);
+
+	PP_ASSERT_WITH_CODE(
+			(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+					PPSMC_MSG_Voltage_Cntl_Enable)),
+			"Failed to enable voltage DPM during DPM Start Function!",
+			return -1);
+
+	if (fiji_enable_sclk_mclk_dpm(hwmgr)) {
+		printk(KERN_ERR "Failed to enable Sclk DPM and Mclk DPM!");
+		return -1;
+	}
+
+	/* enable PCIE dpm */
+	if(!data->pcie_dpm_key_disabled) {
+		PP_ASSERT_WITH_CODE(
+				(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+						PPSMC_MSG_PCIeDPM_Enable)),
+				"Failed to enable pcie DPM during DPM Start Function!",
+				return -1);
+	}
+
+	return 0;
+}
+
+static void fiji_set_dpm_event_sources(struct pp_hwmgr *hwmgr,
+		uint32_t sources)
+{
+	bool protection;
+	enum DPM_EVENT_SRC src;
+
+	switch (sources) {
+	default:
+		printk(KERN_ERR "Unknown throttling event sources.");
+		/* fall through */
+	case 0:
+		protection = false;
+		/* src is unused */
+		break;
+	case (1 << PHM_AutoThrottleSource_Thermal):
+		protection = true;
+		src = DPM_EVENT_SRC_DIGITAL;
+		break;
+	case (1 << PHM_AutoThrottleSource_External):
+		protection = true;
+		src = DPM_EVENT_SRC_EXTERNAL;
+		break;
+	case (1 << PHM_AutoThrottleSource_External) |
+			(1 << PHM_AutoThrottleSource_Thermal):
+		protection = true;
+		src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL;
+		break;
+	}
+	/* Order matters - don't enable thermal protection for the wrong source. */
+	if (protection) {
+		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL,
+				DPM_EVENT_SRC, src);
+		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
+				THERMAL_PROTECTION_DIS,
+				phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_ThermalController));
+	} else
+		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
+				THERMAL_PROTECTION_DIS, 1);
+}
+
+static int fiji_enable_auto_throttle_source(struct pp_hwmgr *hwmgr,
+		PHM_AutoThrottleSource source)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if (!(data->active_auto_throttle_sources & (1 << source))) {
+		data->active_auto_throttle_sources |= 1 << source;
+		fiji_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources);
+	}
+	return 0;
+}
+
+static int fiji_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
+{
+	return fiji_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
+}
+
+static int fiji_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
+{
+	int tmp_result, result = 0;
+
+	tmp_result = (!fiji_is_dpm_running(hwmgr))? 0 : -1;
+	PP_ASSERT_WITH_CODE(result == 0,
+			"DPM is already running right now, no need to enable DPM!",
+			return 0);
+
+	if (fiji_voltage_control(hwmgr)) {
+		tmp_result = fiji_enable_voltage_control(hwmgr);
+		PP_ASSERT_WITH_CODE(tmp_result == 0,
+				"Failed to enable voltage control!",
+				result = tmp_result);
+	}
+
+	if (fiji_voltage_control(hwmgr)) {
+		tmp_result = fiji_construct_voltage_tables(hwmgr);
+		PP_ASSERT_WITH_CODE((0 == tmp_result),
+				"Failed to contruct voltage tables!",
+				result = tmp_result);
+	}
+
+	tmp_result = fiji_initialize_mc_reg_table(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to initialize MC reg table!", result = tmp_result);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_EngineSpreadSpectrumSupport))
+		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 1);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ThermalController))
+		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 0);
+
+	tmp_result = fiji_program_static_screen_threshold_parameters(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to program static screen threshold parameters!",
+			result = tmp_result);
+
+	tmp_result = fiji_enable_display_gap(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable display gap!", result = tmp_result);
+
+	tmp_result = fiji_program_voting_clients(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to program voting clients!", result = tmp_result);
+
+	tmp_result = fiji_process_firmware_header(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to process firmware header!", result = tmp_result);
+
+	tmp_result = fiji_initial_switch_from_arbf0_to_f1(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to initialize switch from ArbF0 to F1!",
+			result = tmp_result);
+
+	tmp_result = fiji_init_smc_table(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to initialize SMC table!", result = tmp_result);
+
+	tmp_result = fiji_init_arb_table_index(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to initialize ARB table index!", result = tmp_result);
+
+	tmp_result = fiji_populate_pm_fuses(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to populate PM fuses!", result = tmp_result);
+
+	tmp_result = fiji_enable_vrhot_gpio_interrupt(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable VR hot GPIO interrupt!", result = tmp_result);
+
+	tmp_result = tonga_notify_smc_display_change(hwmgr, false);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to notify no display!", result = tmp_result);
+
+	tmp_result = fiji_enable_sclk_control(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable SCLK control!", result = tmp_result);
+
+	tmp_result = fiji_enable_ulv(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable ULV!", result = tmp_result);
+
+	tmp_result = fiji_enable_deep_sleep_master_switch(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable deep sleep master switch!", result = tmp_result);
+
+	tmp_result = fiji_start_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to start DPM!", result = tmp_result);
+
+	tmp_result = fiji_enable_smc_cac(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable SMC CAC!", result = tmp_result);
+
+	tmp_result = fiji_enable_power_containment(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable power containment!", result = tmp_result);
+
+	tmp_result = fiji_power_control_set_level(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to power control set level!", result = tmp_result);
+
+	tmp_result = fiji_enable_thermal_auto_throttle(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable thermal auto throttle!", result = tmp_result);
+
+	return result;
+}
+
+static int fiji_force_dpm_highest(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t level, tmp;
+
+	if (!data->sclk_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
+			level = 0;
+			tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask;
+			while (tmp >>= 1)
+				level++;
+			if (level)
+				smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_SCLKDPM_SetEnabledMask,
+						(1 << level));
+		}
+	}
+
+	if (!data->mclk_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
+			level = 0;
+			tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask;
+			while (tmp >>= 1)
+				level++;
+			if (level)
+				smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_MCLKDPM_SetEnabledMask,
+						(1 << level));
+		}
+	}
+
+	if (!data->pcie_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) {
+			level = 0;
+			tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask;
+			while (tmp >>= 1)
+				level++;
+			if (level)
+				smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_PCIeDPM_ForceLevel,
+						(1 << level));
+		}
+	}
+	return 0;
+}
+
+static void fiji_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
+{
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)hwmgr->pptable;
+	struct phm_clock_voltage_dependency_table *table =
+				table_info->vddc_dep_on_dal_pwrl;
+	struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table;
+	enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level;
+	uint32_t req_vddc = 0, req_volt, i;
+
+	if (!table && !(dal_power_level >= PP_DAL_POWERLEVEL_ULTRALOW &&
+			dal_power_level <= PP_DAL_POWERLEVEL_PERFORMANCE))
+		return;
+
+	for (i= 0; i < table->count; i++) {
+		if (dal_power_level == table->entries[i].clk) {
+			req_vddc = table->entries[i].v;
+			break;
+		}
+	}
+
+	vddc_table = table_info->vdd_dep_on_sclk;
+	for (i= 0; i < vddc_table->count; i++) {
+		if (req_vddc <= vddc_table->entries[i].vddc) {
+			req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE)
+					<< VDDC_SHIFT;
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_VddC_Request, req_volt);
+			return;
+		}
+	}
+	printk(KERN_ERR "DAL requested level can not"
+			" found a available voltage in VDDC DPM Table \n");
+}
+
+static int fiji_upload_dpmlevel_enable_mask(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	fiji_apply_dal_min_voltage_request(hwmgr);
+
+	if (!data->sclk_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask)
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_SCLKDPM_SetEnabledMask,
+					data->dpm_level_enable_mask.sclk_dpm_enable_mask);
+	}
+	return 0;
+}
+
+static int fiji_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if (!fiji_is_dpm_running(hwmgr))
+		return -EINVAL;
+
+	if (!data->pcie_dpm_key_disabled) {
+		smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_PCIeDPM_UnForceLevel);
+	}
+
+	return fiji_upload_dpmlevel_enable_mask(hwmgr);
+}
+
+static uint32_t fiji_get_lowest_enabled_level(
+		struct pp_hwmgr *hwmgr, uint32_t mask)
+{
+	uint32_t level = 0;
+
+	while(0 == (mask & (1 << level)))
+		level++;
+
+	return level;
+}
+
+static int fiji_force_dpm_lowest(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data =
+			(struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t level;
+
+	if (!data->sclk_dpm_key_disabled)
+		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
+			level = fiji_get_lowest_enabled_level(hwmgr,
+							      data->dpm_level_enable_mask.sclk_dpm_enable_mask);
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+							    PPSMC_MSG_SCLKDPM_SetEnabledMask,
+							    (1 << level));
+
+	}
+
+	if (!data->mclk_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
+			level = fiji_get_lowest_enabled_level(hwmgr,
+							      data->dpm_level_enable_mask.mclk_dpm_enable_mask);
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+							    PPSMC_MSG_MCLKDPM_SetEnabledMask,
+							    (1 << level));
+		}
+	}
+
+	if (!data->pcie_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) {
+			level = fiji_get_lowest_enabled_level(hwmgr,
+							      data->dpm_level_enable_mask.pcie_dpm_enable_mask);
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+							    PPSMC_MSG_PCIeDPM_ForceLevel,
+							    (1 << level));
+		}
+	}
+
+	return 0;
+
+}
+static int fiji_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
+				enum amd_dpm_forced_level level)
+{
+	int ret = 0;
+
+	switch (level) {
+	case AMD_DPM_FORCED_LEVEL_HIGH:
+		ret = fiji_force_dpm_highest(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	case AMD_DPM_FORCED_LEVEL_LOW:
+		ret = fiji_force_dpm_lowest(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	case AMD_DPM_FORCED_LEVEL_AUTO:
+		ret = fiji_unforce_dpm_levels(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	default:
+		break;
+	}
+
+	hwmgr->dpm_level = level;
+
+	return ret;
+}
+
+static int fiji_get_power_state_size(struct pp_hwmgr *hwmgr)
+{
+	return sizeof(struct fiji_power_state);
+}
+
+static int fiji_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
+		void *state, struct pp_power_state *power_state,
+		void *pp_table, uint32_t classification_flag)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_power_state  *fiji_power_state =
+			(struct fiji_power_state *)(&(power_state->hardware));
+	struct fiji_performance_level *performance_level;
+	ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state;
+	ATOM_Tonga_POWERPLAYTABLE *powerplay_table =
+			(ATOM_Tonga_POWERPLAYTABLE *)pp_table;
+	ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table =
+			(ATOM_Tonga_SCLK_Dependency_Table *)
+			(((unsigned long)powerplay_table) +
+				le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
+	ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
+			(ATOM_Tonga_MCLK_Dependency_Table *)
+			(((unsigned long)powerplay_table) +
+				le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
+
+	/* The following fields are not initialized here: id orderedList allStatesList */
+	power_state->classification.ui_label =
+			(le16_to_cpu(state_entry->usClassification) &
+			ATOM_PPLIB_CLASSIFICATION_UI_MASK) >>
+			ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
+	power_state->classification.flags = classification_flag;
+	/* NOTE: There is a classification2 flag in BIOS that is not being used right now */
+
+	power_state->classification.temporary_state = false;
+	power_state->classification.to_be_deleted = false;
+
+	power_state->validation.disallowOnDC =
+			(0 != (le32_to_cpu(state_entry->ulCapsAndSettings) &
+					ATOM_Tonga_DISALLOW_ON_DC));
+
+	power_state->pcie.lanes = 0;
+
+	power_state->display.disableFrameModulation = false;
+	power_state->display.limitRefreshrate = false;
+	power_state->display.enableVariBright =
+			(0 != (le32_to_cpu(state_entry->ulCapsAndSettings) &
+					ATOM_Tonga_ENABLE_VARIBRIGHT));
+
+	power_state->validation.supportedPowerLevels = 0;
+	power_state->uvd_clocks.VCLK = 0;
+	power_state->uvd_clocks.DCLK = 0;
+	power_state->temperatures.min = 0;
+	power_state->temperatures.max = 0;
+
+	performance_level = &(fiji_power_state->performance_levels
+			[fiji_power_state->performance_level_count++]);
+
+	PP_ASSERT_WITH_CODE(
+			(fiji_power_state->performance_level_count < SMU73_MAX_LEVELS_GRAPHICS),
+			"Performance levels exceeds SMC limit!",
+			return -1);
+
+	PP_ASSERT_WITH_CODE(
+			(fiji_power_state->performance_level_count <=
+					hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),
+			"Performance levels exceeds Driver limit!",
+			return -1);
+
+	/* Performance levels are arranged from low to high. */
+	performance_level->memory_clock = mclk_dep_table->entries
+			[state_entry->ucMemoryClockIndexLow].ulMclk;
+	performance_level->engine_clock = sclk_dep_table->entries
+			[state_entry->ucEngineClockIndexLow].ulSclk;
+	performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
+			state_entry->ucPCIEGenLow);
+	performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
+			state_entry->ucPCIELaneHigh);
+
+	performance_level = &(fiji_power_state->performance_levels
+			[fiji_power_state->performance_level_count++]);
+	performance_level->memory_clock = mclk_dep_table->entries
+			[state_entry->ucMemoryClockIndexHigh].ulMclk;
+	performance_level->engine_clock = sclk_dep_table->entries
+			[state_entry->ucEngineClockIndexHigh].ulSclk;
+	performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
+			state_entry->ucPCIEGenHigh);
+	performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
+			state_entry->ucPCIELaneHigh);
+
+	return 0;
+}
+
+static int fiji_get_pp_table_entry(struct pp_hwmgr *hwmgr,
+		unsigned long entry_index, struct pp_power_state *state)
+{
+	int result;
+	struct fiji_power_state *ps;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
+			table_info->vdd_dep_on_mclk;
+
+	state->hardware.magic = PHM_VIslands_Magic;
+
+	ps = (struct fiji_power_state *)(&state->hardware);
+
+	result = tonga_get_powerplay_table_entry(hwmgr, entry_index, state,
+			fiji_get_pp_table_entry_callback_func);
+
+	/* This is the earliest time we have all the dependency table and the VBIOS boot state
+	 * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state
+	 * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state
+	 */
+	if (dep_mclk_table != NULL && dep_mclk_table->count == 1) {
+		if (dep_mclk_table->entries[0].clk !=
+				data->vbios_boot_state.mclk_bootup_value)
+			printk(KERN_ERR "Single MCLK entry VDDCI/MCLK dependency table "
+					"does not match VBIOS boot MCLK level");
+		if (dep_mclk_table->entries[0].vddci !=
+				data->vbios_boot_state.vddci_bootup_value)
+			printk(KERN_ERR "Single VDDCI entry VDDCI/MCLK dependency table "
+					"does not match VBIOS boot VDDCI level");
+	}
+
+	/* set DC compatible flag if this state supports DC */
+	if (!state->validation.disallowOnDC)
+		ps->dc_compatible = true;
+
+	if (state->classification.flags & PP_StateClassificationFlag_ACPI)
+		data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen;
+
+	ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
+	ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
+
+	if (!result) {
+		uint32_t i;
+
+		switch (state->classification.ui_label) {
+		case PP_StateUILabel_Performance:
+			data->use_pcie_performance_levels = true;
+
+			for (i = 0; i < ps->performance_level_count; i++) {
+				if (data->pcie_gen_performance.max <
+						ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_performance.max =
+							ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_gen_performance.min >
+						ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_performance.min =
+							ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_lane_performance.max <
+						ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_performance.max =
+							ps->performance_levels[i].pcie_lane;
+
+				if (data->pcie_lane_performance.min >
+						ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_performance.min =
+							ps->performance_levels[i].pcie_lane;
+			}
+			break;
+		case PP_StateUILabel_Battery:
+			data->use_pcie_power_saving_levels = true;
+
+			for (i = 0; i < ps->performance_level_count; i++) {
+				if (data->pcie_gen_power_saving.max <
+						ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_power_saving.max =
+							ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_gen_power_saving.min >
+						ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_power_saving.min =
+							ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_lane_power_saving.max <
+						ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_power_saving.max =
+							ps->performance_levels[i].pcie_lane;
+
+				if (data->pcie_lane_power_saving.min >
+						ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_power_saving.min =
+							ps->performance_levels[i].pcie_lane;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	return 0;
+}
+
+static int fiji_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+				struct pp_power_state  *request_ps,
+			const struct pp_power_state *current_ps)
+{
+	struct fiji_power_state *fiji_ps =
+				cast_phw_fiji_power_state(&request_ps->hardware);
+	uint32_t sclk;
+	uint32_t mclk;
+	struct PP_Clocks minimum_clocks = {0};
+	bool disable_mclk_switching;
+	bool disable_mclk_switching_for_frame_lock;
+	struct cgs_display_info info = {0};
+	const struct phm_clock_and_voltage_limits *max_limits;
+	uint32_t i;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	int32_t count;
+	int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
+
+	data->battery_state = (PP_StateUILabel_Battery ==
+			request_ps->classification.ui_label);
+
+	PP_ASSERT_WITH_CODE(fiji_ps->performance_level_count == 2,
+				 "VI should always have 2 performance levels",);
+
+	max_limits = (PP_PowerSource_AC == hwmgr->power_source) ?
+			&(hwmgr->dyn_state.max_clock_voltage_on_ac) :
+			&(hwmgr->dyn_state.max_clock_voltage_on_dc);
+
+	/* Cap clock DPM tables at DC MAX if it is in DC. */
+	if (PP_PowerSource_DC == hwmgr->power_source) {
+		for (i = 0; i < fiji_ps->performance_level_count; i++) {
+			if (fiji_ps->performance_levels[i].memory_clock > max_limits->mclk)
+				fiji_ps->performance_levels[i].memory_clock = max_limits->mclk;
+			if (fiji_ps->performance_levels[i].engine_clock > max_limits->sclk)
+				fiji_ps->performance_levels[i].engine_clock = max_limits->sclk;
+		}
+	}
+
+	fiji_ps->vce_clks.evclk = hwmgr->vce_arbiter.evclk;
+	fiji_ps->vce_clks.ecclk = hwmgr->vce_arbiter.ecclk;
+
+	fiji_ps->acp_clk = hwmgr->acp_arbiter.acpclk;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	/*TO DO result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/
+
+	/* TO DO GetMinClockSettings(hwmgr->pPECI, &minimum_clocks); */
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_StablePState)) {
+		max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
+		stable_pstate_sclk = (max_limits->sclk * 75) / 100;
+
+		for (count = table_info->vdd_dep_on_sclk->count - 1;
+				count >= 0; count--) {
+			if (stable_pstate_sclk >=
+					table_info->vdd_dep_on_sclk->entries[count].clk) {
+				stable_pstate_sclk =
+						table_info->vdd_dep_on_sclk->entries[count].clk;
+				break;
+			}
+		}
+
+		if (count < 0)
+			stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk;
+
+		stable_pstate_mclk = max_limits->mclk;
+
+		minimum_clocks.engineClock = stable_pstate_sclk;
+		minimum_clocks.memoryClock = stable_pstate_mclk;
+	}
+
+	if (minimum_clocks.engineClock < hwmgr->gfx_arbiter.sclk)
+		minimum_clocks.engineClock = hwmgr->gfx_arbiter.sclk;
+
+	if (minimum_clocks.memoryClock < hwmgr->gfx_arbiter.mclk)
+		minimum_clocks.memoryClock = hwmgr->gfx_arbiter.mclk;
+
+	fiji_ps->sclk_threshold = hwmgr->gfx_arbiter.sclk_threshold;
+
+	if (0 != hwmgr->gfx_arbiter.sclk_over_drive) {
+		PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.sclk_over_drive <=
+				hwmgr->platform_descriptor.overdriveLimit.engineClock),
+				"Overdrive sclk exceeds limit",
+				hwmgr->gfx_arbiter.sclk_over_drive =
+						hwmgr->platform_descriptor.overdriveLimit.engineClock);
+
+		if (hwmgr->gfx_arbiter.sclk_over_drive >= hwmgr->gfx_arbiter.sclk)
+			fiji_ps->performance_levels[1].engine_clock =
+					hwmgr->gfx_arbiter.sclk_over_drive;
+	}
+
+	if (0 != hwmgr->gfx_arbiter.mclk_over_drive) {
+		PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.mclk_over_drive <=
+				hwmgr->platform_descriptor.overdriveLimit.memoryClock),
+				"Overdrive mclk exceeds limit",
+				hwmgr->gfx_arbiter.mclk_over_drive =
+						hwmgr->platform_descriptor.overdriveLimit.memoryClock);
+
+		if (hwmgr->gfx_arbiter.mclk_over_drive >= hwmgr->gfx_arbiter.mclk)
+			fiji_ps->performance_levels[1].memory_clock =
+					hwmgr->gfx_arbiter.mclk_over_drive;
+	}
+
+	disable_mclk_switching_for_frame_lock = phm_cap_enabled(
+				    hwmgr->platform_descriptor.platformCaps,
+				    PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
+
+	disable_mclk_switching = (1 < info.display_count) ||
+				    disable_mclk_switching_for_frame_lock;
+
+	sclk = fiji_ps->performance_levels[0].engine_clock;
+	mclk = fiji_ps->performance_levels[0].memory_clock;
+
+	if (disable_mclk_switching)
+		mclk = fiji_ps->performance_levels
+		[fiji_ps->performance_level_count - 1].memory_clock;
+
+	if (sclk < minimum_clocks.engineClock)
+		sclk = (minimum_clocks.engineClock > max_limits->sclk) ?
+				max_limits->sclk : minimum_clocks.engineClock;
+
+	if (mclk < minimum_clocks.memoryClock)
+		mclk = (minimum_clocks.memoryClock > max_limits->mclk) ?
+				max_limits->mclk : minimum_clocks.memoryClock;
+
+	fiji_ps->performance_levels[0].engine_clock = sclk;
+	fiji_ps->performance_levels[0].memory_clock = mclk;
+
+	fiji_ps->performance_levels[1].engine_clock =
+		(fiji_ps->performance_levels[1].engine_clock >=
+				fiji_ps->performance_levels[0].engine_clock) ?
+						fiji_ps->performance_levels[1].engine_clock :
+						fiji_ps->performance_levels[0].engine_clock;
+
+	if (disable_mclk_switching) {
+		if (mclk < fiji_ps->performance_levels[1].memory_clock)
+			mclk = fiji_ps->performance_levels[1].memory_clock;
+
+		fiji_ps->performance_levels[0].memory_clock = mclk;
+		fiji_ps->performance_levels[1].memory_clock = mclk;
+	} else {
+		if (fiji_ps->performance_levels[1].memory_clock <
+				fiji_ps->performance_levels[0].memory_clock)
+			fiji_ps->performance_levels[1].memory_clock =
+					fiji_ps->performance_levels[0].memory_clock;
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_StablePState)) {
+		for (i = 0; i < fiji_ps->performance_level_count; i++) {
+			fiji_ps->performance_levels[i].engine_clock = stable_pstate_sclk;
+			fiji_ps->performance_levels[i].memory_clock = stable_pstate_mclk;
+			fiji_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max;
+			fiji_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max;
+		}
+	}
+
+	return 0;
+}
+
+static int fiji_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	const struct fiji_power_state *fiji_ps =
+			cast_const_phw_fiji_power_state(states->pnew_state);
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
+	uint32_t sclk = fiji_ps->performance_levels
+			[fiji_ps->performance_level_count - 1].engine_clock;
+	struct fiji_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
+	uint32_t mclk = fiji_ps->performance_levels
+			[fiji_ps->performance_level_count - 1].memory_clock;
+	struct PP_Clocks min_clocks = {0};
+	uint32_t i;
+	struct cgs_display_info info = {0};
+
+	data->need_update_smu7_dpm_table = 0;
+
+	for (i = 0; i < sclk_table->count; i++) {
+		if (sclk == sclk_table->dpm_levels[i].value)
+			break;
+	}
+
+	if (i >= sclk_table->count)
+		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
+	else {
+	/* TODO: Check SCLK in DAL's minimum clocks
+	 * in case DeepSleep divider update is required.
+	 */
+		if(data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR)
+			data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK;
+	}
+
+	for (i = 0; i < mclk_table->count; i++) {
+		if (mclk == mclk_table->dpm_levels[i].value)
+			break;
+	}
+
+	if (i >= mclk_table->count)
+		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	if (data->display_timing.num_existing_displays != info.display_count)
+		data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK;
+
+	return 0;
+}
+
+static uint16_t fiji_get_maximum_link_speed(struct pp_hwmgr *hwmgr,
+		const struct fiji_power_state *fiji_ps)
+{
+	uint32_t i;
+	uint32_t sclk, max_sclk = 0;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_dpm_table *dpm_table = &data->dpm_table;
+
+	for (i = 0; i < fiji_ps->performance_level_count; i++) {
+		sclk = fiji_ps->performance_levels[i].engine_clock;
+		if (max_sclk < sclk)
+			max_sclk = sclk;
+	}
+
+	for (i = 0; i < dpm_table->sclk_table.count; i++) {
+		if (dpm_table->sclk_table.dpm_levels[i].value == max_sclk)
+			return (uint16_t) ((i >= dpm_table->pcie_speed_table.count) ?
+					dpm_table->pcie_speed_table.dpm_levels
+					[dpm_table->pcie_speed_table.count - 1].value :
+					dpm_table->pcie_speed_table.dpm_levels[i].value);
+	}
+
+	return 0;
+}
+
+static int fiji_request_link_speed_change_before_state_change(
+		struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	const struct fiji_power_state *fiji_nps =
+			cast_const_phw_fiji_power_state(states->pnew_state);
+	const struct fiji_power_state *fiji_cps =
+			cast_const_phw_fiji_power_state(states->pcurrent_state);
+
+	uint16_t target_link_speed = fiji_get_maximum_link_speed(hwmgr, fiji_nps);
+	uint16_t current_link_speed;
+
+	if (data->force_pcie_gen == PP_PCIEGenInvalid)
+		current_link_speed = fiji_get_maximum_link_speed(hwmgr, fiji_cps);
+	else
+		current_link_speed = data->force_pcie_gen;
+
+	data->force_pcie_gen = PP_PCIEGenInvalid;
+	data->pspp_notify_required = false;
+	if (target_link_speed > current_link_speed) {
+		switch(target_link_speed) {
+		case PP_PCIEGen3:
+			if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN3, false))
+				break;
+			data->force_pcie_gen = PP_PCIEGen2;
+			if (current_link_speed == PP_PCIEGen2)
+				break;
+		case PP_PCIEGen2:
+			if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN2, false))
+				break;
+		default:
+			data->force_pcie_gen = fiji_get_current_pcie_speed(hwmgr);
+			break;
+		}
+	} else {
+		if (target_link_speed < current_link_speed)
+			data->pspp_notify_required = true;
+	}
+
+	return 0;
+}
+
+static int fiji_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if (0 == data->need_update_smu7_dpm_table)
+		return 0;
+
+	if ((0 == data->sclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table &
+			(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
+		PP_ASSERT_WITH_CODE(true == fiji_is_dpm_running(hwmgr),
+				"Trying to freeze SCLK DPM when DPM is disabled",);
+		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_SCLKDPM_FreezeLevel),
+				"Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!",
+				return -1);
+	}
+
+	if ((0 == data->mclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table &
+		 DPMTABLE_OD_UPDATE_MCLK)) {
+		PP_ASSERT_WITH_CODE(true == fiji_is_dpm_running(hwmgr),
+				"Trying to freeze MCLK DPM when DPM is disabled",);
+		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_MCLKDPM_FreezeLevel),
+				"Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!",
+				return -1);
+	}
+
+	return 0;
+}
+
+static int fiji_populate_and_upload_sclk_mclk_dpm_levels(
+		struct pp_hwmgr *hwmgr, const void *input)
+{
+	int result = 0;
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	const struct fiji_power_state *fiji_ps =
+			cast_const_phw_fiji_power_state(states->pnew_state);
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t sclk = fiji_ps->performance_levels
+			[fiji_ps->performance_level_count - 1].engine_clock;
+	uint32_t mclk = fiji_ps->performance_levels
+			[fiji_ps->performance_level_count - 1].memory_clock;
+	struct fiji_dpm_table *dpm_table = &data->dpm_table;
+
+	struct fiji_dpm_table *golden_dpm_table = &data->golden_dpm_table;
+	uint32_t dpm_count, clock_percent;
+	uint32_t i;
+
+	if (0 == data->need_update_smu7_dpm_table)
+		return 0;
+
+	if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) {
+		dpm_table->sclk_table.dpm_levels
+		[dpm_table->sclk_table.count - 1].value = sclk;
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_OD6PlusinACSupport) ||
+			phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_OD6PlusinDCSupport)) {
+		/* Need to do calculation based on the golden DPM table
+		 * as the Heatmap GPU Clock axis is also based on the default values
+		 */
+			PP_ASSERT_WITH_CODE(
+				(golden_dpm_table->sclk_table.dpm_levels
+						[golden_dpm_table->sclk_table.count - 1].value != 0),
+				"Divide by 0!",
+				return -1);
+			dpm_count = dpm_table->sclk_table.count < 2 ?
+					0 : dpm_table->sclk_table.count - 2;
+			for (i = dpm_count; i > 1; i--) {
+				if (sclk > golden_dpm_table->sclk_table.dpm_levels
+						[golden_dpm_table->sclk_table.count-1].value) {
+					clock_percent =
+						((sclk - golden_dpm_table->sclk_table.dpm_levels
+							[golden_dpm_table->sclk_table.count-1].value) * 100) /
+						golden_dpm_table->sclk_table.dpm_levels
+							[golden_dpm_table->sclk_table.count-1].value;
+
+					dpm_table->sclk_table.dpm_levels[i].value =
+							golden_dpm_table->sclk_table.dpm_levels[i].value +
+							(golden_dpm_table->sclk_table.dpm_levels[i].value *
+								clock_percent)/100;
+
+				} else if (golden_dpm_table->sclk_table.dpm_levels
+						[dpm_table->sclk_table.count-1].value > sclk) {
+					clock_percent =
+						((golden_dpm_table->sclk_table.dpm_levels
+						[golden_dpm_table->sclk_table.count - 1].value - sclk) *
+								100) /
+						golden_dpm_table->sclk_table.dpm_levels
+							[golden_dpm_table->sclk_table.count-1].value;
+
+					dpm_table->sclk_table.dpm_levels[i].value =
+							golden_dpm_table->sclk_table.dpm_levels[i].value -
+							(golden_dpm_table->sclk_table.dpm_levels[i].value *
+									clock_percent) / 100;
+				} else
+					dpm_table->sclk_table.dpm_levels[i].value =
+							golden_dpm_table->sclk_table.dpm_levels[i].value;
+			}
+		}
+	}
+
+	if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
+		dpm_table->mclk_table.dpm_levels
+			[dpm_table->mclk_table.count - 1].value = mclk;
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_OD6PlusinACSupport) ||
+			phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_OD6PlusinDCSupport)) {
+
+			PP_ASSERT_WITH_CODE(
+					(golden_dpm_table->mclk_table.dpm_levels
+						[golden_dpm_table->mclk_table.count-1].value != 0),
+					"Divide by 0!",
+					return -1);
+			dpm_count = dpm_table->mclk_table.count < 2 ?
+					0 : dpm_table->mclk_table.count - 2;
+			for (i = dpm_count; i > 1; i--) {
+				if (mclk > golden_dpm_table->mclk_table.dpm_levels
+						[golden_dpm_table->mclk_table.count-1].value) {
+					clock_percent = ((mclk -
+							golden_dpm_table->mclk_table.dpm_levels
+							[golden_dpm_table->mclk_table.count-1].value) * 100) /
+							golden_dpm_table->mclk_table.dpm_levels
+							[golden_dpm_table->mclk_table.count-1].value;
+
+					dpm_table->mclk_table.dpm_levels[i].value =
+							golden_dpm_table->mclk_table.dpm_levels[i].value +
+							(golden_dpm_table->mclk_table.dpm_levels[i].value *
+									clock_percent) / 100;
+
+				} else if (golden_dpm_table->mclk_table.dpm_levels
+						[dpm_table->mclk_table.count-1].value > mclk) {
+					clock_percent = ((golden_dpm_table->mclk_table.dpm_levels
+							[golden_dpm_table->mclk_table.count-1].value - mclk) * 100) /
+									golden_dpm_table->mclk_table.dpm_levels
+									[golden_dpm_table->mclk_table.count-1].value;
+
+					dpm_table->mclk_table.dpm_levels[i].value =
+							golden_dpm_table->mclk_table.dpm_levels[i].value -
+							(golden_dpm_table->mclk_table.dpm_levels[i].value *
+									clock_percent) / 100;
+				} else
+					dpm_table->mclk_table.dpm_levels[i].value =
+							golden_dpm_table->mclk_table.dpm_levels[i].value;
+			}
+		}
+	}
+
+	if (data->need_update_smu7_dpm_table &
+			(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) {
+		result = fiji_populate_all_memory_levels(hwmgr);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
+				return result);
+	}
+
+	if (data->need_update_smu7_dpm_table &
+			(DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) {
+		/*populate MCLK dpm table to SMU7 */
+		result = fiji_populate_all_memory_levels(hwmgr);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
+				return result);
+	}
+
+	return result;
+}
+
+static int fiji_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
+			  struct fiji_single_dpm_table * dpm_table,
+			     uint32_t low_limit, uint32_t high_limit)
+{
+	uint32_t i;
+
+	for (i = 0; i < dpm_table->count; i++) {
+		if ((dpm_table->dpm_levels[i].value < low_limit) ||
+		    (dpm_table->dpm_levels[i].value > high_limit))
+			dpm_table->dpm_levels[i].enabled = false;
+		else
+			dpm_table->dpm_levels[i].enabled = true;
+	}
+	return 0;
+}
+
+static int fiji_trim_dpm_states(struct pp_hwmgr *hwmgr,
+		const struct fiji_power_state *fiji_ps)
+{
+	int result = 0;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t high_limit_count;
+
+	PP_ASSERT_WITH_CODE((fiji_ps->performance_level_count >= 1),
+			"power state did not have any performance level",
+			return -1);
+
+	high_limit_count = (1 == fiji_ps->performance_level_count) ? 0 : 1;
+
+	fiji_trim_single_dpm_states(hwmgr,
+			&(data->dpm_table.sclk_table),
+			fiji_ps->performance_levels[0].engine_clock,
+			fiji_ps->performance_levels[high_limit_count].engine_clock);
+
+	fiji_trim_single_dpm_states(hwmgr,
+			&(data->dpm_table.mclk_table),
+			fiji_ps->performance_levels[0].memory_clock,
+			fiji_ps->performance_levels[high_limit_count].memory_clock);
+
+	return result;
+}
+
+static int fiji_generate_dpm_level_enable_mask(
+		struct pp_hwmgr *hwmgr, const void *input)
+{
+	int result;
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	const struct fiji_power_state *fiji_ps =
+			cast_const_phw_fiji_power_state(states->pnew_state);
+
+	result = fiji_trim_dpm_states(hwmgr, fiji_ps);
+	if (result)
+		return result;
+
+	data->dpm_level_enable_mask.sclk_dpm_enable_mask =
+			fiji_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table);
+	data->dpm_level_enable_mask.mclk_dpm_enable_mask =
+			fiji_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table);
+	data->last_mclk_dpm_enable_mask =
+			data->dpm_level_enable_mask.mclk_dpm_enable_mask;
+
+	if (data->uvd_enabled) {
+		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask & 1)
+			data->dpm_level_enable_mask.mclk_dpm_enable_mask &= 0xFFFFFFFE;
+	}
+
+	data->dpm_level_enable_mask.pcie_dpm_enable_mask =
+			fiji_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table);
+
+	return 0;
+}
+
+int fiji_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
+				  (PPSMC_Msg)PPSMC_MSG_UVDDPM_Enable :
+				  (PPSMC_Msg)PPSMC_MSG_UVDDPM_Disable);
+}
+
+int fiji_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, enable?
+			PPSMC_MSG_VCEDPM_Enable :
+			PPSMC_MSG_VCEDPM_Disable);
+}
+
+int fiji_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, enable?
+			PPSMC_MSG_SAMUDPM_Enable :
+			PPSMC_MSG_SAMUDPM_Disable);
+}
+
+int fiji_enable_disable_acp_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, enable?
+			PPSMC_MSG_ACPDPM_Enable :
+			PPSMC_MSG_ACPDPM_Disable);
+}
+
+int fiji_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t mm_boot_level_offset, mm_boot_level_value;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (!bgate) {
+		data->smc_state_table.UvdBootLevel = 0;
+		if (table_info->mm_dep_table->count > 0)
+			data->smc_state_table.UvdBootLevel =
+					(uint8_t) (table_info->mm_dep_table->count - 1);
+		mm_boot_level_offset = data->dpm_table_start +
+				offsetof(SMU73_Discrete_DpmTable, UvdBootLevel);
+		mm_boot_level_offset /= 4;
+		mm_boot_level_offset *= 4;
+		mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset);
+		mm_boot_level_value &= 0x00FFFFFF;
+		mm_boot_level_value |= data->smc_state_table.UvdBootLevel << 24;
+		cgs_write_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
+
+		if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_UVDDPM) ||
+			phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_StablePState))
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_UVDDPM_SetEnabledMask,
+					(uint32_t)(1 << data->smc_state_table.UvdBootLevel));
+	}
+
+	return fiji_enable_disable_uvd_dpm(hwmgr, !bgate);
+}
+
+int fiji_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	const struct fiji_power_state *fiji_nps =
+			cast_const_phw_fiji_power_state(states->pnew_state);
+	const struct fiji_power_state *fiji_cps =
+			cast_const_phw_fiji_power_state(states->pcurrent_state);
+
+	uint32_t mm_boot_level_offset, mm_boot_level_value;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (fiji_nps->vce_clks.evclk >0 &&
+	(fiji_cps == NULL || fiji_cps->vce_clks.evclk == 0)) {
+		data->smc_state_table.VceBootLevel =
+				(uint8_t) (table_info->mm_dep_table->count - 1);
+
+		mm_boot_level_offset = data->dpm_table_start +
+				offsetof(SMU73_Discrete_DpmTable, VceBootLevel);
+		mm_boot_level_offset /= 4;
+		mm_boot_level_offset *= 4;
+		mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset);
+		mm_boot_level_value &= 0xFF00FFFF;
+		mm_boot_level_value |= data->smc_state_table.VceBootLevel << 16;
+		cgs_write_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_StablePState)) {
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_VCEDPM_SetEnabledMask,
+					(uint32_t)1 << data->smc_state_table.VceBootLevel);
+
+			fiji_enable_disable_vce_dpm(hwmgr, true);
+		} else if (fiji_nps->vce_clks.evclk == 0 &&
+				fiji_cps != NULL &&
+				fiji_cps->vce_clks.evclk > 0)
+			fiji_enable_disable_vce_dpm(hwmgr, false);
+	}
+
+	return 0;
+}
+
+int fiji_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t mm_boot_level_offset, mm_boot_level_value;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (!bgate) {
+		data->smc_state_table.SamuBootLevel =
+				(uint8_t) (table_info->mm_dep_table->count - 1);
+		mm_boot_level_offset = data->dpm_table_start +
+				offsetof(SMU73_Discrete_DpmTable, SamuBootLevel);
+		mm_boot_level_offset /= 4;
+		mm_boot_level_offset *= 4;
+		mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset);
+		mm_boot_level_value &= 0xFFFFFF00;
+		mm_boot_level_value |= data->smc_state_table.SamuBootLevel << 0;
+		cgs_write_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_StablePState))
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_SAMUDPM_SetEnabledMask,
+					(uint32_t)(1 << data->smc_state_table.SamuBootLevel));
+	}
+
+	return fiji_enable_disable_samu_dpm(hwmgr, !bgate);
+}
+
+int fiji_update_acp_dpm(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t mm_boot_level_offset, mm_boot_level_value;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (!bgate) {
+		data->smc_state_table.AcpBootLevel =
+				(uint8_t) (table_info->mm_dep_table->count - 1);
+		mm_boot_level_offset = data->dpm_table_start +
+				offsetof(SMU73_Discrete_DpmTable, AcpBootLevel);
+		mm_boot_level_offset /= 4;
+		mm_boot_level_offset *= 4;
+		mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset);
+		mm_boot_level_value &= 0xFFFF00FF;
+		mm_boot_level_value |= data->smc_state_table.AcpBootLevel << 8;
+		cgs_write_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_StablePState))
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_ACPDPM_SetEnabledMask,
+						(uint32_t)(1 << data->smc_state_table.AcpBootLevel));
+	}
+
+	return fiji_enable_disable_acp_dpm(hwmgr, !bgate);
+}
+
+static int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	int result = 0;
+	uint32_t low_sclk_interrupt_threshold = 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SclkThrottleLowNotification)
+		&& (hwmgr->gfx_arbiter.sclk_threshold !=
+				data->low_sclk_interrupt_threshold)) {
+		data->low_sclk_interrupt_threshold =
+				hwmgr->gfx_arbiter.sclk_threshold;
+		low_sclk_interrupt_threshold =
+				data->low_sclk_interrupt_threshold;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
+
+		result = fiji_copy_bytes_to_smc(
+				hwmgr->smumgr,
+				data->dpm_table_start +
+				offsetof(SMU73_Discrete_DpmTable,
+					LowSclkInterruptThreshold),
+				(uint8_t *)&low_sclk_interrupt_threshold,
+				sizeof(uint32_t),
+				data->sram_end);
+	}
+
+	return result;
+}
+
+static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if (data->need_update_smu7_dpm_table &
+		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
+		return fiji_program_memory_timing_parameters(hwmgr);
+
+	return 0;
+}
+
+static int fiji_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if (0 == data->need_update_smu7_dpm_table)
+		return 0;
+
+	if ((0 == data->sclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table &
+		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
+
+		PP_ASSERT_WITH_CODE(true == fiji_is_dpm_running(hwmgr),
+				"Trying to Unfreeze SCLK DPM when DPM is disabled",);
+		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_SCLKDPM_UnfreezeLevel),
+			"Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!",
+			return -1);
+	}
+
+	if ((0 == data->mclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) {
+
+		PP_ASSERT_WITH_CODE(true == fiji_is_dpm_running(hwmgr),
+				"Trying to Unfreeze MCLK DPM when DPM is disabled",);
+		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_SCLKDPM_UnfreezeLevel),
+		    "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!",
+		    return -1);
+	}
+
+	data->need_update_smu7_dpm_table = 0;
+
+	return 0;
+}
+
+/* Look up the voltaged based on DAL's requested level.
+ * and then send the requested VDDC voltage to SMC
+ */
+static void fiji_apply_dal_minimum_voltage_request(struct pp_hwmgr *hwmgr)
+{
+	return;
+}
+
+int fiji_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr)
+{
+	int result;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	/* Apply minimum voltage based on DAL's request level */
+	fiji_apply_dal_minimum_voltage_request(hwmgr);
+
+	if (0 == data->sclk_dpm_key_disabled) {
+		/* Checking if DPM is running.  If we discover hang because of this,
+		 *  we should skip this message.
+		 */
+		if (!fiji_is_dpm_running(hwmgr))
+			printk(KERN_ERR "[ powerplay ] "
+					"Trying to set Enable Mask when DPM is disabled \n");
+
+		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
+			result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_SCLKDPM_SetEnabledMask,
+					data->dpm_level_enable_mask.sclk_dpm_enable_mask);
+			PP_ASSERT_WITH_CODE((0 == result),
+				"Set Sclk Dpm enable Mask failed", return -1);
+		}
+	}
+
+	if (0 == data->mclk_dpm_key_disabled) {
+		/* Checking if DPM is running.  If we discover hang because of this,
+		 *  we should skip this message.
+		 */
+		if (!fiji_is_dpm_running(hwmgr))
+			printk(KERN_ERR "[ powerplay ]"
+					" Trying to set Enable Mask when DPM is disabled \n");
+
+		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
+			result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_MCLKDPM_SetEnabledMask,
+					data->dpm_level_enable_mask.mclk_dpm_enable_mask);
+			PP_ASSERT_WITH_CODE((0 == result),
+				"Set Mclk Dpm enable Mask failed", return -1);
+		}
+	}
+
+	return 0;
+}
+
+static int fiji_notify_link_speed_change_after_state_change(
+		struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	const struct fiji_power_state *fiji_ps =
+			cast_const_phw_fiji_power_state(states->pnew_state);
+	uint16_t target_link_speed = fiji_get_maximum_link_speed(hwmgr, fiji_ps);
+	uint8_t  request;
+
+	if (data->pspp_notify_required) {
+		if (target_link_speed == PP_PCIEGen3)
+			request = PCIE_PERF_REQ_GEN3;
+		else if (target_link_speed == PP_PCIEGen2)
+			request = PCIE_PERF_REQ_GEN2;
+		else
+			request = PCIE_PERF_REQ_GEN1;
+
+		if(request == PCIE_PERF_REQ_GEN1 &&
+				fiji_get_current_pcie_speed(hwmgr) > 0)
+			return 0;
+
+		if (acpi_pcie_perf_request(hwmgr->device, request, false)) {
+			if (PP_PCIEGen2 == target_link_speed)
+				printk("PSPP request to switch to Gen2 from Gen3 Failed!");
+			else
+				printk("PSPP request to switch to Gen1 from Gen2 Failed!");
+		}
+	}
+
+	return 0;
+}
+
+static int fiji_set_power_state_tasks(struct pp_hwmgr *hwmgr,
+		const void *input)
+{
+	int tmp_result, result = 0;
+
+	tmp_result = fiji_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to find DPM states clocks in DPM table!",
+			result = tmp_result);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PCIEPerformanceRequest)) {
+		tmp_result =
+			fiji_request_link_speed_change_before_state_change(hwmgr, input);
+		PP_ASSERT_WITH_CODE((0 == tmp_result),
+				"Failed to request link speed change before state change!",
+				result = tmp_result);
+	}
+
+	tmp_result = fiji_freeze_sclk_mclk_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to freeze SCLK MCLK DPM!", result = tmp_result);
+
+	tmp_result = fiji_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to populate and upload SCLK MCLK DPM levels!",
+			result = tmp_result);
+
+	tmp_result = fiji_generate_dpm_level_enable_mask(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to generate DPM level enabled mask!",
+			result = tmp_result);
+
+	tmp_result = fiji_update_vce_dpm(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to update VCE DPM!",
+			result = tmp_result);
+
+	tmp_result = fiji_update_sclk_threshold(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to update SCLK threshold!",
+			result = tmp_result);
+
+	tmp_result = fiji_program_mem_timing_parameters(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to program memory timing parameters!",
+			result = tmp_result);
+
+	tmp_result = fiji_unfreeze_sclk_mclk_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to unfreeze SCLK MCLK DPM!",
+			result = tmp_result);
+
+	tmp_result = fiji_upload_dpm_level_enable_mask(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to upload DPM level enabled mask!",
+			result = tmp_result);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PCIEPerformanceRequest)) {
+		tmp_result =
+			fiji_notify_link_speed_change_after_state_change(hwmgr, input);
+		PP_ASSERT_WITH_CODE((0 == tmp_result),
+				"Failed to notify link speed change after state change!",
+				result = tmp_result);
+	}
+
+	return result;
+}
+
+static int fiji_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
+{
+	struct pp_power_state  *ps;
+	struct fiji_power_state  *fiji_ps;
+
+	if (hwmgr == NULL)
+		return -EINVAL;
+
+	ps = hwmgr->request_ps;
+
+	if (ps == NULL)
+		return -EINVAL;
+
+	fiji_ps = cast_phw_fiji_power_state(&ps->hardware);
+
+	if (low)
+		return fiji_ps->performance_levels[0].engine_clock;
+	else
+		return fiji_ps->performance_levels
+				[fiji_ps->performance_level_count-1].engine_clock;
+}
+
+static int fiji_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
+{
+	struct pp_power_state  *ps;
+	struct fiji_power_state  *fiji_ps;
+
+	if (hwmgr == NULL)
+		return -EINVAL;
+
+	ps = hwmgr->request_ps;
+
+	if (ps == NULL)
+		return -EINVAL;
+
+	fiji_ps = cast_phw_fiji_power_state(&ps->hardware);
+
+	if (low)
+		return fiji_ps->performance_levels[0].memory_clock;
+	else
+		return fiji_ps->performance_levels
+				[fiji_ps->performance_level_count-1].memory_clock;
+}
+
+static void fiji_print_current_perforce_level(
+		struct pp_hwmgr *hwmgr, struct seq_file *m)
+{
+	uint32_t sclk, mclk, activity_percent = 0;
+	uint32_t offset;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency);
+
+	sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
+
+	smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency);
+
+	mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
+	seq_printf(m, "\n [  mclk  ]: %u MHz\n\n [  sclk  ]: %u MHz\n",
+			mclk / 100, sclk / 100);
+
+	offset = data->soft_regs_start + offsetof(SMU73_SoftRegisters, AverageGraphicsActivity);
+	activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset);
+	activity_percent += 0x80;
+	activity_percent >>= 8;
+
+	seq_printf(m, "\n [GPU load]: %u%%\n\n", activity_percent > 100 ? 100 : activity_percent);
+}
+
+static int fiji_program_display_gap(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t num_active_displays = 0;
+	uint32_t display_gap = cgs_read_ind_register(hwmgr->device,
+			CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL);
+	uint32_t display_gap2;
+	uint32_t pre_vbi_time_in_us;
+	uint32_t frame_time_in_us;
+	uint32_t ref_clock;
+	uint32_t refresh_rate = 0;
+	struct cgs_display_info info = {0};
+	struct cgs_mode_info mode_info;
+
+	info.mode_info = &mode_info;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+	num_active_displays = info.display_count;
+
+	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL,
+			DISP_GAP, (num_active_displays > 0)?
+			DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_DISPLAY_GAP_CNTL, display_gap);
+
+	ref_clock = mode_info.ref_clock;
+	refresh_rate = mode_info.refresh_rate;
+
+	if (refresh_rate == 0)
+		refresh_rate = 60;
+
+	frame_time_in_us = 1000000 / refresh_rate;
+
+	pre_vbi_time_in_us = frame_time_in_us - 200 - mode_info.vblank_time_us;
+	display_gap2 = pre_vbi_time_in_us * (ref_clock / 100);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_DISPLAY_GAP_CNTL2, display_gap2);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			data->soft_regs_start +
+			offsetof(SMU73_SoftRegisters, PreVBlankGap), 0x64);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			data->soft_regs_start +
+			offsetof(SMU73_SoftRegisters, VBlankTimeout),
+			(frame_time_in_us - pre_vbi_time_in_us));
+
+	if (num_active_displays == 1)
+		tonga_notify_smc_display_change(hwmgr, true);
+
+	return 0;
+}
+
+int fiji_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
+{
+	return fiji_program_display_gap(hwmgr);
+}
+
+static int fiji_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr,
+		uint16_t us_max_fan_pwm)
+{
+	hwmgr->thermal_controller.
+	advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm;
+
+	if (phm_is_hw_access_blocked(hwmgr))
+		return 0;
+
+	return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+			PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm);
+}
+
+static int fiji_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr,
+		uint16_t us_max_fan_rpm)
+{
+	hwmgr->thermal_controller.
+	advanceFanControlParameters.usMaxFanRPM = us_max_fan_rpm;
+
+	if (phm_is_hw_access_blocked(hwmgr))
+		return 0;
+
+	return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+			PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm);
+}
+
+int fiji_dpm_set_interrupt_state(void *private_data,
+					 unsigned src_id, unsigned type,
+					 int enabled)
+{
+	uint32_t cg_thermal_int;
+	struct pp_hwmgr *hwmgr = ((struct pp_eventmgr *)private_data)->hwmgr;
+
+	if (hwmgr == NULL)
+		return -EINVAL;
+
+	switch (type) {
+	case AMD_THERMAL_IRQ_LOW_TO_HIGH:
+		if (enabled) {
+			cg_thermal_int = cgs_read_ind_register(hwmgr->device,
+					CGS_IND_REG__SMC, ixCG_THERMAL_INT);
+			cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
+			cgs_write_ind_register(hwmgr->device,
+					CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
+		} else {
+			cg_thermal_int = cgs_read_ind_register(hwmgr->device,
+					CGS_IND_REG__SMC, ixCG_THERMAL_INT);
+			cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
+			cgs_write_ind_register(hwmgr->device,
+					CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
+		}
+		break;
+
+	case AMD_THERMAL_IRQ_HIGH_TO_LOW:
+		if (enabled) {
+			cg_thermal_int = cgs_read_ind_register(hwmgr->device,
+					CGS_IND_REG__SMC, ixCG_THERMAL_INT);
+			cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
+			cgs_write_ind_register(hwmgr->device,
+					CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
+		} else {
+			cg_thermal_int = cgs_read_ind_register(hwmgr->device,
+					CGS_IND_REG__SMC, ixCG_THERMAL_INT);
+			cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
+			cgs_write_ind_register(hwmgr->device,
+					CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+int fiji_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr,
+					const void *thermal_interrupt_info)
+{
+	int result;
+	const struct pp_interrupt_registration_info *info =
+			(const struct pp_interrupt_registration_info *)
+			thermal_interrupt_info;
+
+	if (info == NULL)
+		return -EINVAL;
+
+	result = cgs_add_irq_source(hwmgr->device, 230, AMD_THERMAL_IRQ_LAST,
+				fiji_dpm_set_interrupt_state,
+				info->call_back, info->context);
+
+	if (result)
+		return -EINVAL;
+
+	result = cgs_add_irq_source(hwmgr->device, 231, AMD_THERMAL_IRQ_LAST,
+				fiji_dpm_set_interrupt_state,
+				info->call_back, info->context);
+
+	if (result)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int fiji_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
+{
+	if (mode) {
+		/* stop auto-manage */
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_MicrocodeFanControl))
+			fiji_fan_ctrl_stop_smc_fan_control(hwmgr);
+		fiji_fan_ctrl_set_static_mode(hwmgr, mode);
+	} else
+		/* restart auto-manage */
+		fiji_fan_ctrl_reset_fan_speed_to_default(hwmgr);
+
+	return 0;
+}
+
+static int fiji_get_fan_control_mode(struct pp_hwmgr *hwmgr)
+{
+	if (hwmgr->fan_ctrl_is_in_default_mode)
+		return hwmgr->fan_ctrl_default_mode;
+	else
+		return PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_FDO_CTRL2, FDO_PWM_MODE);
+}
+
+static const struct pp_hwmgr_func fiji_hwmgr_funcs = {
+	.backend_init = &fiji_hwmgr_backend_init,
+	.backend_fini = &tonga_hwmgr_backend_fini,
+	.asic_setup = &fiji_setup_asic_task,
+	.dynamic_state_management_enable = &fiji_enable_dpm_tasks,
+	.force_dpm_level = &fiji_dpm_force_dpm_level,
+	.get_num_of_pp_table_entries = &tonga_get_number_of_powerplay_table_entries,
+	.get_power_state_size = &fiji_get_power_state_size,
+	.get_pp_table_entry = &fiji_get_pp_table_entry,
+	.patch_boot_state = &fiji_patch_boot_state,
+	.apply_state_adjust_rules = &fiji_apply_state_adjust_rules,
+	.power_state_set = &fiji_set_power_state_tasks,
+	.get_sclk = &fiji_dpm_get_sclk,
+	.get_mclk = &fiji_dpm_get_mclk,
+	.print_current_perforce_level = &fiji_print_current_perforce_level,
+	.powergate_uvd = &fiji_phm_powergate_uvd,
+	.powergate_vce = &fiji_phm_powergate_vce,
+	.disable_clock_power_gating = &fiji_phm_disable_clock_power_gating,
+	.notify_smc_display_config_after_ps_adjustment =
+			&tonga_notify_smc_display_config_after_ps_adjustment,
+	.display_config_changed = &fiji_display_configuration_changed_task,
+	.set_max_fan_pwm_output = fiji_set_max_fan_pwm_output,
+	.set_max_fan_rpm_output = fiji_set_max_fan_rpm_output,
+	.get_temperature = fiji_thermal_get_temperature,
+	.stop_thermal_controller = fiji_thermal_stop_thermal_controller,
+	.get_fan_speed_info = fiji_fan_ctrl_get_fan_speed_info,
+	.get_fan_speed_percent = fiji_fan_ctrl_get_fan_speed_percent,
+	.set_fan_speed_percent = fiji_fan_ctrl_set_fan_speed_percent,
+	.reset_fan_speed_to_default = fiji_fan_ctrl_reset_fan_speed_to_default,
+	.get_fan_speed_rpm = fiji_fan_ctrl_get_fan_speed_rpm,
+	.set_fan_speed_rpm = fiji_fan_ctrl_set_fan_speed_rpm,
+	.uninitialize_thermal_controller = fiji_thermal_ctrl_uninitialize_thermal_controller,
+	.register_internal_thermal_interrupt = fiji_register_internal_thermal_interrupt,
+	.set_fan_control_mode = fiji_set_fan_control_mode,
+	.get_fan_control_mode = fiji_get_fan_control_mode,
+};
+
+int fiji_hwmgr_init(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr  *data;
+	int ret = 0;
+
+	data = kzalloc(sizeof(struct fiji_hwmgr), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+
+	hwmgr->backend = data;
+	hwmgr->hwmgr_func = &fiji_hwmgr_funcs;
+	hwmgr->pptable_func = &tonga_pptable_funcs;
+	pp_fiji_thermal_initialize(hwmgr);
+	return ret;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h
new file mode 100644
index 0000000..22e273b
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _FIJI_HWMGR_H_
+#define _FIJI_HWMGR_H_
+
+#include "hwmgr.h"
+#include "smu73.h"
+#include "smu73_discrete.h"
+#include "ppatomctrl.h"
+#include "fiji_ppsmc.h"
+
+#define FIJI_MAX_HARDWARE_POWERLEVELS	2
+#define FIJI_AT_DFLT	30
+
+#define FIJI_VOLTAGE_CONTROL_NONE                   0x0
+#define FIJI_VOLTAGE_CONTROL_BY_GPIO                0x1
+#define FIJI_VOLTAGE_CONTROL_BY_SVID2               0x2
+#define FIJI_VOLTAGE_CONTROL_MERGED                 0x3
+
+#define DPMTABLE_OD_UPDATE_SCLK     0x00000001
+#define DPMTABLE_OD_UPDATE_MCLK     0x00000002
+#define DPMTABLE_UPDATE_SCLK        0x00000004
+#define DPMTABLE_UPDATE_MCLK        0x00000008
+
+struct fiji_performance_level {
+	uint32_t  memory_clock;
+	uint32_t  engine_clock;
+	uint16_t  pcie_gen;
+	uint16_t  pcie_lane;
+};
+
+struct fiji_uvd_clocks {
+	uint32_t  vclk;
+	uint32_t  dclk;
+};
+
+struct fiji_vce_clocks {
+	uint32_t  evclk;
+	uint32_t  ecclk;
+};
+
+struct fiji_power_state {
+    uint32_t                  magic;
+    struct fiji_uvd_clocks    uvd_clks;
+    struct fiji_vce_clocks    vce_clks;
+    uint32_t                  sam_clk;
+    uint32_t                  acp_clk;
+    uint16_t                  performance_level_count;
+    bool                      dc_compatible;
+    uint32_t                  sclk_threshold;
+    struct fiji_performance_level  performance_levels[FIJI_MAX_HARDWARE_POWERLEVELS];
+};
+
+struct fiji_dpm_level {
+	bool	enabled;
+    uint32_t	value;
+    uint32_t	param1;
+};
+
+#define FIJI_MAX_DEEPSLEEP_DIVIDER_ID 5
+#define MAX_REGULAR_DPM_NUMBER 8
+#define FIJI_MINIMUM_ENGINE_CLOCK 2500
+
+struct fiji_single_dpm_table {
+	uint32_t		count;
+	struct fiji_dpm_level	dpm_levels[MAX_REGULAR_DPM_NUMBER];
+};
+
+struct fiji_dpm_table {
+	struct fiji_single_dpm_table  sclk_table;
+	struct fiji_single_dpm_table  mclk_table;
+	struct fiji_single_dpm_table  pcie_speed_table;
+	struct fiji_single_dpm_table  vddc_table;
+	struct fiji_single_dpm_table  vddci_table;
+	struct fiji_single_dpm_table  mvdd_table;
+};
+
+struct fiji_clock_registers {
+	uint32_t  vCG_SPLL_FUNC_CNTL;
+	uint32_t  vCG_SPLL_FUNC_CNTL_2;
+	uint32_t  vCG_SPLL_FUNC_CNTL_3;
+	uint32_t  vCG_SPLL_FUNC_CNTL_4;
+	uint32_t  vCG_SPLL_SPREAD_SPECTRUM;
+	uint32_t  vCG_SPLL_SPREAD_SPECTRUM_2;
+	uint32_t  vDLL_CNTL;
+	uint32_t  vMCLK_PWRMGT_CNTL;
+	uint32_t  vMPLL_AD_FUNC_CNTL;
+	uint32_t  vMPLL_DQ_FUNC_CNTL;
+	uint32_t  vMPLL_FUNC_CNTL;
+	uint32_t  vMPLL_FUNC_CNTL_1;
+	uint32_t  vMPLL_FUNC_CNTL_2;
+	uint32_t  vMPLL_SS1;
+	uint32_t  vMPLL_SS2;
+};
+
+struct fiji_voltage_smio_registers {
+	uint32_t vS0_VID_LOWER_SMIO_CNTL;
+};
+
+#define FIJI_MAX_LEAKAGE_COUNT  8
+struct fiji_leakage_voltage {
+	uint16_t  count;
+	uint16_t  leakage_id[FIJI_MAX_LEAKAGE_COUNT];
+	uint16_t  actual_voltage[FIJI_MAX_LEAKAGE_COUNT];
+};
+
+struct fiji_vbios_boot_state {
+	uint16_t    mvdd_bootup_value;
+	uint16_t    vddc_bootup_value;
+	uint16_t    vddci_bootup_value;
+	uint32_t    sclk_bootup_value;
+	uint32_t    mclk_bootup_value;
+	uint16_t    pcie_gen_bootup_value;
+	uint16_t    pcie_lane_bootup_value;
+};
+
+struct fiji_bacos {
+	uint32_t                       best_match;
+	uint32_t                       baco_flags;
+	struct fiji_performance_level  performance_level;
+};
+
+/* Ultra Low Voltage parameter structure */
+struct fiji_ulv_parm {
+	bool                           ulv_supported;
+	uint32_t                       cg_ulv_parameter;
+	uint32_t                       ulv_volt_change_delay;
+	struct fiji_performance_level  ulv_power_level;
+};
+
+struct fiji_display_timing {
+	uint32_t  min_clock_in_sr;
+	uint32_t  num_existing_displays;
+};
+
+struct fiji_dpmlevel_enable_mask {
+	uint32_t  uvd_dpm_enable_mask;
+	uint32_t  vce_dpm_enable_mask;
+	uint32_t  acp_dpm_enable_mask;
+	uint32_t  samu_dpm_enable_mask;
+	uint32_t  sclk_dpm_enable_mask;
+	uint32_t  mclk_dpm_enable_mask;
+	uint32_t  pcie_dpm_enable_mask;
+};
+
+struct fiji_pcie_perf_range {
+	uint16_t  max;
+	uint16_t  min;
+};
+
+struct fiji_hwmgr {
+	struct fiji_dpm_table			dpm_table;
+	struct fiji_dpm_table			golden_dpm_table;
+
+	uint32_t						voting_rights_clients0;
+	uint32_t						voting_rights_clients1;
+	uint32_t						voting_rights_clients2;
+	uint32_t						voting_rights_clients3;
+	uint32_t						voting_rights_clients4;
+	uint32_t						voting_rights_clients5;
+	uint32_t						voting_rights_clients6;
+	uint32_t						voting_rights_clients7;
+	uint32_t						static_screen_threshold_unit;
+	uint32_t						static_screen_threshold;
+	uint32_t						voltage_control;
+	uint32_t						vddc_vddci_delta;
+
+	uint32_t						active_auto_throttle_sources;
+
+	struct fiji_clock_registers            clock_registers;
+	struct fiji_voltage_smio_registers      voltage_smio_registers;
+
+	bool                           is_memory_gddr5;
+	uint16_t                       acpi_vddc;
+	bool                           pspp_notify_required;
+	uint16_t                       force_pcie_gen;
+	uint16_t                       acpi_pcie_gen;
+	uint32_t                       pcie_gen_cap;
+	uint32_t                       pcie_lane_cap;
+	uint32_t                       pcie_spc_cap;
+	struct fiji_leakage_voltage          vddc_leakage;
+	struct fiji_leakage_voltage          Vddci_leakage;
+
+	uint32_t                             mvdd_control;
+	uint32_t                             vddc_mask_low;
+	uint32_t                             mvdd_mask_low;
+	uint16_t                            max_vddc_in_pptable;
+	uint16_t                            min_vddc_in_pptable;
+	uint16_t                            max_vddci_in_pptable;
+	uint16_t                            min_vddci_in_pptable;
+	uint32_t                             mclk_strobe_mode_threshold;
+	uint32_t                             mclk_stutter_mode_threshold;
+	uint32_t                             mclk_edc_enable_threshold;
+	uint32_t                             mclk_edcwr_enable_threshold;
+	bool                                is_uvd_enabled;
+	struct fiji_vbios_boot_state        vbios_boot_state;
+
+	bool                           battery_state;
+	bool                           is_tlu_enabled;
+
+	/* ---- SMC SRAM Address of firmware header tables ---- */
+	uint32_t                             sram_end;
+	uint32_t                             dpm_table_start;
+	uint32_t                             soft_regs_start;
+	uint32_t                             mc_reg_table_start;
+	uint32_t                             fan_table_start;
+	uint32_t                             arb_table_start;
+	struct SMU73_Discrete_DpmTable       smc_state_table;
+	struct SMU73_Discrete_Ulv            ulv_setting;
+
+	/* ---- Stuff originally coming from Evergreen ---- */
+	uint32_t                             vddci_control;
+	struct pp_atomctrl_voltage_table     vddc_voltage_table;
+	struct pp_atomctrl_voltage_table     vddci_voltage_table;
+	struct pp_atomctrl_voltage_table     mvdd_voltage_table;
+
+	uint32_t                             mgcg_cgtt_local2;
+	uint32_t                             mgcg_cgtt_local3;
+	uint32_t                             gpio_debug;
+	uint32_t                             mc_micro_code_feature;
+	uint32_t                             highest_mclk;
+	uint16_t                             acpi_vddci;
+	uint8_t                              mvdd_high_index;
+	uint8_t                              mvdd_low_index;
+	bool                                 dll_default_on;
+	bool                                 performance_request_registered;
+
+	/* ---- Low Power Features ---- */
+	struct fiji_bacos                    bacos;
+	struct fiji_ulv_parm                 ulv;
+
+	/* ---- CAC Stuff ---- */
+	uint32_t                       cac_table_start;
+	bool                           cac_configuration_required;
+	bool                           driver_calculate_cac_leakage;
+	bool                           cac_enabled;
+
+	/* ---- DPM2 Parameters ---- */
+	uint32_t                       power_containment_features;
+	bool                           enable_dte_feature;
+	bool                           enable_tdc_limit_feature;
+	bool                           enable_pkg_pwr_tracking_feature;
+	bool                           disable_uvd_power_tune_feature;
+	struct fiji_pt_defaults       *power_tune_defaults;
+	struct SMU73_Discrete_PmFuses  power_tune_table;
+	uint32_t                       dte_tj_offset;
+	uint32_t                       fast_watermark_threshold;
+
+	/* ---- Phase Shedding ---- */
+	bool                           vddc_phase_shed_control;
+
+	/* ---- DI/DT ---- */
+	struct fiji_display_timing        display_timing;
+
+	/* ---- Thermal Temperature Setting ---- */
+	struct fiji_dpmlevel_enable_mask     dpm_level_enable_mask;
+	uint32_t                             need_update_smu7_dpm_table;
+	uint32_t                             sclk_dpm_key_disabled;
+	uint32_t                             mclk_dpm_key_disabled;
+	uint32_t                             pcie_dpm_key_disabled;
+	uint32_t                             min_engine_clocks;
+	struct fiji_pcie_perf_range          pcie_gen_performance;
+	struct fiji_pcie_perf_range          pcie_lane_performance;
+	struct fiji_pcie_perf_range          pcie_gen_power_saving;
+	struct fiji_pcie_perf_range          pcie_lane_power_saving;
+	bool                                 use_pcie_performance_levels;
+	bool                                 use_pcie_power_saving_levels;
+	uint32_t                             activity_target[SMU73_MAX_LEVELS_GRAPHICS];
+	uint32_t                             mclk_activity_target;
+	uint32_t                             mclk_dpm0_activity_target;
+	uint32_t                             low_sclk_interrupt_threshold;
+	uint32_t                             last_mclk_dpm_enable_mask;
+	bool                                 uvd_enabled;
+
+	/* ---- Power Gating States ---- */
+	bool                           uvd_power_gated;
+	bool                           vce_power_gated;
+	bool                           samu_power_gated;
+	bool                           acp_power_gated;
+	bool                           pg_acp_init;
+	bool                           frtc_enabled;
+	bool                           frtc_status_changed;
+};
+
+/* To convert to Q8.8 format for firmware */
+#define FIJI_Q88_FORMAT_CONVERSION_UNIT             256
+
+enum Fiji_I2CLineID {
+    Fiji_I2CLineID_DDC1 = 0x90,
+    Fiji_I2CLineID_DDC2 = 0x91,
+    Fiji_I2CLineID_DDC3 = 0x92,
+    Fiji_I2CLineID_DDC4 = 0x93,
+    Fiji_I2CLineID_DDC5 = 0x94,
+    Fiji_I2CLineID_DDC6 = 0x95,
+    Fiji_I2CLineID_SCLSDA = 0x96,
+    Fiji_I2CLineID_DDCVGA = 0x97
+};
+
+#define Fiji_I2C_DDC1DATA          0
+#define Fiji_I2C_DDC1CLK           1
+#define Fiji_I2C_DDC2DATA          2
+#define Fiji_I2C_DDC2CLK           3
+#define Fiji_I2C_DDC3DATA          4
+#define Fiji_I2C_DDC3CLK           5
+#define Fiji_I2C_SDA               40
+#define Fiji_I2C_SCL               41
+#define Fiji_I2C_DDC4DATA          65
+#define Fiji_I2C_DDC4CLK           66
+#define Fiji_I2C_DDC5DATA          0x48
+#define Fiji_I2C_DDC5CLK           0x49
+#define Fiji_I2C_DDC6DATA          0x4a
+#define Fiji_I2C_DDC6CLK           0x4b
+#define Fiji_I2C_DDCVGADATA        0x4c
+#define Fiji_I2C_DDCVGACLK         0x4d
+
+#define FIJI_UNUSED_GPIO_PIN       0x7F
+
+extern int tonga_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr);
+extern int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr);
+extern int tonga_get_mc_microcode_version (struct pp_hwmgr *hwmgr);
+extern int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr);
+extern int tonga_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display);
+int fiji_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input);
+int fiji_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate);
+int fiji_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate);
+int fiji_update_acp_dpm(struct pp_hwmgr *hwmgr, bool bgate);
+int fiji_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable);
+
+#define PP_HOST_TO_SMC_UL(X) cpu_to_be32(X)
+#define PP_SMC_TO_HOST_UL(X) be32_to_cpu(X)
+
+#define PP_HOST_TO_SMC_US(X) cpu_to_be16(X)
+#define PP_SMC_TO_HOST_US(X) be16_to_cpu(X)
+
+#define CONVERT_FROM_HOST_TO_SMC_UL(X) ((X) = PP_HOST_TO_SMC_UL(X))
+#define CONVERT_FROM_SMC_TO_HOST_UL(X) ((X) = PP_SMC_TO_HOST_UL(X))
+
+#define CONVERT_FROM_HOST_TO_SMC_US(X) ((X) = PP_HOST_TO_SMC_US(X))
+
+#endif /* _FIJI_HWMGR_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c
new file mode 100644
index 0000000..6efcb2b
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c
@@ -0,0 +1,553 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#include "hwmgr.h"
+#include "smumgr.h"
+#include "fiji_hwmgr.h"
+#include "fiji_powertune.h"
+#include "fiji_smumgr.h"
+#include "smu73_discrete.h"
+#include "pp_debug.h"
+
+#define VOLTAGE_SCALE  4
+#define POWERTUNE_DEFAULT_SET_MAX    1
+
+struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
+		/*sviLoadLIneEn,  SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */
+		{1,               0xF,             0xFD,
+		/* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */
+		0x19,        5,               45}
+};
+
+void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *fiji_hwmgr = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct  phm_ppt_v1_information *table_info =
+			(struct  phm_ppt_v1_information *)(hwmgr->pptable);
+	uint32_t tmp = 0;
+
+	if(table_info &&
+			table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX &&
+			table_info->cac_dtp_table->usPowerTuneDataSetID)
+		fiji_hwmgr->power_tune_defaults =
+				&fiji_power_tune_data_set_array
+				[table_info->cac_dtp_table->usPowerTuneDataSetID - 1];
+	else
+		fiji_hwmgr->power_tune_defaults = &fiji_power_tune_data_set_array[0];
+
+	/* Assume disabled */
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PowerContainment);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_CAC);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SQRamping);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_DBRamping);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_TDRamping);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_TCPRamping);
+
+	fiji_hwmgr->dte_tj_offset = tmp;
+
+	if (!tmp) {
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_PowerContainment);
+
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_CAC);
+
+		fiji_hwmgr->fast_watermark_threshold = 100;
+
+		tmp = 1;
+		fiji_hwmgr->enable_dte_feature = tmp ? false : true;
+		fiji_hwmgr->enable_tdc_limit_feature = tmp ? true : false;
+		fiji_hwmgr->enable_pkg_pwr_tracking_feature = tmp ? true : false;
+	}
+}
+
+/* PPGen has the gain setting generated in x * 100 unit
+ * This function is to convert the unit to x * 4096(0x1000) unit.
+ *  This is the unit expected by SMC firmware
+ */
+static uint16_t scale_fan_gain_settings(uint16_t raw_setting)
+{
+	uint32_t tmp;
+	tmp = raw_setting * 4096 / 100;
+	return (uint16_t)tmp;
+}
+
+static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda)
+{
+	switch (line) {
+	case Fiji_I2CLineID_DDC1 :
+		*scl = Fiji_I2C_DDC1CLK;
+		*sda = Fiji_I2C_DDC1DATA;
+		break;
+	case Fiji_I2CLineID_DDC2 :
+		*scl = Fiji_I2C_DDC2CLK;
+		*sda = Fiji_I2C_DDC2DATA;
+		break;
+	case Fiji_I2CLineID_DDC3 :
+		*scl = Fiji_I2C_DDC3CLK;
+		*sda = Fiji_I2C_DDC3DATA;
+		break;
+	case Fiji_I2CLineID_DDC4 :
+		*scl = Fiji_I2C_DDC4CLK;
+		*sda = Fiji_I2C_DDC4DATA;
+		break;
+	case Fiji_I2CLineID_DDC5 :
+		*scl = Fiji_I2C_DDC5CLK;
+		*sda = Fiji_I2C_DDC5DATA;
+		break;
+	case Fiji_I2CLineID_DDC6 :
+		*scl = Fiji_I2C_DDC6CLK;
+		*sda = Fiji_I2C_DDC6DATA;
+		break;
+	case Fiji_I2CLineID_SCLSDA :
+		*scl = Fiji_I2C_SCL;
+		*sda = Fiji_I2C_SDA;
+		break;
+	case Fiji_I2CLineID_DDCVGA :
+		*scl = Fiji_I2C_DDCVGACLK;
+		*sda = Fiji_I2C_DDCVGADATA;
+		break;
+	default:
+		*scl = 0;
+		*sda = 0;
+		break;
+	}
+}
+
+int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct fiji_pt_defaults *defaults = data->power_tune_defaults;
+	SMU73_Discrete_DpmTable  *dpm_table = &(data->smc_state_table);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table;
+	struct pp_advance_fan_control_parameters *fan_table=
+			&hwmgr->thermal_controller.advanceFanControlParameters;
+	uint8_t uc_scl, uc_sda;
+
+	/* TDP number of fraction bits are changed from 8 to 7 for Fiji
+	 * as requested by SMC team
+	 */
+	dpm_table->DefaultTdp = PP_HOST_TO_SMC_US(
+			(uint16_t)(cac_dtp_table->usTDP * 128));
+	dpm_table->TargetTdp = PP_HOST_TO_SMC_US(
+			(uint16_t)(cac_dtp_table->usTDP * 128));
+
+	PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255,
+			"Target Operating Temp is out of Range!",);
+
+	dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp);
+	dpm_table->GpuTjHyst = 8;
+
+	dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase;
+
+	/* The following are for new Fiji Multi-input fan/thermal control */
+	dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US(
+			cac_dtp_table->usTargetOperatingTemp * 256);
+	dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US(
+			cac_dtp_table->usTemperatureLimitHotspot * 256);
+	dpm_table->TemperatureLimitLiquid1 = PP_HOST_TO_SMC_US(
+			cac_dtp_table->usTemperatureLimitLiquid1 * 256);
+	dpm_table->TemperatureLimitLiquid2 = PP_HOST_TO_SMC_US(
+			cac_dtp_table->usTemperatureLimitLiquid2 * 256);
+	dpm_table->TemperatureLimitVrVddc = PP_HOST_TO_SMC_US(
+			cac_dtp_table->usTemperatureLimitVrVddc * 256);
+	dpm_table->TemperatureLimitVrMvdd = PP_HOST_TO_SMC_US(
+			cac_dtp_table->usTemperatureLimitVrMvdd * 256);
+	dpm_table->TemperatureLimitPlx = PP_HOST_TO_SMC_US(
+			cac_dtp_table->usTemperatureLimitPlx * 256);
+
+	dpm_table->FanGainEdge = PP_HOST_TO_SMC_US(
+			scale_fan_gain_settings(fan_table->usFanGainEdge));
+	dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US(
+			scale_fan_gain_settings(fan_table->usFanGainHotspot));
+	dpm_table->FanGainLiquid = PP_HOST_TO_SMC_US(
+			scale_fan_gain_settings(fan_table->usFanGainLiquid));
+	dpm_table->FanGainVrVddc = PP_HOST_TO_SMC_US(
+			scale_fan_gain_settings(fan_table->usFanGainVrVddc));
+	dpm_table->FanGainVrMvdd = PP_HOST_TO_SMC_US(
+			scale_fan_gain_settings(fan_table->usFanGainVrMvdd));
+	dpm_table->FanGainPlx = PP_HOST_TO_SMC_US(
+			scale_fan_gain_settings(fan_table->usFanGainPlx));
+	dpm_table->FanGainHbm = PP_HOST_TO_SMC_US(
+			scale_fan_gain_settings(fan_table->usFanGainHbm));
+
+	dpm_table->Liquid1_I2C_address = cac_dtp_table->ucLiquid1_I2C_address;
+	dpm_table->Liquid2_I2C_address = cac_dtp_table->ucLiquid2_I2C_address;
+	dpm_table->Vr_I2C_address = cac_dtp_table->ucVr_I2C_address;
+	dpm_table->Plx_I2C_address = cac_dtp_table->ucPlx_I2C_address;
+
+	get_scl_sda_value(cac_dtp_table->ucLiquid_I2C_Line, &uc_scl, &uc_sda);
+	dpm_table->Liquid_I2C_LineSCL = uc_scl;
+	dpm_table->Liquid_I2C_LineSDA = uc_sda;
+
+	get_scl_sda_value(cac_dtp_table->ucVr_I2C_Line, &uc_scl, &uc_sda);
+	dpm_table->Vr_I2C_LineSCL = uc_scl;
+	dpm_table->Vr_I2C_LineSDA = uc_sda;
+
+	get_scl_sda_value(cac_dtp_table->ucPlx_I2C_Line, &uc_scl, &uc_sda);
+	dpm_table->Plx_I2C_LineSCL = uc_scl;
+	dpm_table->Plx_I2C_LineSDA = uc_sda;
+
+	return 0;
+}
+
+static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr)
+{
+    struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+    struct fiji_pt_defaults *defaults = data->power_tune_defaults;
+
+    data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn;
+    data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC;
+    data->power_tune_table.SviLoadLineTrimVddC = 3;
+    data->power_tune_table.SviLoadLineOffsetVddC = 0;
+
+    return 0;
+}
+
+static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr)
+{
+	uint16_t tdc_limit;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct  fiji_pt_defaults *defaults = data->power_tune_defaults;
+
+	/* TDC number of fraction bits are changed from 8 to 7
+	 * for Fiji as requested by SMC team
+	 */
+	tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128);
+	data->power_tune_table.TDC_VDDC_PkgLimit =
+			CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
+	data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
+			defaults->TDC_VDDC_ThrottleReleaseLimitPerc;
+	data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt;
+
+	return 0;
+}
+
+static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct  fiji_pt_defaults *defaults = data->power_tune_defaults;
+	uint32_t temp;
+
+	if (fiji_read_smc_sram_dword(hwmgr->smumgr,
+			fuse_table_offset +
+			offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl),
+			(uint32_t *)&temp, data->sram_end))
+		PP_ASSERT_WITH_CODE(false,
+				"Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
+				return -EINVAL);
+	else {
+		data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl;
+		data->power_tune_table.LPMLTemperatureMin =
+				(uint8_t)((temp >> 16) & 0xff);
+		data->power_tune_table.LPMLTemperatureMax =
+				(uint8_t)((temp >> 8) & 0xff);
+		data->power_tune_table.Reserved = (uint8_t)(temp & 0xff);
+	}
+	return 0;
+}
+
+static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
+{
+	int i;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	/* Currently not used. Set all to zero. */
+	for (i = 0; i < 16; i++)
+		data->power_tune_table.LPMLTemperatureScaler[i] = 0;
+
+	return 0;
+}
+
+static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if( (hwmgr->thermal_controller.advanceFanControlParameters.
+			usFanOutputSensitivity & (1 << 15)) ||
+			0 == hwmgr->thermal_controller.advanceFanControlParameters.
+			usFanOutputSensitivity )
+		hwmgr->thermal_controller.advanceFanControlParameters.
+		usFanOutputSensitivity = hwmgr->thermal_controller.
+			advanceFanControlParameters.usDefaultFanOutputSensitivity;
+
+	data->power_tune_table.FuzzyFan_PwmSetDelta =
+			PP_HOST_TO_SMC_US(hwmgr->thermal_controller.
+					advanceFanControlParameters.usFanOutputSensitivity);
+	return 0;
+}
+
+static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
+{
+	int i;
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	/* Currently not used. Set all to zero. */
+	for (i = 0; i < 16; i++)
+		data->power_tune_table.GnbLPML[i] = 0;
+
+	return 0;
+}
+
+static int fiji_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr)
+{
+ /*   int  i, min, max;
+    struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+    uint8_t * pHiVID = data->power_tune_table.BapmVddCVidHiSidd;
+    uint8_t * pLoVID = data->power_tune_table.BapmVddCVidLoSidd;
+
+    min = max = pHiVID[0];
+    for (i = 0; i < 8; i++) {
+        if (0 != pHiVID[i]) {
+            if (min > pHiVID[i])
+                min = pHiVID[i];
+            if (max < pHiVID[i])
+                max = pHiVID[i];
+        }
+
+        if (0 != pLoVID[i]) {
+            if (min > pLoVID[i])
+                min = pLoVID[i];
+            if (max < pLoVID[i])
+                max = pLoVID[i];
+        }
+    }
+
+    PP_ASSERT_WITH_CODE((0 != min) && (0 != max), "BapmVddcVidSidd table does not exist!", return int_Failed);
+    data->power_tune_table.GnbLPMLMaxVid = (uint8_t)max;
+    data->power_tune_table.GnbLPMLMinVid = (uint8_t)min;
+*/
+    return 0;
+}
+
+static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint16_t HiSidd = data->power_tune_table.BapmVddCBaseLeakageHiSidd;
+	uint16_t LoSidd = data->power_tune_table.BapmVddCBaseLeakageLoSidd;
+	struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
+
+	HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
+	LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
+
+	data->power_tune_table.BapmVddCBaseLeakageHiSidd =
+			CONVERT_FROM_HOST_TO_SMC_US(HiSidd);
+	data->power_tune_table.BapmVddCBaseLeakageLoSidd =
+			CONVERT_FROM_HOST_TO_SMC_US(LoSidd);
+
+	return 0;
+}
+
+int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	uint32_t pm_fuse_table_offset;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PowerContainment)) {
+		if (fiji_read_smc_sram_dword(hwmgr->smumgr,
+				SMU7_FIRMWARE_HEADER_LOCATION +
+				offsetof(SMU73_Firmware_Header, PmFuseTable),
+				&pm_fuse_table_offset, data->sram_end))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to get pm_fuse_table_offset Failed!",
+					return -EINVAL);
+
+		/* DW6 */
+		if (fiji_populate_svi_load_line(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate SviLoadLine Failed!",
+					return -EINVAL);
+		/* DW7 */
+		if (fiji_populate_tdc_limit(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate TDCLimit Failed!", return -EINVAL);
+		/* DW8 */
+		if (fiji_populate_dw8(hwmgr, pm_fuse_table_offset))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate TdcWaterfallCtl, "
+					"LPMLTemperature Min and Max Failed!",
+					return -EINVAL);
+
+		/* DW9-DW12 */
+		if (0 != fiji_populate_temperature_scaler(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate LPMLTemperatureScaler Failed!",
+					return -EINVAL);
+
+		/* DW13-DW14 */
+		if(fiji_populate_fuzzy_fan(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate Fuzzy Fan Control parameters Failed!",
+					return -EINVAL);
+
+		/* DW15-DW18 */
+		if (fiji_populate_gnb_lpml(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate GnbLPML Failed!",
+					return -EINVAL);
+
+		/* DW19 */
+		if (fiji_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate GnbLPML Min and Max Vid Failed!",
+					return -EINVAL);
+
+		/* DW20 */
+		if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate BapmVddCBaseLeakage Hi and Lo "
+					"Sidd Failed!", return -EINVAL);
+
+		if (fiji_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset,
+				(uint8_t *)&data->power_tune_table,
+				sizeof(struct SMU73_Discrete_PmFuses), data->sram_end))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to download PmFuseTable Failed!",
+					return -EINVAL);
+	}
+	return 0;
+}
+
+int fiji_enable_smc_cac(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	int result = 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_CAC)) {
+		int smc_result;
+		smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
+				(uint16_t)(PPSMC_MSG_EnableCac));
+		PP_ASSERT_WITH_CODE((0 == smc_result),
+				"Failed to enable CAC in SMC.", result = -1);
+
+        data->cac_enabled = (0 == smc_result) ? true : false;
+	}
+	return result;
+}
+
+int fiji_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if(data->power_containment_features &
+			POWERCONTAINMENT_FEATURE_PkgPwrLimit)
+		return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_PkgPwrSetLimit, n);
+	return 0;
+}
+
+static int fiji_set_overdriver_target_tdp(struct pp_hwmgr *pHwMgr, uint32_t target_tdp)
+{
+	return smum_send_msg_to_smc_with_parameter(pHwMgr->smumgr,
+			PPSMC_MSG_OverDriveSetTargetTdp, target_tdp);
+}
+
+int fiji_enable_power_containment(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	int smc_result;
+	int result = 0;
+
+	data->power_containment_features = 0;
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PowerContainment)) {
+		if (data->enable_dte_feature) {
+			smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
+					(uint16_t)(PPSMC_MSG_EnableDTE));
+			PP_ASSERT_WITH_CODE((0 == smc_result),
+					"Failed to enable DTE in SMC.", result = -1;);
+			if (0 == smc_result)
+				data->power_containment_features |= POWERCONTAINMENT_FEATURE_DTE;
+		}
+
+		if (data->enable_tdc_limit_feature) {
+			smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
+					(uint16_t)(PPSMC_MSG_TDCLimitEnable));
+			PP_ASSERT_WITH_CODE((0 == smc_result),
+					"Failed to enable TDCLimit in SMC.", result = -1;);
+			if (0 == smc_result)
+				data->power_containment_features |=
+						POWERCONTAINMENT_FEATURE_TDCLimit;
+		}
+
+		if (data->enable_pkg_pwr_tracking_feature) {
+			smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
+					(uint16_t)(PPSMC_MSG_PkgPwrLimitEnable));
+			PP_ASSERT_WITH_CODE((0 == smc_result),
+					"Failed to enable PkgPwrTracking in SMC.", result = -1;);
+			if (0 == smc_result) {
+				struct phm_cac_tdp_table *cac_table =
+						table_info->cac_dtp_table;
+				uint32_t default_limit =
+					(uint32_t)(cac_table->usMaximumPowerDeliveryLimit * 256);
+
+				data->power_containment_features |=
+						POWERCONTAINMENT_FEATURE_PkgPwrLimit;
+
+				if (fiji_set_power_limit(hwmgr, default_limit))
+					printk(KERN_ERR "Failed to set Default Power Limit in SMC!");
+			}
+		}
+	}
+	return result;
+}
+
+int fiji_power_control_set_level(struct pp_hwmgr *hwmgr)
+{
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
+	int adjust_percent, target_tdp;
+	int result = 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PowerContainment)) {
+		/* adjustment percentage has already been validated */
+		adjust_percent = hwmgr->platform_descriptor.TDPAdjustmentPolarity ?
+				hwmgr->platform_descriptor.TDPAdjustment :
+				(-1 * hwmgr->platform_descriptor.TDPAdjustment);
+		/* SMC requested that target_tdp to be 7 bit fraction in DPM table
+		 * but message to be 8 bit fraction for messages
+		 */
+		target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100;
+		result = fiji_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp);
+	}
+
+	return result;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.h
new file mode 100644
index 0000000..55e5820
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef FIJI_POWERTUNE_H
+#define FIJI_POWERTUNE_H
+
+enum fiji_pt_config_reg_type {
+	FIJI_CONFIGREG_MMR = 0,
+	FIJI_CONFIGREG_SMC_IND,
+	FIJI_CONFIGREG_DIDT_IND,
+	FIJI_CONFIGREG_CACHE,
+	FIJI_CONFIGREG_MAX
+};
+
+/* PowerContainment Features */
+#define POWERCONTAINMENT_FEATURE_DTE             0x00000001
+#define POWERCONTAINMENT_FEATURE_TDCLimit        0x00000002
+#define POWERCONTAINMENT_FEATURE_PkgPwrLimit     0x00000004
+
+struct fiji_pt_config_reg {
+	uint32_t                           offset;
+	uint32_t                           mask;
+	uint32_t                           shift;
+	uint32_t                           value;
+	enum fiji_pt_config_reg_type       type;
+};
+
+struct fiji_pt_defaults
+{
+    uint8_t   SviLoadLineEn;
+    uint8_t   SviLoadLineVddC;
+    uint8_t   TDC_VDDC_ThrottleReleaseLimitPerc;
+    uint8_t   TDC_MAWt;
+    uint8_t   TdcWaterfallCtl;
+    uint8_t   DTEAmbientTempBase;
+};
+
+void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr);
+int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr);
+int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr);
+int fiji_enable_smc_cac(struct pp_hwmgr *hwmgr);
+int fiji_enable_power_containment(struct pp_hwmgr *hwmgr);
+int fiji_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n);
+int fiji_power_control_set_level(struct pp_hwmgr *hwmgr);
+
+#endif  /* FIJI_POWERTUNE_H */
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c
new file mode 100644
index 0000000..e76a7de
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c
@@ -0,0 +1,687 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <asm/div64.h>
+#include "fiji_thermal.h"
+#include "fiji_hwmgr.h"
+#include "fiji_smumgr.h"
+#include "fiji_ppsmc.h"
+#include "smu/smu_7_1_3_d.h"
+#include "smu/smu_7_1_3_sh_mask.h"
+
+int fiji_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
+		struct phm_fan_speed_info *fan_speed_info)
+{
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	fan_speed_info->supports_percent_read = true;
+	fan_speed_info->supports_percent_write = true;
+	fan_speed_info->min_percent = 0;
+	fan_speed_info->max_percent = 100;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_FanSpeedInTableIsRPM) &&
+		hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) {
+		fan_speed_info->supports_rpm_read = true;
+		fan_speed_info->supports_rpm_write = true;
+		fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM;
+		fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM;
+	} else {
+		fan_speed_info->min_rpm = 0;
+		fan_speed_info->max_rpm = 0;
+	}
+
+	return 0;
+}
+
+int fiji_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
+		uint32_t *speed)
+{
+	uint32_t duty100;
+	uint32_t duty;
+	uint64_t tmp64;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL1, FMAX_DUTY100);
+	duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_STATUS, FDO_PWM_DUTY);
+
+	if (duty100 == 0)
+		return -EINVAL;
+
+
+	tmp64 = (uint64_t)duty * 100;
+	do_div(tmp64, duty100);
+	*speed = (uint32_t)tmp64;
+
+	if (*speed > 100)
+		*speed = 100;
+
+	return 0;
+}
+
+int fiji_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
+{
+	uint32_t tach_period;
+	uint32_t crystal_clock_freq;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan ||
+			(hwmgr->thermal_controller.fanInfo.
+				ucTachometerPulsesPerRevolution == 0))
+		return 0;
+
+	tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_TACH_STATUS, TACH_PERIOD);
+
+	if (tach_period == 0)
+		return -EINVAL;
+
+	crystal_clock_freq = tonga_get_xclk(hwmgr);
+
+	*speed = 60 * crystal_clock_freq * 10000/ tach_period;
+
+	return 0;
+}
+
+/**
+* Set Fan Speed Control to static mode, so that the user can decide what speed to use.
+* @param    hwmgr  the address of the powerplay hardware manager.
+*           mode    the fan control mode, 0 default, 1 by percent, 5, by RPM
+* @exception Should always succeed.
+*/
+int fiji_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
+{
+
+	if (hwmgr->fan_ctrl_is_in_default_mode) {
+		hwmgr->fan_ctrl_default_mode =
+				PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,	CGS_IND_REG__SMC,
+						CG_FDO_CTRL2, FDO_PWM_MODE);
+		hwmgr->tmin =
+				PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+						CG_FDO_CTRL2, TMIN);
+		hwmgr->fan_ctrl_is_in_default_mode = false;
+	}
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL2, TMIN, 0);
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL2, FDO_PWM_MODE, mode);
+
+	return 0;
+}
+
+/**
+* Reset Fan Speed Control to default mode.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @exception Should always succeed.
+*/
+int fiji_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
+{
+	if (!hwmgr->fan_ctrl_is_in_default_mode) {
+		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode);
+		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_FDO_CTRL2, TMIN, hwmgr->tmin);
+		hwmgr->fan_ctrl_is_in_default_mode = true;
+	}
+
+	return 0;
+}
+
+int fiji_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
+{
+	int result;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ODFuzzyFanControlSupport)) {
+		cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_FUZZY);
+		result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl);
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_FanSpeedInTableIsRPM))
+			hwmgr->hwmgr_func->set_max_fan_rpm_output(hwmgr,
+					hwmgr->thermal_controller.
+					advanceFanControlParameters.usMaxFanRPM);
+		else
+			hwmgr->hwmgr_func->set_max_fan_pwm_output(hwmgr,
+					hwmgr->thermal_controller.
+					advanceFanControlParameters.usMaxFanPWM);
+
+	} else {
+		cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_TABLE);
+		result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl);
+	}
+
+	if (!result && hwmgr->thermal_controller.
+			advanceFanControlParameters.ucTargetTemperature)
+		result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetFanTemperatureTarget,
+				hwmgr->thermal_controller.
+				advanceFanControlParameters.ucTargetTemperature);
+
+	return result;
+}
+
+
+int fiji_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl);
+}
+
+/**
+* Set Fan Speed in percent.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    speed is the percentage value (0% - 100%) to be set.
+* @exception Fails is the 100% setting appears to be 0.
+*/
+int fiji_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
+		uint32_t speed)
+{
+	uint32_t duty100;
+	uint32_t duty;
+	uint64_t tmp64;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	if (speed > 100)
+		speed = 100;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl))
+		fiji_fan_ctrl_stop_smc_fan_control(hwmgr);
+
+	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL1, FMAX_DUTY100);
+
+	if (duty100 == 0)
+		return -EINVAL;
+
+	tmp64 = (uint64_t)speed * 100;
+	do_div(tmp64, duty100);
+	duty = (uint32_t)tmp64;
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL0, FDO_STATIC_DUTY, duty);
+
+	return fiji_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+}
+
+/**
+* Reset Fan Speed to default.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @exception Always succeeds.
+*/
+int fiji_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
+{
+	int result;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl)) {
+		result = fiji_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+		if (!result)
+			result = fiji_fan_ctrl_start_smc_fan_control(hwmgr);
+	} else
+		result = fiji_fan_ctrl_set_default_mode(hwmgr);
+
+	return result;
+}
+
+/**
+* Set Fan Speed in RPM.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    speed is the percentage value (min - max) to be set.
+* @exception Fails is the speed not lie between min and max.
+*/
+int fiji_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
+{
+	uint32_t tach_period;
+	uint32_t crystal_clock_freq;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan ||
+			(hwmgr->thermal_controller.fanInfo.
+			ucTachometerPulsesPerRevolution == 0) ||
+			(speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
+			(speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
+		return 0;
+
+	crystal_clock_freq = tonga_get_xclk(hwmgr);
+
+	tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_TACH_STATUS, TACH_PERIOD, tach_period);
+
+	return fiji_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+}
+
+/**
+* Reads the remote temperature from the SIslands thermal controller.
+*
+* @param    hwmgr The address of the hardware manager.
+*/
+int fiji_thermal_get_temperature(struct pp_hwmgr *hwmgr)
+{
+	int temp;
+
+	temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_MULT_THERMAL_STATUS, CTF_TEMP);
+
+	/* Bit 9 means the reading is lower than the lowest usable value. */
+	if (temp & 0x200)
+		temp = FIJI_THERMAL_MAXIMUM_TEMP_READING;
+	else
+		temp = temp & 0x1ff;
+
+	temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+	return temp;
+}
+
+/**
+* Set the requested temperature range for high and low alert signals
+*
+* @param    hwmgr The address of the hardware manager.
+* @param    range Temperature range to be programmed for high and low alert signals
+* @exception PP_Result_BadInput if the input data is not valid.
+*/
+static int fiji_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
+		uint32_t low_temp, uint32_t high_temp)
+{
+	uint32_t low = FIJI_THERMAL_MINIMUM_ALERT_TEMP *
+			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+	uint32_t high = FIJI_THERMAL_MAXIMUM_ALERT_TEMP *
+			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+	if (low < low_temp)
+		low = low_temp;
+	if (high > high_temp)
+		high = high_temp;
+
+	if (low > high)
+		return -EINVAL;
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, DIG_THERM_INTH,
+			(high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, DIG_THERM_INTL,
+			(low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_CTRL, DIG_THERM_DPM,
+			(high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+
+	return 0;
+}
+
+/**
+* Programs thermal controller one-time setting registers
+*
+* @param    hwmgr The address of the hardware manager.
+*/
+static int fiji_thermal_initialize(struct pp_hwmgr *hwmgr)
+{
+	if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution)
+		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_TACH_CTRL, EDGE_PER_REV,
+				hwmgr->thermal_controller.fanInfo.
+				ucTachometerPulsesPerRevolution - 1);
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28);
+
+	return 0;
+}
+
+/**
+* Enable thermal alerts on the RV770 thermal controller.
+*
+* @param    hwmgr The address of the hardware manager.
+*/
+static int fiji_thermal_enable_alert(struct pp_hwmgr *hwmgr)
+{
+	uint32_t alert;
+
+	alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, THERM_INT_MASK);
+	alert &= ~(FIJI_THERMAL_HIGH_ALERT_MASK | FIJI_THERMAL_LOW_ALERT_MASK);
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, THERM_INT_MASK, alert);
+
+	/* send message to SMU to enable internal thermal interrupts */
+	return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Enable);
+}
+
+/**
+* Disable thermal alerts on the RV770 thermal controller.
+* @param    hwmgr The address of the hardware manager.
+*/
+static int fiji_thermal_disable_alert(struct pp_hwmgr *hwmgr)
+{
+	uint32_t alert;
+
+	alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, THERM_INT_MASK);
+	alert |= (FIJI_THERMAL_HIGH_ALERT_MASK | FIJI_THERMAL_LOW_ALERT_MASK);
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, THERM_INT_MASK, alert);
+
+	/* send message to SMU to disable internal thermal interrupts */
+	return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Disable);
+}
+
+/**
+* Uninitialize the thermal controller.
+* Currently just disables alerts.
+* @param    hwmgr The address of the hardware manager.
+*/
+int fiji_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
+{
+	int result = fiji_thermal_disable_alert(hwmgr);
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		fiji_fan_ctrl_set_default_mode(hwmgr);
+
+	return result;
+}
+
+/**
+* Set up the fan table to control the fan using the SMC.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from set temperature range routine
+*/
+int tf_fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+	SMU73_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
+	uint32_t duty100;
+	uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
+	uint16_t fdo_min, slope1, slope2;
+	uint32_t reference_clock;
+	int res;
+	uint64_t tmp64;
+
+	if (data->fan_table_start == 0) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_MicrocodeFanControl);
+		return 0;
+	}
+
+	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL1, FMAX_DUTY100);
+
+	if (duty100 == 0) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_MicrocodeFanControl);
+		return 0;
+	}
+
+	tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.
+			usPWMMin * duty100;
+	do_div(tmp64, 10000);
+	fdo_min = (uint16_t)tmp64;
+
+	t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed -
+			hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
+	t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh -
+			hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
+
+	pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed -
+			hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
+	pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh -
+			hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
+
+	slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
+	slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
+
+	fan_table.TempMin = cpu_to_be16((50 + hwmgr->
+			thermal_controller.advanceFanControlParameters.usTMin) / 100);
+	fan_table.TempMed = cpu_to_be16((50 + hwmgr->
+			thermal_controller.advanceFanControlParameters.usTMed) / 100);
+	fan_table.TempMax = cpu_to_be16((50 + hwmgr->
+			thermal_controller.advanceFanControlParameters.usTMax) / 100);
+
+	fan_table.Slope1 = cpu_to_be16(slope1);
+	fan_table.Slope2 = cpu_to_be16(slope2);
+
+	fan_table.FdoMin = cpu_to_be16(fdo_min);
+
+	fan_table.HystDown = cpu_to_be16(hwmgr->
+			thermal_controller.advanceFanControlParameters.ucTHyst);
+
+	fan_table.HystUp = cpu_to_be16(1);
+
+	fan_table.HystSlope = cpu_to_be16(1);
+
+	fan_table.TempRespLim = cpu_to_be16(5);
+
+	reference_clock = tonga_get_xclk(hwmgr);
+
+	fan_table.RefreshPeriod = cpu_to_be32((hwmgr->
+			thermal_controller.advanceFanControlParameters.ulCycleDelay *
+			reference_clock) / 1600);
+
+	fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
+
+	fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(
+			hwmgr->device, CGS_IND_REG__SMC,
+			CG_MULT_THERMAL_CTRL, TEMP_SEL);
+
+	res = fiji_copy_bytes_to_smc(hwmgr->smumgr, data->fan_table_start,
+			(uint8_t *)&fan_table, (uint32_t)sizeof(fan_table),
+			data->sram_end);
+
+	if (!res && hwmgr->thermal_controller.
+			advanceFanControlParameters.ucMinimumPWMLimit)
+		res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetFanMinPwm,
+				hwmgr->thermal_controller.
+				advanceFanControlParameters.ucMinimumPWMLimit);
+
+	if (!res && hwmgr->thermal_controller.
+			advanceFanControlParameters.ulMinFanSCLKAcousticLimit)
+		res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetFanSclkTarget,
+				hwmgr->thermal_controller.
+				advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
+
+	if (res)
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_MicrocodeFanControl);
+
+	return 0;
+}
+
+/**
+* Start the fan control on the SMC.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from set temperature range routine
+*/
+int tf_fiji_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+/* If the fantable setup has failed we could have disabled
+ * PHM_PlatformCaps_MicrocodeFanControl even after
+ * this function was included in the table.
+ * Make sure that we still think controlling the fan is OK.
+*/
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl)) {
+		fiji_fan_ctrl_start_smc_fan_control(hwmgr);
+		fiji_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+	}
+
+	return 0;
+}
+
+/**
+* Set temperature range for high and low alerts
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from set temperature range routine
+*/
+int tf_fiji_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+	struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input;
+
+	if (range == NULL)
+		return -EINVAL;
+
+	return fiji_thermal_set_temperature_range(hwmgr, range->min, range->max);
+}
+
+/**
+* Programs one-time setting registers
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from initialize thermal controller routine
+*/
+int tf_fiji_thermal_initialize(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+    return fiji_thermal_initialize(hwmgr);
+}
+
+/**
+* Enable high and low alerts
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from enable alert routine
+*/
+int tf_fiji_thermal_enable_alert(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+	return fiji_thermal_enable_alert(hwmgr);
+}
+
+/**
+* Disable high and low alerts
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from disable alert routine
+*/
+static int tf_fiji_thermal_disable_alert(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+	return fiji_thermal_disable_alert(hwmgr);
+}
+
+static struct phm_master_table_item
+fiji_thermal_start_thermal_controller_master_list[] = {
+	{NULL, tf_fiji_thermal_initialize},
+	{NULL, tf_fiji_thermal_set_temperature_range},
+	{NULL, tf_fiji_thermal_enable_alert},
+/* We should restrict performance levels to low before we halt the SMC.
+ * On the other hand we are still in boot state when we do this
+ * so it would be pointless.
+ * If this assumption changes we have to revisit this table.
+ */
+	{NULL, tf_fiji_thermal_setup_fan_table},
+	{NULL, tf_fiji_thermal_start_smc_fan_control},
+	{NULL, NULL}
+};
+
+static struct phm_master_table_header
+fiji_thermal_start_thermal_controller_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	fiji_thermal_start_thermal_controller_master_list
+};
+
+static struct phm_master_table_item
+fiji_thermal_set_temperature_range_master_list[] = {
+	{NULL, tf_fiji_thermal_disable_alert},
+	{NULL, tf_fiji_thermal_set_temperature_range},
+	{NULL, tf_fiji_thermal_enable_alert},
+	{NULL, NULL}
+};
+
+struct phm_master_table_header
+fiji_thermal_set_temperature_range_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	fiji_thermal_set_temperature_range_master_list
+};
+
+int fiji_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
+{
+	if (!hwmgr->thermal_controller.fanInfo.bNoFan)
+		fiji_fan_ctrl_set_default_mode(hwmgr);
+	return 0;
+}
+
+/**
+* Initializes the thermal controller related functions in the Hardware Manager structure.
+* @param    hwmgr The address of the hardware manager.
+* @exception Any error code from the low-level communication.
+*/
+int pp_fiji_thermal_initialize(struct pp_hwmgr *hwmgr)
+{
+	int result;
+
+	result = phm_construct_table(hwmgr,
+			&fiji_thermal_set_temperature_range_master,
+			&(hwmgr->set_temperature_range));
+
+	if (!result) {
+		result = phm_construct_table(hwmgr,
+				&fiji_thermal_start_thermal_controller_master,
+				&(hwmgr->start_thermal_controller));
+		if (result)
+			phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range));
+	}
+
+	if (!result)
+		hwmgr->fan_ctrl_is_in_default_mode = true;
+	return result;
+}
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.h
new file mode 100644
index 0000000..8621493
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef FIJI_THERMAL_H
+#define FIJI_THERMAL_H
+
+#include "hwmgr.h"
+
+#define FIJI_THERMAL_HIGH_ALERT_MASK         0x1
+#define FIJI_THERMAL_LOW_ALERT_MASK          0x2
+
+#define FIJI_THERMAL_MINIMUM_TEMP_READING    -256
+#define FIJI_THERMAL_MAXIMUM_TEMP_READING    255
+
+#define FIJI_THERMAL_MINIMUM_ALERT_TEMP      0
+#define FIJI_THERMAL_MAXIMUM_ALERT_TEMP      255
+
+#define FDO_PWM_MODE_STATIC  1
+#define FDO_PWM_MODE_STATIC_RPM 5
+
+
+extern int tf_fiji_thermal_initialize(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result);
+extern int tf_fiji_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result);
+extern int tf_fiji_thermal_enable_alert(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result);
+
+extern int fiji_thermal_get_temperature(struct pp_hwmgr *hwmgr);
+extern int fiji_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
+extern int fiji_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info);
+extern int fiji_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed);
+extern int fiji_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr);
+extern int fiji_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode);
+extern int fiji_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed);
+extern int fiji_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr);
+extern int pp_fiji_thermal_initialize(struct pp_hwmgr *hwmgr);
+extern int fiji_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr);
+extern int fiji_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed);
+extern int fiji_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed);
+extern int fiji_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
+extern uint32_t tonga_get_xclk(struct pp_hwmgr *hwmgr);
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c
new file mode 100644
index 0000000..9deadab
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include "hwmgr.h"
+
+static int phm_run_table(struct pp_hwmgr *hwmgr,
+			 struct phm_runtime_table_header *rt_table,
+			 void *input,
+			 void *output,
+			 void *temp_storage)
+{
+	int result = 0;
+	phm_table_function *function;
+
+	for (function = rt_table->function_list; NULL != *function; function++) {
+		int tmp = (*function)(hwmgr, input, output, temp_storage, result);
+
+		if (tmp == PP_Result_TableImmediateExit)
+			break;
+		if (tmp) {
+			if (0 == result)
+				result = tmp;
+			if (rt_table->exit_error)
+				break;
+		}
+	}
+
+	return result;
+}
+
+int phm_dispatch_table(struct pp_hwmgr *hwmgr,
+		       struct phm_runtime_table_header *rt_table,
+		       void *input, void *output)
+{
+	int result = 0;
+	void *temp_storage = NULL;
+
+	if (hwmgr == NULL || rt_table == NULL || rt_table->function_list == NULL) {
+		printk(KERN_ERR "[ powerplay ] Invalid Parameter!\n");
+		return 0; /*temp return ture because some function not implement on some asic */
+	}
+
+	if (0 != rt_table->storage_size) {
+		temp_storage = kzalloc(rt_table->storage_size, GFP_KERNEL);
+		if (temp_storage == NULL) {
+			printk(KERN_ERR "[ powerplay ] Could not allocate table temporary storage\n");
+			return -ENOMEM;
+		}
+	}
+
+	result = phm_run_table(hwmgr, rt_table, input, output, temp_storage);
+
+	if (NULL != temp_storage)
+		kfree(temp_storage);
+
+	return result;
+}
+
+int phm_construct_table(struct pp_hwmgr *hwmgr,
+			struct phm_master_table_header *master_table,
+			struct phm_runtime_table_header *rt_table)
+{
+	uint32_t function_count = 0;
+	const struct phm_master_table_item *table_item;
+	uint32_t size;
+	phm_table_function *run_time_list;
+	phm_table_function *rtf;
+
+	if (hwmgr == NULL || master_table == NULL || rt_table == NULL) {
+		printk(KERN_ERR "[ powerplay ] Invalid Parameter!\n");
+		return -EINVAL;
+	}
+
+	for (table_item = master_table->master_list;
+		NULL != table_item->tableFunction; table_item++) {
+		if ((NULL == table_item->isFunctionNeededInRuntimeTable) ||
+		    (table_item->isFunctionNeededInRuntimeTable(hwmgr)))
+			function_count++;
+	}
+
+	size = (function_count + 1) * sizeof(phm_table_function);
+	run_time_list = kzalloc(size, GFP_KERNEL);
+
+	if (NULL == run_time_list)
+		return -ENOMEM;
+
+	rtf = run_time_list;
+	for (table_item = master_table->master_list;
+		NULL != table_item->tableFunction; table_item++) {
+		if ((rtf - run_time_list) > function_count) {
+			printk(KERN_ERR "[ powerplay ] Check function results have changed\n");
+			kfree(run_time_list);
+			return -EINVAL;
+		}
+
+		if ((NULL == table_item->isFunctionNeededInRuntimeTable) ||
+		     (table_item->isFunctionNeededInRuntimeTable(hwmgr))) {
+			*(rtf++) = table_item->tableFunction;
+		}
+	}
+
+	if ((rtf - run_time_list) > function_count) {
+		printk(KERN_ERR "[ powerplay ] Check function results have changed\n");
+		kfree(run_time_list);
+		return -EINVAL;
+	}
+
+	*rtf = NULL;
+	rt_table->function_list = run_time_list;
+	rt_table->exit_error = (0 != (master_table->flags & PHM_MasterTableFlag_ExitOnError));
+	rt_table->storage_size = master_table->storage_size;
+	return 0;
+}
+
+int phm_destroy_table(struct pp_hwmgr *hwmgr,
+		      struct phm_runtime_table_header *rt_table)
+{
+	if (hwmgr == NULL || rt_table == NULL) {
+		printk(KERN_ERR "[ powerplay ] Invalid Parameter\n");
+		return -EINVAL;
+	}
+
+	if (NULL == rt_table->function_list)
+		return 0;
+
+	kfree(rt_table->function_list);
+
+	rt_table->function_list = NULL;
+	rt_table->storage_size = 0;
+	rt_table->exit_error = false;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
new file mode 100644
index 0000000..0f2d5e4
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/errno.h>
+#include "hwmgr.h"
+#include "hardwaremanager.h"
+#include "power_state.h"
+#include "pp_acpi.h"
+#include "amd_acpi.h"
+#include "amd_powerplay.h"
+
+#define PHM_FUNC_CHECK(hw) \
+	do {							\
+		if ((hw) == NULL || (hw)->hwmgr_func == NULL)	\
+			return -EINVAL;				\
+	} while (0)
+
+void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr)
+{
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableVoltageTransition);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableEngineTransition);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMemoryTransition);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGClockGating);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGCGTSSM);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLSClockGating);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_Force3DClockSupport);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLightSleep);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMCLS);
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisablePowerGating);
+
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableDPM);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableSMUUVDHandshake);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ThermalAutoThrottling);
+
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
+
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_NoOD5Support);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UserMaxClockForMultiDisplays);
+
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VpuRecoveryInProgress);
+
+	if (acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST) &&
+		acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION))
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
+}
+
+bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr)
+{
+	return hwmgr->block_hw_access;
+}
+
+int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block)
+{
+	hwmgr->block_hw_access = block;
+	return 0;
+}
+
+int phm_setup_asic(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_TablelessHardwareInterface)) {
+		if (NULL != hwmgr->hwmgr_func->asic_setup)
+			return hwmgr->hwmgr_func->asic_setup(hwmgr);
+	} else {
+		return phm_dispatch_table(hwmgr, &(hwmgr->setup_asic),
+					  NULL, NULL);
+	}
+
+	return 0;
+}
+
+int phm_power_down_asic(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_TablelessHardwareInterface)) {
+		if (NULL != hwmgr->hwmgr_func->power_off_asic)
+			return hwmgr->hwmgr_func->power_off_asic(hwmgr);
+	} else {
+		return phm_dispatch_table(hwmgr, &(hwmgr->power_down_asic),
+					  NULL, NULL);
+	}
+
+	return 0;
+}
+
+int phm_set_power_state(struct pp_hwmgr *hwmgr,
+		    const struct pp_hw_power_state *pcurrent_state,
+		    const struct pp_hw_power_state *pnew_power_state)
+{
+	struct phm_set_power_state_input states;
+
+	PHM_FUNC_CHECK(hwmgr);
+
+	states.pcurrent_state = pcurrent_state;
+	states.pnew_state = pnew_power_state;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_TablelessHardwareInterface)) {
+		if (NULL != hwmgr->hwmgr_func->power_state_set)
+			return hwmgr->hwmgr_func->power_state_set(hwmgr, &states);
+	} else {
+		return phm_dispatch_table(hwmgr, &(hwmgr->set_power_state), &states, NULL);
+	}
+
+	return 0;
+}
+
+int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_TablelessHardwareInterface)) {
+		if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable)
+			return hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr);
+	} else {
+		return phm_dispatch_table(hwmgr,
+				&(hwmgr->enable_dynamic_state_management),
+				NULL, NULL);
+	}
+	return 0;
+}
+
+int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->force_dpm_level != NULL)
+		return hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
+
+	return 0;
+}
+
+int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+				   struct pp_power_state *adjusted_ps,
+			     const struct pp_power_state *current_ps)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->apply_state_adjust_rules != NULL)
+		return hwmgr->hwmgr_func->apply_state_adjust_rules(
+									hwmgr,
+								 adjusted_ps,
+								 current_ps);
+	return 0;
+}
+
+int phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->powerdown_uvd != NULL)
+		return hwmgr->hwmgr_func->powerdown_uvd(hwmgr);
+	return 0;
+}
+
+int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->powergate_uvd != NULL)
+		return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
+	return 0;
+}
+
+int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->powergate_vce != NULL)
+		return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
+	return 0;
+}
+
+int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_TablelessHardwareInterface)) {
+		if (NULL != hwmgr->hwmgr_func->enable_clock_power_gating)
+			return hwmgr->hwmgr_func->enable_clock_power_gating(hwmgr);
+	} else {
+		return phm_dispatch_table(hwmgr, &(hwmgr->enable_clock_power_gatings), NULL, NULL);
+	}
+	return 0;
+}
+
+int phm_display_configuration_changed(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				 PHM_PlatformCaps_TablelessHardwareInterface)) {
+		if (NULL != hwmgr->hwmgr_func->display_config_changed)
+			hwmgr->hwmgr_func->display_config_changed(hwmgr);
+	} else
+		return phm_dispatch_table(hwmgr, &hwmgr->display_configuration_changed, NULL, NULL);
+	return 0;
+}
+
+int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				 PHM_PlatformCaps_TablelessHardwareInterface))
+		if (NULL != hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment)
+			hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment(hwmgr);
+
+	return 0;
+}
+
+int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->stop_thermal_controller == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->stop_thermal_controller(hwmgr);
+}
+
+int phm_register_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *info)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->register_internal_thermal_interrupt == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->register_internal_thermal_interrupt(hwmgr, info);
+}
+
+/**
+* Initializes the thermal controller subsystem.
+*
+* @param    pHwMgr  the address of the powerplay hardware manager.
+* @param    pTemperatureRange the address of the structure holding the temperature range.
+* @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the dispatcher.
+*/
+int phm_start_thermal_controller(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *temperature_range)
+{
+	return phm_dispatch_table(hwmgr, &(hwmgr->start_thermal_controller), temperature_range, NULL);
+}
+
+
+bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration(hwmgr);
+}
+
+
+int phm_check_states_equal(struct pp_hwmgr *hwmgr,
+				 const struct pp_hw_power_state *pstate1,
+				 const struct pp_hw_power_state *pstate2,
+				 bool *equal)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->check_states_equal == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->check_states_equal(hwmgr, pstate1, pstate2, equal);
+}
+
+int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr,
+		    const struct amd_pp_display_configuration *display_config)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->store_cc6_data == NULL)
+		return -EINVAL;
+
+	hwmgr->display_config = *display_config;
+	/* to do pass other display configuration in furture */
+
+	if (hwmgr->hwmgr_func->store_cc6_data)
+		hwmgr->hwmgr_func->store_cc6_data(hwmgr,
+				display_config->cpu_pstate_separation_time,
+				display_config->cpu_cc6_disable,
+				display_config->cpu_pstate_disable,
+				display_config->nb_pstate_switch_disable);
+
+	return 0;
+}
+
+int phm_get_dal_power_level(struct pp_hwmgr *hwmgr,
+		struct amd_pp_dal_clock_info *info)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (info == NULL || hwmgr->hwmgr_func->get_dal_power_level == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->get_dal_power_level(hwmgr, info);
+}
+
+int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (hwmgr->hwmgr_func->set_cpu_power_state != NULL)
+		return hwmgr->hwmgr_func->set_cpu_power_state(hwmgr);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
new file mode 100644
index 0000000..5fb98aa
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
@@ -0,0 +1,563 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include "linux/delay.h"
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include "cgs_common.h"
+#include "power_state.h"
+#include "hwmgr.h"
+#include "pppcielanes.h"
+#include "pp_debug.h"
+#include "ppatomctrl.h"
+
+extern int cz_hwmgr_init(struct pp_hwmgr *hwmgr);
+extern int tonga_hwmgr_init(struct pp_hwmgr *hwmgr);
+extern int fiji_hwmgr_init(struct pp_hwmgr *hwmgr);
+
+int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
+{
+	struct pp_hwmgr *hwmgr;
+
+	if ((handle == NULL) || (pp_init == NULL))
+		return -EINVAL;
+
+	hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL);
+	if (hwmgr == NULL)
+		return -ENOMEM;
+
+	handle->hwmgr = hwmgr;
+	hwmgr->smumgr = handle->smu_mgr;
+	hwmgr->device = pp_init->device;
+	hwmgr->chip_family = pp_init->chip_family;
+	hwmgr->chip_id = pp_init->chip_id;
+	hwmgr->hw_revision = pp_init->rev_id;
+	hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
+	hwmgr->power_source = PP_PowerSource_AC;
+
+	switch (hwmgr->chip_family) {
+	case AMD_FAMILY_CZ:
+		cz_hwmgr_init(hwmgr);
+		break;
+	case AMD_FAMILY_VI:
+		switch (hwmgr->chip_id) {
+		case CHIP_TONGA:
+			tonga_hwmgr_init(hwmgr);
+			break;
+		case CHIP_FIJI:
+			fiji_hwmgr_init(hwmgr);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	phm_init_dynamic_caps(hwmgr);
+
+	return 0;
+}
+
+int hwmgr_fini(struct pp_hwmgr *hwmgr)
+{
+	if (hwmgr == NULL || hwmgr->ps == NULL)
+		return -EINVAL;
+
+	kfree(hwmgr->ps);
+	kfree(hwmgr);
+	return 0;
+}
+
+int hw_init_power_state_table(struct pp_hwmgr *hwmgr)
+{
+	int result;
+	unsigned int i;
+	unsigned int table_entries;
+	struct pp_power_state *state;
+	int size;
+
+	if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL)
+		return -EINVAL;
+
+	if (hwmgr->hwmgr_func->get_power_state_size == NULL)
+		return -EINVAL;
+
+	hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr);
+
+	hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) +
+					  sizeof(struct pp_power_state);
+
+	hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL);
+
+	if (hwmgr->ps == NULL)
+		return -ENOMEM;
+
+	state = hwmgr->ps;
+
+	for (i = 0; i < table_entries; i++) {
+		result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state);
+
+		if (state->classification.flags & PP_StateClassificationFlag_Boot) {
+			hwmgr->boot_ps = state;
+			hwmgr->current_ps = hwmgr->request_ps = state;
+		}
+
+		state->id = i + 1; /* assigned unique num for every power state id */
+
+		if (state->classification.flags & PP_StateClassificationFlag_Uvd)
+			hwmgr->uvd_ps = state;
+		state = (struct pp_power_state *)((unsigned long)state + size);
+	}
+
+	return 0;
+}
+
+
+/**
+ * Returns once the part of the register indicated by the mask has
+ * reached the given value.
+ */
+int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index,
+			 uint32_t value, uint32_t mask)
+{
+	uint32_t i;
+	uint32_t cur_value;
+
+	if (hwmgr == NULL || hwmgr->device == NULL) {
+		printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < hwmgr->usec_timeout; i++) {
+		cur_value = cgs_read_register(hwmgr->device, index);
+		if ((cur_value & mask) == (value & mask))
+			break;
+		udelay(1);
+	}
+
+	/* timeout means wrong logic*/
+	if (i == hwmgr->usec_timeout)
+		return -1;
+	return 0;
+}
+
+int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr,
+				uint32_t index, uint32_t value, uint32_t mask)
+{
+	uint32_t i;
+	uint32_t cur_value;
+
+	if (hwmgr == NULL || hwmgr->device == NULL) {
+		printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < hwmgr->usec_timeout; i++) {
+		cur_value = cgs_read_register(hwmgr->device, index);
+		if ((cur_value & mask) != (value & mask))
+			break;
+		udelay(1);
+	}
+
+	/* timeout means wrong logic*/
+	if (i == hwmgr->usec_timeout)
+		return -1;
+	return 0;
+}
+
+
+/**
+ * Returns once the part of the register indicated by the mask has
+ * reached the given value.The indirect space is described by giving
+ * the memory-mapped index of the indirect index register.
+ */
+void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr,
+				uint32_t indirect_port,
+				uint32_t index,
+				uint32_t value,
+				uint32_t mask)
+{
+	if (hwmgr == NULL || hwmgr->device == NULL) {
+		printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
+		return;
+	}
+
+	cgs_write_register(hwmgr->device, indirect_port, index);
+	phm_wait_on_register(hwmgr, indirect_port + 1, mask, value);
+}
+
+void phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr,
+					uint32_t indirect_port,
+					uint32_t index,
+					uint32_t value,
+					uint32_t mask)
+{
+	if (hwmgr == NULL || hwmgr->device == NULL) {
+		printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
+		return;
+	}
+
+	cgs_write_register(hwmgr->device, indirect_port, index);
+	phm_wait_for_register_unequal(hwmgr, indirect_port + 1,
+				      value, mask);
+}
+
+bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr)
+{
+	return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating);
+}
+
+bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr)
+{
+	return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating);
+}
+
+
+int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table)
+{
+	uint32_t i, j;
+	uint16_t vvalue;
+	bool found = false;
+	struct pp_atomctrl_voltage_table *table;
+
+	PP_ASSERT_WITH_CODE((NULL != vol_table),
+			"Voltage Table empty.", return -EINVAL);
+
+	table = kzalloc(sizeof(struct pp_atomctrl_voltage_table),
+			GFP_KERNEL);
+
+	if (NULL == table)
+		return -EINVAL;
+
+	table->mask_low = vol_table->mask_low;
+	table->phase_delay = vol_table->phase_delay;
+
+	for (i = 0; i < vol_table->count; i++) {
+		vvalue = vol_table->entries[i].value;
+		found = false;
+
+		for (j = 0; j < table->count; j++) {
+			if (vvalue == table->entries[j].value) {
+				found = true;
+				break;
+			}
+		}
+
+		if (!found) {
+			table->entries[table->count].value = vvalue;
+			table->entries[table->count].smio_low =
+					vol_table->entries[i].smio_low;
+			table->count++;
+		}
+	}
+
+	memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table));
+	kfree(table);
+
+	return 0;
+}
+
+int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
+		phm_ppt_v1_clock_voltage_dependency_table *dep_table)
+{
+	uint32_t i;
+	int result;
+
+	PP_ASSERT_WITH_CODE((0 != dep_table->count),
+			"Voltage Dependency Table empty.", return -EINVAL);
+
+	PP_ASSERT_WITH_CODE((NULL != vol_table),
+			"vol_table empty.", return -EINVAL);
+
+	vol_table->mask_low = 0;
+	vol_table->phase_delay = 0;
+	vol_table->count = dep_table->count;
+
+	for (i = 0; i < dep_table->count; i++) {
+		vol_table->entries[i].value = dep_table->entries[i].mvdd;
+		vol_table->entries[i].smio_low = 0;
+	}
+
+	result = phm_trim_voltage_table(vol_table);
+	PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to trim MVDD table.", return result);
+
+	return 0;
+}
+
+int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
+		phm_ppt_v1_clock_voltage_dependency_table *dep_table)
+{
+	uint32_t i;
+	int result;
+
+	PP_ASSERT_WITH_CODE((0 != dep_table->count),
+			"Voltage Dependency Table empty.", return -EINVAL);
+
+	PP_ASSERT_WITH_CODE((NULL != vol_table),
+			"vol_table empty.", return -EINVAL);
+
+	vol_table->mask_low = 0;
+	vol_table->phase_delay = 0;
+	vol_table->count = dep_table->count;
+
+	for (i = 0; i < dep_table->count; i++) {
+		vol_table->entries[i].value = dep_table->entries[i].vddci;
+		vol_table->entries[i].smio_low = 0;
+	}
+
+	result = phm_trim_voltage_table(vol_table);
+	PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to trim VDDCI table.", return result);
+
+	return 0;
+}
+
+int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
+		phm_ppt_v1_voltage_lookup_table *lookup_table)
+{
+	int i = 0;
+
+	PP_ASSERT_WITH_CODE((0 != lookup_table->count),
+			"Voltage Lookup Table empty.", return -EINVAL);
+
+	PP_ASSERT_WITH_CODE((NULL != vol_table),
+			"vol_table empty.", return -EINVAL);
+
+	vol_table->mask_low = 0;
+	vol_table->phase_delay = 0;
+
+	vol_table->count = lookup_table->count;
+
+	for (i = 0; i < vol_table->count; i++) {
+		vol_table->entries[i].value = lookup_table->entries[i].us_vdd;
+		vol_table->entries[i].smio_low = 0;
+	}
+
+	return 0;
+}
+
+void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps,
+				struct pp_atomctrl_voltage_table *vol_table)
+{
+	unsigned int i, diff;
+
+	if (vol_table->count <= max_vol_steps)
+		return;
+
+	diff = vol_table->count - max_vol_steps;
+
+	for (i = 0; i < max_vol_steps; i++)
+		vol_table->entries[i] = vol_table->entries[i + diff];
+
+	vol_table->count = max_vol_steps;
+
+	return;
+}
+
+int phm_reset_single_dpm_table(void *table,
+				uint32_t count, int max)
+{
+	int i;
+
+	struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
+
+	PP_ASSERT_WITH_CODE(count <= max,
+			"Fatal error, can not set up single DPM table entries to exceed max number!",
+			   );
+
+	dpm_table->count = count;
+	for (i = 0; i < max; i++)
+		dpm_table->dpm_level[i].enabled = false;
+
+	return 0;
+}
+
+void phm_setup_pcie_table_entry(
+	void *table,
+	uint32_t index, uint32_t pcie_gen,
+	uint32_t pcie_lanes)
+{
+	struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
+	dpm_table->dpm_level[index].value = pcie_gen;
+	dpm_table->dpm_level[index].param1 = pcie_lanes;
+	dpm_table->dpm_level[index].enabled = 1;
+}
+
+int32_t phm_get_dpm_level_enable_mask_value(void *table)
+{
+	int32_t i;
+	int32_t mask = 0;
+	struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
+
+	for (i = dpm_table->count; i > 0; i--) {
+		mask = mask << 1;
+		if (dpm_table->dpm_level[i - 1].enabled)
+			mask |= 0x1;
+		else
+			mask &= 0xFFFFFFFE;
+	}
+
+	return mask;
+}
+
+uint8_t phm_get_voltage_index(
+		struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage)
+{
+	uint8_t count = (uint8_t) (lookup_table->count);
+	uint8_t i;
+
+	PP_ASSERT_WITH_CODE((NULL != lookup_table),
+			"Lookup Table empty.", return 0);
+	PP_ASSERT_WITH_CODE((0 != count),
+			"Lookup Table empty.", return 0);
+
+	for (i = 0; i < lookup_table->count; i++) {
+		/* find first voltage equal or bigger than requested */
+		if (lookup_table->entries[i].us_vdd >= voltage)
+			return i;
+	}
+	/* voltage is bigger than max voltage in the table */
+	return i - 1;
+}
+
+uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci)
+{
+	uint32_t  i;
+
+	for (i = 0; i < vddci_table->count; i++) {
+		if (vddci_table->entries[i].value >= vddci)
+			return vddci_table->entries[i].value;
+	}
+
+	PP_ASSERT_WITH_CODE(false,
+			"VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
+			return vddci_table->entries[i].value);
+}
+
+int phm_find_boot_level(void *table,
+		uint32_t value, uint32_t *boot_level)
+{
+	int result = -EINVAL;
+	uint32_t i;
+	struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
+
+	for (i = 0; i < dpm_table->count; i++) {
+		if (value == dpm_table->dpm_level[i].value) {
+			*boot_level = i;
+			result = 0;
+		}
+	}
+
+	return result;
+}
+
+int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
+	phm_ppt_v1_voltage_lookup_table *lookup_table,
+	uint16_t virtual_voltage_id, int32_t *sclk)
+{
+	uint8_t entryId;
+	uint8_t voltageId;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL);
+
+	/* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */
+	for (entryId = 0; entryId < table_info->vdd_dep_on_sclk->count; entryId++) {
+		voltageId = table_info->vdd_dep_on_sclk->entries[entryId].vddInd;
+		if (lookup_table->entries[voltageId].us_vdd == virtual_voltage_id)
+			break;
+	}
+
+	PP_ASSERT_WITH_CODE(entryId < table_info->vdd_dep_on_sclk->count,
+			"Can't find requested voltage id in vdd_dep_on_sclk table!",
+			return -EINVAL;
+			);
+
+	*sclk = table_info->vdd_dep_on_sclk->entries[entryId].clk;
+
+	return 0;
+}
+
+/**
+ * Initialize Dynamic State Adjustment Rule Settings
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ */
+int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr)
+{
+	uint32_t table_size;
+	struct phm_clock_voltage_dependency_table *table_clk_vlt;
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	/* initialize vddc_dep_on_dal_pwrl table */
+	table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record);
+	table_clk_vlt = (struct phm_clock_voltage_dependency_table *)kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == table_clk_vlt) {
+		printk(KERN_ERR "[ powerplay ] Can not allocate space for vddc_dep_on_dal_pwrl! \n");
+		return -ENOMEM;
+	} else {
+		table_clk_vlt->count = 4;
+		table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW;
+		table_clk_vlt->entries[0].v = 0;
+		table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW;
+		table_clk_vlt->entries[1].v = 720;
+		table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL;
+		table_clk_vlt->entries[2].v = 810;
+		table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE;
+		table_clk_vlt->entries[3].v = 900;
+		pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
+		hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
+	}
+
+	return 0;
+}
+
+int phm_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
+{
+	if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) {
+		kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
+		hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
+	}
+
+	if (NULL != hwmgr->backend) {
+		kfree(hwmgr->backend);
+		hwmgr->backend = NULL;
+	}
+
+	return 0;
+}
+
+uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask)
+{
+	uint32_t level = 0;
+
+	while (0 == (mask & (1 << level)))
+		level++;
+
+	return level;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h
new file mode 100644
index 0000000..c9e6c2d
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef PP_HWMGR_PPT_H
+#define PP_HWMGR_PPT_H
+
+#include "hardwaremanager.h"
+#include "smumgr.h"
+#include "atom-types.h"
+
+struct phm_ppt_v1_clock_voltage_dependency_record {
+	uint32_t clk;
+	uint8_t vddInd;
+	uint16_t vdd_offset;
+	uint16_t vddc;
+	uint16_t vddgfx;
+	uint16_t vddci;
+	uint16_t mvdd;
+	uint8_t phases;
+	uint8_t cks_enable;
+	uint8_t cks_voffset;
+};
+
+typedef struct phm_ppt_v1_clock_voltage_dependency_record phm_ppt_v1_clock_voltage_dependency_record;
+
+struct phm_ppt_v1_clock_voltage_dependency_table {
+	uint32_t count;                                            /* Number of entries. */
+	phm_ppt_v1_clock_voltage_dependency_record entries[1];     /* Dynamically allocate count entries. */
+};
+
+typedef struct phm_ppt_v1_clock_voltage_dependency_table phm_ppt_v1_clock_voltage_dependency_table;
+
+
+/* Multimedia Clock Voltage Dependency records and table */
+struct phm_ppt_v1_mm_clock_voltage_dependency_record {
+	uint32_t  dclk;                                              /* UVD D-clock */
+	uint32_t  vclk;                                              /* UVD V-clock */
+	uint32_t  eclk;                                              /* VCE clock */
+	uint32_t  aclk;                                              /* ACP clock */
+	uint32_t  samclock;                                          /* SAMU clock */
+	uint8_t	vddcInd;
+	uint16_t vddgfx_offset;
+	uint16_t vddc;
+	uint16_t vddgfx;
+	uint8_t phases;
+};
+typedef struct phm_ppt_v1_mm_clock_voltage_dependency_record phm_ppt_v1_mm_clock_voltage_dependency_record;
+
+struct phm_ppt_v1_mm_clock_voltage_dependency_table {
+	uint32_t count;													/* Number of entries. */
+	phm_ppt_v1_mm_clock_voltage_dependency_record entries[1];		/* Dynamically allocate count entries. */
+};
+typedef struct phm_ppt_v1_mm_clock_voltage_dependency_table phm_ppt_v1_mm_clock_voltage_dependency_table;
+
+struct phm_ppt_v1_voltage_lookup_record {
+	uint16_t us_calculated;
+	uint16_t us_vdd;												/* Base voltage */
+	uint16_t us_cac_low;
+	uint16_t us_cac_mid;
+	uint16_t us_cac_high;
+};
+typedef struct phm_ppt_v1_voltage_lookup_record phm_ppt_v1_voltage_lookup_record;
+
+struct phm_ppt_v1_voltage_lookup_table {
+	uint32_t count;
+	phm_ppt_v1_voltage_lookup_record entries[1];    /* Dynamically allocate count entries. */
+};
+typedef struct phm_ppt_v1_voltage_lookup_table phm_ppt_v1_voltage_lookup_table;
+
+/* PCIE records and Table */
+
+struct phm_ppt_v1_pcie_record {
+	uint8_t gen_speed;
+	uint8_t lane_width;
+};
+typedef struct phm_ppt_v1_pcie_record phm_ppt_v1_pcie_record;
+
+struct phm_ppt_v1_pcie_table {
+	uint32_t count;                                            /* Number of entries. */
+	phm_ppt_v1_pcie_record entries[1];                         /* Dynamically allocate count entries. */
+};
+typedef struct phm_ppt_v1_pcie_table phm_ppt_v1_pcie_table;
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c
new file mode 100644
index 0000000..7b2d500
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c
@@ -0,0 +1,76 @@
+#include <linux/errno.h>
+#include "linux/delay.h"
+#include "hwmgr.h"
+#include "amd_acpi.h"
+
+bool acpi_atcs_functions_supported(void *device, uint32_t index)
+{
+	int32_t result;
+	struct atcs_verify_interface output_buf = {0};
+
+	int32_t temp_buffer = 1;
+
+	result = cgs_call_acpi_method(device, CGS_ACPI_METHOD_ATCS,
+						ATCS_FUNCTION_VERIFY_INTERFACE,
+						&temp_buffer,
+						&output_buf,
+						1,
+						sizeof(temp_buffer),
+						sizeof(output_buf));
+
+	return result == 0 ? (output_buf.function_bits & (1 << (index - 1))) != 0 : false;
+}
+
+int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise)
+{
+	struct atcs_pref_req_input atcs_input;
+	struct atcs_pref_req_output atcs_output;
+	u32 retry = 3;
+	int result;
+	struct cgs_system_info info = {0};
+
+	if (!acpi_atcs_functions_supported(device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST))
+		return -EINVAL;
+
+	info.size = sizeof(struct cgs_system_info);
+	info.info_id = CGS_SYSTEM_INFO_ADAPTER_BDF_ID;
+	result = cgs_query_system_info(device, &info);
+	if (result != 0)
+		return -EINVAL;
+	atcs_input.client_id = (uint16_t)info.value;
+	atcs_input.size = sizeof(struct atcs_pref_req_input);
+	atcs_input.valid_flags_mask = ATCS_VALID_FLAGS_MASK;
+	atcs_input.flags = ATCS_WAIT_FOR_COMPLETION;
+	if (advertise)
+		atcs_input.flags |= ATCS_ADVERTISE_CAPS;
+	atcs_input.req_type = ATCS_PCIE_LINK_SPEED;
+	atcs_input.perf_req = perf_req;
+
+	atcs_output.size = sizeof(struct atcs_pref_req_input);
+
+	while (retry--) {
+		result = cgs_call_acpi_method(device,
+						CGS_ACPI_METHOD_ATCS,
+						ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST,
+						&atcs_input,
+						&atcs_output,
+						0,
+						sizeof(atcs_input),
+						sizeof(atcs_output));
+		if (result != 0)
+			return -EIO;
+
+		switch (atcs_output.ret_val) {
+		case ATCS_REQUEST_REFUSED:
+		default:
+			return -EINVAL;
+		case ATCS_REQUEST_COMPLETE:
+			return 0;
+		case ATCS_REQUEST_IN_PROGRESS:
+			udelay(10);
+			break;
+		}
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c
new file mode 100644
index 0000000..2a83a4a
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c
@@ -0,0 +1,1207 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+
+#include "ppatomctrl.h"
+#include "atombios.h"
+#include "cgs_common.h"
+#include "pp_debug.h"
+#include "ppevvmath.h"
+
+#define MEM_ID_MASK           0xff000000
+#define MEM_ID_SHIFT          24
+#define CLOCK_RANGE_MASK      0x00ffffff
+#define CLOCK_RANGE_SHIFT     0
+#define LOW_NIBBLE_MASK       0xf
+#define DATA_EQU_PREV         0
+#define DATA_FROM_TABLE       4
+
+union voltage_object_info {
+	struct _ATOM_VOLTAGE_OBJECT_INFO v1;
+	struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2;
+	struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1 v3;
+};
+
+static int atomctrl_retrieve_ac_timing(
+		uint8_t index,
+		ATOM_INIT_REG_BLOCK *reg_block,
+		pp_atomctrl_mc_reg_table *table)
+{
+	uint32_t i, j;
+	uint8_t tmem_id;
+	ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *)
+		((uint8_t *)reg_block + (2 * sizeof(uint16_t)) + le16_to_cpu(reg_block->usRegIndexTblSize));
+
+	uint8_t num_ranges = 0;
+
+	while (*(uint32_t *)reg_data != END_OF_REG_DATA_BLOCK &&
+			num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES) {
+		tmem_id = (uint8_t)((*(uint32_t *)reg_data & MEM_ID_MASK) >> MEM_ID_SHIFT);
+
+		if (index == tmem_id) {
+			table->mc_reg_table_entry[num_ranges].mclk_max =
+				(uint32_t)((*(uint32_t *)reg_data & CLOCK_RANGE_MASK) >>
+						CLOCK_RANGE_SHIFT);
+
+			for (i = 0, j = 1; i < table->last; i++) {
+				if ((table->mc_reg_address[i].uc_pre_reg_data &
+							LOW_NIBBLE_MASK) == DATA_FROM_TABLE) {
+					table->mc_reg_table_entry[num_ranges].mc_data[i] =
+						(uint32_t)*((uint32_t *)reg_data + j);
+					j++;
+				} else if ((table->mc_reg_address[i].uc_pre_reg_data &
+							LOW_NIBBLE_MASK) == DATA_EQU_PREV) {
+					table->mc_reg_table_entry[num_ranges].mc_data[i] =
+						table->mc_reg_table_entry[num_ranges].mc_data[i-1];
+				}
+			}
+			num_ranges++;
+		}
+
+		reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *)
+			((uint8_t *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize)) ;
+	}
+
+	PP_ASSERT_WITH_CODE((*(uint32_t *)reg_data == END_OF_REG_DATA_BLOCK),
+			"Invalid VramInfo table.", return -1);
+	table->num_entries = num_ranges;
+
+	return 0;
+}
+
+/**
+ * Get memory clock AC timing registers index from VBIOS table
+ * VBIOS set end of memory clock AC timing registers by ucPreRegDataLength bit6 = 1
+ * @param    reg_block the address ATOM_INIT_REG_BLOCK
+ * @param    table the address of MCRegTable
+ * @return   0
+ */
+static int atomctrl_set_mc_reg_address_table(
+		ATOM_INIT_REG_BLOCK *reg_block,
+		pp_atomctrl_mc_reg_table *table)
+{
+	uint8_t i = 0;
+	uint8_t num_entries = (uint8_t)((le16_to_cpu(reg_block->usRegIndexTblSize))
+			/ sizeof(ATOM_INIT_REG_INDEX_FORMAT));
+	ATOM_INIT_REG_INDEX_FORMAT *format = &reg_block->asRegIndexBuf[0];
+
+	num_entries--;        /* subtract 1 data end mark entry */
+
+	PP_ASSERT_WITH_CODE((num_entries <= VBIOS_MC_REGISTER_ARRAY_SIZE),
+			"Invalid VramInfo table.", return -1);
+
+	/* ucPreRegDataLength bit6 = 1 is the end of memory clock AC timing registers */
+	while ((!(format->ucPreRegDataLength & ACCESS_PLACEHOLDER)) &&
+			(i < num_entries)) {
+		table->mc_reg_address[i].s1 =
+			(uint16_t)(le16_to_cpu(format->usRegIndex));
+		table->mc_reg_address[i].uc_pre_reg_data =
+			format->ucPreRegDataLength;
+
+		i++;
+		format = (ATOM_INIT_REG_INDEX_FORMAT *)
+			((uint8_t *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT));
+	}
+
+	table->last = i;
+	return 0;
+}
+
+
+int atomctrl_initialize_mc_reg_table(
+		struct pp_hwmgr *hwmgr,
+		uint8_t module_index,
+		pp_atomctrl_mc_reg_table *table)
+{
+	ATOM_VRAM_INFO_HEADER_V2_1 *vram_info;
+	ATOM_INIT_REG_BLOCK *reg_block;
+	int result = 0;
+	u8 frev, crev;
+	u16 size;
+
+	vram_info = (ATOM_VRAM_INFO_HEADER_V2_1 *)
+		cgs_atom_get_data_table(hwmgr->device,
+				GetIndexIntoMasterTable(DATA, VRAM_Info), &size, &frev, &crev);
+
+	if (module_index >= vram_info->ucNumOfVRAMModule) {
+		printk(KERN_ERR "[ powerplay ] Invalid VramInfo table.");
+		result = -1;
+	} else if (vram_info->sHeader.ucTableFormatRevision < 2) {
+		printk(KERN_ERR "[ powerplay ] Invalid VramInfo table.");
+		result = -1;
+	}
+
+	if (0 == result) {
+		reg_block = (ATOM_INIT_REG_BLOCK *)
+			((uint8_t *)vram_info + le16_to_cpu(vram_info->usMemClkPatchTblOffset));
+		result = atomctrl_set_mc_reg_address_table(reg_block, table);
+	}
+
+	if (0 == result) {
+		result = atomctrl_retrieve_ac_timing(module_index,
+					reg_block, table);
+	}
+
+	return result;
+}
+
+/**
+ * Set DRAM timings based on engine clock and memory clock.
+ */
+int atomctrl_set_engine_dram_timings_rv770(
+		struct pp_hwmgr *hwmgr,
+		uint32_t engine_clock,
+		uint32_t memory_clock)
+{
+	SET_ENGINE_CLOCK_PS_ALLOCATION engine_clock_parameters;
+
+	/* They are both in 10KHz Units. */
+	engine_clock_parameters.ulTargetEngineClock =
+		(uint32_t) engine_clock & SET_CLOCK_FREQ_MASK;
+	engine_clock_parameters.ulTargetEngineClock |=
+		(COMPUTE_ENGINE_PLL_PARAM << 24);
+
+	/* in 10 khz units.*/
+	engine_clock_parameters.sReserved.ulClock =
+		(uint32_t) memory_clock & SET_CLOCK_FREQ_MASK;
+	return cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings),
+			&engine_clock_parameters);
+}
+
+/**
+ * Private Function to get the PowerPlay Table Address.
+ * WARNING: The tabled returned by this function is in
+ * dynamically allocated memory.
+ * The caller has to release if by calling kfree.
+ */
+static ATOM_VOLTAGE_OBJECT_INFO *get_voltage_info_table(void *device)
+{
+	int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
+	u8 frev, crev;
+	u16 size;
+	union voltage_object_info *voltage_info;
+
+	voltage_info = (union voltage_object_info *)
+		cgs_atom_get_data_table(device, index,
+			&size, &frev, &crev);
+
+	if (voltage_info != NULL)
+		return (ATOM_VOLTAGE_OBJECT_INFO *) &(voltage_info->v3);
+	else
+		return NULL;
+}
+
+static const ATOM_VOLTAGE_OBJECT_V3 *atomctrl_lookup_voltage_type_v3(
+		const ATOM_VOLTAGE_OBJECT_INFO_V3_1 * voltage_object_info_table,
+		uint8_t voltage_type, uint8_t voltage_mode)
+{
+	unsigned int size = le16_to_cpu(voltage_object_info_table->sHeader.usStructureSize);
+	unsigned int offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, asVoltageObj[0]);
+	uint8_t *start = (uint8_t *)voltage_object_info_table;
+
+	while (offset < size) {
+		const ATOM_VOLTAGE_OBJECT_V3 *voltage_object =
+			(const ATOM_VOLTAGE_OBJECT_V3 *)(start + offset);
+
+		if (voltage_type == voltage_object->asGpioVoltageObj.sHeader.ucVoltageType &&
+			voltage_mode == voltage_object->asGpioVoltageObj.sHeader.ucVoltageMode)
+			return voltage_object;
+
+		offset += le16_to_cpu(voltage_object->asGpioVoltageObj.sHeader.usSize);
+	}
+
+	return NULL;
+}
+
+/** atomctrl_get_memory_pll_dividers_si().
+ *
+ * @param hwmgr                 input parameter: pointer to HwMgr
+ * @param clock_value             input parameter: memory clock
+ * @param dividers                 output parameter: memory PLL dividers
+ * @param strobe_mode            input parameter: 1 for strobe mode,  0 for performance mode
+ */
+int atomctrl_get_memory_pll_dividers_si(
+		struct pp_hwmgr *hwmgr,
+		uint32_t clock_value,
+		pp_atomctrl_memory_clock_param *mpll_param,
+		bool strobe_mode)
+{
+	COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 mpll_parameters;
+	int result;
+
+	mpll_parameters.ulClock = (uint32_t) clock_value;
+	mpll_parameters.ucInputFlag = (uint8_t)((strobe_mode) ? 1 : 0);
+
+	result = cgs_atom_exec_cmd_table
+		(hwmgr->device,
+		 GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam),
+		 &mpll_parameters);
+
+	if (0 == result) {
+		mpll_param->mpll_fb_divider.clk_frac =
+			mpll_parameters.ulFbDiv.usFbDivFrac;
+		mpll_param->mpll_fb_divider.cl_kf =
+			mpll_parameters.ulFbDiv.usFbDiv;
+		mpll_param->mpll_post_divider =
+			(uint32_t)mpll_parameters.ucPostDiv;
+		mpll_param->vco_mode =
+			(uint32_t)(mpll_parameters.ucPllCntlFlag &
+					MPLL_CNTL_FLAG_VCO_MODE_MASK);
+		mpll_param->yclk_sel =
+			(uint32_t)((mpll_parameters.ucPllCntlFlag &
+						MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0);
+		mpll_param->qdr =
+			(uint32_t)((mpll_parameters.ucPllCntlFlag &
+						MPLL_CNTL_FLAG_QDR_ENABLE) ? 1 : 0);
+		mpll_param->half_rate =
+			(uint32_t)((mpll_parameters.ucPllCntlFlag &
+						MPLL_CNTL_FLAG_AD_HALF_RATE) ? 1 : 0);
+		mpll_param->dll_speed =
+			(uint32_t)(mpll_parameters.ucDllSpeed);
+		mpll_param->bw_ctrl =
+			(uint32_t)(mpll_parameters.ucBWCntl);
+	}
+
+	return result;
+}
+
+/** atomctrl_get_memory_pll_dividers_vi().
+ *
+ * @param hwmgr                 input parameter: pointer to HwMgr
+ * @param clock_value             input parameter: memory clock
+ * @param dividers               output parameter: memory PLL dividers
+ */
+int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr,
+		uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param)
+{
+	COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_2 mpll_parameters;
+	int result;
+
+	mpll_parameters.ulClock.ulClock = (uint32_t)clock_value;
+
+	result = cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam),
+			&mpll_parameters);
+
+	if (!result)
+		mpll_param->mpll_post_divider =
+				(uint32_t)mpll_parameters.ulClock.ucPostDiv;
+
+	return result;
+}
+
+int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr,
+					  uint32_t clock_value,
+					  pp_atomctrl_clock_dividers_kong *dividers)
+{
+	COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 pll_parameters;
+	int result;
+
+	pll_parameters.ulClock = clock_value;
+
+	result = cgs_atom_exec_cmd_table
+		(hwmgr->device,
+		 GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL),
+		 &pll_parameters);
+
+	if (0 == result) {
+		dividers->pll_post_divider = pll_parameters.ucPostDiv;
+		dividers->real_clock = pll_parameters.ulClock;
+	}
+
+	return result;
+}
+
+int atomctrl_get_engine_pll_dividers_vi(
+		struct pp_hwmgr *hwmgr,
+		uint32_t clock_value,
+		pp_atomctrl_clock_dividers_vi *dividers)
+{
+	COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 pll_patameters;
+	int result;
+
+	pll_patameters.ulClock.ulClock = clock_value;
+	pll_patameters.ulClock.ucPostDiv = COMPUTE_GPUCLK_INPUT_FLAG_SCLK;
+
+	result = cgs_atom_exec_cmd_table
+		(hwmgr->device,
+		 GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL),
+		 &pll_patameters);
+
+	if (0 == result) {
+		dividers->pll_post_divider =
+			pll_patameters.ulClock.ucPostDiv;
+		dividers->real_clock =
+			pll_patameters.ulClock.ulClock;
+
+		dividers->ul_fb_div.ul_fb_div_frac =
+			pll_patameters.ulFbDiv.usFbDivFrac;
+		dividers->ul_fb_div.ul_fb_div =
+			pll_patameters.ulFbDiv.usFbDiv;
+
+		dividers->uc_pll_ref_div =
+			pll_patameters.ucPllRefDiv;
+		dividers->uc_pll_post_div =
+			pll_patameters.ucPllPostDiv;
+		dividers->uc_pll_cntl_flag =
+			pll_patameters.ucPllCntlFlag;
+	}
+
+	return result;
+}
+
+int atomctrl_get_dfs_pll_dividers_vi(
+		struct pp_hwmgr *hwmgr,
+		uint32_t clock_value,
+		pp_atomctrl_clock_dividers_vi *dividers)
+{
+	COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 pll_patameters;
+	int result;
+
+	pll_patameters.ulClock.ulClock = clock_value;
+	pll_patameters.ulClock.ucPostDiv =
+		COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK;
+
+	result = cgs_atom_exec_cmd_table
+		(hwmgr->device,
+		 GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL),
+		 &pll_patameters);
+
+	if (0 == result) {
+		dividers->pll_post_divider =
+			pll_patameters.ulClock.ucPostDiv;
+		dividers->real_clock =
+			pll_patameters.ulClock.ulClock;
+
+		dividers->ul_fb_div.ul_fb_div_frac =
+			pll_patameters.ulFbDiv.usFbDivFrac;
+		dividers->ul_fb_div.ul_fb_div =
+			pll_patameters.ulFbDiv.usFbDiv;
+
+		dividers->uc_pll_ref_div =
+			pll_patameters.ucPllRefDiv;
+		dividers->uc_pll_post_div =
+			pll_patameters.ucPllPostDiv;
+		dividers->uc_pll_cntl_flag =
+			pll_patameters.ucPllCntlFlag;
+	}
+
+	return result;
+}
+
+/**
+ * Get the reference clock in 10KHz
+ */
+uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr)
+{
+	ATOM_FIRMWARE_INFO *fw_info;
+	u8 frev, crev;
+	u16 size;
+	uint32_t clock;
+
+	fw_info = (ATOM_FIRMWARE_INFO *)
+		cgs_atom_get_data_table(hwmgr->device,
+			GetIndexIntoMasterTable(DATA, FirmwareInfo),
+			&size, &frev, &crev);
+
+	if (fw_info == NULL)
+		clock = 2700;
+	else
+		clock = (uint32_t)(le16_to_cpu(fw_info->usReferenceClock));
+
+	return clock;
+}
+
+/**
+ * Returns true if the given voltage type is controlled by GPIO pins.
+ * voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC,
+ * SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ.
+ * voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE
+ */
+bool atomctrl_is_voltage_controled_by_gpio_v3(
+		struct pp_hwmgr *hwmgr,
+		uint8_t voltage_type,
+		uint8_t voltage_mode)
+{
+	ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info =
+		(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->device);
+	bool ret;
+
+	PP_ASSERT_WITH_CODE((NULL != voltage_info),
+			"Could not find Voltage Table in BIOS.", return false;);
+
+	ret = (NULL != atomctrl_lookup_voltage_type_v3
+			(voltage_info, voltage_type, voltage_mode)) ? true : false;
+
+	return ret;
+}
+
+int atomctrl_get_voltage_table_v3(
+		struct pp_hwmgr *hwmgr,
+		uint8_t voltage_type,
+		uint8_t voltage_mode,
+		pp_atomctrl_voltage_table *voltage_table)
+{
+	ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info =
+		(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->device);
+	const ATOM_VOLTAGE_OBJECT_V3 *voltage_object;
+	unsigned int i;
+
+	PP_ASSERT_WITH_CODE((NULL != voltage_info),
+			"Could not find Voltage Table in BIOS.", return -1;);
+
+	voltage_object = atomctrl_lookup_voltage_type_v3
+		(voltage_info, voltage_type, voltage_mode);
+
+	if (voltage_object == NULL)
+		return -1;
+
+	PP_ASSERT_WITH_CODE(
+			(voltage_object->asGpioVoltageObj.ucGpioEntryNum <=
+			PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES),
+			"Too many voltage entries!",
+			return -1;
+			);
+
+	for (i = 0; i < voltage_object->asGpioVoltageObj.ucGpioEntryNum; i++) {
+		voltage_table->entries[i].value =
+			voltage_object->asGpioVoltageObj.asVolGpioLut[i].usVoltageValue;
+		voltage_table->entries[i].smio_low =
+			voltage_object->asGpioVoltageObj.asVolGpioLut[i].ulVoltageId;
+	}
+
+	voltage_table->mask_low    =
+		voltage_object->asGpioVoltageObj.ulGpioMaskVal;
+	voltage_table->count      =
+		voltage_object->asGpioVoltageObj.ucGpioEntryNum;
+	voltage_table->phase_delay =
+		voltage_object->asGpioVoltageObj.ucPhaseDelay;
+
+	return 0;
+}
+
+static bool atomctrl_lookup_gpio_pin(
+		ATOM_GPIO_PIN_LUT * gpio_lookup_table,
+		const uint32_t pinId,
+		pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment)
+{
+	unsigned int size = le16_to_cpu(gpio_lookup_table->sHeader.usStructureSize);
+	unsigned int offset = offsetof(ATOM_GPIO_PIN_LUT, asGPIO_Pin[0]);
+	uint8_t *start = (uint8_t *)gpio_lookup_table;
+
+	while (offset < size) {
+		const ATOM_GPIO_PIN_ASSIGNMENT *pin_assignment =
+			(const ATOM_GPIO_PIN_ASSIGNMENT *)(start + offset);
+
+		if (pinId == pin_assignment->ucGPIO_ID) {
+			gpio_pin_assignment->uc_gpio_pin_bit_shift =
+				pin_assignment->ucGpioPinBitShift;
+			gpio_pin_assignment->us_gpio_pin_aindex =
+				le16_to_cpu(pin_assignment->usGpioPin_AIndex);
+			return false;
+		}
+
+		offset += offsetof(ATOM_GPIO_PIN_ASSIGNMENT, ucGPIO_ID) + 1;
+	}
+
+	return true;
+}
+
+/**
+ * Private Function to get the PowerPlay Table Address.
+ * WARNING: The tabled returned by this function is in
+ * dynamically allocated memory.
+ * The caller has to release if by calling kfree.
+ */
+static ATOM_GPIO_PIN_LUT *get_gpio_lookup_table(void *device)
+{
+	u8 frev, crev;
+	u16 size;
+	void *table_address;
+
+	table_address = (ATOM_GPIO_PIN_LUT *)
+		cgs_atom_get_data_table(device,
+				GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT),
+				&size, &frev, &crev);
+
+	PP_ASSERT_WITH_CODE((NULL != table_address),
+			"Error retrieving BIOS Table Address!", return NULL;);
+
+	return (ATOM_GPIO_PIN_LUT *)table_address;
+}
+
+/**
+ * Returns 1 if the given pin id find in lookup table.
+ */
+bool atomctrl_get_pp_assign_pin(
+		struct pp_hwmgr *hwmgr,
+		const uint32_t pinId,
+		pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment)
+{
+	bool bRet = 0;
+	ATOM_GPIO_PIN_LUT *gpio_lookup_table =
+		get_gpio_lookup_table(hwmgr->device);
+
+	PP_ASSERT_WITH_CODE((NULL != gpio_lookup_table),
+			"Could not find GPIO lookup Table in BIOS.", return -1);
+
+	bRet = atomctrl_lookup_gpio_pin(gpio_lookup_table, pinId,
+		gpio_pin_assignment);
+
+	return bRet;
+}
+
+int atomctrl_calculate_voltage_evv_on_sclk(
+		struct pp_hwmgr *hwmgr,
+		uint8_t voltage_type,
+		uint32_t sclk,
+		uint16_t virtual_voltage_Id,
+		uint16_t *voltage,
+		uint16_t dpm_level,
+		bool debug)
+{
+	ATOM_ASIC_PROFILING_INFO_V3_4 *getASICProfilingInfo;
+
+	EFUSE_LINEAR_FUNC_PARAM sRO_fuse;
+	EFUSE_LINEAR_FUNC_PARAM sCACm_fuse;
+	EFUSE_LINEAR_FUNC_PARAM sCACb_fuse;
+	EFUSE_LOGISTIC_FUNC_PARAM sKt_Beta_fuse;
+	EFUSE_LOGISTIC_FUNC_PARAM sKv_m_fuse;
+	EFUSE_LOGISTIC_FUNC_PARAM sKv_b_fuse;
+	EFUSE_INPUT_PARAMETER sInput_FuseValues;
+	READ_EFUSE_VALUE_PARAMETER sOutput_FuseValues;
+
+	uint32_t ul_RO_fused, ul_CACb_fused, ul_CACm_fused, ul_Kt_Beta_fused, ul_Kv_m_fused, ul_Kv_b_fused;
+	fInt fSM_A0, fSM_A1, fSM_A2, fSM_A3, fSM_A4, fSM_A5, fSM_A6, fSM_A7;
+	fInt fMargin_RO_a, fMargin_RO_b, fMargin_RO_c, fMargin_fixed, fMargin_FMAX_mean, fMargin_Plat_mean, fMargin_FMAX_sigma, fMargin_Plat_sigma, fMargin_DC_sigma;
+	fInt fLkg_FT, repeat;
+	fInt fMicro_FMAX, fMicro_CR, fSigma_FMAX, fSigma_CR, fSigma_DC, fDC_SCLK, fSquared_Sigma_DC, fSquared_Sigma_CR, fSquared_Sigma_FMAX;
+	fInt fRLL_LoadLine, fPowerDPMx, fDerateTDP, fVDDC_base, fA_Term, fC_Term, fB_Term, fRO_DC_margin;
+	fInt fRO_fused, fCACm_fused, fCACb_fused, fKv_m_fused, fKv_b_fused, fKt_Beta_fused, fFT_Lkg_V0NORM;
+	fInt fSclk_margin, fSclk, fEVV_V;
+	fInt fV_min, fV_max, fT_prod, fLKG_Factor, fT_FT, fV_FT, fV_x, fTDP_Power, fTDP_Power_right, fTDP_Power_left, fTDP_Current, fV_NL;
+	uint32_t ul_FT_Lkg_V0NORM;
+	fInt fLn_MaxDivMin, fMin, fAverage, fRange;
+	fInt fRoots[2];
+	fInt fStepSize = GetScaledFraction(625, 100000);
+
+	int result;
+
+	getASICProfilingInfo = (ATOM_ASIC_PROFILING_INFO_V3_4 *)
+			cgs_atom_get_data_table(hwmgr->device,
+					GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo),
+					NULL, NULL, NULL);
+
+	if (!getASICProfilingInfo)
+		return -1;
+
+	if(getASICProfilingInfo->asHeader.ucTableFormatRevision < 3 ||
+			(getASICProfilingInfo->asHeader.ucTableFormatRevision == 3 &&
+			getASICProfilingInfo->asHeader.ucTableContentRevision < 4))
+		return -1;
+
+	/*-----------------------------------------------------------
+	 *GETTING MULTI-STEP PARAMETERS RELATED TO CURRENT DPM LEVEL
+	 *-----------------------------------------------------------
+	 */
+	fRLL_LoadLine = Divide(getASICProfilingInfo->ulLoadLineSlop, 1000);
+
+	switch (dpm_level) {
+	case 1:
+		fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm1);
+		fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM1, 1000);
+		break;
+	case 2:
+		fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm2);
+		fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM2, 1000);
+		break;
+	case 3:
+		fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm3);
+		fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM3, 1000);
+		break;
+	case 4:
+		fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm4);
+		fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM4, 1000);
+		break;
+	case 5:
+		fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm5);
+		fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM5, 1000);
+		break;
+	case 6:
+		fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm6);
+		fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM6, 1000);
+		break;
+	case 7:
+		fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm7);
+		fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM7, 1000);
+		break;
+	default:
+		printk(KERN_ERR "DPM Level not supported\n");
+		fPowerDPMx = Convert_ULONG_ToFraction(1);
+		fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM0, 1000);
+	}
+
+	/*-------------------------
+	 * DECODING FUSE VALUES
+	 * ------------------------
+	 */
+	/*Decode RO_Fused*/
+	sRO_fuse = getASICProfilingInfo->sRoFuse;
+
+	sInput_FuseValues.usEfuseIndex = sRO_fuse.usEfuseIndex;
+	sInput_FuseValues.ucBitShift = sRO_fuse.ucEfuseBitLSB;
+	sInput_FuseValues.ucBitLength = sRO_fuse.ucEfuseLength;
+
+	sOutput_FuseValues.sEfuse = sInput_FuseValues;
+
+	result = cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, ReadEfuseValue),
+			&sOutput_FuseValues);
+
+	if (result)
+		return result;
+
+	/* Finally, the actual fuse value */
+	ul_RO_fused = sOutput_FuseValues.ulEfuseValue;
+	fMin = GetScaledFraction(sRO_fuse.ulEfuseMin, 1);
+	fRange = GetScaledFraction(sRO_fuse.ulEfuseEncodeRange, 1);
+	fRO_fused = fDecodeLinearFuse(ul_RO_fused, fMin, fRange, sRO_fuse.ucEfuseLength);
+
+	sCACm_fuse = getASICProfilingInfo->sCACm;
+
+	sInput_FuseValues.usEfuseIndex = sCACm_fuse.usEfuseIndex;
+	sInput_FuseValues.ucBitShift = sCACm_fuse.ucEfuseBitLSB;
+	sInput_FuseValues.ucBitLength = sCACm_fuse.ucEfuseLength;
+
+	sOutput_FuseValues.sEfuse = sInput_FuseValues;
+
+	result = cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, ReadEfuseValue),
+			&sOutput_FuseValues);
+
+	if (result)
+		return result;
+
+	ul_CACm_fused = sOutput_FuseValues.ulEfuseValue;
+	fMin = GetScaledFraction(sCACm_fuse.ulEfuseMin, 1000);
+	fRange = GetScaledFraction(sCACm_fuse.ulEfuseEncodeRange, 1000);
+
+	fCACm_fused = fDecodeLinearFuse(ul_CACm_fused, fMin, fRange, sCACm_fuse.ucEfuseLength);
+
+	sCACb_fuse = getASICProfilingInfo->sCACb;
+
+	sInput_FuseValues.usEfuseIndex = sCACb_fuse.usEfuseIndex;
+	sInput_FuseValues.ucBitShift = sCACb_fuse.ucEfuseBitLSB;
+	sInput_FuseValues.ucBitLength = sCACb_fuse.ucEfuseLength;
+	sOutput_FuseValues.sEfuse = sInput_FuseValues;
+
+	result = cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, ReadEfuseValue),
+			&sOutput_FuseValues);
+
+	if (result)
+		return result;
+
+	ul_CACb_fused = sOutput_FuseValues.ulEfuseValue;
+	fMin = GetScaledFraction(sCACb_fuse.ulEfuseMin, 1000);
+	fRange = GetScaledFraction(sCACb_fuse.ulEfuseEncodeRange, 1000);
+
+	fCACb_fused = fDecodeLinearFuse(ul_CACb_fused, fMin, fRange, sCACb_fuse.ucEfuseLength);
+
+	sKt_Beta_fuse = getASICProfilingInfo->sKt_b;
+
+	sInput_FuseValues.usEfuseIndex = sKt_Beta_fuse.usEfuseIndex;
+	sInput_FuseValues.ucBitShift = sKt_Beta_fuse.ucEfuseBitLSB;
+	sInput_FuseValues.ucBitLength = sKt_Beta_fuse.ucEfuseLength;
+
+	sOutput_FuseValues.sEfuse = sInput_FuseValues;
+
+	result = cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, ReadEfuseValue),
+			&sOutput_FuseValues);
+
+	if (result)
+		return result;
+
+	ul_Kt_Beta_fused = sOutput_FuseValues.ulEfuseValue;
+	fAverage = GetScaledFraction(sKt_Beta_fuse.ulEfuseEncodeAverage, 1000);
+	fRange = GetScaledFraction(sKt_Beta_fuse.ulEfuseEncodeRange, 1000);
+
+	fKt_Beta_fused = fDecodeLogisticFuse(ul_Kt_Beta_fused,
+			fAverage, fRange, sKt_Beta_fuse.ucEfuseLength);
+
+	sKv_m_fuse = getASICProfilingInfo->sKv_m;
+
+	sInput_FuseValues.usEfuseIndex = sKv_m_fuse.usEfuseIndex;
+	sInput_FuseValues.ucBitShift = sKv_m_fuse.ucEfuseBitLSB;
+	sInput_FuseValues.ucBitLength = sKv_m_fuse.ucEfuseLength;
+
+	sOutput_FuseValues.sEfuse = sInput_FuseValues;
+
+	result = cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, ReadEfuseValue),
+			&sOutput_FuseValues);
+	if (result)
+		return result;
+
+	ul_Kv_m_fused = sOutput_FuseValues.ulEfuseValue;
+	fAverage = GetScaledFraction(sKv_m_fuse.ulEfuseEncodeAverage, 1000);
+	fRange = GetScaledFraction((sKv_m_fuse.ulEfuseEncodeRange & 0x7fffffff), 1000);
+	fRange = fMultiply(fRange, ConvertToFraction(-1));
+
+	fKv_m_fused = fDecodeLogisticFuse(ul_Kv_m_fused,
+			fAverage, fRange, sKv_m_fuse.ucEfuseLength);
+
+	sKv_b_fuse = getASICProfilingInfo->sKv_b;
+
+	sInput_FuseValues.usEfuseIndex = sKv_b_fuse.usEfuseIndex;
+	sInput_FuseValues.ucBitShift = sKv_b_fuse.ucEfuseBitLSB;
+	sInput_FuseValues.ucBitLength = sKv_b_fuse.ucEfuseLength;
+	sOutput_FuseValues.sEfuse = sInput_FuseValues;
+
+	result = cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, ReadEfuseValue),
+			&sOutput_FuseValues);
+
+	if (result)
+		return result;
+
+	ul_Kv_b_fused = sOutput_FuseValues.ulEfuseValue;
+	fAverage = GetScaledFraction(sKv_b_fuse.ulEfuseEncodeAverage, 1000);
+	fRange = GetScaledFraction(sKv_b_fuse.ulEfuseEncodeRange, 1000);
+
+	fKv_b_fused = fDecodeLogisticFuse(ul_Kv_b_fused,
+			fAverage, fRange, sKv_b_fuse.ucEfuseLength);
+
+	/* Decoding the Leakage - No special struct container */
+	/*
+	 * usLkgEuseIndex=56
+	 * ucLkgEfuseBitLSB=6
+	 * ucLkgEfuseLength=10
+	 * ulLkgEncodeLn_MaxDivMin=69077
+	 * ulLkgEncodeMax=1000000
+	 * ulLkgEncodeMin=1000
+	 * ulEfuseLogisticAlpha=13
+	 */
+
+	sInput_FuseValues.usEfuseIndex = getASICProfilingInfo->usLkgEuseIndex;
+	sInput_FuseValues.ucBitShift = getASICProfilingInfo->ucLkgEfuseBitLSB;
+	sInput_FuseValues.ucBitLength = getASICProfilingInfo->ucLkgEfuseLength;
+
+	sOutput_FuseValues.sEfuse = sInput_FuseValues;
+
+	result = cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, ReadEfuseValue),
+			&sOutput_FuseValues);
+
+	if (result)
+		return result;
+
+	ul_FT_Lkg_V0NORM = sOutput_FuseValues.ulEfuseValue;
+	fLn_MaxDivMin = GetScaledFraction(getASICProfilingInfo->ulLkgEncodeLn_MaxDivMin, 10000);
+	fMin = GetScaledFraction(getASICProfilingInfo->ulLkgEncodeMin, 10000);
+
+	fFT_Lkg_V0NORM = fDecodeLeakageID(ul_FT_Lkg_V0NORM,
+			fLn_MaxDivMin, fMin, getASICProfilingInfo->ucLkgEfuseLength);
+	fLkg_FT = fFT_Lkg_V0NORM;
+
+	/*-------------------------------------------
+	 * PART 2 - Grabbing all required values
+	 *-------------------------------------------
+	 */
+	fSM_A0 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A0, 1000000),
+			ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A0_sign)));
+	fSM_A1 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A1, 1000000),
+			ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A1_sign)));
+	fSM_A2 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A2, 100000),
+			ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A2_sign)));
+	fSM_A3 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A3, 1000000),
+			ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A3_sign)));
+	fSM_A4 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A4, 1000000),
+			ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A4_sign)));
+	fSM_A5 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A5, 1000),
+			ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A5_sign)));
+	fSM_A6 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A6, 1000),
+			ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A6_sign)));
+	fSM_A7 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A7, 1000),
+			ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A7_sign)));
+
+	fMargin_RO_a = ConvertToFraction(getASICProfilingInfo->ulMargin_RO_a);
+	fMargin_RO_b = ConvertToFraction(getASICProfilingInfo->ulMargin_RO_b);
+	fMargin_RO_c = ConvertToFraction(getASICProfilingInfo->ulMargin_RO_c);
+
+	fMargin_fixed = ConvertToFraction(getASICProfilingInfo->ulMargin_fixed);
+
+	fMargin_FMAX_mean = GetScaledFraction(
+			getASICProfilingInfo->ulMargin_Fmax_mean, 10000);
+	fMargin_Plat_mean = GetScaledFraction(
+			getASICProfilingInfo->ulMargin_plat_mean, 10000);
+	fMargin_FMAX_sigma = GetScaledFraction(
+			getASICProfilingInfo->ulMargin_Fmax_sigma, 10000);
+	fMargin_Plat_sigma = GetScaledFraction(
+			getASICProfilingInfo->ulMargin_plat_sigma, 10000);
+
+	fMargin_DC_sigma = GetScaledFraction(
+			getASICProfilingInfo->ulMargin_DC_sigma, 100);
+	fMargin_DC_sigma = fDivide(fMargin_DC_sigma, ConvertToFraction(1000));
+
+	fCACm_fused = fDivide(fCACm_fused, ConvertToFraction(100));
+	fCACb_fused = fDivide(fCACb_fused, ConvertToFraction(100));
+	fKt_Beta_fused = fDivide(fKt_Beta_fused, ConvertToFraction(100));
+	fKv_m_fused =  fNegate(fDivide(fKv_m_fused, ConvertToFraction(100)));
+	fKv_b_fused = fDivide(fKv_b_fused, ConvertToFraction(10));
+
+	fSclk = GetScaledFraction(sclk, 100);
+
+	fV_max = fDivide(GetScaledFraction(
+			getASICProfilingInfo->ulMaxVddc, 1000), ConvertToFraction(4));
+	fT_prod = GetScaledFraction(getASICProfilingInfo->ulBoardCoreTemp, 10);
+	fLKG_Factor = GetScaledFraction(getASICProfilingInfo->ulEvvLkgFactor, 100);
+	fT_FT = GetScaledFraction(getASICProfilingInfo->ulLeakageTemp, 10);
+	fV_FT = fDivide(GetScaledFraction(
+			getASICProfilingInfo->ulLeakageVoltage, 1000), ConvertToFraction(4));
+	fV_min = fDivide(GetScaledFraction(
+			getASICProfilingInfo->ulMinVddc, 1000), ConvertToFraction(4));
+
+	/*-----------------------
+	 * PART 3
+	 *-----------------------
+	 */
+
+	fA_Term = fAdd(fMargin_RO_a, fAdd(fMultiply(fSM_A4,fSclk), fSM_A5));
+	fB_Term = fAdd(fAdd(fMultiply(fSM_A2, fSclk), fSM_A6), fMargin_RO_b);
+	fC_Term = fAdd(fMargin_RO_c,
+			fAdd(fMultiply(fSM_A0,fLkg_FT),
+			fAdd(fMultiply(fSM_A1, fMultiply(fLkg_FT,fSclk)),
+			fAdd(fMultiply(fSM_A3, fSclk),
+			fSubtract(fSM_A7,fRO_fused)))));
+
+	fVDDC_base = fSubtract(fRO_fused,
+			fSubtract(fMargin_RO_c,
+					fSubtract(fSM_A3, fMultiply(fSM_A1, fSclk))));
+	fVDDC_base = fDivide(fVDDC_base, fAdd(fMultiply(fSM_A0,fSclk), fSM_A2));
+
+	repeat = fSubtract(fVDDC_base,
+			fDivide(fMargin_DC_sigma, ConvertToFraction(1000)));
+
+	fRO_DC_margin = fAdd(fMultiply(fMargin_RO_a,
+			fGetSquare(repeat)),
+			fAdd(fMultiply(fMargin_RO_b, repeat),
+			fMargin_RO_c));
+
+	fDC_SCLK = fSubtract(fRO_fused,
+			fSubtract(fRO_DC_margin,
+			fSubtract(fSM_A3,
+			fMultiply(fSM_A2, repeat))));
+	fDC_SCLK = fDivide(fDC_SCLK, fAdd(fMultiply(fSM_A0,repeat), fSM_A1));
+
+	fSigma_DC = fSubtract(fSclk, fDC_SCLK);
+
+	fMicro_FMAX = fMultiply(fSclk, fMargin_FMAX_mean);
+	fMicro_CR = fMultiply(fSclk, fMargin_Plat_mean);
+	fSigma_FMAX = fMultiply(fSclk, fMargin_FMAX_sigma);
+	fSigma_CR = fMultiply(fSclk, fMargin_Plat_sigma);
+
+	fSquared_Sigma_DC = fGetSquare(fSigma_DC);
+	fSquared_Sigma_CR = fGetSquare(fSigma_CR);
+	fSquared_Sigma_FMAX = fGetSquare(fSigma_FMAX);
+
+	fSclk_margin = fAdd(fMicro_FMAX,
+			fAdd(fMicro_CR,
+			fAdd(fMargin_fixed,
+			fSqrt(fAdd(fSquared_Sigma_FMAX,
+			fAdd(fSquared_Sigma_DC, fSquared_Sigma_CR))))));
+	/*
+	 fA_Term = fSM_A4 * (fSclk + fSclk_margin) + fSM_A5;
+	 fB_Term = fSM_A2 * (fSclk + fSclk_margin) + fSM_A6;
+	 fC_Term = fRO_DC_margin + fSM_A0 * fLkg_FT + fSM_A1 * fLkg_FT * (fSclk + fSclk_margin) + fSM_A3 * (fSclk + fSclk_margin) + fSM_A7 - fRO_fused;
+	 */
+
+	fA_Term = fAdd(fMultiply(fSM_A4, fAdd(fSclk, fSclk_margin)), fSM_A5);
+	fB_Term = fAdd(fMultiply(fSM_A2, fAdd(fSclk, fSclk_margin)), fSM_A6);
+	fC_Term = fAdd(fRO_DC_margin,
+			fAdd(fMultiply(fSM_A0, fLkg_FT),
+			fAdd(fMultiply(fMultiply(fSM_A1, fLkg_FT),
+			fAdd(fSclk, fSclk_margin)),
+			fAdd(fMultiply(fSM_A3,
+			fAdd(fSclk, fSclk_margin)),
+			fSubtract(fSM_A7, fRO_fused)))));
+
+	SolveQuadracticEqn(fA_Term, fB_Term, fC_Term, fRoots);
+
+	if (GreaterThan(fRoots[0], fRoots[1]))
+		fEVV_V = fRoots[1];
+	else
+		fEVV_V = fRoots[0];
+
+	if (GreaterThan(fV_min, fEVV_V))
+		fEVV_V = fV_min;
+	else if (GreaterThan(fEVV_V, fV_max))
+		fEVV_V = fSubtract(fV_max, fStepSize);
+
+	fEVV_V = fRoundUpByStepSize(fEVV_V, fStepSize, 0);
+
+	/*-----------------
+	 * PART 4
+	 *-----------------
+	 */
+
+	fV_x = fV_min;
+
+	while (GreaterThan(fAdd(fV_max, fStepSize), fV_x)) {
+		fTDP_Power_left = fMultiply(fMultiply(fMultiply(fAdd(
+				fMultiply(fCACm_fused, fV_x), fCACb_fused), fSclk),
+				fGetSquare(fV_x)), fDerateTDP);
+
+		fTDP_Power_right = fMultiply(fFT_Lkg_V0NORM, fMultiply(fLKG_Factor,
+				fMultiply(fExponential(fMultiply(fAdd(fMultiply(fKv_m_fused,
+				fT_prod), fKv_b_fused), fV_x)), fV_x)));
+		fTDP_Power_right = fMultiply(fTDP_Power_right, fExponential(fMultiply(
+				fKt_Beta_fused, fT_prod)));
+		fTDP_Power_right = fDivide(fTDP_Power_right, fExponential(fMultiply(
+				fAdd(fMultiply(fKv_m_fused, fT_prod), fKv_b_fused), fV_FT)));
+		fTDP_Power_right = fDivide(fTDP_Power_right, fExponential(fMultiply(
+				fKt_Beta_fused, fT_FT)));
+
+		fTDP_Power = fAdd(fTDP_Power_left, fTDP_Power_right);
+
+		fTDP_Current = fDivide(fTDP_Power, fV_x);
+
+		fV_NL = fAdd(fV_x, fDivide(fMultiply(fTDP_Current, fRLL_LoadLine),
+				ConvertToFraction(10)));
+
+		fV_NL = fRoundUpByStepSize(fV_NL, fStepSize, 0);
+
+		if (GreaterThan(fV_max, fV_NL) &&
+			(GreaterThan(fV_NL,fEVV_V) ||
+			Equal(fV_NL, fEVV_V))) {
+			fV_NL = fMultiply(fV_NL, ConvertToFraction(1000));
+
+			*voltage = (uint16_t)fV_NL.partial.real;
+			break;
+		} else
+			fV_x = fAdd(fV_x, fStepSize);
+	}
+
+	return result;
+}
+
+/** atomctrl_get_voltage_evv_on_sclk gets voltage via call to ATOM COMMAND table.
+ * @param hwmgr               	input: pointer to hwManager
+ * @param voltage_type            input: type of EVV voltage VDDC or VDDGFX
+ * @param sclk                        input: in 10Khz unit. DPM state SCLK frequency
+ *                                   		which is define in PPTable SCLK/VDDC dependence
+ *				table associated with this virtual_voltage_Id
+ * @param virtual_voltage_Id      input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08
+ * @param voltage		       output: real voltage level in unit of mv
+ */
+int atomctrl_get_voltage_evv_on_sclk(
+		struct pp_hwmgr *hwmgr,
+		uint8_t voltage_type,
+		uint32_t sclk, uint16_t virtual_voltage_Id,
+		uint16_t *voltage)
+{
+	int result;
+	GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 get_voltage_info_param_space;
+
+	get_voltage_info_param_space.ucVoltageType   =
+		voltage_type;
+	get_voltage_info_param_space.ucVoltageMode   =
+		ATOM_GET_VOLTAGE_EVV_VOLTAGE;
+	get_voltage_info_param_space.usVoltageLevel  =
+		virtual_voltage_Id;
+	get_voltage_info_param_space.ulSCLKFreq      =
+		sclk;
+
+	result = cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, GetVoltageInfo),
+			&get_voltage_info_param_space);
+
+	if (0 != result)
+		return result;
+
+	*voltage = ((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 *)
+			(&get_voltage_info_param_space))->usVoltageLevel;
+
+	return result;
+}
+
+/**
+ * Get the mpll reference clock in 10KHz
+ */
+uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr)
+{
+	ATOM_COMMON_TABLE_HEADER *fw_info;
+	uint32_t clock;
+	u8 frev, crev;
+	u16 size;
+
+	fw_info = (ATOM_COMMON_TABLE_HEADER *)
+		cgs_atom_get_data_table(hwmgr->device,
+				GetIndexIntoMasterTable(DATA, FirmwareInfo),
+				&size, &frev, &crev);
+
+	if (fw_info == NULL)
+		clock = 2700;
+	else {
+		if ((fw_info->ucTableFormatRevision == 2) &&
+			(le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1))) {
+			ATOM_FIRMWARE_INFO_V2_1 *fwInfo_2_1 =
+				(ATOM_FIRMWARE_INFO_V2_1 *)fw_info;
+			clock = (uint32_t)(le16_to_cpu(fwInfo_2_1->usMemoryReferenceClock));
+		} else {
+			ATOM_FIRMWARE_INFO *fwInfo_0_0 =
+				(ATOM_FIRMWARE_INFO *)fw_info;
+			clock = (uint32_t)(le16_to_cpu(fwInfo_0_0->usReferenceClock));
+		}
+	}
+
+	return clock;
+}
+
+/**
+ * Get the asic internal spread spectrum table
+ */
+static ATOM_ASIC_INTERNAL_SS_INFO *asic_internal_ss_get_ss_table(void *device)
+{
+	ATOM_ASIC_INTERNAL_SS_INFO *table = NULL;
+	u8 frev, crev;
+	u16 size;
+
+	table = (ATOM_ASIC_INTERNAL_SS_INFO *)
+		cgs_atom_get_data_table(device,
+			GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info),
+			&size, &frev, &crev);
+
+	return table;
+}
+
+/**
+ * Get the asic internal spread spectrum assignment
+ */
+static int asic_internal_ss_get_ss_asignment(struct pp_hwmgr *hwmgr,
+		const uint8_t clockSource,
+		const uint32_t clockSpeed,
+		pp_atomctrl_internal_ss_info *ssEntry)
+{
+	ATOM_ASIC_INTERNAL_SS_INFO *table;
+	ATOM_ASIC_SS_ASSIGNMENT *ssInfo;
+	int entry_found = 0;
+
+	memset(ssEntry, 0x00, sizeof(pp_atomctrl_internal_ss_info));
+
+	table = asic_internal_ss_get_ss_table(hwmgr->device);
+
+	if (NULL == table)
+		return -1;
+
+	ssInfo = &table->asSpreadSpectrum[0];
+
+	while (((uint8_t *)ssInfo - (uint8_t *)table) <
+		le16_to_cpu(table->sHeader.usStructureSize)) {
+		if ((clockSource == ssInfo->ucClockIndication) &&
+			((uint32_t)clockSpeed <= le32_to_cpu(ssInfo->ulTargetClockRange))) {
+			entry_found = 1;
+			break;
+		}
+
+		ssInfo = (ATOM_ASIC_SS_ASSIGNMENT *)((uint8_t *)ssInfo +
+				sizeof(ATOM_ASIC_SS_ASSIGNMENT));
+	}
+
+	if (entry_found) {
+		ssEntry->speed_spectrum_percentage =
+			ssInfo->usSpreadSpectrumPercentage;
+		ssEntry->speed_spectrum_rate = ssInfo->usSpreadRateInKhz;
+
+		if (((GET_DATA_TABLE_MAJOR_REVISION(table) == 2) &&
+			(GET_DATA_TABLE_MINOR_REVISION(table) >= 2)) ||
+			(GET_DATA_TABLE_MAJOR_REVISION(table) == 3)) {
+			ssEntry->speed_spectrum_rate /= 100;
+		}
+
+		switch (ssInfo->ucSpreadSpectrumMode) {
+		case 0:
+			ssEntry->speed_spectrum_mode =
+				pp_atomctrl_spread_spectrum_mode_down;
+			break;
+		case 1:
+			ssEntry->speed_spectrum_mode =
+				pp_atomctrl_spread_spectrum_mode_center;
+			break;
+		default:
+			ssEntry->speed_spectrum_mode =
+				pp_atomctrl_spread_spectrum_mode_down;
+			break;
+		}
+	}
+
+	return entry_found ? 0 : 1;
+}
+
+/**
+ * Get the memory clock spread spectrum info
+ */
+int atomctrl_get_memory_clock_spread_spectrum(
+		struct pp_hwmgr *hwmgr,
+		const uint32_t memory_clock,
+		pp_atomctrl_internal_ss_info *ssInfo)
+{
+	return asic_internal_ss_get_ss_asignment(hwmgr,
+			ASIC_INTERNAL_MEMORY_SS, memory_clock, ssInfo);
+}
+/**
+ * Get the engine clock spread spectrum info
+ */
+int atomctrl_get_engine_clock_spread_spectrum(
+		struct pp_hwmgr *hwmgr,
+		const uint32_t engine_clock,
+		pp_atomctrl_internal_ss_info *ssInfo)
+{
+	return asic_internal_ss_get_ss_asignment(hwmgr,
+			ASIC_INTERNAL_ENGINE_SS, engine_clock, ssInfo);
+}
+
+int atomctrl_read_efuse(void *device, uint16_t start_index,
+		uint16_t end_index, uint32_t mask, uint32_t *efuse)
+{
+	int result;
+	READ_EFUSE_VALUE_PARAMETER efuse_param;
+
+	efuse_param.sEfuse.usEfuseIndex = (start_index / 32) * 4;
+	efuse_param.sEfuse.ucBitShift = (uint8_t)
+			(start_index - ((start_index / 32) * 32));
+	efuse_param.sEfuse.ucBitLength  = (uint8_t)
+			((end_index - start_index) + 1);
+
+	result = cgs_atom_exec_cmd_table(device,
+			GetIndexIntoMasterTable(COMMAND, ReadEfuseValue),
+			&efuse_param);
+	if (!result)
+		*efuse = efuse_param.ulEfuseValue & mask;
+
+	return result;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h
new file mode 100644
index 0000000..627420b
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef PP_ATOMVOLTAGECTRL_H
+#define PP_ATOMVOLTAGECTRL_H
+
+#include "hwmgr.h"
+
+#define MEM_TYPE_GDDR5  0x50
+#define MEM_TYPE_GDDR4  0x40
+#define MEM_TYPE_GDDR3  0x30
+#define MEM_TYPE_DDR2   0x20
+#define MEM_TYPE_GDDR1  0x10
+#define MEM_TYPE_DDR3   0xb0
+#define MEM_TYPE_MASK   0xF0
+
+
+/* As returned from PowerConnectorDetectionTable. */
+#define PP_ATOM_POWER_BUDGET_DISABLE_OVERDRIVE  0x80
+#define PP_ATOM_POWER_BUDGET_SHOW_WARNING       0x40
+#define PP_ATOM_POWER_BUDGET_SHOW_WAIVER        0x20
+#define PP_ATOM_POWER_POWER_BUDGET_BEHAVIOUR    0x0F
+
+/* New functions for Evergreen and beyond. */
+#define PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES 32
+
+struct pp_atomctrl_clock_dividers {
+	uint32_t pll_post_divider;
+	uint32_t pll_feedback_divider;
+	uint32_t pll_ref_divider;
+	bool  enable_post_divider;
+};
+
+typedef struct pp_atomctrl_clock_dividers pp_atomctrl_clock_dividers;
+
+union pp_atomctrl_tcipll_fb_divider {
+	struct {
+		uint32_t ul_fb_div_frac : 14;
+		uint32_t ul_fb_div : 12;
+		uint32_t un_used : 6;
+	};
+	uint32_t ul_fb_divider;
+};
+
+typedef union pp_atomctrl_tcipll_fb_divider pp_atomctrl_tcipll_fb_divider;
+
+struct pp_atomctrl_clock_dividers_rv730 {
+	uint32_t pll_post_divider;
+	pp_atomctrl_tcipll_fb_divider mpll_feedback_divider;
+	uint32_t pll_ref_divider;
+	bool  enable_post_divider;
+	bool  enable_dithen;
+	uint32_t vco_mode;
+};
+typedef struct pp_atomctrl_clock_dividers_rv730 pp_atomctrl_clock_dividers_rv730;
+
+
+struct pp_atomctrl_clock_dividers_kong {
+	uint32_t    pll_post_divider;
+	uint32_t    real_clock;
+};
+typedef struct pp_atomctrl_clock_dividers_kong pp_atomctrl_clock_dividers_kong;
+
+struct pp_atomctrl_clock_dividers_ci {
+	uint32_t    pll_post_divider;               /* post divider value */
+	uint32_t    real_clock;
+	pp_atomctrl_tcipll_fb_divider   ul_fb_div;         /* Output Parameter: PLL FB divider */
+	uint8_t   uc_pll_ref_div;                      /* Output Parameter: PLL ref divider */
+	uint8_t   uc_pll_post_div;                      /* Output Parameter: PLL post divider */
+	uint8_t   uc_pll_cntl_flag;                    /*Output Flags: control flag */
+};
+typedef struct pp_atomctrl_clock_dividers_ci pp_atomctrl_clock_dividers_ci;
+
+struct pp_atomctrl_clock_dividers_vi {
+	uint32_t    pll_post_divider;               /* post divider value */
+	uint32_t    real_clock;
+	pp_atomctrl_tcipll_fb_divider   ul_fb_div;         /*Output Parameter: PLL FB divider */
+	uint8_t   uc_pll_ref_div;                      /*Output Parameter: PLL ref divider */
+	uint8_t   uc_pll_post_div;                     /*Output Parameter: PLL post divider */
+	uint8_t   uc_pll_cntl_flag;                    /*Output Flags: control flag */
+};
+typedef struct pp_atomctrl_clock_dividers_vi pp_atomctrl_clock_dividers_vi;
+
+union pp_atomctrl_s_mpll_fb_divider {
+	struct {
+		uint32_t cl_kf : 12;
+		uint32_t clk_frac : 12;
+		uint32_t un_used : 8;
+	};
+	uint32_t ul_fb_divider;
+};
+typedef union pp_atomctrl_s_mpll_fb_divider pp_atomctrl_s_mpll_fb_divider;
+
+enum pp_atomctrl_spread_spectrum_mode {
+	pp_atomctrl_spread_spectrum_mode_down = 0,
+	pp_atomctrl_spread_spectrum_mode_center
+};
+typedef enum pp_atomctrl_spread_spectrum_mode pp_atomctrl_spread_spectrum_mode;
+
+struct pp_atomctrl_memory_clock_param {
+	pp_atomctrl_s_mpll_fb_divider mpll_fb_divider;
+	uint32_t mpll_post_divider;
+	uint32_t bw_ctrl;
+	uint32_t dll_speed;
+	uint32_t vco_mode;
+	uint32_t yclk_sel;
+	uint32_t qdr;
+	uint32_t half_rate;
+};
+typedef struct pp_atomctrl_memory_clock_param pp_atomctrl_memory_clock_param;
+
+struct pp_atomctrl_internal_ss_info {
+	uint32_t speed_spectrum_percentage;                      /* in 1/100 percentage */
+	uint32_t speed_spectrum_rate;                            /* in KHz */
+	pp_atomctrl_spread_spectrum_mode speed_spectrum_mode;
+};
+typedef struct pp_atomctrl_internal_ss_info pp_atomctrl_internal_ss_info;
+
+#ifndef NUMBER_OF_M3ARB_PARAMS
+#define NUMBER_OF_M3ARB_PARAMS 3
+#endif
+
+#ifndef NUMBER_OF_M3ARB_PARAM_SETS
+#define NUMBER_OF_M3ARB_PARAM_SETS 10
+#endif
+
+struct pp_atomctrl_kong_system_info {
+	uint32_t			ul_bootup_uma_clock;          /* in 10kHz unit */
+	uint16_t			us_max_nb_voltage;            /* high NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; */
+	uint16_t			us_min_nb_voltage;            /* low NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; */
+	uint16_t			us_bootup_nb_voltage;         /* boot up NB voltage */
+	uint8_t			uc_htc_tmp_lmt;               /* bit [22:16] of D24F3x64 Hardware Thermal Control (HTC) Register, may not be needed, TBD */
+	uint8_t			uc_tj_offset;                /* bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed, TBD */
+	/* 0: default 1: uvd 2: fs-3d */
+	uint32_t          ul_csr_m3_srb_cntl[NUMBER_OF_M3ARB_PARAM_SETS][NUMBER_OF_M3ARB_PARAMS];/* arrays with values for CSR M3 arbiter for default */
+};
+typedef struct pp_atomctrl_kong_system_info pp_atomctrl_kong_system_info;
+
+struct pp_atomctrl_memory_info {
+	uint8_t memory_vendor;
+	uint8_t memory_type;
+};
+typedef struct pp_atomctrl_memory_info pp_atomctrl_memory_info;
+
+#define MAX_AC_TIMING_ENTRIES 16
+
+struct pp_atomctrl_memory_clock_range_table {
+	uint8_t   num_entries;
+	uint8_t   rsv[3];
+
+	uint32_t mclk[MAX_AC_TIMING_ENTRIES];
+};
+typedef struct pp_atomctrl_memory_clock_range_table pp_atomctrl_memory_clock_range_table;
+
+struct pp_atomctrl_voltage_table_entry {
+	uint16_t value;
+	uint32_t smio_low;
+};
+
+typedef struct pp_atomctrl_voltage_table_entry pp_atomctrl_voltage_table_entry;
+
+struct pp_atomctrl_voltage_table {
+	uint32_t count;
+	uint32_t mask_low;
+	uint32_t phase_delay;   /* Used for ATOM_GPIO_VOLTAGE_OBJECT_V3 and later */
+	pp_atomctrl_voltage_table_entry entries[PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES];
+};
+
+typedef struct pp_atomctrl_voltage_table pp_atomctrl_voltage_table;
+
+#define VBIOS_MC_REGISTER_ARRAY_SIZE           32
+#define VBIOS_MAX_AC_TIMING_ENTRIES            20
+
+struct pp_atomctrl_mc_reg_entry {
+	uint32_t           mclk_max;
+	uint32_t mc_data[VBIOS_MC_REGISTER_ARRAY_SIZE];
+};
+typedef struct pp_atomctrl_mc_reg_entry pp_atomctrl_mc_reg_entry;
+
+struct pp_atomctrl_mc_register_address {
+	uint16_t s1;
+	uint8_t  uc_pre_reg_data;
+};
+
+typedef struct pp_atomctrl_mc_register_address pp_atomctrl_mc_register_address;
+
+struct pp_atomctrl_mc_reg_table {
+	uint8_t                         last;                    /* number of registers */
+	uint8_t                         num_entries;             /* number of AC timing entries */
+	pp_atomctrl_mc_reg_entry        mc_reg_table_entry[VBIOS_MAX_AC_TIMING_ENTRIES];
+	pp_atomctrl_mc_register_address mc_reg_address[VBIOS_MC_REGISTER_ARRAY_SIZE];
+};
+typedef struct pp_atomctrl_mc_reg_table pp_atomctrl_mc_reg_table;
+
+struct pp_atomctrl_gpio_pin_assignment {
+	uint16_t                   us_gpio_pin_aindex;
+	uint8_t                    uc_gpio_pin_bit_shift;
+};
+typedef struct pp_atomctrl_gpio_pin_assignment pp_atomctrl_gpio_pin_assignment;
+
+extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment);
+extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage);
+extern uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr);
+extern int atomctrl_get_memory_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t memory_clock, pp_atomctrl_internal_ss_info *ssInfo);
+extern int atomctrl_get_engine_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t engine_clock, pp_atomctrl_internal_ss_info *ssInfo);
+extern int atomctrl_initialize_mc_reg_table(struct pp_hwmgr *hwmgr, uint8_t module_index, pp_atomctrl_mc_reg_table *table);
+extern int atomctrl_set_engine_dram_timings_rv770(struct pp_hwmgr *hwmgr, uint32_t engine_clock, uint32_t memory_clock);
+extern uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr);
+extern int atomctrl_get_memory_pll_dividers_si(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param, bool strobe_mode);
+extern int atomctrl_get_engine_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers);
+extern int atomctrl_get_dfs_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers);
+extern bool atomctrl_is_voltage_controled_by_gpio_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode);
+extern int atomctrl_get_voltage_table_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode, pp_atomctrl_voltage_table *voltage_table);
+extern int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr,
+		uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param);
+extern int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr,
+						 uint32_t clock_value,
+						 pp_atomctrl_clock_dividers_kong *dividers);
+extern int atomctrl_read_efuse(void *device, uint16_t start_index,
+		uint16_t end_index, uint32_t mask, uint32_t *efuse);
+extern int atomctrl_calculate_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
+		uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage, uint16_t dpm_level, bool debug);
+
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h
new file mode 100644
index 0000000..b7429a5
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h
@@ -0,0 +1,612 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <asm/div64.h>
+
+#define SHIFT_AMOUNT 16 /* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */
+
+#define PRECISION 5 /* Change this value to change the number of decimal places in the final output - 5 is a good default */
+
+#define SHIFTED_2 (2 << SHIFT_AMOUNT)
+#define MAX (1 << (SHIFT_AMOUNT - 1)) - 1 /* 32767 - Might change in the future */
+
+/* -------------------------------------------------------------------------------
+ * NEW TYPE - fINT
+ * -------------------------------------------------------------------------------
+ * A variable of type fInt can be accessed in 3 ways using the dot (.) operator
+ * fInt A;
+ * A.full => The full number as it is. Generally not easy to read
+ * A.partial.real => Only the integer portion
+ * A.partial.decimal => Only the fractional portion
+ */
+typedef union _fInt {
+    int full;
+    struct _partial {
+        unsigned int decimal: SHIFT_AMOUNT; /*Needs to always be unsigned*/
+        int real: 32 - SHIFT_AMOUNT;
+    } partial;
+} fInt;
+
+/* -------------------------------------------------------------------------------
+ * Function Declarations
+ *  -------------------------------------------------------------------------------
+ */
+fInt ConvertToFraction(int);                       /* Use this to convert an INT to a FINT */
+fInt Convert_ULONG_ToFraction(uint32_t);              /* Use this to convert an uint32_t to a FINT */
+fInt GetScaledFraction(int, int);                  /* Use this to convert an INT to a FINT after scaling it by a factor */
+int ConvertBackToInteger(fInt);                    /* Convert a FINT back to an INT that is scaled by 1000 (i.e. last 3 digits are the decimal digits) */
+
+fInt fNegate(fInt);                                /* Returns -1 * input fInt value */
+fInt fAdd (fInt, fInt);                            /* Returns the sum of two fInt numbers */
+fInt fSubtract (fInt A, fInt B);                   /* Returns A-B - Sometimes easier than Adding negative numbers */
+fInt fMultiply (fInt, fInt);                       /* Returns the product of two fInt numbers */
+fInt fDivide (fInt A, fInt B);                     /* Returns A/B */
+fInt fGetSquare(fInt);                             /* Returns the square of a fInt number */
+fInt fSqrt(fInt);                                  /* Returns the Square Root of a fInt number */
+
+int uAbs(int);                                     /* Returns the Absolute value of the Int */
+fInt fAbs(fInt);                                   /* Returns the Absolute value of the fInt */
+int uPow(int base, int exponent);                  /* Returns base^exponent an INT */
+
+void SolveQuadracticEqn(fInt, fInt, fInt, fInt[]); /* Returns the 2 roots via the array */
+bool Equal(fInt, fInt);                         /* Returns true if two fInts are equal to each other */
+bool GreaterThan(fInt A, fInt B);               /* Returns true if A > B */
+
+fInt fExponential(fInt exponent);                  /* Can be used to calculate e^exponent */
+fInt fNaturalLog(fInt value);                      /* Can be used to calculate ln(value) */
+
+/* Fuse decoding functions
+ * -------------------------------------------------------------------------------------
+ */
+fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength);
+fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength);
+fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength);
+
+/* Internal Support Functions - Use these ONLY for testing or adding to internal functions
+ * -------------------------------------------------------------------------------------
+ * Some of the following functions take two INTs as their input - This is unsafe for a variety of reasons.
+ */
+fInt Add (int, int);                               /* Add two INTs and return Sum as FINT */
+fInt Multiply (int, int);                          /* Multiply two INTs and return Product as FINT */
+fInt Divide (int, int);                            /* You get the idea... */
+fInt fNegate(fInt);
+
+int uGetScaledDecimal (fInt);                      /* Internal function */
+int GetReal (fInt A);                              /* Internal function */
+
+/* Future Additions and Incomplete Functions
+ * -------------------------------------------------------------------------------------
+ */
+int GetRoundedValue(fInt);                         /* Incomplete function - Useful only when Precision is lacking */
+                                                   /* Let us say we have 2.126 but can only handle 2 decimal points. We could */
+                                                   /* either chop of 6 and keep 2.12 or use this function to get 2.13, which is more accurate */
+
+/* -------------------------------------------------------------------------------------
+ * TROUBLESHOOTING INFORMATION
+ * -------------------------------------------------------------------------------------
+ * 1) ConvertToFraction - InputOutOfRangeException: Only accepts numbers smaller than MAX (default: 32767)
+ * 2) fAdd - OutputOutOfRangeException: Output bigger than MAX (default: 32767)
+ * 3) fMultiply - OutputOutOfRangeException:
+ * 4) fGetSquare - OutputOutOfRangeException:
+ * 5) fDivide - DivideByZeroException
+ * 6) fSqrt - NegativeSquareRootException: Input cannot be a negative number
+ */
+
+/* -------------------------------------------------------------------------------------
+ * START OF CODE
+ * -------------------------------------------------------------------------------------
+ */
+fInt fExponential(fInt exponent)        /*Can be used to calculate e^exponent*/
+{
+	uint32_t i;
+	bool bNegated = false;
+
+	fInt fPositiveOne = ConvertToFraction(1);
+	fInt fZERO = ConvertToFraction(0);
+
+	fInt lower_bound = Divide(78, 10000);
+	fInt solution = fPositiveOne; /*Starting off with baseline of 1 */
+	fInt error_term;
+
+	uint32_t k_array[11] = {55452, 27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
+	uint32_t expk_array[11] = {2560000, 160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
+
+	if (GreaterThan(fZERO, exponent)) {
+		exponent = fNegate(exponent);
+		bNegated = true;
+	}
+
+	while (GreaterThan(exponent, lower_bound)) {
+		for (i = 0; i < 11; i++) {
+			if (GreaterThan(exponent, GetScaledFraction(k_array[i], 10000))) {
+				exponent = fSubtract(exponent, GetScaledFraction(k_array[i], 10000));
+				solution = fMultiply(solution, GetScaledFraction(expk_array[i], 10000));
+			}
+		}
+	}
+
+	error_term = fAdd(fPositiveOne, exponent);
+
+	solution = fMultiply(solution, error_term);
+
+	if (bNegated)
+		solution = fDivide(fPositiveOne, solution);
+
+	return solution;
+}
+
+fInt fNaturalLog(fInt value)
+{
+	uint32_t i;
+	fInt upper_bound = Divide(8, 1000);
+	fInt fNegativeOne = ConvertToFraction(-1);
+	fInt solution = ConvertToFraction(0); /*Starting off with baseline of 0 */
+	fInt error_term;
+
+	uint32_t k_array[10] = {160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
+	uint32_t logk_array[10] = {27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
+
+	while (GreaterThan(fAdd(value, fNegativeOne), upper_bound)) {
+		for (i = 0; i < 10; i++) {
+			if (GreaterThan(value, GetScaledFraction(k_array[i], 10000))) {
+				value = fDivide(value, GetScaledFraction(k_array[i], 10000));
+				solution = fAdd(solution, GetScaledFraction(logk_array[i], 10000));
+			}
+		}
+	}
+
+	error_term = fAdd(fNegativeOne, value);
+
+	return (fAdd(solution, error_term));
+}
+
+fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength)
+{
+	fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value);
+	fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
+
+	fInt f_decoded_value;
+
+	f_decoded_value = fDivide(f_fuse_value, f_bit_max_value);
+	f_decoded_value = fMultiply(f_decoded_value, f_range);
+	f_decoded_value = fAdd(f_decoded_value, f_min);
+
+	return f_decoded_value;
+}
+
+
+fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength)
+{
+	fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value);
+	fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
+
+	fInt f_CONSTANT_NEG13 = ConvertToFraction(-13);
+	fInt f_CONSTANT1 = ConvertToFraction(1);
+
+	fInt f_decoded_value;
+
+	f_decoded_value = fSubtract(fDivide(f_bit_max_value, f_fuse_value), f_CONSTANT1);
+	f_decoded_value = fNaturalLog(f_decoded_value);
+	f_decoded_value = fMultiply(f_decoded_value, fDivide(f_range, f_CONSTANT_NEG13));
+	f_decoded_value = fAdd(f_decoded_value, f_average);
+
+	return f_decoded_value;
+}
+
+fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength)
+{
+	fInt fLeakage;
+	fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
+
+	fLeakage = fMultiply(ln_max_div_min, Convert_ULONG_ToFraction(leakageID_fuse));
+	fLeakage = fDivide(fLeakage, f_bit_max_value);
+	fLeakage = fExponential(fLeakage);
+	fLeakage = fMultiply(fLeakage, f_min);
+
+	return fLeakage;
+}
+
+fInt ConvertToFraction(int X) /*Add all range checking here. Is it possible to make fInt a private declaration? */
+{
+	fInt temp;
+
+	if (X <= MAX)
+		temp.full = (X << SHIFT_AMOUNT);
+	else
+		temp.full = 0;
+
+	return temp;
+}
+
+fInt fNegate(fInt X)
+{
+	fInt CONSTANT_NEGONE = ConvertToFraction(-1);
+	return (fMultiply(X, CONSTANT_NEGONE));
+}
+
+fInt Convert_ULONG_ToFraction(uint32_t X)
+{
+	fInt temp;
+
+	if (X <= MAX)
+		temp.full = (X << SHIFT_AMOUNT);
+	else
+		temp.full = 0;
+
+	return temp;
+}
+
+fInt GetScaledFraction(int X, int factor)
+{
+	int times_shifted, factor_shifted;
+	bool bNEGATED;
+	fInt fValue;
+
+	times_shifted = 0;
+	factor_shifted = 0;
+	bNEGATED = false;
+
+	if (X < 0) {
+		X = -1*X;
+		bNEGATED = true;
+	}
+
+	if (factor < 0) {
+		factor = -1*factor;
+		bNEGATED = !bNEGATED; /*If bNEGATED = true due to X < 0, this will cover the case of negative cancelling negative */
+	}
+
+	if ((X > MAX) || factor > MAX) {
+		if ((X/factor) <= MAX) {
+			while (X > MAX) {
+				X = X >> 1;
+				times_shifted++;
+			}
+
+			while (factor > MAX) {
+				factor = factor >> 1;
+				factor_shifted++;
+			}
+		} else {
+			fValue.full = 0;
+			return fValue;
+		}
+	}
+
+	if (factor == 1)
+	return (ConvertToFraction(X));
+
+	fValue = fDivide(ConvertToFraction(X * uPow(-1, bNEGATED)), ConvertToFraction(factor));
+
+	fValue.full = fValue.full << times_shifted;
+	fValue.full = fValue.full >> factor_shifted;
+
+	return fValue;
+}
+
+/* Addition using two fInts */
+fInt fAdd (fInt X, fInt Y)
+{
+	fInt Sum;
+
+	Sum.full = X.full + Y.full;
+
+	return Sum;
+}
+
+/* Addition using two fInts */
+fInt fSubtract (fInt X, fInt Y)
+{
+	fInt Difference;
+
+	Difference.full = X.full - Y.full;
+
+	return Difference;
+}
+
+bool Equal(fInt A, fInt B)
+{
+	if (A.full == B.full)
+		return true;
+	else
+		return false;
+}
+
+bool GreaterThan(fInt A, fInt B)
+{
+	if (A.full > B.full)
+		return true;
+	else
+		return false;
+}
+
+fInt fMultiply (fInt X, fInt Y) /* Uses 64-bit integers (int64_t) */
+{
+	fInt Product;
+	int64_t tempProduct;
+	bool X_LessThanOne, Y_LessThanOne;
+
+	X_LessThanOne = (X.partial.real == 0 && X.partial.decimal != 0 && X.full >= 0);
+	Y_LessThanOne = (Y.partial.real == 0 && Y.partial.decimal != 0 && Y.full >= 0);
+
+	/*The following is for a very specific common case: Non-zero number with ONLY fractional portion*/
+	/* TEMPORARILY DISABLED - CAN BE USED TO IMPROVE PRECISION
+
+	if (X_LessThanOne && Y_LessThanOne) {
+		Product.full = X.full * Y.full;
+		return Product
+	}*/
+
+	tempProduct = ((int64_t)X.full) * ((int64_t)Y.full); /*Q(16,16)*Q(16,16) = Q(32, 32) - Might become a negative number! */
+	tempProduct = tempProduct >> 16; /*Remove lagging 16 bits - Will lose some precision from decimal; */
+	Product.full = (int)tempProduct; /*The int64_t will lose the leading 16 bits that were part of the integer portion */
+
+	return Product;
+}
+
+fInt fDivide (fInt X, fInt Y)
+{
+	fInt fZERO, fQuotient;
+	int64_t longlongX, longlongY;
+
+	fZERO = ConvertToFraction(0);
+
+	if (Equal(Y, fZERO))
+	return fZERO;
+
+	longlongX = (int64_t)X.full;
+	longlongY = (int64_t)Y.full;
+
+	longlongX = longlongX << 16; /*Q(16,16) -> Q(32,32) */
+
+	div64_s64(longlongX, longlongY); /*Q(32,32) divided by Q(16,16) = Q(16,16) Back to original format */
+
+	fQuotient.full = (int)longlongX;
+	return fQuotient;
+}
+
+int ConvertBackToInteger (fInt A) /*THIS is the function that will be used to check with the Golden settings table*/
+{
+	fInt fullNumber, scaledDecimal, scaledReal;
+
+	scaledReal.full = GetReal(A) * uPow(10, PRECISION-1); /* DOUBLE CHECK THISSSS!!! */
+
+	scaledDecimal.full = uGetScaledDecimal(A);
+
+	fullNumber = fAdd(scaledDecimal,scaledReal);
+
+	return fullNumber.full;
+}
+
+fInt fGetSquare(fInt A)
+{
+	return fMultiply(A,A);
+}
+
+/* x_new = x_old - (x_old^2 - C) / (2 * x_old) */
+fInt fSqrt(fInt num)
+{
+	fInt F_divide_Fprime, Fprime;
+	fInt test;
+	fInt twoShifted;
+	int seed, counter, error;
+	fInt x_new, x_old, C, y;
+
+	fInt fZERO = ConvertToFraction(0);
+
+	/* (0 > num) is the same as (num < 0), i.e., num is negative */
+
+	if (GreaterThan(fZERO, num) || Equal(fZERO, num))
+		return fZERO;
+
+	C = num;
+
+	if (num.partial.real > 3000)
+		seed = 60;
+	else if (num.partial.real > 1000)
+		seed = 30;
+	else if (num.partial.real > 100)
+		seed = 10;
+	else
+		seed = 2;
+
+	counter = 0;
+
+	if (Equal(num, fZERO)) /*Square Root of Zero is zero */
+		return fZERO;
+
+	twoShifted = ConvertToFraction(2);
+	x_new = ConvertToFraction(seed);
+
+	do {
+		counter++;
+
+		x_old.full = x_new.full;
+
+		test = fGetSquare(x_old); /*1.75*1.75 is reverting back to 1 when shifted down */
+		y = fSubtract(test, C); /*y = f(x) = x^2 - C; */
+
+		Fprime = fMultiply(twoShifted, x_old);
+		F_divide_Fprime = fDivide(y, Fprime);
+
+		x_new = fSubtract(x_old, F_divide_Fprime);
+
+		error = ConvertBackToInteger(x_new) - ConvertBackToInteger(x_old);
+
+		if (counter > 20) /*20 is already way too many iterations. If we dont have an answer by then, we never will*/
+			return x_new;
+
+	} while (uAbs(error) > 0);
+
+	return (x_new);
+}
+
+void SolveQuadracticEqn(fInt A, fInt B, fInt C, fInt Roots[])
+{
+	fInt *pRoots = &Roots[0];
+	fInt temp, root_first, root_second;
+	fInt f_CONSTANT10, f_CONSTANT100;
+
+	f_CONSTANT100 = ConvertToFraction(100);
+	f_CONSTANT10 = ConvertToFraction(10);
+
+	while(GreaterThan(A, f_CONSTANT100) || GreaterThan(B, f_CONSTANT100) || GreaterThan(C, f_CONSTANT100)) {
+		A = fDivide(A, f_CONSTANT10);
+		B = fDivide(B, f_CONSTANT10);
+		C = fDivide(C, f_CONSTANT10);
+	}
+
+	temp = fMultiply(ConvertToFraction(4), A); /* root = 4*A */
+	temp = fMultiply(temp, C); /* root = 4*A*C */
+	temp = fSubtract(fGetSquare(B), temp); /* root = b^2 - 4AC */
+	temp = fSqrt(temp); /*root = Sqrt (b^2 - 4AC); */
+
+	root_first = fSubtract(fNegate(B), temp); /* b - Sqrt(b^2 - 4AC) */
+	root_second = fAdd(fNegate(B), temp); /* b + Sqrt(b^2 - 4AC) */
+
+	root_first = fDivide(root_first, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */
+	root_first = fDivide(root_first, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */
+
+	root_second = fDivide(root_second, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */
+	root_second = fDivide(root_second, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */
+
+	*(pRoots + 0) = root_first;
+	*(pRoots + 1) = root_second;
+}
+
+/* -----------------------------------------------------------------------------
+ * SUPPORT FUNCTIONS
+ * -----------------------------------------------------------------------------
+ */
+
+/* Addition using two normal ints - Temporary - Use only for testing purposes?. */
+fInt Add (int X, int Y)
+{
+	fInt A, B, Sum;
+
+	A.full = (X << SHIFT_AMOUNT);
+	B.full = (Y << SHIFT_AMOUNT);
+
+	Sum.full = A.full + B.full;
+
+	return Sum;
+}
+
+/* Conversion Functions */
+int GetReal (fInt A)
+{
+	return (A.full >> SHIFT_AMOUNT);
+}
+
+/* Temporarily Disabled */
+int GetRoundedValue(fInt A) /*For now, round the 3rd decimal place */
+{
+	/* ROUNDING TEMPORARLY DISABLED
+	int temp = A.full;
+	int decimal_cutoff, decimal_mask = 0x000001FF;
+	decimal_cutoff = temp & decimal_mask;
+	if (decimal_cutoff > 0x147) {
+		temp += 673;
+	}*/
+
+	return ConvertBackToInteger(A)/10000; /*Temporary - in case this was used somewhere else */
+}
+
+fInt Multiply (int X, int Y)
+{
+	fInt A, B, Product;
+
+	A.full = X << SHIFT_AMOUNT;
+	B.full = Y << SHIFT_AMOUNT;
+
+	Product = fMultiply(A, B);
+
+	return Product;
+}
+
+fInt Divide (int X, int Y)
+{
+	fInt A, B, Quotient;
+
+	A.full = X << SHIFT_AMOUNT;
+	B.full = Y << SHIFT_AMOUNT;
+
+	Quotient = fDivide(A, B);
+
+	return Quotient;
+}
+
+int uGetScaledDecimal (fInt A) /*Converts the fractional portion to whole integers - Costly function */
+{
+	int dec[PRECISION];
+	int i, scaledDecimal = 0, tmp = A.partial.decimal;
+
+	for (i = 0; i < PRECISION; i++) {
+		dec[i] = tmp / (1 << SHIFT_AMOUNT);
+		tmp = tmp - ((1 << SHIFT_AMOUNT)*dec[i]);
+		tmp *= 10;
+		scaledDecimal = scaledDecimal + dec[i]*uPow(10, PRECISION - 1 -i);
+	}
+
+	return scaledDecimal;
+}
+
+int uPow(int base, int power)
+{
+	if (power == 0)
+		return 1;
+	else
+		return (base)*uPow(base, power - 1);
+}
+
+fInt fAbs(fInt A)
+{
+	if (A.partial.real < 0)
+		return (fMultiply(A, ConvertToFraction(-1)));
+	else
+		return A;
+}
+
+int uAbs(int X)
+{
+	if (X < 0)
+		return (X * -1);
+	else
+		return X;
+}
+
+fInt fRoundUpByStepSize(fInt A, fInt fStepSize, bool error_term)
+{
+	fInt solution;
+
+	solution = fDivide(A, fStepSize);
+	solution.partial.decimal = 0; /*All fractional digits changes to 0 */
+
+	if (error_term)
+		solution.partial.real += 1; /*Error term of 1 added */
+
+	solution = fMultiply(solution, fStepSize);
+	solution = fAdd(solution, fStepSize);
+
+	return solution;
+}
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c
new file mode 100644
index 0000000..186496a
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#include <linux/types.h>
+#include "atom-types.h"
+#include "atombios.h"
+#include "pppcielanes.h"
+
+/** \file
+ * Functions related to PCIe lane changes.
+ */
+
+/* For converting from number of lanes to lane bits.  */
+static const unsigned char pp_r600_encode_lanes[] = {
+	0,          /*  0 Not Supported  */
+	1,          /*  1 Lane  */
+	2,          /*  2 Lanes  */
+	0,          /*  3 Not Supported  */
+	3,          /*  4 Lanes  */
+	0,          /*  5 Not Supported  */
+	0,          /*  6 Not Supported  */
+	0,          /*  7 Not Supported  */
+	4,          /*  8 Lanes  */
+	0,          /*  9 Not Supported  */
+	0,          /* 10 Not Supported  */
+	0,          /* 11 Not Supported  */
+	5,          /* 12 Lanes (Not actually supported)  */
+	0,          /* 13 Not Supported  */
+	0,          /* 14 Not Supported  */
+	0,          /* 15 Not Supported  */
+	6           /* 16 Lanes  */
+};
+
+static const unsigned char pp_r600_decoded_lanes[8] = { 16, 1, 2, 4, 8, 12, 16, };
+
+uint8_t encode_pcie_lane_width(uint32_t num_lanes)
+{
+	return pp_r600_encode_lanes[num_lanes];
+}
+
+uint8_t decode_pcie_lane_width(uint32_t num_lanes)
+{
+	return pp_r600_decoded_lanes[num_lanes];
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h b/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h
new file mode 100644
index 0000000..70b163b
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef PP_PCIELANES_H
+#define PP_PCIELANES_H
+
+extern uint8_t encode_pcie_lane_width(uint32_t num_lanes);
+extern uint8_t decode_pcie_lane_width(uint32_t num_lanes);
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
new file mode 100644
index 0000000..2f1a14f
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
@@ -0,0 +1,1688 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "processpptables.h"
+#include <atom-types.h>
+#include <atombios.h>
+#include "pp_debug.h"
+#include "pptable.h"
+#include "power_state.h"
+#include "hwmgr.h"
+#include "hardwaremanager.h"
+
+
+#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
+#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
+#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
+#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
+#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
+#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
+#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
+#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
+
+#define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6
+
+static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t vce_table_offset = 0;
+
+	if (le16_to_cpu(powerplay_table->usTableSize) >=
+	   sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
+		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
+			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
+
+		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
+			const ATOM_PPLIB_EXTENDEDHEADER  *extended_header =
+						(const ATOM_PPLIB_EXTENDEDHEADER *)
+						(((unsigned long)powerplay_table3) +
+						le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
+			if (le16_to_cpu(extended_header->usSize) >=
+			   SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2)
+				vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset);
+		}
+	}
+
+	return vce_table_offset;
+}
+
+static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t table_offset = get_vce_table_offset(hwmgr,
+						powerplay_table);
+
+	if (table_offset > 0)
+		return table_offset + 1;
+
+	return 0;
+}
+
+static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
+							powerplay_table);
+	uint16_t table_size = 0;
+
+	if (table_offset > 0) {
+		const VCEClockInfoArray *p = (const VCEClockInfoArray *)
+			(((unsigned long) powerplay_table) + table_offset);
+		table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo);
+	}
+
+	return table_size;
+}
+
+static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr,
+				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
+							powerplay_table);
+
+	if (table_offset > 0)
+		return table_offset + get_vce_clock_info_array_size(hwmgr,
+							powerplay_table);
+
+	return 0;
+}
+
+static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr,
+							const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
+	uint16_t table_size = 0;
+
+	if (table_offset > 0) {
+		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable =
+			(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset);
+
+		table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record);
+	}
+	return table_size;
+}
+
+static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
+
+	if (table_offset > 0)
+		return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table);
+
+	return 0;
+}
+
+static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table(
+						struct pp_hwmgr *hwmgr,
+						const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table);
+
+	if (table_offset > 0)
+		return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset);
+
+	return NULL;
+}
+
+static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t uvd_table_offset = 0;
+
+	if (le16_to_cpu(powerplay_table->usTableSize) >=
+	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
+		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
+			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
+		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
+			const ATOM_PPLIB_EXTENDEDHEADER  *extended_header =
+					(const ATOM_PPLIB_EXTENDEDHEADER *)
+					(((unsigned long)powerplay_table3) +
+				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
+			if (le16_to_cpu(extended_header->usSize) >=
+			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3)
+				uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset);
+		}
+	}
+	return uvd_table_offset;
+}
+
+static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr,
+			 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t table_offset = get_uvd_table_offset(hwmgr,
+						    powerplay_table);
+
+	if (table_offset > 0)
+		return table_offset + 1;
+	return 0;
+}
+
+static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
+						    powerplay_table);
+	uint16_t table_size = 0;
+
+	if (table_offset > 0) {
+		const UVDClockInfoArray *p = (const UVDClockInfoArray *)
+					(((unsigned long) powerplay_table)
+					+ table_offset);
+		table_size = sizeof(UCHAR) +
+			     p->ucNumEntries * sizeof(UVDClockInfo);
+	}
+
+	return table_size;
+}
+
+static uint16_t get_uvd_clock_voltage_limit_table_offset(
+			struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
+						     powerplay_table);
+
+	if (table_offset > 0)
+		return table_offset +
+			get_uvd_clock_info_array_size(hwmgr, powerplay_table);
+
+	return 0;
+}
+
+static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t samu_table_offset = 0;
+
+	if (le16_to_cpu(powerplay_table->usTableSize) >=
+	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
+		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
+			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
+		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
+			const ATOM_PPLIB_EXTENDEDHEADER  *extended_header =
+				(const ATOM_PPLIB_EXTENDEDHEADER *)
+				(((unsigned long)powerplay_table3) +
+				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
+			if (le16_to_cpu(extended_header->usSize) >=
+			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4)
+				samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset);
+		}
+	}
+
+	return samu_table_offset;
+}
+
+static uint16_t get_samu_clock_voltage_limit_table_offset(
+			struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t table_offset = get_samu_table_offset(hwmgr,
+					    powerplay_table);
+
+	if (table_offset > 0)
+		return table_offset + 1;
+
+	return 0;
+}
+
+static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr,
+				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t acp_table_offset = 0;
+
+	if (le16_to_cpu(powerplay_table->usTableSize) >=
+	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
+		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
+			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
+		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
+			const ATOM_PPLIB_EXTENDEDHEADER  *pExtendedHeader =
+				(const ATOM_PPLIB_EXTENDEDHEADER *)
+				(((unsigned long)powerplay_table3) +
+				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
+			if (le16_to_cpu(pExtendedHeader->usSize) >=
+			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6)
+				acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset);
+		}
+	}
+
+	return acp_table_offset;
+}
+
+static uint16_t get_acp_clock_voltage_limit_table_offset(
+				struct pp_hwmgr *hwmgr,
+				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table);
+
+	if (tableOffset > 0)
+		return tableOffset + 1;
+
+	return 0;
+}
+
+static uint16_t get_cacp_tdp_table_offset(
+				struct pp_hwmgr *hwmgr,
+				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t cacTdpTableOffset = 0;
+
+	if (le16_to_cpu(powerplay_table->usTableSize) >=
+	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
+		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
+				(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
+		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
+			const ATOM_PPLIB_EXTENDEDHEADER  *pExtendedHeader =
+					(const ATOM_PPLIB_EXTENDEDHEADER *)
+					(((unsigned long)powerplay_table3) +
+				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
+			if (le16_to_cpu(pExtendedHeader->usSize) >=
+			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7)
+				cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset);
+		}
+	}
+
+	return cacTdpTableOffset;
+}
+
+static int get_cac_tdp_table(struct pp_hwmgr *hwmgr,
+				struct phm_cac_tdp_table **ptable,
+				const ATOM_PowerTune_Table *table,
+				uint16_t us_maximum_power_delivery_limit)
+{
+	unsigned long table_size;
+	struct phm_cac_tdp_table *tdp_table;
+
+	table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table);
+
+	tdp_table = kzalloc(table_size, GFP_KERNEL);
+	if (NULL == tdp_table)
+		return -ENOMEM;
+
+	tdp_table->usTDP = le16_to_cpu(table->usTDP);
+	tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP);
+	tdp_table->usTDC = le16_to_cpu(table->usTDC);
+	tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit);
+	tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit);
+	tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage);
+	tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage);
+	tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit;
+
+	*ptable = tdp_table;
+
+	return 0;
+}
+
+static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t sclk_vdd_gfx_table_offset = 0;
+
+	if (le16_to_cpu(powerplay_table->usTableSize) >=
+	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
+		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
+				(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
+		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
+			const ATOM_PPLIB_EXTENDEDHEADER  *pExtendedHeader =
+				(const ATOM_PPLIB_EXTENDEDHEADER *)
+				(((unsigned long)powerplay_table3) +
+				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
+			if (le16_to_cpu(pExtendedHeader->usSize) >=
+			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8)
+				sclk_vdd_gfx_table_offset =
+					le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset);
+		}
+	}
+
+	return sclk_vdd_gfx_table_offset;
+}
+
+static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(
+			struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table);
+
+	if (tableOffset > 0)
+		return tableOffset;
+
+	return 0;
+}
+
+
+static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
+		struct phm_clock_voltage_dependency_table **ptable,
+		const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table)
+{
+
+	unsigned long table_size, i;
+	struct phm_clock_voltage_dependency_table *dep_table;
+
+	table_size = sizeof(unsigned long) +
+		sizeof(struct phm_clock_voltage_dependency_table)
+		* table->ucNumEntries;
+
+	dep_table = kzalloc(table_size, GFP_KERNEL);
+	if (NULL == dep_table)
+		return -ENOMEM;
+
+	dep_table->count = (unsigned long)table->ucNumEntries;
+
+	for (i = 0; i < dep_table->count; i++) {
+		dep_table->entries[i].clk =
+			((unsigned long)table->entries[i].ucClockHigh << 16) |
+			le16_to_cpu(table->entries[i].usClockLow);
+			dep_table->entries[i].v =
+				(unsigned long)le16_to_cpu(table->entries[i].usVoltage);
+	}
+
+	*ptable = dep_table;
+
+	return 0;
+}
+
+static int get_valid_clk(struct pp_hwmgr *hwmgr,
+			struct phm_clock_array **ptable,
+			const struct phm_clock_voltage_dependency_table *table)
+{
+	unsigned long table_size, i;
+	struct phm_clock_array *clock_table;
+
+	table_size = sizeof(unsigned long) + sizeof(unsigned long) * table->count;
+	clock_table = kzalloc(table_size, GFP_KERNEL);
+	if (NULL == clock_table)
+		return -ENOMEM;
+
+	clock_table->count = (unsigned long)table->count;
+
+	for (i = 0; i < clock_table->count; i++)
+		clock_table->values[i] = (unsigned long)table->entries[i].clk;
+
+	*ptable = clock_table;
+
+	return 0;
+}
+
+static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr,
+			struct phm_clock_and_voltage_limits *limits,
+			const ATOM_PPLIB_Clock_Voltage_Limit_Table *table)
+{
+	limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) |
+			le16_to_cpu(table->entries[0].usSclkLow);
+	limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) |
+			le16_to_cpu(table->entries[0].usMclkLow);
+	limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc);
+	limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci);
+
+	return 0;
+}
+
+
+static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
+		       enum phm_platform_caps cap)
+{
+	if (enable)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
+	else
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
+}
+
+static int set_platform_caps(struct pp_hwmgr *hwmgr,
+			unsigned long powerplay_caps)
+{
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY),
+		PHM_PlatformCaps_PowerPlaySupport
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
+		PHM_PlatformCaps_BiosPowerSourceControl
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s),
+		PHM_PlatformCaps_EnableASPML0s
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1),
+		PHM_PlatformCaps_EnableASPML1
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS),
+		PHM_PlatformCaps_EnableBackbias
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC),
+		PHM_PlatformCaps_AutomaticDCTransition
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY),
+		PHM_PlatformCaps_GeminiPrimary
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC),
+		PHM_PlatformCaps_StepVddc
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL),
+		PHM_PlatformCaps_EnableVoltageControl
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL),
+		PHM_PlatformCaps_EnableSideportControl
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1),
+		PHM_PlatformCaps_TurnOffPll_ASPML1
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL),
+		PHM_PlatformCaps_EnableHTLinkControl
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL),
+		PHM_PlatformCaps_EnableMVDDControl
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL),
+		PHM_PlatformCaps_ControlVDDCI
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT),
+		PHM_PlatformCaps_RegulatorHot
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT),
+		PHM_PlatformCaps_BootStateOnAlert
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT),
+		PHM_PlatformCaps_DontWaitForVBlankOnAlert
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO),
+		PHM_PlatformCaps_BACO
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE),
+		PHM_PlatformCaps_NewCACVoltage
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY),
+		PHM_PlatformCaps_RevertGPIO5Polarity
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17),
+		PHM_PlatformCaps_Thermal2GPIO17
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE),
+		PHM_PlatformCaps_VRHotGPIOConfigurable
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION),
+		PHM_PlatformCaps_TempInversion
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV),
+		PHM_PlatformCaps_EVV
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
+		PHM_PlatformCaps_CombinePCCWithThermalSignal
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
+		PHM_PlatformCaps_LoadPostProductionFirmware
+	);
+
+	set_hw_cap(
+		hwmgr,
+		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC),
+		PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
+	);
+
+	return 0;
+}
+
+static PP_StateClassificationFlags make_classification_flags(
+						   struct pp_hwmgr *hwmgr,
+						    USHORT classification,
+						   USHORT classification2)
+{
+	PP_StateClassificationFlags result = 0;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
+		result |= PP_StateClassificationFlag_Boot;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
+		result |= PP_StateClassificationFlag_Thermal;
+
+	if (classification &
+			ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
+		result |= PP_StateClassificationFlag_LimitedPowerSource;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
+		result |= PP_StateClassificationFlag_Rest;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
+		result |= PP_StateClassificationFlag_Forced;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
+		result |= PP_StateClassificationFlag_3DPerformance;
+
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
+		result |= PP_StateClassificationFlag_ACOverdriveTemplate;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
+		result |= PP_StateClassificationFlag_Uvd;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
+		result |= PP_StateClassificationFlag_UvdHD;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
+		result |= PP_StateClassificationFlag_UvdSD;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
+		result |= PP_StateClassificationFlag_HD2;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
+		result |= PP_StateClassificationFlag_ACPI;
+
+	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
+		result |= PP_StateClassificationFlag_LimitedPowerSource_2;
+
+
+	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
+		result |= PP_StateClassificationFlag_ULV;
+
+	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
+		result |= PP_StateClassificationFlag_UvdMVC;
+
+	return result;
+}
+
+static int init_non_clock_fields(struct pp_hwmgr *hwmgr,
+						struct pp_power_state *ps,
+							    uint8_t version,
+			 const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) {
+	unsigned long rrr_index;
+	unsigned long tmp;
+
+	ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) &
+					ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
+	ps->classification.flags = make_classification_flags(hwmgr,
+				le16_to_cpu(pnon_clock_info->usClassification),
+				le16_to_cpu(pnon_clock_info->usClassification2));
+
+	ps->classification.temporary_state = false;
+	ps->classification.to_be_deleted = false;
+	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
+		ATOM_PPLIB_SINGLE_DISPLAY_ONLY;
+
+	ps->validation.singleDisplayOnly = (0 != tmp);
+
+	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
+		ATOM_PPLIB_DISALLOW_ON_DC;
+
+	ps->validation.disallowOnDC = (0 != tmp);
+
+	ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
+				ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
+				ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
+
+	ps->pcie.lanes = 0;
+
+	ps->display.disableFrameModulation = false;
+
+	rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
+			ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >>
+			ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT;
+
+	if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) {
+		static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \
+								{ 0, 50, 0 };
+
+		ps->display.refreshrateSource = PP_RefreshrateSource_Explicit;
+		ps->display.explicitRefreshrate = look_up[rrr_index];
+		ps->display.limitRefreshrate = true;
+
+		if (ps->display.explicitRefreshrate == 0)
+			ps->display.limitRefreshrate = false;
+	} else
+		ps->display.limitRefreshrate = false;
+
+	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
+		ATOM_PPLIB_ENABLE_VARIBRIGHT;
+
+	ps->display.enableVariBright = (0 != tmp);
+
+	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
+		ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF;
+
+	ps->memory.dllOff = (0 != tmp);
+
+	ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
+			    ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
+
+	ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
+				     pnon_clock_info->ucMinTemperature;
+
+	ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
+				     pnon_clock_info->ucMaxTemperature;
+
+	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
+		ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING;
+
+	ps->software.disableLoadBalancing = tmp;
+
+	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
+		ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS;
+
+	ps->software.enableSleepForTimestamps = (0 != tmp);
+
+	ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower;
+
+	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) {
+		ps->uvd_clocks.VCLK = pnon_clock_info->ulVCLK;
+		ps->uvd_clocks.DCLK = pnon_clock_info->ulDCLK;
+	} else {
+		ps->uvd_clocks.VCLK = 0;
+		ps->uvd_clocks.DCLK = 0;
+	}
+
+	return 0;
+}
+
+static ULONG size_of_entry_v2(ULONG num_dpm_levels)
+{
+	return (sizeof(UCHAR) + sizeof(UCHAR) +
+			(num_dpm_levels * sizeof(UCHAR)));
+}
+
+static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(
+					const StateArray * pstate_arrays,
+							 ULONG entry_index)
+{
+	ULONG i;
+	const ATOM_PPLIB_STATE_V2 *pstate;
+
+	pstate = pstate_arrays->states;
+	if (entry_index <= pstate_arrays->ucNumEntries) {
+		for (i = 0; i < entry_index; i++)
+			pstate = (ATOM_PPLIB_STATE_V2 *)(
+						  (unsigned long)pstate +
+			     size_of_entry_v2(pstate->ucNumDPMLevels));
+	}
+	return pstate;
+}
+
+
+static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
+				     struct pp_hwmgr *hwmgr)
+{
+	const void *table_addr = NULL;
+	uint8_t frev, crev;
+	uint16_t size;
+
+	table_addr = cgs_atom_get_data_table(hwmgr->device,
+			GetIndexIntoMasterTable(DATA, PowerPlayInfo),
+			&size, &frev, &crev);
+
+	hwmgr->soft_pp_table = table_addr;
+
+	return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
+}
+
+
+int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
+				     unsigned long *num_of_entries)
+{
+	const StateArray *pstate_arrays;
+	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
+
+	if (powerplay_table == NULL)
+		return -1;
+
+	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
+		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
+					le16_to_cpu(powerplay_table->usStateArrayOffset));
+
+		*num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
+	} else
+		*num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
+
+	return 0;
+}
+
+int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
+				unsigned long entry_index,
+				struct pp_power_state *ps,
+			 pp_tables_hw_clock_info_callback func)
+{
+	int i;
+	const StateArray *pstate_arrays;
+	const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
+	const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
+	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
+	int result = 0;
+	int res = 0;
+
+	const ClockInfoArray *pclock_arrays;
+
+	const NonClockInfoArray *pnon_clock_arrays;
+
+	const ATOM_PPLIB_STATE *pstate_entry;
+
+	if (powerplay_table == NULL)
+		return -1;
+
+	ps->classification.bios_index = entry_index;
+
+	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
+		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
+					le16_to_cpu(powerplay_table->usStateArrayOffset));
+
+		if (entry_index > pstate_arrays->ucNumEntries)
+			return -1;
+
+		pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
+		pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
+					le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
+
+		pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
+						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
+
+		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
+					(pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
+
+		result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
+
+		for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
+			const void *pclock_info = (const void *)(
+							(unsigned long)(pclock_arrays->clockInfo) +
+							(pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
+			res = func(hwmgr, &ps->hardware, i, pclock_info);
+			if ((0 == result) && (0 != res))
+				result = res;
+		}
+	} else {
+		if (entry_index > powerplay_table->ucNumStates)
+			return -1;
+
+		pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table + powerplay_table->usStateArrayOffset +
+				entry_index * powerplay_table->ucStateEntrySize);
+
+		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
+						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
+						pstate_entry->ucNonClockStateIndex *
+						powerplay_table->ucNonClockSize);
+
+		result = init_non_clock_fields(hwmgr, ps,
+							powerplay_table->ucNonClockSize,
+							pnon_clock_info);
+
+		for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
+			const void *pclock_info = (const void *)((unsigned long)powerplay_table +
+						le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
+						pstate_entry->ucClockStateIndices[i] *
+						powerplay_table->ucClockInfoSize);
+
+			int res = func(hwmgr, &ps->hardware, i, pclock_info);
+
+			if ((0 == result) && (0 != res))
+					result = res;
+		}
+	}
+
+	if ((0 == result) &&
+		(0 != (ps->classification.flags & PP_StateClassificationFlag_Boot)))
+		result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
+
+	return result;
+}
+
+
+
+static int init_powerplay_tables(
+			struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
+)
+{
+	return 0;
+}
+
+
+static int init_thermal_controller(
+			struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	return 0;
+}
+
+static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
+			const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
+{
+	hwmgr->platform_descriptor.overdriveLimit.engineClock =
+				le32_to_cpu(fw_info->ulASICMaxEngineClock);
+
+	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
+				le32_to_cpu(fw_info->ulASICMaxMemoryClock);
+
+	hwmgr->platform_descriptor.maxOverdriveVDDC =
+		le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
+
+	hwmgr->platform_descriptor.minOverdriveVDDC =
+			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
+
+	hwmgr->platform_descriptor.maxOverdriveVDDC =
+			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
+
+	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
+	return 0;
+}
+
+static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
+			const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
+{
+	const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
+	const ATOM_PPLIB_EXTENDEDHEADER *header;
+
+	if (le16_to_cpu(powerplay_table->usTableSize) <
+	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
+		return 0;
+
+	powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
+
+	if (0 == powerplay_table3->usExtendendedHeaderOffset)
+		return 0;
+
+	header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
+			le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
+
+	hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
+	hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
+
+
+	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
+	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
+	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
+
+	return 0;
+}
+
+static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	int result;
+	uint8_t frev, crev;
+	uint16_t size;
+
+	const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
+
+	hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
+	hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
+	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
+	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
+
+	/* We assume here that fw_info is unchanged if this call fails.*/
+	fw_info = cgs_atom_get_data_table(hwmgr->device,
+			 GetIndexIntoMasterTable(DATA, FirmwareInfo),
+			 &size, &frev, &crev);
+
+	if ((fw_info->ucTableFormatRevision == 1)
+		&& (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
+		result = init_overdrive_limits_V1_4(hwmgr,
+				powerplay_table,
+				(const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
+
+	else if ((fw_info->ucTableFormatRevision == 2)
+		&& (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
+		result = init_overdrive_limits_V2_1(hwmgr,
+				powerplay_table,
+				(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
+
+	if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0
+		&& hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0
+		&& !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_OverdriveDisabledByPowerBudget))
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_ACOverdriveSupport);
+
+	return result;
+}
+
+static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
+		struct phm_uvd_clock_voltage_dependency_table **ptable,
+		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
+		const UVDClockInfoArray *array)
+{
+	unsigned long table_size, i;
+	struct phm_uvd_clock_voltage_dependency_table *uvd_table;
+
+	table_size = sizeof(unsigned long) +
+		 sizeof(struct phm_uvd_clock_voltage_dependency_table) *
+		 table->numEntries;
+
+	uvd_table = kzalloc(table_size, GFP_KERNEL);
+	if (NULL == uvd_table)
+		return -ENOMEM;
+
+	uvd_table->count = table->numEntries;
+
+	for (i = 0; i < table->numEntries; i++) {
+		const UVDClockInfo *entry =
+			&array->entries[table->entries[i].ucUVDClockInfoIndex];
+		uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
+		uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
+					 | le16_to_cpu(entry->usVClkLow);
+		uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
+					 | le16_to_cpu(entry->usDClkLow);
+	}
+
+	*ptable = uvd_table;
+
+	return 0;
+}
+
+static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
+		struct phm_vce_clock_voltage_dependency_table **ptable,
+		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
+		const VCEClockInfoArray    *array)
+{
+	unsigned long table_size, i;
+	struct phm_vce_clock_voltage_dependency_table *vce_table = NULL;
+
+	table_size = sizeof(unsigned long) +
+			sizeof(struct phm_vce_clock_voltage_dependency_table)
+			* table->numEntries;
+
+	vce_table = kzalloc(table_size, GFP_KERNEL);
+	if (NULL == vce_table)
+		return -ENOMEM;
+
+	vce_table->count = table->numEntries;
+	for (i = 0; i < table->numEntries; i++) {
+		const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
+
+		vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
+		vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
+					| le16_to_cpu(entry->usEVClkLow);
+		vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
+					| le16_to_cpu(entry->usECClkLow);
+	}
+
+	*ptable = vce_table;
+
+	return 0;
+}
+
+static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
+		 struct phm_samu_clock_voltage_dependency_table **ptable,
+		 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
+{
+	unsigned long table_size, i;
+	struct phm_samu_clock_voltage_dependency_table *samu_table;
+
+	table_size = sizeof(unsigned long) +
+		sizeof(struct phm_samu_clock_voltage_dependency_table) *
+		table->numEntries;
+
+	samu_table = kzalloc(table_size, GFP_KERNEL);
+	if (NULL == samu_table)
+		return -ENOMEM;
+
+	samu_table->count = table->numEntries;
+
+	for (i = 0; i < table->numEntries; i++) {
+		samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
+		samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
+					 | le16_to_cpu(table->entries[i].usSAMClockLow);
+	}
+
+	*ptable = samu_table;
+
+	return 0;
+}
+
+static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
+		struct phm_acp_clock_voltage_dependency_table **ptable,
+		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
+{
+	unsigned table_size, i;
+	struct phm_acp_clock_voltage_dependency_table *acp_table;
+
+	table_size = sizeof(unsigned long) +
+		sizeof(struct phm_acp_clock_voltage_dependency_table) *
+		table->numEntries;
+
+	acp_table = kzalloc(table_size, GFP_KERNEL);
+	if (NULL == acp_table)
+		return -ENOMEM;
+
+	acp_table->count = (unsigned long)table->numEntries;
+
+	for (i = 0; i < table->numEntries; i++) {
+		acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
+		acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
+					 | le16_to_cpu(table->entries[i].usACPClockLow);
+	}
+
+	*ptable = acp_table;
+
+	return 0;
+}
+
+static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
+	ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
+	int result = 0;
+
+	uint16_t vce_clock_info_array_offset;
+	uint16_t uvd_clock_info_array_offset;
+	uint16_t table_offset;
+
+	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
+	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
+	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
+	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
+	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
+	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
+	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
+	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
+	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
+	hwmgr->dyn_state.ppm_parameter_table = NULL;
+	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
+
+	vce_clock_info_array_offset = get_vce_clock_info_array_offset(
+						hwmgr, powerplay_table);
+	table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
+						powerplay_table);
+	if (vce_clock_info_array_offset > 0 && table_offset > 0) {
+		const VCEClockInfoArray *array = (const VCEClockInfoArray *)
+				(((unsigned long) powerplay_table) +
+				vce_clock_info_array_offset);
+		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
+				(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
+				(((unsigned long) powerplay_table) + table_offset);
+		result = get_vce_clock_voltage_limit_table(hwmgr,
+				&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
+				table, array);
+	}
+
+	uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
+	table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
+
+	if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
+		const UVDClockInfoArray *array = (const UVDClockInfoArray *)
+				(((unsigned long) powerplay_table) +
+				uvd_clock_info_array_offset);
+		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
+				(const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
+				(((unsigned long) powerplay_table) + table_offset);
+		result = get_uvd_clock_voltage_limit_table(hwmgr,
+				&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
+	}
+
+	table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
+							    powerplay_table);
+
+	if (table_offset > 0) {
+		const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
+				(const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
+				(((unsigned long) powerplay_table) + table_offset);
+		result = get_samu_clock_voltage_limit_table(hwmgr,
+				&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
+	}
+
+	table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
+							     powerplay_table);
+
+	if (table_offset > 0) {
+		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
+				(const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
+				(((unsigned long) powerplay_table) + table_offset);
+		result = get_acp_clock_voltage_limit_table(hwmgr,
+				&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
+	}
+
+	table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
+	if (table_offset > 0) {
+		UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
+
+		if (rev_id > 0) {
+			const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
+				(const ATOM_PPLIB_POWERTUNE_Table_V1 *)
+				(((unsigned long) powerplay_table) + table_offset);
+			result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
+				&tune_table->power_tune_table,
+				le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
+			hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
+				le16_to_cpu(tune_table->usTjMax);
+		} else {
+			const ATOM_PPLIB_POWERTUNE_Table *tune_table =
+				(const ATOM_PPLIB_POWERTUNE_Table *)
+				(((unsigned long) powerplay_table) + table_offset);
+			result = get_cac_tdp_table(hwmgr,
+				&hwmgr->dyn_state.cac_dtp_table,
+				&tune_table->power_tune_table, 255);
+		}
+	}
+
+	if (le16_to_cpu(powerplay_table->usTableSize) >=
+		sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
+		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
+				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
+		if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
+			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
+				(((unsigned long) powerplay_table4) +
+				powerplay_table4->usVddcDependencyOnSCLKOffset);
+			result = get_clock_voltage_dependency_table(hwmgr,
+				&hwmgr->dyn_state.vddc_dependency_on_sclk, table);
+		}
+
+		if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
+			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
+				(((unsigned long) powerplay_table4) +
+				powerplay_table4->usVddciDependencyOnMCLKOffset);
+			result = get_clock_voltage_dependency_table(hwmgr,
+				&hwmgr->dyn_state.vddci_dependency_on_mclk, table);
+		}
+
+		if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
+			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
+				(((unsigned long) powerplay_table4) +
+				powerplay_table4->usVddcDependencyOnMCLKOffset);
+			result = get_clock_voltage_dependency_table(hwmgr,
+				&hwmgr->dyn_state.vddc_dependency_on_mclk, table);
+		}
+
+		if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
+			limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
+				(((unsigned long) powerplay_table4) +
+				powerplay_table4->usMaxClockVoltageOnDCOffset);
+			result = get_clock_voltage_limit(hwmgr,
+				&hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
+		}
+
+		if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
+			(0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
+			result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
+					hwmgr->dyn_state.vddc_dependency_on_mclk);
+
+		if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
+			(0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
+			result = get_valid_clk(hwmgr,
+				&hwmgr->dyn_state.valid_sclk_values,
+				hwmgr->dyn_state.vddc_dependency_on_sclk);
+
+		if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
+			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
+				(((unsigned long) powerplay_table4) +
+				powerplay_table4->usMvddDependencyOnMCLKOffset);
+			result = get_clock_voltage_dependency_table(hwmgr,
+				&hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
+		}
+	}
+
+	table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
+								powerplay_table);
+
+	if (table_offset > 0) {
+		table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
+			(((unsigned long) powerplay_table) + table_offset);
+		result = get_clock_voltage_dependency_table(hwmgr,
+			&hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
+	}
+
+	return result;
+}
+
+static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
+				 struct phm_cac_leakage_table **ptable,
+				const ATOM_PPLIB_CAC_Leakage_Table *table)
+{
+	struct phm_cac_leakage_table  *cac_leakage_table;
+	unsigned long            table_size, i;
+
+	if (hwmgr == NULL || table == NULL || ptable == NULL)
+		return -EINVAL;
+
+	table_size = sizeof(ULONG) +
+		(sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
+
+	cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
+
+	if (cac_leakage_table == NULL)
+		return -ENOMEM;
+
+	cac_leakage_table->count = (ULONG)table->ucNumEntries;
+
+	for (i = 0; i < cac_leakage_table->count; i++) {
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_EVV)) {
+			cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
+			cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
+			cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
+		} else {
+			cac_leakage_table->entries[i].Vddc    = le16_to_cpu(table->entries[i].usVddc);
+			cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
+		}
+	}
+
+	*ptable = cac_leakage_table;
+
+	return 0;
+}
+
+static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
+			ATOM_PPLIB_PPM_Table *atom_ppm_table)
+{
+	struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
+
+	if (NULL == ptr)
+		return -ENOMEM;
+
+	ptr->ppm_design            = atom_ppm_table->ucPpmDesign;
+	ptr->cpu_core_number        = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
+	ptr->platform_tdp          = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
+	ptr->small_ac_platform_tdp   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
+	ptr->platform_tdc          = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
+	ptr->small_ac_platform_tdc   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
+	ptr->apu_tdp               = le32_to_cpu(atom_ppm_table->ulApuTDP);
+	ptr->dgpu_tdp              = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
+	ptr->dgpu_ulv_power         = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
+	ptr->tj_max                = le32_to_cpu(atom_ppm_table->ulTjmax);
+	hwmgr->dyn_state.ppm_parameter_table = ptr;
+
+	return 0;
+}
+
+static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
+			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	int result = 0;
+
+	if (le16_to_cpu(powerplay_table->usTableSize) >=
+	    sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
+		const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
+				(const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
+		const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
+				(const ATOM_PPLIB_POWERPLAYTABLE4 *)
+				(&ptable5->basicTable4);
+		const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
+				(const ATOM_PPLIB_POWERPLAYTABLE3 *)
+				(&ptable4->basicTable3);
+		const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
+		uint16_t table_offset;
+		ATOM_PPLIB_PPM_Table *atom_ppm_table;
+
+		hwmgr->platform_descriptor.TDPLimit     = le32_to_cpu(ptable5->ulTDPLimit);
+		hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
+
+		hwmgr->platform_descriptor.TDPODLimit   = le16_to_cpu(ptable5->usTDPODLimit);
+		hwmgr->platform_descriptor.TDPAdjustment = 0;
+
+		hwmgr->platform_descriptor.VidAdjustment = 0;
+		hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
+		hwmgr->platform_descriptor.VidMinLimit     = 0;
+		hwmgr->platform_descriptor.VidMaxLimit     = 1500000;
+		hwmgr->platform_descriptor.VidStep         = 6250;
+
+		hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
+
+		if (hwmgr->platform_descriptor.TDPODLimit != 0)
+			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_PowerControl);
+
+		hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
+
+		hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
+
+		hwmgr->dyn_state.cac_leakage_table = NULL;
+
+		if (0 != ptable5->usCACLeakageTableOffset) {
+			const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
+				(ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
+				le16_to_cpu(ptable5->usCACLeakageTableOffset));
+			result = get_cac_leakage_table(hwmgr,
+				&hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
+		}
+
+		hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
+
+		hwmgr->dyn_state.ppm_parameter_table = NULL;
+
+		if (0 != ptable3->usExtendendedHeaderOffset) {
+			extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
+					(((unsigned long)powerplay_table) +
+					le16_to_cpu(ptable3->usExtendendedHeaderOffset));
+			if ((extended_header->usPPMTableOffset > 0) &&
+				le16_to_cpu(extended_header->usSize) >=
+				    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
+				table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
+				atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
+					(((unsigned long)powerplay_table) + table_offset);
+				if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
+					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_EnablePlatformPowerManagement);
+			}
+		}
+	}
+	return result;
+}
+
+static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
+		const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
+{
+	if (le16_to_cpu(powerplay_table->usTableSize) >=
+	    sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
+		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
+				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
+
+		if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
+			const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
+				(ATOM_PPLIB_PhaseSheddingLimits_Table *)
+				(((unsigned long)powerplay_table4) +
+				le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
+			struct phm_phase_shedding_limits_table *table;
+			unsigned long size, i;
+
+
+			size = sizeof(unsigned long) +
+				(sizeof(struct phm_phase_shedding_limits_table) *
+				ptable->ucNumEntries);
+
+			table = kzalloc(size, GFP_KERNEL);
+
+			if (table == NULL)
+				return -ENOMEM;
+
+			table->count = (unsigned long)ptable->ucNumEntries;
+
+			for (i = 0; i < table->count; i++) {
+				table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
+				table->entries[i].Sclk    = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
+							| le16_to_cpu(ptable->entries[i].usSclkLow);
+				table->entries[i].Mclk    = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
+							| le16_to_cpu(ptable->entries[i].usMclkLow);
+			}
+			hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
+		}
+	}
+
+	return 0;
+}
+
+int get_number_of_vce_state_table_entries(
+						  struct pp_hwmgr *hwmgr)
+{
+	const ATOM_PPLIB_POWERPLAYTABLE *table =
+					     get_powerplay_table(hwmgr);
+	const ATOM_PPLIB_VCE_State_Table *vce_table =
+				    get_vce_state_table(hwmgr, table);
+
+	if (vce_table > 0)
+		return vce_table->numEntries;
+
+	return 0;
+}
+
+int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
+							unsigned long i,
+							struct PP_VCEState *vce_state,
+							void **clock_info,
+							unsigned long *flag)
+{
+	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
+
+	const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
+
+	unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
+
+	const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
+
+	const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + powerplay_table->usClockInfoArrayOffset);
+
+	const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
+
+	const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
+
+	unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
+
+	*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
+
+	vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | vce_clock_info->usEVClkLow;
+	vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | vce_clock_info->usECClkLow;
+
+	*clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
+
+	return 0;
+}
+
+
+static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
+{
+	int result;
+	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
+
+	hwmgr->need_pp_table_upload = true;
+
+	powerplay_table = get_powerplay_table(hwmgr);
+
+	result = init_powerplay_tables(hwmgr, powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "init_powerplay_tables failed", return result);
+
+	result = set_platform_caps(hwmgr,
+				le32_to_cpu(powerplay_table->ulPlatformCaps));
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "set_platform_caps failed", return result);
+
+	result = init_thermal_controller(hwmgr, powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "init_thermal_controller failed", return result);
+
+	result = init_overdrive_limits(hwmgr, powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "init_overdrive_limits failed", return result);
+
+	result = init_clock_voltage_dependency(hwmgr,
+					       powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "init_clock_voltage_dependency failed", return result);
+
+	result = init_dpm2_parameters(hwmgr, powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "init_dpm2_parameters failed", return result);
+
+	result = init_phase_shedding_table(hwmgr, powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "init_phase_shedding_table failed", return result);
+
+	return result;
+}
+
+static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
+{
+	if (NULL != hwmgr->soft_pp_table) {
+		kfree(hwmgr->soft_pp_table);
+		hwmgr->soft_pp_table = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) {
+		kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
+		hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) {
+		kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
+		hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) {
+		kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
+		hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) {
+		kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
+		hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.valid_mclk_values) {
+		kfree(hwmgr->dyn_state.valid_mclk_values);
+		hwmgr->dyn_state.valid_mclk_values = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.valid_sclk_values) {
+		kfree(hwmgr->dyn_state.valid_sclk_values);
+		hwmgr->dyn_state.valid_sclk_values = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.cac_leakage_table) {
+		kfree(hwmgr->dyn_state.cac_leakage_table);
+		hwmgr->dyn_state.cac_leakage_table = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.vddc_phase_shed_limits_table) {
+		kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
+		hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.vce_clock_voltage_dependency_table) {
+		kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
+		hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.uvd_clock_voltage_dependency_table) {
+		kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
+		hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.samu_clock_voltage_dependency_table) {
+		kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
+		hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.acp_clock_voltage_dependency_table) {
+		kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
+		hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.cac_dtp_table) {
+		kfree(hwmgr->dyn_state.cac_dtp_table);
+		hwmgr->dyn_state.cac_dtp_table = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.ppm_parameter_table) {
+		kfree(hwmgr->dyn_state.ppm_parameter_table);
+		hwmgr->dyn_state.ppm_parameter_table = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.vdd_gfx_dependency_on_sclk) {
+		kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
+		hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
+	}
+
+	if (NULL != hwmgr->dyn_state.vq_budgeting_table) {
+		kfree(hwmgr->dyn_state.vq_budgeting_table);
+		hwmgr->dyn_state.vq_budgeting_table = NULL;
+	}
+
+	return 0;
+}
+
+const struct pp_table_func pptable_funcs = {
+	.pptable_init = pp_tables_initialize,
+	.pptable_fini = pp_tables_uninitialize,
+	.pptable_get_number_of_vce_state_table_entries =
+				get_number_of_vce_state_table_entries,
+	.pptable_get_vce_state_table_entry =
+						get_vce_state_table_entry,
+};
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h
new file mode 100644
index 0000000..3043480
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ * Interface Functions related to the BIOS PowerPlay Tables.
+ *
+ */
+
+#ifndef PROCESSPPTABLES_H
+#define PROCESSPPTABLES_H
+
+struct pp_hwmgr;
+struct pp_power_state;
+struct pp_hw_power_state;
+
+extern const struct pp_table_func pptable_funcs;
+
+typedef int (*pp_tables_hw_clock_info_callback)(struct pp_hwmgr *hwmgr,
+					struct pp_hw_power_state *hw_ps,
+							unsigned int index,
+						 const void *clock_info);
+
+int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
+				     unsigned long *num_of_entries);
+
+int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
+						unsigned long entry_index,
+						struct pp_power_state *ps,
+				pp_tables_hw_clock_info_callback func);
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.c
new file mode 100644
index 0000000..e58d038
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#include "hwmgr.h"
+#include "tonga_clockpowergating.h"
+#include "tonga_ppsmc.h"
+#include "tonga_hwmgr.h"
+
+int tonga_phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cf_want_uvd_power_gating(hwmgr))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+						     PPSMC_MSG_UVDPowerOFF);
+	return 0;
+}
+
+int tonga_phm_powerup_uvd(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cf_want_uvd_power_gating(hwmgr)) {
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				  PHM_PlatformCaps_UVDDynamicPowerGating)) {
+			return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+								PPSMC_MSG_UVDPowerON, 1);
+		} else {
+			return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+								PPSMC_MSG_UVDPowerON, 0);
+		}
+	}
+
+	return 0;
+}
+
+int tonga_phm_powerdown_vce(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cf_want_vce_power_gating(hwmgr))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+						  PPSMC_MSG_VCEPowerOFF);
+	return 0;
+}
+
+int tonga_phm_powerup_vce(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cf_want_vce_power_gating(hwmgr))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+						  PPSMC_MSG_VCEPowerON);
+	return 0;
+}
+
+int tonga_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating)
+{
+	int ret = 0;
+
+	switch (block) {
+	case PHM_AsicBlock_UVD_MVC:
+	case PHM_AsicBlock_UVD:
+	case PHM_AsicBlock_UVD_HD:
+	case PHM_AsicBlock_UVD_SD:
+		if (gating == PHM_ClockGateSetting_StaticOff)
+			ret = tonga_phm_powerdown_uvd(hwmgr);
+		else
+			ret = tonga_phm_powerup_uvd(hwmgr);
+		break;
+	case PHM_AsicBlock_GFX:
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+int tonga_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	data->uvd_power_gated = false;
+	data->vce_power_gated = false;
+
+	tonga_phm_powerup_uvd(hwmgr);
+	tonga_phm_powerup_vce(hwmgr);
+
+	return 0;
+}
+
+int tonga_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	if (data->uvd_power_gated == bgate)
+		return 0;
+
+	data->uvd_power_gated = bgate;
+
+	if (bgate) {
+		cgs_set_clockgating_state(hwmgr->device,
+						AMD_IP_BLOCK_TYPE_UVD,
+						AMD_CG_STATE_UNGATE);
+		cgs_set_powergating_state(hwmgr->device,
+						AMD_IP_BLOCK_TYPE_UVD,
+						AMD_PG_STATE_GATE);
+		tonga_update_uvd_dpm(hwmgr, true);
+		tonga_phm_powerdown_uvd(hwmgr);
+	} else {
+		tonga_phm_powerup_uvd(hwmgr);
+		cgs_set_powergating_state(hwmgr->device,
+						AMD_IP_BLOCK_TYPE_UVD,
+						AMD_PG_STATE_UNGATE);
+		cgs_set_clockgating_state(hwmgr->device,
+						AMD_IP_BLOCK_TYPE_UVD,
+						AMD_PG_STATE_GATE);
+
+		tonga_update_uvd_dpm(hwmgr, false);
+	}
+
+	return 0;
+}
+
+int tonga_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	struct phm_set_power_state_input states;
+	const struct pp_power_state  *pcurrent;
+	struct pp_power_state  *requested;
+
+	pcurrent = hwmgr->current_ps;
+	requested = hwmgr->request_ps;
+
+	states.pcurrent_state = &(pcurrent->hardware);
+	states.pnew_state = &(requested->hardware);
+
+	if (phm_cf_want_vce_power_gating(hwmgr)) {
+		if (data->vce_power_gated != bgate) {
+			if (bgate) {
+				cgs_set_clockgating_state(
+							hwmgr->device,
+							AMD_IP_BLOCK_TYPE_VCE,
+							AMD_CG_STATE_UNGATE);
+				cgs_set_powergating_state(
+							hwmgr->device,
+							AMD_IP_BLOCK_TYPE_VCE,
+							AMD_PG_STATE_GATE);
+				tonga_enable_disable_vce_dpm(hwmgr, false);
+				data->vce_power_gated = true;
+			} else {
+				tonga_phm_powerup_vce(hwmgr);
+				data->vce_power_gated = false;
+				cgs_set_powergating_state(
+							hwmgr->device,
+							AMD_IP_BLOCK_TYPE_VCE,
+							AMD_PG_STATE_UNGATE);
+				cgs_set_clockgating_state(
+							hwmgr->device,
+							AMD_IP_BLOCK_TYPE_VCE,
+							AMD_PG_STATE_GATE);
+
+				tonga_update_vce_dpm(hwmgr, &states);
+				tonga_enable_disable_vce_dpm(hwmgr, true);
+				return 0;
+			}
+		}
+	} else {
+		tonga_update_vce_dpm(hwmgr, &states);
+		tonga_enable_disable_vce_dpm(hwmgr, true);
+		return 0;
+	}
+
+	if (!data->vce_power_gated)
+		tonga_update_vce_dpm(hwmgr, &states);
+
+	return 0;
+}
+
+int tonga_phm_update_clock_gatings(struct pp_hwmgr *hwmgr,
+					const uint32_t *msg_id)
+{
+	PPSMC_Msg msg;
+	uint32_t value;
+
+	switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
+	case PP_GROUP_GFX:
+		switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
+		case PP_BLOCK_GFX_CG:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
+				  ? PPSMC_MSG_EnableClockGatingFeature
+				  : PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_GFX_CGCG_MASK;
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
+					? PPSMC_MSG_EnableClockGatingFeature
+					: PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_GFX_CGLS_MASK;
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_GFX_MG:
+			/* For GFX MGCG, there are three different ones;
+			 * CPF, RLC, and all others.  CPF MGCG will not be used for Tonga.
+			 * For GFX MGLS, Tonga will not support it.
+			 * */
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
+				? PPSMC_MSG_EnableClockGatingFeature
+				: PPSMC_MSG_DisableClockGatingFeature;
+				value = (CG_RLC_MGCG_MASK | CG_GFX_OTHERS_MGCG_MASK);
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		default:
+			return -1;
+		}
+		break;
+
+	case PP_GROUP_SYS:
+		switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
+		case PP_BLOCK_SYS_BIF:
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
+				? PPSMC_MSG_EnableClockGatingFeature
+				: PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_BIF_MGLS_MASK;
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_SYS_MC:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
+				? PPSMC_MSG_EnableClockGatingFeature
+				: PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_MC_MGCG_MASK;
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+			}
+
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
+				? PPSMC_MSG_EnableClockGatingFeature
+				: PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_MC_MGLS_MASK;
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+
+			}
+			break;
+
+		case PP_BLOCK_SYS_HDP:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
+					? PPSMC_MSG_EnableClockGatingFeature
+					: PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_HDP_MGCG_MASK;
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+			}
+
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
+					? PPSMC_MSG_EnableClockGatingFeature
+					: PPSMC_MSG_DisableClockGatingFeature;
+
+				value = CG_SYS_HDP_MGLS_MASK;
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_SYS_SDMA:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
+				? PPSMC_MSG_EnableClockGatingFeature
+				: PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_SDMA_MGCG_MASK;
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+			}
+
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
+				? PPSMC_MSG_EnableClockGatingFeature
+				: PPSMC_MSG_DisableClockGatingFeature;
+
+				value = CG_SYS_SDMA_MGLS_MASK;
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_SYS_ROM:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
+				? PPSMC_MSG_EnableClockGatingFeature
+				: PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_ROM_MASK;
+
+				if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		default:
+			return -1;
+
+		}
+		break;
+
+	default:
+		return -1;
+
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.h
new file mode 100644
index 0000000..8bc38cb
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _TONGA_CLOCK_POWER_GATING_H_
+#define _TONGA_CLOCK_POWER_GATING_H_
+
+#include "tonga_hwmgr.h"
+#include "pp_asicblocks.h"
+
+extern int tonga_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating);
+extern int tonga_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate);
+extern int tonga_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate);
+extern int tonga_phm_powerdown_uvd(struct pp_hwmgr *hwmgr);
+extern int tonga_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr);
+extern int tonga_phm_update_clock_gatings(struct pp_hwmgr *hwmgr, const uint32_t *msg_id);
+#endif /* _TONGA_CLOCK_POWER_GATING_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_dyn_defaults.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_dyn_defaults.h
new file mode 100644
index 0000000..080d69d
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_dyn_defaults.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef TONGA_DYN_DEFAULTS_H
+#define TONGA_DYN_DEFAULTS_H
+
+
+/** \file
+ * Volcanic Islands Dynamic default parameters.
+ */
+
+enum TONGAdpm_TrendDetection {
+	TONGAdpm_TrendDetection_AUTO,
+	TONGAdpm_TrendDetection_UP,
+	TONGAdpm_TrendDetection_DOWN
+};
+typedef enum TONGAdpm_TrendDetection TONGAdpm_TrendDetection;
+
+/* Bit vector representing same fields as hardware register. */
+#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT0              0x3FFFC102  /* CP_Gfx_busy */
+/* HDP_busy */
+/* IH_busy */
+/* DRM_busy */
+/* DRMDMA_busy */
+/* UVD_busy */
+/* VCE_busy */
+/* ACP_busy */
+/* SAMU_busy */
+/* AVP_busy  */
+/* SDMA enabled */
+#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT1              0x000400  /* FE_Gfx_busy  - Intended for primary usage.   Rest are for flexibility. */
+/* SH_Gfx_busy */
+/* RB_Gfx_busy */
+/* VCE_busy */
+
+#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT2              0xC00080  /* SH_Gfx_busy - Intended for primary usage.   Rest are for flexibility. */
+/* FE_Gfx_busy */
+/* RB_Gfx_busy */
+/* ACP_busy */
+
+#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT3              0xC00200  /* RB_Gfx_busy - Intended for primary usage.   Rest are for flexibility. */
+/* FE_Gfx_busy */
+/* SH_Gfx_busy */
+/* UVD_busy */
+
+#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT4              0xC01680  /* UVD_busy */
+/* VCE_busy */
+/* ACP_busy */
+/* SAMU_busy */
+
+#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT5              0xC00033  /* GFX, HDP, DRMDMA */
+#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT6              0xC00033  /* GFX, HDP, DRMDMA */
+#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT7              0x3FFFC000  /* GFX, HDP, DRMDMA */
+
+
+/* thermal protection counter (units).*/
+#define PPTONGA_THERMALPROTECTCOUNTER_DFLT            0x200 /* ~19us */
+
+/* static screen threshold unit */
+#define PPTONGA_STATICSCREENTHRESHOLDUNIT_DFLT        0
+
+/* static screen threshold */
+#define PPTONGA_STATICSCREENTHRESHOLD_DFLT            0x00C8
+
+/* gfx idle clock stop threshold */
+#define PPTONGA_GFXIDLECLOCKSTOPTHRESHOLD_DFLT        0x200 /* ~19us with static screen threshold unit of 0 */
+
+/* Fixed reference divider to use when building baby stepping tables. */
+#define PPTONGA_REFERENCEDIVIDER_DFLT                  4
+
+/*
+ * ULV voltage change delay time
+ * Used to be delay_vreg in N.I. split for S.I.
+ * Using N.I. delay_vreg value as default
+ * ReferenceClock = 2700
+ * VoltageResponseTime = 1000
+ * VDDCDelayTime = (VoltageResponseTime * ReferenceClock) / 1600 = 1687
+ */
+
+#define PPTONGA_ULVVOLTAGECHANGEDELAY_DFLT             1687
+
+#define PPTONGA_CGULVPARAMETER_DFLT                    0x00040035
+#define PPTONGA_CGULVCONTROL_DFLT                      0x00007450
+#define PPTONGA_TARGETACTIVITY_DFLT                     30  /*30%  */
+#define PPTONGA_MCLK_TARGETACTIVITY_DFLT                10  /*10%  */
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
new file mode 100644
index 0000000..44a9250
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
@@ -0,0 +1,6075 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include "linux/delay.h"
+#include "pp_acpi.h"
+#include "hwmgr.h"
+#include <atombios.h>
+#include "tonga_hwmgr.h"
+#include "pptable.h"
+#include "processpptables.h"
+#include "tonga_processpptables.h"
+#include "tonga_pptable.h"
+#include "pp_debug.h"
+#include "tonga_ppsmc.h"
+#include "cgs_common.h"
+#include "pppcielanes.h"
+#include "tonga_dyn_defaults.h"
+#include "smumgr.h"
+#include "tonga_smumgr.h"
+#include "tonga_clockpowergating.h"
+#include "tonga_thermal.h"
+
+#include "smu/smu_7_1_2_d.h"
+#include "smu/smu_7_1_2_sh_mask.h"
+
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+
+#include "bif/bif_5_0_d.h"
+#include "bif/bif_5_0_sh_mask.h"
+
+#include "cgs_linux.h"
+#include "eventmgr.h"
+#include "amd_pcie_helpers.h"
+
+#define MC_CG_ARB_FREQ_F0           0x0a
+#define MC_CG_ARB_FREQ_F1           0x0b
+#define MC_CG_ARB_FREQ_F2           0x0c
+#define MC_CG_ARB_FREQ_F3           0x0d
+
+#define MC_CG_SEQ_DRAMCONF_S0       0x05
+#define MC_CG_SEQ_DRAMCONF_S1       0x06
+#define MC_CG_SEQ_YCLK_SUSPEND      0x04
+#define MC_CG_SEQ_YCLK_RESUME       0x0a
+
+#define PCIE_BUS_CLK                10000
+#define TCLK                        (PCIE_BUS_CLK / 10)
+
+#define SMC_RAM_END 0x40000
+#define SMC_CG_IND_START            0xc0030000
+#define SMC_CG_IND_END              0xc0040000  /* First byte after SMC_CG_IND*/
+
+#define VOLTAGE_SCALE               4
+#define VOLTAGE_VID_OFFSET_SCALE1   625
+#define VOLTAGE_VID_OFFSET_SCALE2   100
+
+#define VDDC_VDDCI_DELTA            200
+#define VDDC_VDDGFX_DELTA           300
+
+#define MC_SEQ_MISC0_GDDR5_SHIFT 28
+#define MC_SEQ_MISC0_GDDR5_MASK  0xf0000000
+#define MC_SEQ_MISC0_GDDR5_VALUE 5
+
+typedef uint32_t PECI_RegistryValue;
+
+/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */
+uint16_t PP_ClockStretcherLookupTable[2][4] = {
+	{600, 1050, 3, 0},
+	{600, 1050, 6, 1} };
+
+/* [FF, SS] type, [] 4 voltage ranges, and [Floor Freq, Boundary Freq, VID min , VID max] */
+uint32_t PP_ClockStretcherDDTTable[2][4][4] = {
+	{ {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
+	{ {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } };
+
+/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] (coming from PWR_CKS_CNTL.stretch_amount reg spec) */
+uint8_t PP_ClockStretchAmountConversion[2][6] = {
+	{0, 1, 3, 2, 4, 5},
+	{0, 2, 4, 5, 6, 5} };
+
+/* Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */
+enum DPM_EVENT_SRC {
+	DPM_EVENT_SRC_ANALOG = 0,               /* Internal analog trip point */
+	DPM_EVENT_SRC_EXTERNAL = 1,             /* External (GPIO 17) signal */
+	DPM_EVENT_SRC_DIGITAL = 2,              /* Internal digital trip point (DIG_THERM_DPM) */
+	DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,   /* Internal analog or external */
+	DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4   /* Internal digital or external */
+};
+typedef enum DPM_EVENT_SRC DPM_EVENT_SRC;
+
+const unsigned long PhwTonga_Magic = (unsigned long)(PHM_VIslands_Magic);
+
+struct tonga_power_state *cast_phw_tonga_power_state(
+				  struct pp_hw_power_state *hw_ps)
+{
+	if (hw_ps == NULL)
+		return NULL;
+
+	PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic),
+				"Invalid Powerstate Type!",
+				 return NULL);
+
+	return (struct tonga_power_state *)hw_ps;
+}
+
+const struct tonga_power_state *cast_const_phw_tonga_power_state(
+				 const struct pp_hw_power_state *hw_ps)
+{
+	if (hw_ps == NULL)
+		return NULL;
+
+	PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic),
+				"Invalid Powerstate Type!",
+				 return NULL);
+
+	return (const struct tonga_power_state *)hw_ps;
+}
+
+int tonga_add_voltage(struct pp_hwmgr *hwmgr,
+	phm_ppt_v1_voltage_lookup_table *look_up_table,
+	phm_ppt_v1_voltage_lookup_record *record)
+{
+	uint32_t i;
+	PP_ASSERT_WITH_CODE((NULL != look_up_table),
+		"Lookup Table empty.", return -1;);
+	PP_ASSERT_WITH_CODE((0 != look_up_table->count),
+		"Lookup Table empty.", return -1;);
+	PP_ASSERT_WITH_CODE((SMU72_MAX_LEVELS_VDDGFX >= look_up_table->count),
+		"Lookup Table is full.", return -1;);
+
+	/* This is to avoid entering duplicate calculated records. */
+	for (i = 0; i < look_up_table->count; i++) {
+		if (look_up_table->entries[i].us_vdd == record->us_vdd) {
+			if (look_up_table->entries[i].us_calculated == 1)
+				return 0;
+			else
+				break;
+		}
+	}
+
+	look_up_table->entries[i].us_calculated = 1;
+	look_up_table->entries[i].us_vdd = record->us_vdd;
+	look_up_table->entries[i].us_cac_low = record->us_cac_low;
+	look_up_table->entries[i].us_cac_mid = record->us_cac_mid;
+	look_up_table->entries[i].us_cac_high = record->us_cac_high;
+	/* Only increment the count when we're appending, not replacing duplicate entry. */
+	if (i == look_up_table->count)
+		look_up_table->count++;
+
+	return 0;
+}
+
+int tonga_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display)
+{
+	PPSMC_Msg msg = has_display? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay;
+
+	return (smum_send_msg_to_smc(hwmgr->smumgr, msg) == 0) ?  0 : -1;
+}
+
+uint8_t tonga_get_voltage_id(pp_atomctrl_voltage_table *voltage_table,
+		uint32_t voltage)
+{
+	uint8_t count = (uint8_t) (voltage_table->count);
+	uint8_t i = 0;
+
+	PP_ASSERT_WITH_CODE((NULL != voltage_table),
+		"Voltage Table empty.", return 0;);
+	PP_ASSERT_WITH_CODE((0 != count),
+		"Voltage Table empty.", return 0;);
+
+	for (i = 0; i < count; i++) {
+		/* find first voltage bigger than requested */
+		if (voltage_table->entries[i].value >= voltage)
+			return i;
+	}
+
+	/* voltage is bigger than max voltage in the table */
+	return i - 1;
+}
+
+/**
+ * @brief PhwTonga_GetVoltageOrder
+ *  Returns index of requested voltage record in lookup(table)
+ * @param hwmgr - pointer to hardware manager
+ * @param lookupTable - lookup list to search in
+ * @param voltage - voltage to look for
+ * @return 0 on success
+ */
+uint8_t tonga_get_voltage_index(phm_ppt_v1_voltage_lookup_table *look_up_table,
+		uint16_t voltage)
+{
+	uint8_t count = (uint8_t) (look_up_table->count);
+	uint8_t i;
+
+	PP_ASSERT_WITH_CODE((NULL != look_up_table), "Lookup Table empty.", return 0;);
+	PP_ASSERT_WITH_CODE((0 != count), "Lookup Table empty.", return 0;);
+
+	for (i = 0; i < count; i++) {
+		/* find first voltage equal or bigger than requested */
+		if (look_up_table->entries[i].us_vdd >= voltage)
+			return i;
+	}
+
+	/* voltage is bigger than max voltage in the table */
+	return i-1;
+}
+
+bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr)
+{
+	/*
+	 * We return the status of Voltage Control instead of checking SCLK/MCLK DPM
+	 * because we may have test scenarios that need us intentionly disable SCLK/MCLK DPM,
+	 * whereas voltage control is a fundemental change that will not be disabled
+	 */
+
+	return (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+					FEATURE_STATUS, VOLTAGE_CONTROLLER_ON) ? 1 : 0);
+}
+
+/**
+ * Re-generate the DPM level mask value
+ * @param    hwmgr      the address of the hardware manager
+ */
+static uint32_t tonga_get_dpm_level_enable_mask_value(
+			struct tonga_single_dpm_table * dpm_table)
+{
+	uint32_t i;
+	uint32_t mask_value = 0;
+
+	for (i = dpm_table->count; i > 0; i--) {
+		mask_value = mask_value << 1;
+
+		if (dpm_table->dpm_levels[i-1].enabled)
+			mask_value |= 0x1;
+		else
+			mask_value &= 0xFFFFFFFE;
+	}
+	return mask_value;
+}
+
+/**
+ * Retrieve DPM default values from registry (if available)
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ */
+void tonga_initialize_dpm_defaults(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	phw_tonga_ulv_parm *ulv = &(data->ulv);
+	uint32_t tmp;
+
+	ulv->ch_ulv_parameter = PPTONGA_CGULVPARAMETER_DFLT;
+	data->voting_rights_clients0 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT0;
+	data->voting_rights_clients1 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT1;
+	data->voting_rights_clients2 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT2;
+	data->voting_rights_clients3 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT3;
+	data->voting_rights_clients4 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT4;
+	data->voting_rights_clients5 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT5;
+	data->voting_rights_clients6 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT6;
+	data->voting_rights_clients7 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT7;
+
+	data->static_screen_threshold_unit = PPTONGA_STATICSCREENTHRESHOLDUNIT_DFLT;
+	data->static_screen_threshold = PPTONGA_STATICSCREENTHRESHOLD_DFLT;
+
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_ABM);
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_NonABMSupportInPPLib);
+
+	tmp = 0;
+	if (tmp == 0)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_DynamicACTiming);
+
+	tmp = 0;
+	if (0 != tmp)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_DisableMemoryTransition);
+
+	data->mclk_strobe_mode_threshold = 40000;
+	data->mclk_stutter_mode_threshold = 30000;
+	data->mclk_edc_enable_threshold = 40000;
+	data->mclk_edc_wr_enable_threshold = 40000;
+
+	tmp = 0;
+	if (tmp != 0)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_DisableMCLS);
+
+	data->pcie_gen_performance.max = PP_PCIEGen1;
+	data->pcie_gen_performance.min = PP_PCIEGen3;
+	data->pcie_gen_power_saving.max = PP_PCIEGen1;
+	data->pcie_gen_power_saving.min = PP_PCIEGen3;
+
+	data->pcie_lane_performance.max = 0;
+	data->pcie_lane_performance.min = 16;
+	data->pcie_lane_power_saving.max = 0;
+	data->pcie_lane_power_saving.min = 16;
+
+	tmp = 0;
+
+	if (tmp)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SclkThrottleLowNotification);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_DynamicUVDState);
+
+}
+
+int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	int result = 0;
+	uint32_t low_sclk_interrupt_threshold = 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SclkThrottleLowNotification)
+		&& (hwmgr->gfx_arbiter.sclk_threshold != data->low_sclk_interrupt_threshold)) {
+		data->low_sclk_interrupt_threshold = hwmgr->gfx_arbiter.sclk_threshold;
+		low_sclk_interrupt_threshold = data->low_sclk_interrupt_threshold;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
+
+		result = tonga_copy_bytes_to_smc(
+				hwmgr->smumgr,
+				data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable,
+				LowSclkInterruptThreshold),
+				(uint8_t *)&low_sclk_interrupt_threshold,
+				sizeof(uint32_t),
+				data->sram_end
+				);
+	}
+
+	return result;
+}
+
+/**
+ * Find SCLK value that is associated with specified virtual_voltage_Id.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @param    virtual_voltage_Id  voltageId to look for.
+ * @param    sclk output value .
+ * @return   always 0 if success and 2 if association not found
+ */
+static int tonga_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
+	phm_ppt_v1_voltage_lookup_table *lookup_table,
+	uint16_t virtual_voltage_id, uint32_t *sclk)
+{
+	uint8_t entryId;
+	uint8_t voltageId;
+	struct phm_ppt_v1_information *pptable_info =
+					(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -1);
+
+	/* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */
+	for (entryId = 0; entryId < pptable_info->vdd_dep_on_sclk->count; entryId++) {
+		voltageId = pptable_info->vdd_dep_on_sclk->entries[entryId].vddInd;
+		if (lookup_table->entries[voltageId].us_vdd == virtual_voltage_id)
+			break;
+	}
+
+	PP_ASSERT_WITH_CODE(entryId < pptable_info->vdd_dep_on_sclk->count,
+			"Can't find requested voltage id in vdd_dep_on_sclk table!",
+			return -1;
+			);
+
+	*sclk = pptable_info->vdd_dep_on_sclk->entries[entryId].clk;
+
+	return 0;
+}
+
+/**
+ * Get Leakage VDDC based on leakage ID.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   2 if vddgfx returned is greater than 2V or if BIOS
+ */
+int tonga_get_evv_voltage(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk;
+	uint16_t    virtual_voltage_id;
+	uint16_t    vddc = 0;
+	uint16_t    vddgfx = 0;
+	uint16_t    i, j;
+	uint32_t  sclk = 0;
+
+	/* retrieve voltage for leakage ID (0xff01 + i) */
+	for (i = 0; i < TONGA_MAX_LEAKAGE_COUNT; i++) {
+		virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
+
+		/* in split mode we should have only vddgfx EVV leakages */
+		if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) {
+			if (0 == tonga_get_sclk_for_voltage_evv(hwmgr,
+						pptable_info->vddgfx_lookup_table, virtual_voltage_id, &sclk)) {
+				if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+							PHM_PlatformCaps_ClockStretcher)) {
+					for (j = 1; j < sclk_table->count; j++) {
+						if (sclk_table->entries[j].clk == sclk &&
+								sclk_table->entries[j].cks_enable == 0) {
+							sclk += 5000;
+							break;
+						}
+					}
+				}
+				PP_ASSERT_WITH_CODE(0 == atomctrl_get_voltage_evv_on_sclk
+						(hwmgr, VOLTAGE_TYPE_VDDGFX, sclk,
+						 virtual_voltage_id, &vddgfx),
+						"Error retrieving EVV voltage value!", continue);
+
+				/* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */
+				PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -1);
+
+				/* the voltage should not be zero nor equal to leakage ID */
+				if (vddgfx != 0 && vddgfx != virtual_voltage_id) {
+					data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx;
+					data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = virtual_voltage_id;
+					data->vddcgfx_leakage.count++;
+				}
+			}
+		} else {
+			/*  in merged mode we have only vddc EVV leakages */
+			if (0 == tonga_get_sclk_for_voltage_evv(hwmgr,
+						pptable_info->vddc_lookup_table,
+						virtual_voltage_id, &sclk)) {
+				PP_ASSERT_WITH_CODE(0 == atomctrl_get_voltage_evv_on_sclk
+						(hwmgr, VOLTAGE_TYPE_VDDC, sclk,
+						 virtual_voltage_id, &vddc),
+						"Error retrieving EVV voltage value!", continue);
+
+				/* need to make sure vddc is less than 2v or else, it could burn the ASIC. */
+				if (vddc > 2000)
+					printk(KERN_ERR "[ powerplay ] Invalid VDDC value! \n");
+
+				/* the voltage should not be zero nor equal to leakage ID */
+				if (vddc != 0 && vddc != virtual_voltage_id) {
+					data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc;
+					data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id;
+					data->vddc_leakage.count++;
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+int tonga_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	/* enable SCLK dpm */
+	if (0 == data->sclk_dpm_key_disabled) {
+		PP_ASSERT_WITH_CODE(
+				(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+						   PPSMC_MSG_DPM_Enable)),
+				"Failed to enable SCLK DPM during DPM Start Function!",
+				return -1);
+	}
+
+	/* enable MCLK dpm */
+	if (0 == data->mclk_dpm_key_disabled) {
+		PP_ASSERT_WITH_CODE(
+				(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+					     PPSMC_MSG_MCLKDPM_Enable)),
+				"Failed to enable MCLK DPM during DPM Start Function!",
+				return -1);
+
+		PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1);
+
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixLCAC_MC0_CNTL, 0x05);/* CH0,1 read */
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixLCAC_MC1_CNTL, 0x05);/* CH2,3 read */
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixLCAC_CPL_CNTL, 0x100005);/*Read */
+
+		udelay(10);
+
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixLCAC_MC0_CNTL, 0x400005);/* CH0,1 write */
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixLCAC_MC1_CNTL, 0x400005);/* CH2,3 write */
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixLCAC_CPL_CNTL, 0x500005);/* write */
+
+	}
+
+	return 0;
+}
+
+int tonga_start_dpm(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	/* enable general power management */
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, 1);
+	/* enable sclk deep sleep */
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, DYNAMIC_PM_EN, 1);
+
+	/* prepare for PCIE DPM */
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start +
+			offsetof(SMU72_SoftRegisters, VoltageChangeTimeout), 0x1000);
+
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, SWRST_COMMAND_1, RESETLC, 0x0);
+
+	PP_ASSERT_WITH_CODE(
+			(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+					PPSMC_MSG_Voltage_Cntl_Enable)),
+			"Failed to enable voltage DPM during DPM Start Function!",
+			return -1);
+
+	if (0 != tonga_enable_sclk_mclk_dpm(hwmgr)) {
+		PP_ASSERT_WITH_CODE(0, "Failed to enable Sclk DPM and Mclk DPM!", return -1);
+	}
+
+	/* enable PCIE dpm */
+	if (0 == data->pcie_dpm_key_disabled) {
+		PP_ASSERT_WITH_CODE(
+				(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+						PPSMC_MSG_PCIeDPM_Enable)),
+				"Failed to enable pcie DPM during DPM Start Function!",
+				return -1
+				);
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_Falcon_QuickTransition)) {
+				   smum_send_msg_to_smc(hwmgr->smumgr,
+				    PPSMC_MSG_EnableACDCGPIOInterrupt);
+	}
+
+	return 0;
+}
+
+int tonga_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	/* disable SCLK dpm */
+	if (0 == data->sclk_dpm_key_disabled) {
+		/* Checking if DPM is running.  If we discover hang because of this, we should skip this message.*/
+		PP_ASSERT_WITH_CODE(
+				(0 == tonga_is_dpm_running(hwmgr)),
+				"Trying to Disable SCLK DPM when DPM is disabled",
+				return -1
+				);
+
+		PP_ASSERT_WITH_CODE(
+				(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+						  PPSMC_MSG_DPM_Disable)),
+				"Failed to disable SCLK DPM during DPM stop Function!",
+				return -1);
+	}
+
+	/* disable MCLK dpm */
+	if (0 == data->mclk_dpm_key_disabled) {
+		/* Checking if DPM is running.  If we discover hang because of this, we should skip this message. */
+		PP_ASSERT_WITH_CODE(
+				(0 == tonga_is_dpm_running(hwmgr)),
+				"Trying to Disable MCLK DPM when DPM is disabled",
+				return -1
+				);
+
+		PP_ASSERT_WITH_CODE(
+				(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+					    PPSMC_MSG_MCLKDPM_Disable)),
+				"Failed to Disable MCLK DPM during DPM stop Function!",
+				return -1);
+	}
+
+	return 0;
+}
+
+int tonga_stop_dpm(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, 0);
+	/* disable sclk deep sleep*/
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, DYNAMIC_PM_EN, 0);
+
+	/* disable PCIE dpm */
+	if (0 == data->pcie_dpm_key_disabled) {
+		/* Checking if DPM is running.  If we discover hang because of this, we should skip this message.*/
+		PP_ASSERT_WITH_CODE(
+				(0 == tonga_is_dpm_running(hwmgr)),
+				"Trying to Disable PCIE DPM when DPM is disabled",
+				return -1
+				);
+		PP_ASSERT_WITH_CODE(
+				(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+						PPSMC_MSG_PCIeDPM_Disable)),
+				"Failed to disable pcie DPM during DPM stop Function!",
+				return -1);
+	}
+
+	if (0 != tonga_disable_sclk_mclk_dpm(hwmgr))
+		PP_ASSERT_WITH_CODE(0, "Failed to disable Sclk DPM and Mclk DPM!", return -1);
+
+	/* Checking if DPM is running.  If we discover hang because of this, we should skip this message.*/
+	PP_ASSERT_WITH_CODE(
+			(0 == tonga_is_dpm_running(hwmgr)),
+			"Trying to Disable Voltage CNTL when DPM is disabled",
+			return -1
+			);
+
+	PP_ASSERT_WITH_CODE(
+			(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+					PPSMC_MSG_Voltage_Cntl_Disable)),
+			"Failed to disable voltage DPM during DPM stop Function!",
+			return -1);
+
+	return 0;
+}
+
+int tonga_enable_sclk_control(struct pp_hwmgr *hwmgr)
+{
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, 0);
+
+	return 0;
+}
+
+/**
+ * Send a message to the SMC and return a parameter
+ *
+ * @param    hwmgr:  the address of the powerplay hardware manager.
+ * @param    msg: the message to send.
+ * @param    parameter: pointer to the received parameter
+ * @return   The response that came from the SMC.
+ */
+PPSMC_Result tonga_send_msg_to_smc_return_parameter(
+		struct pp_hwmgr *hwmgr,
+		PPSMC_Msg msg,
+		uint32_t *parameter)
+{
+	int result;
+
+	result = smum_send_msg_to_smc(hwmgr->smumgr, msg);
+
+	if ((0 == result) && parameter) {
+		*parameter = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
+	}
+
+	return result;
+}
+
+/**
+ * force DPM power State
+ *
+ * @param    hwmgr:  the address of the powerplay hardware manager.
+ * @param    n     :  DPM level
+ * @return   The response that came from the SMC.
+ */
+int tonga_dpm_force_state(struct pp_hwmgr *hwmgr, uint32_t n)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	uint32_t level_mask = 1 << n;
+
+	/* Checking if DPM is running.  If we discover hang because of this, we should skip this message. */
+	PP_ASSERT_WITH_CODE(0 == tonga_is_dpm_running(hwmgr),
+			"Trying to force SCLK when DPM is disabled", return -1;);
+	if (0 == data->sclk_dpm_key_disabled)
+		return (0 == smum_send_msg_to_smc_with_parameter(
+							     hwmgr->smumgr,
+		     (PPSMC_Msg)(PPSMC_MSG_SCLKDPM_SetEnabledMask),
+						    level_mask) ? 0 : 1);
+
+	return 0;
+}
+
+/**
+ * force DPM power State
+ *
+ * @param    hwmgr:  the address of the powerplay hardware manager.
+ * @param    n     :  DPM level
+ * @return   The response that came from the SMC.
+ */
+int tonga_dpm_force_state_mclk(struct pp_hwmgr *hwmgr, uint32_t n)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	uint32_t level_mask = 1 << n;
+
+	/* Checking if DPM is running.  If we discover hang because of this, we should skip this message. */
+	PP_ASSERT_WITH_CODE(0 == tonga_is_dpm_running(hwmgr),
+			"Trying to Force MCLK when DPM is disabled", return -1;);
+	if (0 == data->mclk_dpm_key_disabled)
+		return (0 == smum_send_msg_to_smc_with_parameter(
+								hwmgr->smumgr,
+								(PPSMC_Msg)(PPSMC_MSG_MCLKDPM_SetEnabledMask),
+								level_mask) ? 0 : 1);
+
+	return 0;
+}
+
+/**
+ * force DPM power State
+ *
+ * @param    hwmgr:  the address of the powerplay hardware manager.
+ * @param    n     :  DPM level
+ * @return   The response that came from the SMC.
+ */
+int tonga_dpm_force_state_pcie(struct pp_hwmgr *hwmgr, uint32_t n)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	/* Checking if DPM is running.  If we discover hang because of this, we should skip this message.*/
+	PP_ASSERT_WITH_CODE(0 == tonga_is_dpm_running(hwmgr),
+			"Trying to Force PCIE level when DPM is disabled", return -1;);
+	if (0 == data->pcie_dpm_key_disabled)
+		return (0 == smum_send_msg_to_smc_with_parameter(
+							     hwmgr->smumgr,
+			   (PPSMC_Msg)(PPSMC_MSG_PCIeDPM_ForceLevel),
+								n) ? 0 : 1);
+
+	return 0;
+}
+
+/**
+ * Set the initial state by calling SMC to switch to this state directly
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_set_boot_state(struct pp_hwmgr *hwmgr)
+{
+	/*
+	* SMC only stores one state that SW will ask to switch too,
+	* so we switch the the just uploaded one
+	*/
+	return (0 == tonga_disable_sclk_mclk_dpm(hwmgr)) ? 0 : 1;
+}
+
+/**
+ * Get the location of various tables inside the FW image.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_process_firmware_header(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct tonga_smumgr *tonga_smu = (struct tonga_smumgr *)(hwmgr->smumgr->backend);
+
+	uint32_t tmp;
+	int result;
+	bool error = 0;
+
+	result = tonga_read_smc_sram_dword(hwmgr->smumgr,
+				SMU72_FIRMWARE_HEADER_LOCATION +
+				offsetof(SMU72_Firmware_Header, DpmTable),
+				&tmp, data->sram_end);
+
+	if (0 == result) {
+		data->dpm_table_start = tmp;
+	}
+
+	error |= (0 != result);
+
+	result = tonga_read_smc_sram_dword(hwmgr->smumgr,
+				SMU72_FIRMWARE_HEADER_LOCATION +
+				offsetof(SMU72_Firmware_Header, SoftRegisters),
+				&tmp, data->sram_end);
+
+	if (0 == result) {
+		data->soft_regs_start = tmp;
+		tonga_smu->ulSoftRegsStart = tmp;
+	}
+
+	error |= (0 != result);
+
+
+	result = tonga_read_smc_sram_dword(hwmgr->smumgr,
+				SMU72_FIRMWARE_HEADER_LOCATION +
+				offsetof(SMU72_Firmware_Header, mcRegisterTable),
+				&tmp, data->sram_end);
+
+	if (0 == result) {
+		data->mc_reg_table_start = tmp;
+	}
+
+	result = tonga_read_smc_sram_dword(hwmgr->smumgr,
+				SMU72_FIRMWARE_HEADER_LOCATION +
+				offsetof(SMU72_Firmware_Header, FanTable),
+				&tmp, data->sram_end);
+
+	if (0 == result) {
+		data->fan_table_start = tmp;
+	}
+
+	error |= (0 != result);
+
+	result = tonga_read_smc_sram_dword(hwmgr->smumgr,
+				SMU72_FIRMWARE_HEADER_LOCATION +
+				offsetof(SMU72_Firmware_Header, mcArbDramTimingTable),
+				&tmp, data->sram_end);
+
+	if (0 == result) {
+		data->arb_table_start = tmp;
+	}
+
+	error |= (0 != result);
+
+
+	result = tonga_read_smc_sram_dword(hwmgr->smumgr,
+				SMU72_FIRMWARE_HEADER_LOCATION +
+				offsetof(SMU72_Firmware_Header, Version),
+				&tmp, data->sram_end);
+
+	if (0 == result) {
+		hwmgr->microcode_version_info.SMC = tmp;
+	}
+
+	error |= (0 != result);
+
+	return error ? 1 : 0;
+}
+
+/**
+ * Read clock related registers.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_read_clock_registers(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	data->clock_registers.vCG_SPLL_FUNC_CNTL         =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL);
+	data->clock_registers.vCG_SPLL_FUNC_CNTL_2       =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_2);
+	data->clock_registers.vCG_SPLL_FUNC_CNTL_3       =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_3);
+	data->clock_registers.vCG_SPLL_FUNC_CNTL_4       =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_4);
+	data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM   =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM);
+	data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 =
+		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM_2);
+	data->clock_registers.vDLL_CNTL                  =
+		cgs_read_register(hwmgr->device, mmDLL_CNTL);
+	data->clock_registers.vMCLK_PWRMGT_CNTL          =
+		cgs_read_register(hwmgr->device, mmMCLK_PWRMGT_CNTL);
+	data->clock_registers.vMPLL_AD_FUNC_CNTL         =
+		cgs_read_register(hwmgr->device, mmMPLL_AD_FUNC_CNTL);
+	data->clock_registers.vMPLL_DQ_FUNC_CNTL         =
+		cgs_read_register(hwmgr->device, mmMPLL_DQ_FUNC_CNTL);
+	data->clock_registers.vMPLL_FUNC_CNTL            =
+		cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL);
+	data->clock_registers.vMPLL_FUNC_CNTL_1          =
+		cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_1);
+	data->clock_registers.vMPLL_FUNC_CNTL_2          =
+		cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_2);
+	data->clock_registers.vMPLL_SS1                  =
+		cgs_read_register(hwmgr->device, mmMPLL_SS1);
+	data->clock_registers.vMPLL_SS2                  =
+		cgs_read_register(hwmgr->device, mmMPLL_SS2);
+
+	return 0;
+}
+
+/**
+ * Find out if memory is GDDR5.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_get_memory_type(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	uint32_t temp;
+
+	temp = cgs_read_register(hwmgr->device, mmMC_SEQ_MISC0);
+
+	data->is_memory_GDDR5 = (MC_SEQ_MISC0_GDDR5_VALUE ==
+			((temp & MC_SEQ_MISC0_GDDR5_MASK) >>
+			 MC_SEQ_MISC0_GDDR5_SHIFT));
+
+	return 0;
+}
+
+/**
+ * Enables Dynamic Power Management by SMC
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_enable_acpi_power_management(struct pp_hwmgr *hwmgr)
+{
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, STATIC_PM_EN, 1);
+
+	return 0;
+}
+
+/**
+ * Initialize PowerGating States for different engines
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_init_power_gate_state(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	data->uvd_power_gated = 0;
+	data->vce_power_gated = 0;
+	data->samu_power_gated = 0;
+	data->acp_power_gated = 0;
+	data->pg_acp_init = 1;
+
+	return 0;
+}
+
+/**
+ * Checks if DPM is enabled
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_check_for_dpm_running(struct pp_hwmgr *hwmgr)
+{
+	/*
+	 * We return the status of Voltage Control instead of checking SCLK/MCLK DPM
+	 * because we may have test scenarios that need us intentionly disable SCLK/MCLK DPM,
+	 * whereas voltage control is a fundemental change that will not be disabled
+	 */
+	return (0 == tonga_is_dpm_running(hwmgr) ? 0 : 1);
+}
+
+/**
+ * Checks if DPM is stopped
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_check_for_dpm_stopped(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	if (0 != tonga_is_dpm_running(hwmgr)) {
+		/* If HW Virtualization is enabled, dpm_table_start will not have a valid value */
+		if (!data->dpm_table_start) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Remove repeated voltage values and create table with unique values.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @param    voltage_table  the pointer to changing voltage table
+ * @return    1 in success
+ */
+
+static int tonga_trim_voltage_table(struct pp_hwmgr *hwmgr,
+			pp_atomctrl_voltage_table *voltage_table)
+{
+	uint32_t table_size, i, j;
+	uint16_t vvalue;
+	bool bVoltageFound = 0;
+	pp_atomctrl_voltage_table *table;
+
+	PP_ASSERT_WITH_CODE((NULL != voltage_table), "Voltage Table empty.", return -1;);
+	table_size = sizeof(pp_atomctrl_voltage_table);
+	table = kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == table)
+		return -ENOMEM;
+
+	memset(table, 0x00, table_size);
+	table->mask_low = voltage_table->mask_low;
+	table->phase_delay = voltage_table->phase_delay;
+
+	for (i = 0; i < voltage_table->count; i++) {
+		vvalue = voltage_table->entries[i].value;
+		bVoltageFound = 0;
+
+		for (j = 0; j < table->count; j++) {
+			if (vvalue == table->entries[j].value) {
+				bVoltageFound = 1;
+				break;
+			}
+		}
+
+		if (!bVoltageFound) {
+			table->entries[table->count].value = vvalue;
+			table->entries[table->count].smio_low =
+				voltage_table->entries[i].smio_low;
+			table->count++;
+		}
+	}
+
+	memcpy(table, voltage_table, sizeof(pp_atomctrl_voltage_table));
+
+	kfree(table);
+
+	return 0;
+}
+
+static int tonga_get_svi2_vdd_ci_voltage_table(
+		struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_clock_voltage_dependency_table *voltage_dependency_table)
+{
+	uint32_t i;
+	int result;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	pp_atomctrl_voltage_table *vddci_voltage_table = &(data->vddci_voltage_table);
+
+	PP_ASSERT_WITH_CODE((0 != voltage_dependency_table->count),
+			"Voltage Dependency Table empty.", return -1;);
+
+	vddci_voltage_table->mask_low = 0;
+	vddci_voltage_table->phase_delay = 0;
+	vddci_voltage_table->count = voltage_dependency_table->count;
+
+	for (i = 0; i < voltage_dependency_table->count; i++) {
+		vddci_voltage_table->entries[i].value =
+			voltage_dependency_table->entries[i].vddci;
+		vddci_voltage_table->entries[i].smio_low = 0;
+	}
+
+	result = tonga_trim_voltage_table(hwmgr, vddci_voltage_table);
+	PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to trim VDDCI table.", return result;);
+
+	return 0;
+}
+
+
+
+static int tonga_get_svi2_vdd_voltage_table(
+		struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_voltage_lookup_table *look_up_table,
+		pp_atomctrl_voltage_table *voltage_table)
+{
+	uint8_t i = 0;
+
+	PP_ASSERT_WITH_CODE((0 != look_up_table->count),
+			"Voltage Lookup Table empty.", return -1;);
+
+	voltage_table->mask_low = 0;
+	voltage_table->phase_delay = 0;
+
+	voltage_table->count = look_up_table->count;
+
+	for (i = 0; i < voltage_table->count; i++) {
+		voltage_table->entries[i].value = look_up_table->entries[i].us_vdd;
+		voltage_table->entries[i].smio_low = 0;
+	}
+
+	return 0;
+}
+
+/*
+ * -------------------------------------------------------- Voltage Tables --------------------------------------------------------------------------
+ * If the voltage table would be bigger than what will fit into the state table on the SMC keep only the higher entries.
+ */
+
+static void tonga_trim_voltage_table_to_fit_state_table(
+		struct pp_hwmgr *hwmgr,
+		uint32_t max_voltage_steps,
+		pp_atomctrl_voltage_table *voltage_table)
+{
+	unsigned int i, diff;
+
+	if (voltage_table->count <= max_voltage_steps) {
+		return;
+	}
+
+	diff = voltage_table->count - max_voltage_steps;
+
+	for (i = 0; i < max_voltage_steps; i++) {
+		voltage_table->entries[i] = voltage_table->entries[i + diff];
+	}
+
+	voltage_table->count = max_voltage_steps;
+
+	return;
+}
+
+/**
+ * Create Voltage Tables.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_construct_voltage_tables(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	int result;
+
+	/* MVDD has only GPIO voltage control */
+	if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
+		result = atomctrl_get_voltage_table_v3(hwmgr,
+					VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT, &(data->mvdd_voltage_table));
+		PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to retrieve MVDD table.", return result;);
+	}
+
+	if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->vdd_ci_control) {
+		/* GPIO voltage */
+		result = atomctrl_get_voltage_table_v3(hwmgr,
+					VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT, &(data->vddci_voltage_table));
+		PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to retrieve VDDCI table.", return result;);
+	} else if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_ci_control) {
+		/* SVI2 voltage */
+		result = tonga_get_svi2_vdd_ci_voltage_table(hwmgr,
+					pptable_info->vdd_dep_on_mclk);
+		PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to retrieve SVI2 VDDCI table from dependancy table.", return result;);
+	}
+
+	if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
+		/* VDDGFX has only SVI2 voltage control */
+		result = tonga_get_svi2_vdd_voltage_table(hwmgr,
+					pptable_info->vddgfx_lookup_table, &(data->vddgfx_voltage_table));
+		PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to retrieve SVI2 VDDGFX table from lookup table.", return result;);
+	}
+
+	if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
+		/* VDDC has only SVI2 voltage control */
+		result = tonga_get_svi2_vdd_voltage_table(hwmgr,
+					pptable_info->vddc_lookup_table, &(data->vddc_voltage_table));
+		PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to retrieve SVI2 VDDC table from lookup table.", return result;);
+	}
+
+	PP_ASSERT_WITH_CODE(
+			(data->vddc_voltage_table.count <= (SMU72_MAX_LEVELS_VDDC)),
+			"Too many voltage values for VDDC. Trimming to fit state table.",
+			tonga_trim_voltage_table_to_fit_state_table(hwmgr,
+			SMU72_MAX_LEVELS_VDDC, &(data->vddc_voltage_table));
+			);
+
+	PP_ASSERT_WITH_CODE(
+			(data->vddgfx_voltage_table.count <= (SMU72_MAX_LEVELS_VDDGFX)),
+			"Too many voltage values for VDDGFX. Trimming to fit state table.",
+			tonga_trim_voltage_table_to_fit_state_table(hwmgr,
+			SMU72_MAX_LEVELS_VDDGFX, &(data->vddgfx_voltage_table));
+			);
+
+	PP_ASSERT_WITH_CODE(
+			(data->vddci_voltage_table.count <= (SMU72_MAX_LEVELS_VDDCI)),
+			"Too many voltage values for VDDCI. Trimming to fit state table.",
+			tonga_trim_voltage_table_to_fit_state_table(hwmgr,
+			SMU72_MAX_LEVELS_VDDCI, &(data->vddci_voltage_table));
+			);
+
+	PP_ASSERT_WITH_CODE(
+			(data->mvdd_voltage_table.count <= (SMU72_MAX_LEVELS_MVDD)),
+			"Too many voltage values for MVDD. Trimming to fit state table.",
+			tonga_trim_voltage_table_to_fit_state_table(hwmgr,
+			SMU72_MAX_LEVELS_MVDD, &(data->mvdd_voltage_table));
+			);
+
+	return 0;
+}
+
+/**
+ * Vddc table preparation for SMC.
+ *
+ * @param    hwmgr      the address of the hardware manager
+ * @param    table     the SMC DPM table structure to be populated
+ * @return   always 0
+ */
+static int tonga_populate_smc_vddc_table(struct pp_hwmgr *hwmgr,
+			SMU72_Discrete_DpmTable *table)
+{
+	unsigned int count;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
+		table->VddcLevelCount = data->vddc_voltage_table.count;
+		for (count = 0; count < table->VddcLevelCount; count++) {
+			table->VddcTable[count] =
+				PP_HOST_TO_SMC_US(data->vddc_voltage_table.entries[count].value * VOLTAGE_SCALE);
+		}
+		CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount);
+	}
+	return 0;
+}
+
+/**
+ * VddGfx table preparation for SMC.
+ *
+ * @param    hwmgr      the address of the hardware manager
+ * @param    table     the SMC DPM table structure to be populated
+ * @return   always 0
+ */
+static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr *hwmgr,
+			SMU72_Discrete_DpmTable *table)
+{
+	unsigned int count;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
+		table->VddGfxLevelCount = data->vddgfx_voltage_table.count;
+		for (count = 0; count < data->vddgfx_voltage_table.count; count++) {
+			table->VddGfxTable[count] =
+				PP_HOST_TO_SMC_US(data->vddgfx_voltage_table.entries[count].value * VOLTAGE_SCALE);
+		}
+		CONVERT_FROM_HOST_TO_SMC_UL(table->VddGfxLevelCount);
+	}
+	return 0;
+}
+
+/**
+ * Vddci table preparation for SMC.
+ *
+ * @param    *hwmgr The address of the hardware manager.
+ * @param    *table The SMC DPM table structure to be populated.
+ * @return   0
+ */
+static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr,
+			SMU72_Discrete_DpmTable *table)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	uint32_t count;
+
+	table->VddciLevelCount = data->vddci_voltage_table.count;
+	for (count = 0; count < table->VddciLevelCount; count++) {
+		if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_ci_control) {
+			table->VddciTable[count] =
+				PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
+		} else if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->vdd_ci_control) {
+			table->SmioTable1.Pattern[count].Voltage =
+				PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
+			/* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */
+			table->SmioTable1.Pattern[count].Smio =
+				(uint8_t) count;
+			table->Smio[count] |=
+				data->vddci_voltage_table.entries[count].smio_low;
+			table->VddciTable[count] =
+				PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
+		}
+	}
+
+	table->SmioMask1 = data->vddci_voltage_table.mask_low;
+	CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount);
+
+	return 0;
+}
+
+/**
+ * Mvdd table preparation for SMC.
+ *
+ * @param    *hwmgr The address of the hardware manager.
+ * @param    *table The SMC DPM table structure to be populated.
+ * @return   0
+ */
+static int tonga_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
+			SMU72_Discrete_DpmTable *table)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	uint32_t count;
+
+	if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
+		table->MvddLevelCount = data->mvdd_voltage_table.count;
+		for (count = 0; count < table->MvddLevelCount; count++) {
+			table->SmioTable2.Pattern[count].Voltage =
+				PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE);
+			/* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/
+			table->SmioTable2.Pattern[count].Smio =
+				(uint8_t) count;
+			table->Smio[count] |=
+				data->mvdd_voltage_table.entries[count].smio_low;
+		}
+		table->SmioMask2 = data->vddci_voltage_table.mask_low;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount);
+	}
+
+	return 0;
+}
+
+/**
+ * Convert a voltage value in mv unit to VID number required by SMU firmware
+ */
+static uint8_t convert_to_vid(uint16_t vddc)
+{
+	return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25);
+}
+
+
+/**
+ * Preparation of vddc and vddgfx CAC tables for SMC.
+ *
+ * @param    hwmgr      the address of the hardware manager
+ * @param    table     the SMC DPM table structure to be populated
+ * @return   always 0
+ */
+static int tonga_populate_cac_tables(struct pp_hwmgr *hwmgr,
+			SMU72_Discrete_DpmTable *table)
+{
+	uint32_t count;
+	uint8_t index;
+	int result = 0;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table = pptable_info->vddgfx_lookup_table;
+	struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table = pptable_info->vddc_lookup_table;
+
+	/* pTables is already swapped, so in order to use the value from it, we need to swap it back. */
+	uint32_t vddcLevelCount = PP_SMC_TO_HOST_UL(table->VddcLevelCount);
+	uint32_t vddgfxLevelCount = PP_SMC_TO_HOST_UL(table->VddGfxLevelCount);
+
+	for (count = 0; count < vddcLevelCount; count++) {
+		/* We are populating vddc CAC data to BapmVddc table in split and merged mode */
+		index = tonga_get_voltage_index(vddc_lookup_table,
+			data->vddc_voltage_table.entries[count].value);
+		table->BapmVddcVidLoSidd[count] =
+			convert_to_vid(vddc_lookup_table->entries[index].us_cac_low);
+		table->BapmVddcVidHiSidd[count] =
+			convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid);
+		table->BapmVddcVidHiSidd2[count] =
+			convert_to_vid(vddc_lookup_table->entries[index].us_cac_high);
+	}
+
+	if ((data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2)) {
+		/* We are populating vddgfx CAC data to BapmVddgfx table in split mode */
+		for (count = 0; count < vddgfxLevelCount; count++) {
+			index = tonga_get_voltage_index(vddgfx_lookup_table,
+				data->vddgfx_voltage_table.entries[count].value);
+			table->BapmVddGfxVidLoSidd[count] =
+				convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_low);
+			table->BapmVddGfxVidHiSidd[count] =
+				convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_mid);
+			table->BapmVddGfxVidHiSidd2[count] =
+				convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_high);
+		}
+	} else {
+		for (count = 0; count < vddcLevelCount; count++) {
+			index = tonga_get_voltage_index(vddc_lookup_table,
+				data->vddc_voltage_table.entries[count].value);
+			table->BapmVddGfxVidLoSidd[count] =
+				convert_to_vid(vddc_lookup_table->entries[index].us_cac_low);
+			table->BapmVddGfxVidHiSidd[count] =
+				convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid);
+			table->BapmVddGfxVidHiSidd2[count] =
+				convert_to_vid(vddc_lookup_table->entries[index].us_cac_high);
+		}
+	}
+
+	return result;
+}
+
+
+/**
+ * Preparation of voltage tables for SMC.
+ *
+ * @param    hwmgr      the address of the hardware manager
+ * @param    table     the SMC DPM table structure to be populated
+ * @return   always 0
+ */
+
+int tonga_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
+	SMU72_Discrete_DpmTable *table)
+{
+	int result;
+
+	result = tonga_populate_smc_vddc_table(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"can not populate VDDC voltage table to SMC", return -1);
+
+	result = tonga_populate_smc_vdd_ci_table(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"can not populate VDDCI voltage table to SMC", return -1);
+
+	result = tonga_populate_smc_vdd_gfx_table(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"can not populate VDDGFX voltage table to SMC", return -1);
+
+	result = tonga_populate_smc_mvdd_table(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"can not populate MVDD voltage table to SMC", return -1);
+
+	result = tonga_populate_cac_tables(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"can not populate CAC voltage tables to SMC", return -1);
+
+	return 0;
+}
+
+/**
+ * Populates the SMC VRConfig field in DPM table.
+ *
+ * @param    hwmgr      the address of the hardware manager
+ * @param    table     the SMC DPM table structure to be populated
+ * @return   always 0
+ */
+static int tonga_populate_vr_config(struct pp_hwmgr *hwmgr,
+			SMU72_Discrete_DpmTable *table)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	uint16_t config;
+
+	if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
+		/*  Splitted mode */
+		config = VR_SVI2_PLANE_1;
+		table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT);
+
+		if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
+			config = VR_SVI2_PLANE_2;
+			table->VRConfig |= config;
+		} else {
+			printk(KERN_ERR "[ powerplay ] VDDC and VDDGFX should be both on SVI2 control in splitted mode! \n");
+		}
+	} else {
+		/* Merged mode  */
+		config = VR_MERGED_WITH_VDDC;
+		table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT);
+
+		/* Set Vddc Voltage Controller  */
+		if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
+			config = VR_SVI2_PLANE_1;
+			table->VRConfig |= config;
+		} else {
+			printk(KERN_ERR "[ powerplay ] VDDC should be on SVI2 control in merged mode! \n");
+		}
+	}
+
+	/* Set Vddci Voltage Controller  */
+	if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_ci_control) {
+		config = VR_SVI2_PLANE_2;  /* only in merged mode */
+		table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
+	} else if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->vdd_ci_control) {
+		config = VR_SMIO_PATTERN_1;
+		table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
+	}
+
+	/* Set Mvdd Voltage Controller */
+	if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
+		config = VR_SMIO_PATTERN_2;
+		table->VRConfig |= (config<<VRCONF_MVDD_SHIFT);
+	}
+
+	return 0;
+}
+
+static int tonga_get_dependecy_volt_by_clk(struct pp_hwmgr *hwmgr,
+	phm_ppt_v1_clock_voltage_dependency_table *allowed_clock_voltage_table,
+	uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd)
+{
+	uint32_t i = 0;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	/* clock - voltage dependency table is empty table */
+	if (allowed_clock_voltage_table->count == 0)
+		return -1;
+
+	for (i = 0; i < allowed_clock_voltage_table->count; i++) {
+		/* find first sclk bigger than request */
+		if (allowed_clock_voltage_table->entries[i].clk >= clock) {
+			voltage->VddGfx = tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
+								allowed_clock_voltage_table->entries[i].vddgfx);
+
+			voltage->Vddc = tonga_get_voltage_index(pptable_info->vddc_lookup_table,
+								allowed_clock_voltage_table->entries[i].vddc);
+
+			if (allowed_clock_voltage_table->entries[i].vddci) {
+				voltage->Vddci = tonga_get_voltage_id(&data->vddci_voltage_table,
+									allowed_clock_voltage_table->entries[i].vddci);
+			} else {
+				voltage->Vddci = tonga_get_voltage_id(&data->vddci_voltage_table,
+									allowed_clock_voltage_table->entries[i].vddc - data->vddc_vddci_delta);
+			}
+
+			if (allowed_clock_voltage_table->entries[i].mvdd) {
+				*mvdd = (uint32_t) allowed_clock_voltage_table->entries[i].mvdd;
+			}
+
+			voltage->Phases = 1;
+			return 0;
+		}
+	}
+
+	/* sclk is bigger than max sclk in the dependence table */
+	voltage->VddGfx = tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
+		allowed_clock_voltage_table->entries[i-1].vddgfx);
+	voltage->Vddc = tonga_get_voltage_index(pptable_info->vddc_lookup_table,
+		allowed_clock_voltage_table->entries[i-1].vddc);
+
+	if (allowed_clock_voltage_table->entries[i-1].vddci) {
+		voltage->Vddci = tonga_get_voltage_id(&data->vddci_voltage_table,
+			allowed_clock_voltage_table->entries[i-1].vddci);
+	}
+	if (allowed_clock_voltage_table->entries[i-1].mvdd) {
+		*mvdd = (uint32_t) allowed_clock_voltage_table->entries[i-1].mvdd;
+	}
+
+	return 0;
+}
+
+/**
+ * Call SMC to reset S0/S1 to S1 and Reset SMIO to initial value
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_reset_to_default(struct pp_hwmgr *hwmgr)
+{
+	return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ResetToDefaults) == 0) ? 0 : 1;
+}
+
+int tonga_populate_memory_timing_parameters(
+		struct pp_hwmgr *hwmgr,
+		uint32_t engine_clock,
+		uint32_t memory_clock,
+		struct SMU72_Discrete_MCArbDramTimingTableEntry *arb_regs
+		)
+{
+	uint32_t dramTiming;
+	uint32_t dramTiming2;
+	uint32_t burstTime;
+	int result;
+
+	result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
+				engine_clock, memory_clock);
+
+	PP_ASSERT_WITH_CODE(result == 0,
+		"Error calling VBIOS to set DRAM_TIMING.", return result);
+
+	dramTiming  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
+	dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
+	burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
+
+	arb_regs->McArbDramTiming  = PP_HOST_TO_SMC_UL(dramTiming);
+	arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2);
+	arb_regs->McArbBurstTime = (uint8_t)burstTime;
+
+	return 0;
+}
+
+/**
+ * Setup parameters for the MC ARB.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ * This function is to be called from the SetPowerState table.
+ */
+int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	int result = 0;
+	SMU72_Discrete_MCArbDramTimingTable  arb_regs;
+	uint32_t i, j;
+
+	memset(&arb_regs, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable));
+
+	for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
+		for (j = 0; j < data->dpm_table.mclk_table.count; j++) {
+			result = tonga_populate_memory_timing_parameters
+				(hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value,
+				 data->dpm_table.mclk_table.dpm_levels[j].value,
+				 &arb_regs.entries[i][j]);
+
+			if (0 != result) {
+				break;
+			}
+		}
+	}
+
+	if (0 == result) {
+		result = tonga_copy_bytes_to_smc(
+				hwmgr->smumgr,
+				data->arb_table_start,
+				(uint8_t *)&arb_regs,
+				sizeof(SMU72_Discrete_MCArbDramTimingTable),
+				data->sram_end
+				);
+	}
+
+	return result;
+}
+
+static int tonga_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU72_Discrete_DpmTable *table)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct tonga_dpm_table *dpm_table = &data->dpm_table;
+	uint32_t i;
+
+	/* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */
+	for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
+		table->LinkLevel[i].PcieGenSpeed  =
+			(uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
+		table->LinkLevel[i].PcieLaneCount =
+			(uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1);
+		table->LinkLevel[i].EnabledForActivity =
+			1;
+		table->LinkLevel[i].SPC =
+			(uint8_t)(data->pcie_spc_cap & 0xff);
+		table->LinkLevel[i].DownThreshold =
+			PP_HOST_TO_SMC_UL(5);
+		table->LinkLevel[i].UpThreshold =
+			PP_HOST_TO_SMC_UL(30);
+	}
+
+	data->smc_state_table.LinkLevelCount =
+		(uint8_t)dpm_table->pcie_speed_table.count;
+	data->dpm_level_enable_mask.pcie_dpm_enable_mask =
+		tonga_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
+
+	return 0;
+}
+
+static int tonga_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
+					SMU72_Discrete_DpmTable *table)
+{
+	int result = 0;
+
+	uint8_t count;
+	pp_atomctrl_clock_dividers_vi dividers;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
+
+	table->UvdLevelCount = (uint8_t) (mm_table->count);
+	table->UvdBootLevel = 0;
+
+	for (count = 0; count < table->UvdLevelCount; count++) {
+		table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk;
+		table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk;
+		table->UvdLevel[count].MinVoltage.Vddc =
+			tonga_get_voltage_index(pptable_info->vddc_lookup_table,
+						mm_table->entries[count].vddc);
+		table->UvdLevel[count].MinVoltage.VddGfx =
+			(data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ?
+			tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
+						mm_table->entries[count].vddgfx) : 0;
+		table->UvdLevel[count].MinVoltage.Vddci =
+			tonga_get_voltage_id(&data->vddci_voltage_table,
+					     mm_table->entries[count].vddc - data->vddc_vddci_delta);
+		table->UvdLevel[count].MinVoltage.Phases = 1;
+
+		/* retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+							  table->UvdLevel[count].VclkFrequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				    "can not find divide id for Vclk clock", return result);
+
+		table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider;
+
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+							  table->UvdLevel[count].DclkFrequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				    "can not find divide id for Dclk clock", return result);
+
+		table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
+		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
+		//CONVERT_FROM_HOST_TO_SMC_UL((uint32_t)table->UvdLevel[count].MinVoltage);
+	}
+
+	return result;
+
+}
+
+static int tonga_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
+		SMU72_Discrete_DpmTable *table)
+{
+	int result = 0;
+
+	uint8_t count;
+	pp_atomctrl_clock_dividers_vi dividers;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
+
+	table->VceLevelCount = (uint8_t) (mm_table->count);
+	table->VceBootLevel = 0;
+
+	for (count = 0; count < table->VceLevelCount; count++) {
+		table->VceLevel[count].Frequency =
+			mm_table->entries[count].eclk;
+		table->VceLevel[count].MinVoltage.Vddc =
+			tonga_get_voltage_index(pptable_info->vddc_lookup_table,
+				mm_table->entries[count].vddc);
+		table->VceLevel[count].MinVoltage.VddGfx =
+			(data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ?
+			tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
+				mm_table->entries[count].vddgfx) : 0;
+		table->VceLevel[count].MinVoltage.Vddci =
+			tonga_get_voltage_id(&data->vddci_voltage_table,
+				mm_table->entries[count].vddc - data->vddc_vddci_delta);
+		table->VceLevel[count].MinVoltage.Phases = 1;
+
+		/* retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+					table->VceLevel[count].Frequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find divide id for VCE engine clock", return result);
+
+		table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
+	}
+
+	return result;
+}
+
+static int tonga_populate_smc_acp_level(struct pp_hwmgr *hwmgr,
+		SMU72_Discrete_DpmTable *table)
+{
+	int result = 0;
+	uint8_t count;
+	pp_atomctrl_clock_dividers_vi dividers;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
+
+	table->AcpLevelCount = (uint8_t) (mm_table->count);
+	table->AcpBootLevel = 0;
+
+	for (count = 0; count < table->AcpLevelCount; count++) {
+		table->AcpLevel[count].Frequency =
+			pptable_info->mm_dep_table->entries[count].aclk;
+		table->AcpLevel[count].MinVoltage.Vddc =
+			tonga_get_voltage_index(pptable_info->vddc_lookup_table,
+			mm_table->entries[count].vddc);
+		table->AcpLevel[count].MinVoltage.VddGfx =
+			(data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ?
+			tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
+				mm_table->entries[count].vddgfx) : 0;
+		table->AcpLevel[count].MinVoltage.Vddci =
+			tonga_get_voltage_id(&data->vddci_voltage_table,
+				mm_table->entries[count].vddc - data->vddc_vddci_delta);
+		table->AcpLevel[count].MinVoltage.Phases = 1;
+
+		/* retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+			table->AcpLevel[count].Frequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+			"can not find divide id for engine clock", return result);
+
+		table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency);
+	}
+
+	return result;
+}
+
+static int tonga_populate_smc_samu_level(struct pp_hwmgr *hwmgr,
+	SMU72_Discrete_DpmTable *table)
+{
+	int result = 0;
+	uint8_t count;
+	pp_atomctrl_clock_dividers_vi dividers;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
+
+	table->SamuBootLevel = 0;
+	table->SamuLevelCount = (uint8_t) (mm_table->count);
+
+	for (count = 0; count < table->SamuLevelCount; count++) {
+		/* not sure whether we need evclk or not */
+		table->SamuLevel[count].Frequency =
+			pptable_info->mm_dep_table->entries[count].samclock;
+		table->SamuLevel[count].MinVoltage.Vddc =
+			tonga_get_voltage_index(pptable_info->vddc_lookup_table,
+				mm_table->entries[count].vddc);
+		table->SamuLevel[count].MinVoltage.VddGfx =
+			(data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ?
+			tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
+				mm_table->entries[count].vddgfx) : 0;
+		table->SamuLevel[count].MinVoltage.Vddci =
+			tonga_get_voltage_id(&data->vddci_voltage_table,
+				mm_table->entries[count].vddc - data->vddc_vddci_delta);
+		table->SamuLevel[count].MinVoltage.Phases = 1;
+
+		/* retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+					table->SamuLevel[count].Frequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+			"can not find divide id for samu clock", return result);
+
+		table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency);
+	}
+
+	return result;
+}
+
+/**
+ * Populates the SMC MCLK structure using the provided memory clock
+ *
+ * @param    hwmgr      the address of the hardware manager
+ * @param    memory_clock the memory clock to use to populate the structure
+ * @param    sclk        the SMC SCLK structure to be populated
+ */
+static int tonga_calculate_mclk_params(
+		struct pp_hwmgr *hwmgr,
+		uint32_t memory_clock,
+		SMU72_Discrete_MemoryLevel *mclk,
+		bool strobe_mode,
+		bool dllStateOn
+		)
+{
+	const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	uint32_t  dll_cntl = data->clock_registers.vDLL_CNTL;
+	uint32_t  mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
+	uint32_t  mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL;
+	uint32_t  mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL;
+	uint32_t  mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL;
+	uint32_t  mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1;
+	uint32_t  mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2;
+	uint32_t  mpll_ss1 = data->clock_registers.vMPLL_SS1;
+	uint32_t  mpll_ss2 = data->clock_registers.vMPLL_SS2;
+
+	pp_atomctrl_memory_clock_param mpll_param;
+	int result;
+
+	result = atomctrl_get_memory_pll_dividers_si(hwmgr,
+				memory_clock, &mpll_param, strobe_mode);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Error retrieving Memory Clock Parameters from VBIOS.", return result);
+
+	/* MPLL_FUNC_CNTL setup*/
+	mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl);
+
+	/* MPLL_FUNC_CNTL_1 setup*/
+	mpll_func_cntl_1  = PHM_SET_FIELD(mpll_func_cntl_1,
+							MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf);
+	mpll_func_cntl_1  = PHM_SET_FIELD(mpll_func_cntl_1,
+							MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac);
+	mpll_func_cntl_1  = PHM_SET_FIELD(mpll_func_cntl_1,
+							MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode);
+
+	/* MPLL_AD_FUNC_CNTL setup*/
+	mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl,
+							MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider);
+
+	if (data->is_memory_GDDR5) {
+		/* MPLL_DQ_FUNC_CNTL setup*/
+		mpll_dq_func_cntl  = PHM_SET_FIELD(mpll_dq_func_cntl,
+								MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel);
+		mpll_dq_func_cntl  = PHM_SET_FIELD(mpll_dq_func_cntl,
+								MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider);
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MemorySpreadSpectrumSupport)) {
+		/*
+		 ************************************
+		 Fref = Reference Frequency
+		 NF = Feedback divider ratio
+		 NR = Reference divider ratio
+		 Fnom = Nominal VCO output frequency = Fref * NF / NR
+		 Fs = Spreading Rate
+		 D = Percentage down-spread / 2
+		 Fint = Reference input frequency to PFD = Fref / NR
+		 NS = Spreading rate divider ratio = int(Fint / (2 * Fs))
+		 CLKS = NS - 1 = ISS_STEP_NUM[11:0]
+		 NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2)
+		 CLKV = 65536 * NV = ISS_STEP_SIZE[25:0]
+		 *************************************
+		 */
+		pp_atomctrl_internal_ss_info ss_info;
+		uint32_t freq_nom;
+		uint32_t tmp;
+		uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr);
+
+		/* for GDDR5 for all modes and DDR3 */
+		if (1 == mpll_param.qdr)
+			freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider);
+		else
+			freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider);
+
+		/* tmp = (freq_nom / reference_clock * reference_divider) ^ 2  Note: S.I. reference_divider = 1*/
+		tmp = (freq_nom / reference_clock);
+		tmp = tmp * tmp;
+
+		if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) {
+			/* ss_info.speed_spectrum_percentage -- in unit of 0.01% */
+			/* ss.Info.speed_spectrum_rate -- in unit of khz */
+			/* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */
+			/*     = reference_clock * 5 / speed_spectrum_rate */
+			uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate;
+
+			/* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */
+			/*     = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */
+			uint32_t clkv =
+				(uint32_t)((((131 * ss_info.speed_spectrum_percentage *
+							ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom);
+
+			mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv);
+			mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks);
+		}
+	}
+
+	/* MCLK_PWRMGT_CNTL setup */
+	mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
+		MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed);
+	mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
+		MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn);
+	mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
+		MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn);
+
+
+	/* Save the result data to outpupt memory level structure */
+	mclk->MclkFrequency   = memory_clock;
+	mclk->MpllFuncCntl    = mpll_func_cntl;
+	mclk->MpllFuncCntl_1  = mpll_func_cntl_1;
+	mclk->MpllFuncCntl_2  = mpll_func_cntl_2;
+	mclk->MpllAdFuncCntl  = mpll_ad_func_cntl;
+	mclk->MpllDqFuncCntl  = mpll_dq_func_cntl;
+	mclk->MclkPwrmgtCntl  = mclk_pwrmgt_cntl;
+	mclk->DllCntl         = dll_cntl;
+	mclk->MpllSs1         = mpll_ss1;
+	mclk->MpllSs2         = mpll_ss2;
+
+	return 0;
+}
+
+static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock,
+		bool strobe_mode)
+{
+	uint8_t mc_para_index;
+
+	if (strobe_mode) {
+		if (memory_clock < 12500) {
+			mc_para_index = 0x00;
+		} else if (memory_clock > 47500) {
+			mc_para_index = 0x0f;
+		} else {
+			mc_para_index = (uint8_t)((memory_clock - 10000) / 2500);
+		}
+	} else {
+		if (memory_clock < 65000) {
+			mc_para_index = 0x00;
+		} else if (memory_clock > 135000) {
+			mc_para_index = 0x0f;
+		} else {
+			mc_para_index = (uint8_t)((memory_clock - 60000) / 5000);
+		}
+	}
+
+	return mc_para_index;
+}
+
+static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock)
+{
+	uint8_t mc_para_index;
+
+	if (memory_clock < 10000) {
+		mc_para_index = 0;
+	} else if (memory_clock >= 80000) {
+		mc_para_index = 0x0f;
+	} else {
+		mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1);
+	}
+
+	return mc_para_index;
+}
+
+static int tonga_populate_single_memory_level(
+		struct pp_hwmgr *hwmgr,
+		uint32_t memory_clock,
+		SMU72_Discrete_MemoryLevel *memory_level
+		)
+{
+	uint32_t minMvdd = 0;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	int result = 0;
+	bool dllStateOn;
+	struct cgs_display_info info = {0};
+
+
+	if (NULL != pptable_info->vdd_dep_on_mclk) {
+		result = tonga_get_dependecy_volt_by_clk(hwmgr,
+			pptable_info->vdd_dep_on_mclk, memory_clock, &memory_level->MinVoltage, &minMvdd);
+		PP_ASSERT_WITH_CODE((0 == result),
+			"can not find MinVddc voltage value from memory VDDC voltage dependency table", return result);
+	}
+
+	if (data->mvdd_control == TONGA_VOLTAGE_CONTROL_NONE) {
+		memory_level->MinMvdd = data->vbios_boot_state.mvdd_bootup_value;
+	} else {
+		memory_level->MinMvdd = minMvdd;
+	}
+	memory_level->EnabledForThrottle = 1;
+	memory_level->EnabledForActivity = 0;
+	memory_level->UpHyst = 0;
+	memory_level->DownHyst = 100;
+	memory_level->VoltageDownHyst = 0;
+
+	/* Indicates maximum activity level for this performance level.*/
+	memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
+	memory_level->StutterEnable = 0;
+	memory_level->StrobeEnable = 0;
+	memory_level->EdcReadEnable = 0;
+	memory_level->EdcWriteEnable = 0;
+	memory_level->RttEnable = 0;
+
+	/* default set to low watermark. Highest level will be set to high later.*/
+	memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+	data->display_timing.num_existing_displays = info.display_count;
+
+	if ((data->mclk_stutter_mode_threshold != 0) &&
+			(memory_clock <= data->mclk_stutter_mode_threshold) &&
+			(data->is_uvd_enabled == 0)
+#if defined(LINUX)
+			&& (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1)
+			&& (data->display_timing.num_existing_displays <= 2)
+			&& (data->display_timing.num_existing_displays != 0)
+#endif
+	)
+		memory_level->StutterEnable = 1;
+
+	/* decide strobe mode*/
+	memory_level->StrobeEnable = (data->mclk_strobe_mode_threshold != 0) &&
+		(memory_clock <= data->mclk_strobe_mode_threshold);
+
+	/* decide EDC mode and memory clock ratio*/
+	if (data->is_memory_GDDR5) {
+		memory_level->StrobeRatio = tonga_get_mclk_frequency_ratio(memory_clock,
+					memory_level->StrobeEnable);
+
+		if ((data->mclk_edc_enable_threshold != 0) &&
+				(memory_clock > data->mclk_edc_enable_threshold)) {
+			memory_level->EdcReadEnable = 1;
+		}
+
+		if ((data->mclk_edc_wr_enable_threshold != 0) &&
+				(memory_clock > data->mclk_edc_wr_enable_threshold)) {
+			memory_level->EdcWriteEnable = 1;
+		}
+
+		if (memory_level->StrobeEnable) {
+			if (tonga_get_mclk_frequency_ratio(memory_clock, 1) >=
+					((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) {
+				dllStateOn = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
+			} else {
+				dllStateOn = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0;
+			}
+
+		} else {
+			dllStateOn = data->dll_defaule_on;
+		}
+	} else {
+		memory_level->StrobeRatio =
+			tonga_get_ddr3_mclk_frequency_ratio(memory_clock);
+		dllStateOn = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
+	}
+
+	result = tonga_calculate_mclk_params(hwmgr,
+		memory_clock, memory_level, memory_level->StrobeEnable, dllStateOn);
+
+	if (0 == result) {
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinMvdd);
+		/* MCLK frequency in units of 10KHz*/
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency);
+		/* Indicates maximum activity level for this performance level.*/
+		CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel);
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl);
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1);
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2);
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl);
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl);
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl);
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl);
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1);
+		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2);
+	}
+
+	return result;
+}
+
+/**
+ * Populates the SMC MVDD structure using the provided memory clock.
+ *
+ * @param    hwmgr      the address of the hardware manager
+ * @param    mclk        the MCLK value to be used in the decision if MVDD should be high or low.
+ * @param    voltage     the SMC VOLTAGE structure to be populated
+ */
+int tonga_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, SMIO_Pattern *smio_pattern)
+{
+	const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint32_t i = 0;
+
+	if (TONGA_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
+		/* find mvdd value which clock is more than request */
+		for (i = 0; i < pptable_info->vdd_dep_on_mclk->count; i++) {
+			if (mclk <= pptable_info->vdd_dep_on_mclk->entries[i].clk) {
+				/* Always round to higher voltage. */
+				smio_pattern->Voltage = data->mvdd_voltage_table.entries[i].value;
+				break;
+			}
+		}
+
+		PP_ASSERT_WITH_CODE(i < pptable_info->vdd_dep_on_mclk->count,
+			"MVDD Voltage is outside the supported range.", return -1);
+
+	} else {
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int tonga_populate_smv_acpi_level(struct pp_hwmgr *hwmgr,
+	SMU72_Discrete_DpmTable *table)
+{
+	int result = 0;
+	const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	pp_atomctrl_clock_dividers_vi dividers;
+	SMIO_Pattern voltage_level;
+	uint32_t spll_func_cntl    = data->clock_registers.vCG_SPLL_FUNC_CNTL;
+	uint32_t spll_func_cntl_2  = data->clock_registers.vCG_SPLL_FUNC_CNTL_2;
+	uint32_t dll_cntl          = data->clock_registers.vDLL_CNTL;
+	uint32_t mclk_pwrmgt_cntl  = data->clock_registers.vMCLK_PWRMGT_CNTL;
+
+	/* The ACPI state should not do DPM on DC (or ever).*/
+	table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
+
+	table->ACPILevel.MinVoltage = data->smc_state_table.GraphicsLevel[0].MinVoltage;
+
+	/* assign zero for now*/
+	table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr);
+
+	/* get the engine clock dividers for this clock value*/
+	result = atomctrl_get_engine_pll_dividers_vi(hwmgr,
+		table->ACPILevel.SclkFrequency,  &dividers);
+
+	PP_ASSERT_WITH_CODE(result == 0,
+		"Error retrieving Engine Clock dividers from VBIOS.", return result);
+
+	/* divider ID for required SCLK*/
+	table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider;
+	table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
+	table->ACPILevel.DeepSleepDivId = 0;
+
+	spll_func_cntl      = PHM_SET_FIELD(spll_func_cntl,
+							CG_SPLL_FUNC_CNTL,   SPLL_PWRON,     0);
+	spll_func_cntl      = PHM_SET_FIELD(spll_func_cntl,
+							CG_SPLL_FUNC_CNTL,   SPLL_RESET,     1);
+	spll_func_cntl_2    = PHM_SET_FIELD(spll_func_cntl_2,
+							CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL,   4);
+
+	table->ACPILevel.CgSpllFuncCntl = spll_func_cntl;
+	table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2;
+	table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
+	table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
+	table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
+	table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
+	table->ACPILevel.CcPwrDynRm = 0;
+	table->ACPILevel.CcPwrDynRm1 = 0;
+
+
+	/* For various features to be enabled/disabled while this level is active.*/
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
+	/* SCLK frequency in units of 10KHz*/
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
+
+	/* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/
+	table->MemoryACPILevel.MinVoltage = data->smc_state_table.MemoryLevel[0].MinVoltage;
+
+	/*  CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/
+
+	if (0 == tonga_populate_mvdd_value(hwmgr, 0, &voltage_level))
+		table->MemoryACPILevel.MinMvdd =
+			PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE);
+	else
+		table->MemoryACPILevel.MinMvdd = 0;
+
+	/* Force reset on DLL*/
+	mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
+		MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1);
+	mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
+		MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1);
+
+	/* Disable DLL in ACPIState*/
+	mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
+		MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0);
+	mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
+		MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0);
+
+	/* Enable DLL bypass signal*/
+	dll_cntl            = PHM_SET_FIELD(dll_cntl,
+		DLL_CNTL, MRDCK0_BYPASS, 0);
+	dll_cntl            = PHM_SET_FIELD(dll_cntl,
+		DLL_CNTL, MRDCK1_BYPASS, 0);
+
+	table->MemoryACPILevel.DllCntl            =
+		PP_HOST_TO_SMC_UL(dll_cntl);
+	table->MemoryACPILevel.MclkPwrmgtCntl     =
+		PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl);
+	table->MemoryACPILevel.MpllAdFuncCntl     =
+		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL);
+	table->MemoryACPILevel.MpllDqFuncCntl     =
+		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL);
+	table->MemoryACPILevel.MpllFuncCntl       =
+		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL);
+	table->MemoryACPILevel.MpllFuncCntl_1     =
+		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1);
+	table->MemoryACPILevel.MpllFuncCntl_2     =
+		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2);
+	table->MemoryACPILevel.MpllSs1            =
+		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1);
+	table->MemoryACPILevel.MpllSs2            =
+		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2);
+
+	table->MemoryACPILevel.EnabledForThrottle = 0;
+	table->MemoryACPILevel.EnabledForActivity = 0;
+	table->MemoryACPILevel.UpHyst = 0;
+	table->MemoryACPILevel.DownHyst = 100;
+	table->MemoryACPILevel.VoltageDownHyst = 0;
+	/* Indicates maximum activity level for this performance level.*/
+	table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
+
+	table->MemoryACPILevel.StutterEnable = 0;
+	table->MemoryACPILevel.StrobeEnable = 0;
+	table->MemoryACPILevel.EdcReadEnable = 0;
+	table->MemoryACPILevel.EdcWriteEnable = 0;
+	table->MemoryACPILevel.RttEnable = 0;
+
+	return result;
+}
+
+static int tonga_find_boot_level(struct tonga_single_dpm_table *table, uint32_t value, uint32_t *boot_level)
+{
+	int result = 0;
+	uint32_t i;
+
+	for (i = 0; i < table->count; i++) {
+		if (value == table->dpm_levels[i].value) {
+			*boot_level = i;
+			result = 0;
+		}
+	}
+	return result;
+}
+
+static int tonga_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
+			SMU72_Discrete_DpmTable *table)
+{
+	int result = 0;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	table->GraphicsBootLevel  = 0;        /* 0 == DPM[0] (low), etc. */
+	table->MemoryBootLevel    = 0;        /* 0 == DPM[0] (low), etc. */
+
+	/* find boot level from dpm table*/
+	result = tonga_find_boot_level(&(data->dpm_table.sclk_table),
+	data->vbios_boot_state.sclk_bootup_value,
+	(uint32_t *)&(data->smc_state_table.GraphicsBootLevel));
+
+	if (0 != result) {
+		data->smc_state_table.GraphicsBootLevel = 0;
+		printk(KERN_ERR "[ powerplay ] VBIOS did not find boot engine clock value \
+			in dependency table. Using Graphics DPM level 0!");
+		result = 0;
+	}
+
+	result = tonga_find_boot_level(&(data->dpm_table.mclk_table),
+		data->vbios_boot_state.mclk_bootup_value,
+		(uint32_t *)&(data->smc_state_table.MemoryBootLevel));
+
+	if (0 != result) {
+		data->smc_state_table.MemoryBootLevel = 0;
+		printk(KERN_ERR "[ powerplay ] VBIOS did not find boot engine clock value \
+			in dependency table. Using Memory DPM level 0!");
+		result = 0;
+	}
+
+	table->BootVoltage.Vddc =
+		tonga_get_voltage_id(&(data->vddc_voltage_table),
+			data->vbios_boot_state.vddc_bootup_value);
+	table->BootVoltage.VddGfx =
+		tonga_get_voltage_id(&(data->vddgfx_voltage_table),
+			data->vbios_boot_state.vddgfx_bootup_value);
+	table->BootVoltage.Vddci =
+		tonga_get_voltage_id(&(data->vddci_voltage_table),
+			data->vbios_boot_state.vddci_bootup_value);
+	table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value;
+
+	CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd);
+
+	return result;
+}
+
+
+/**
+ * Calculates the SCLK dividers using the provided engine clock
+ *
+ * @param    hwmgr      the address of the hardware manager
+ * @param    engine_clock the engine clock to use to populate the structure
+ * @param    sclk        the SMC SCLK structure to be populated
+ */
+int tonga_calculate_sclk_params(struct pp_hwmgr *hwmgr,
+		uint32_t engine_clock, SMU72_Discrete_GraphicsLevel *sclk)
+{
+	const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	pp_atomctrl_clock_dividers_vi dividers;
+	uint32_t spll_func_cntl            = data->clock_registers.vCG_SPLL_FUNC_CNTL;
+	uint32_t spll_func_cntl_3          = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
+	uint32_t spll_func_cntl_4          = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
+	uint32_t cg_spll_spread_spectrum   = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
+	uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
+	uint32_t    reference_clock;
+	uint32_t reference_divider;
+	uint32_t fbdiv;
+	int result;
+
+	/* get the engine clock dividers for this clock value*/
+	result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock,  &dividers);
+
+	PP_ASSERT_WITH_CODE(result == 0,
+		"Error retrieving Engine Clock dividers from VBIOS.", return result);
+
+	/* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/
+	reference_clock = atomctrl_get_reference_clock(hwmgr);
+
+	reference_divider = 1 + dividers.uc_pll_ref_div;
+
+	/* low 14 bits is fraction and high 12 bits is divider*/
+	fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF;
+
+	/* SPLL_FUNC_CNTL setup*/
+	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
+		CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div);
+	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
+		CG_SPLL_FUNC_CNTL, SPLL_PDIV_A,  dividers.uc_pll_post_div);
+
+	/* SPLL_FUNC_CNTL_3 setup*/
+	spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
+		CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv);
+
+	/* set to use fractional accumulation*/
+	spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
+		CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_EngineSpreadSpectrumSupport)) {
+		pp_atomctrl_internal_ss_info ss_info;
+
+		uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div;
+		if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) {
+			/*
+			* ss_info.speed_spectrum_percentage -- in unit of 0.01%
+			* ss_info.speed_spectrum_rate -- in unit of khz
+			*/
+			/* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */
+			uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate);
+
+			/* clkv = 2 * D * fbdiv / NS */
+			uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000);
+
+			cg_spll_spread_spectrum =
+				PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS);
+			cg_spll_spread_spectrum =
+				PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1);
+			cg_spll_spread_spectrum_2 =
+				PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV);
+		}
+	}
+
+	sclk->SclkFrequency        = engine_clock;
+	sclk->CgSpllFuncCntl3      = spll_func_cntl_3;
+	sclk->CgSpllFuncCntl4      = spll_func_cntl_4;
+	sclk->SpllSpreadSpectrum   = cg_spll_spread_spectrum;
+	sclk->SpllSpreadSpectrum2  = cg_spll_spread_spectrum_2;
+	sclk->SclkDid              = (uint8_t)dividers.pll_post_divider;
+
+	return 0;
+}
+
+/**
+ * Populates single SMC SCLK structure using the provided engine clock
+ *
+ * @param    hwmgr      the address of the hardware manager
+ * @param    engine_clock the engine clock to use to populate the structure
+ * @param    sclk        the SMC SCLK structure to be populated
+ */
+static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr, uint32_t engine_clock, uint16_t sclk_activity_level_threshold, SMU72_Discrete_GraphicsLevel *graphic_level)
+{
+	int result;
+	uint32_t threshold;
+	uint32_t mvdd;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level);
+
+
+	/* populate graphics levels*/
+	result = tonga_get_dependecy_volt_by_clk(hwmgr,
+		pptable_info->vdd_dep_on_sclk, engine_clock,
+		&graphic_level->MinVoltage, &mvdd);
+	PP_ASSERT_WITH_CODE((0 == result),
+		"can not find VDDC voltage value for VDDC	\
+		engine clock dependency table", return result);
+
+	/* SCLK frequency in units of 10KHz*/
+	graphic_level->SclkFrequency = engine_clock;
+
+	/* Indicates maximum activity level for this performance level. 50% for now*/
+	graphic_level->ActivityLevel = sclk_activity_level_threshold;
+
+	graphic_level->CcPwrDynRm = 0;
+	graphic_level->CcPwrDynRm1 = 0;
+	/* this level can be used if activity is high enough.*/
+	graphic_level->EnabledForActivity = 0;
+	/* this level can be used for throttling.*/
+	graphic_level->EnabledForThrottle = 1;
+	graphic_level->UpHyst = 0;
+	graphic_level->DownHyst = 0;
+	graphic_level->VoltageDownHyst = 0;
+	graphic_level->PowerThrottle = 0;
+
+	threshold = engine_clock * data->fast_watemark_threshold / 100;
+/*
+	*get the DAL clock. do it in funture.
+	PECI_GetMinClockSettings(hwmgr->peci, &minClocks);
+	data->display_timing.min_clock_insr = minClocks.engineClockInSR;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
+	{
+		graphic_level->DeepSleepDivId = PhwTonga_GetSleepDividerIdFromClock(hwmgr, engine_clock, minClocks.engineClockInSR);
+	}
+*/
+
+	/* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
+	graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
+
+	if (0 == result) {
+		/* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/
+		/* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/
+		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency);
+		CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel);
+		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3);
+		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4);
+		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum);
+		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2);
+		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm);
+		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1);
+	}
+
+	return result;
+}
+
+/**
+ * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
+ *
+ * @param    hwmgr      the address of the hardware manager
+ */
+static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct tonga_dpm_table *dpm_table = &data->dpm_table;
+	phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table;
+	uint8_t pcie_entry_count = (uint8_t) data->dpm_table.pcie_speed_table.count;
+	int result = 0;
+	uint32_t level_array_adress = data->dpm_table_start +
+		offsetof(SMU72_Discrete_DpmTable, GraphicsLevel);
+	uint32_t level_array_size = sizeof(SMU72_Discrete_GraphicsLevel) *
+		SMU72_MAX_LEVELS_GRAPHICS;   /* 64 -> long; 32 -> int*/
+	SMU72_Discrete_GraphicsLevel *levels = data->smc_state_table.GraphicsLevel;
+	uint32_t i, maxEntry;
+	uint8_t highest_pcie_level_enabled = 0, lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0, count = 0;
+	PECI_RegistryValue reg_value;
+	memset(levels, 0x00, level_array_size);
+
+	for (i = 0; i < dpm_table->sclk_table.count; i++) {
+		result = tonga_populate_single_graphic_level(hwmgr,
+					dpm_table->sclk_table.dpm_levels[i].value,
+					(uint16_t)data->activity_target[i],
+					&(data->smc_state_table.GraphicsLevel[i]));
+
+		if (0 != result)
+			return result;
+
+		/* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
+		if (i > 1)
+			data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0;
+
+		if (0 == i) {
+			reg_value = 0;
+			if (reg_value != 0)
+				data->smc_state_table.GraphicsLevel[0].UpHyst = (uint8_t)reg_value;
+		}
+
+		if (1 == i) {
+			reg_value = 0;
+			if (reg_value != 0)
+				data->smc_state_table.GraphicsLevel[1].UpHyst = (uint8_t)reg_value;
+		}
+	}
+
+	/* Only enable level 0 for now. */
+	data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
+
+	/* set highest level watermark to high */
+	if (dpm_table->sclk_table.count > 1)
+		data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark =
+			PPSMC_DISPLAY_WATERMARK_HIGH;
+
+	data->smc_state_table.GraphicsDpmLevelCount =
+		(uint8_t)dpm_table->sclk_table.count;
+	data->dpm_level_enable_mask.sclk_dpm_enable_mask =
+		tonga_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
+
+	if (pcie_table != NULL) {
+		PP_ASSERT_WITH_CODE((pcie_entry_count >= 1),
+			"There must be 1 or more PCIE levels defined in PPTable.", return -1);
+		maxEntry = pcie_entry_count - 1; /* for indexing, we need to decrement by 1.*/
+		for (i = 0; i < dpm_table->sclk_table.count; i++) {
+			data->smc_state_table.GraphicsLevel[i].pcieDpmLevel =
+				(uint8_t) ((i < maxEntry) ? i : maxEntry);
+		}
+	} else {
+		if (0 == data->dpm_level_enable_mask.pcie_dpm_enable_mask)
+			printk(KERN_ERR "[ powerplay ] Pcie Dpm Enablemask is 0!");
+
+		while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
+				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
+					(1<<(highest_pcie_level_enabled+1))) != 0)) {
+			highest_pcie_level_enabled++;
+		}
+
+		while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
+				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
+					(1<<lowest_pcie_level_enabled)) == 0)) {
+			lowest_pcie_level_enabled++;
+		}
+
+		while ((count < highest_pcie_level_enabled) &&
+				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
+					(1<<(lowest_pcie_level_enabled+1+count))) == 0)) {
+			count++;
+		}
+		mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ?
+			(lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled;
+
+
+		/* set pcieDpmLevel to highest_pcie_level_enabled*/
+		for (i = 2; i < dpm_table->sclk_table.count; i++) {
+			data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled;
+		}
+
+		/* set pcieDpmLevel to lowest_pcie_level_enabled*/
+		data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled;
+
+		/* set pcieDpmLevel to mid_pcie_level_enabled*/
+		data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled;
+	}
+	/* level count will send to smc once at init smc table and never change*/
+	result = tonga_copy_bytes_to_smc(hwmgr->smumgr, level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, data->sram_end);
+
+	if (0 != result)
+		return result;
+
+	return 0;
+}
+
+/**
+ * Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states
+ *
+ * @param    hwmgr      the address of the hardware manager
+ */
+
+static int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct tonga_dpm_table *dpm_table = &data->dpm_table;
+	int result;
+	/* populate MCLK dpm table to SMU7 */
+	uint32_t level_array_adress = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, MemoryLevel);
+	uint32_t level_array_size = sizeof(SMU72_Discrete_MemoryLevel) * SMU72_MAX_LEVELS_MEMORY;
+	SMU72_Discrete_MemoryLevel *levels = data->smc_state_table.MemoryLevel;
+	uint32_t i;
+
+	memset(levels, 0x00, level_array_size);
+
+	for (i = 0; i < dpm_table->mclk_table.count; i++) {
+		PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
+			"can not populate memory level as memory clock is zero", return -1);
+		result = tonga_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value,
+			&(data->smc_state_table.MemoryLevel[i]));
+		if (0 != result) {
+			return result;
+		}
+	}
+
+	/* Only enable level 0 for now.*/
+	data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
+
+	/*
+	* in order to prevent MC activity from stutter mode to push DPM up.
+	* the UVD change complements this by putting the MCLK in a higher state
+	* by default such that we are not effected by up threshold or and MCLK DPM latency.
+	*/
+	data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F;
+	CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.MemoryLevel[0].ActivityLevel);
+
+	data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count;
+	data->dpm_level_enable_mask.mclk_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
+	/* set highest level watermark to high*/
+	data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
+
+	/* level count will send to smc once at init smc table and never change*/
+	result = tonga_copy_bytes_to_smc(hwmgr->smumgr,
+		level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, data->sram_end);
+
+	if (0 != result) {
+		return result;
+	}
+
+	return 0;
+}
+
+struct TONGA_DLL_SPEED_SETTING {
+	uint16_t            Min;                          /* Minimum Data Rate*/
+	uint16_t            Max;                          /* Maximum Data Rate*/
+	uint32_t 			dll_speed;                     /* The desired DLL_SPEED setting*/
+};
+
+static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
+{
+	return 0;
+}
+
+/* ---------------------------------------- ULV related functions ----------------------------------------------------*/
+
+
+static int tonga_reset_single_dpm_table(
+	struct pp_hwmgr *hwmgr,
+	struct tonga_single_dpm_table *dpm_table,
+	uint32_t count)
+{
+	uint32_t i;
+	if (!(count <= MAX_REGULAR_DPM_NUMBER))
+		printk(KERN_ERR "[ powerplay ] Fatal error, can not set up single DPM \
+			table entries to exceed max number! \n");
+
+	dpm_table->count = count;
+	for (i = 0; i < MAX_REGULAR_DPM_NUMBER; i++) {
+		dpm_table->dpm_levels[i].enabled = 0;
+	}
+
+	return 0;
+}
+
+static void tonga_setup_pcie_table_entry(
+	struct tonga_single_dpm_table *dpm_table,
+	uint32_t index, uint32_t pcie_gen,
+	uint32_t pcie_lanes)
+{
+	dpm_table->dpm_levels[index].value = pcie_gen;
+	dpm_table->dpm_levels[index].param1 = pcie_lanes;
+	dpm_table->dpm_levels[index].enabled = 1;
+}
+
+static int tonga_setup_default_pcie_tables(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table;
+	uint32_t i, maxEntry;
+
+	if (data->use_pcie_performance_levels && !data->use_pcie_power_saving_levels) {
+		data->pcie_gen_power_saving = data->pcie_gen_performance;
+		data->pcie_lane_power_saving = data->pcie_lane_performance;
+	} else if (!data->use_pcie_performance_levels && data->use_pcie_power_saving_levels) {
+		data->pcie_gen_performance = data->pcie_gen_power_saving;
+		data->pcie_lane_performance = data->pcie_lane_power_saving;
+	}
+
+	tonga_reset_single_dpm_table(hwmgr, &data->dpm_table.pcie_speed_table, SMU72_MAX_LEVELS_LINK);
+
+	if (pcie_table != NULL) {
+		/*
+		* maxEntry is used to make sure we reserve one PCIE level for boot level (fix for A+A PSPP issue).
+		* If PCIE table from PPTable have ULV entry + 8 entries, then ignore the last entry.
+		*/
+		maxEntry = (SMU72_MAX_LEVELS_LINK < pcie_table->count) ?
+						SMU72_MAX_LEVELS_LINK : pcie_table->count;
+		for (i = 1; i < maxEntry; i++) {
+			tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i-1,
+				get_pcie_gen_support(data->pcie_gen_cap, pcie_table->entries[i].gen_speed),
+				get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
+		}
+		data->dpm_table.pcie_speed_table.count = maxEntry - 1;
+	} else {
+		/* Hardcode Pcie Table */
+		tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0,
+			get_pcie_gen_support(data->pcie_gen_cap, PP_Min_PCIEGen),
+			get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
+		tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1,
+			get_pcie_gen_support(data->pcie_gen_cap, PP_Min_PCIEGen),
+			get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
+		tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2,
+			get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen),
+			get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
+		tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3,
+			get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen),
+			get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
+		tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4,
+			get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen),
+			get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
+		tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5,
+			get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen),
+			get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
+		data->dpm_table.pcie_speed_table.count = 6;
+	}
+	/* Populate last level for boot PCIE level, but do not increment count. */
+	tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table,
+		data->dpm_table.pcie_speed_table.count,
+		get_pcie_gen_support(data->pcie_gen_cap, PP_Min_PCIEGen),
+		get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
+
+	return 0;
+
+}
+
+/*
+ * This function is to initalize all DPM state tables for SMU7 based on the dependency table.
+ * Dynamic state patching function will then trim these state tables to the allowed range based
+ * on the power policy or external client requests, such as UVD request, etc.
+ */
+static int tonga_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint32_t i;
+
+	phm_ppt_v1_clock_voltage_dependency_table *allowed_vdd_sclk_table =
+		pptable_info->vdd_dep_on_sclk;
+	phm_ppt_v1_clock_voltage_dependency_table *allowed_vdd_mclk_table =
+		pptable_info->vdd_dep_on_mclk;
+
+	PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL,
+		"SCLK dependency table is missing. This table is mandatory", return -1);
+	PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table->count >= 1,
+		"SCLK dependency table has to have is missing. This table is mandatory", return -1);
+
+	PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL,
+		"MCLK dependency table is missing. This table is mandatory", return -1);
+	PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table->count >= 1,
+		"VMCLK dependency table has to have is missing. This table is mandatory", return -1);
+
+	/* clear the state table to reset everything to default */
+	memset(&(data->dpm_table), 0x00, sizeof(data->dpm_table));
+	tonga_reset_single_dpm_table(hwmgr, &data->dpm_table.sclk_table, SMU72_MAX_LEVELS_GRAPHICS);
+	tonga_reset_single_dpm_table(hwmgr, &data->dpm_table.mclk_table, SMU72_MAX_LEVELS_MEMORY);
+	/* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.VddcTable, SMU72_MAX_LEVELS_VDDC); */
+	/* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.vdd_gfx_table, SMU72_MAX_LEVELS_VDDGFX);*/
+	/* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.vdd_ci_table, SMU72_MAX_LEVELS_VDDCI);*/
+	/* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.mvdd_table, SMU72_MAX_LEVELS_MVDD);*/
+
+	PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL,
+		"SCLK dependency table is missing. This table is mandatory", return -1);
+	/* Initialize Sclk DPM table based on allow Sclk values*/
+	data->dpm_table.sclk_table.count = 0;
+
+	for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
+		if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value !=
+				allowed_vdd_sclk_table->entries[i].clk) {
+			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
+				allowed_vdd_sclk_table->entries[i].clk;
+			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = 1; /*(i==0) ? 1 : 0; to do */
+			data->dpm_table.sclk_table.count++;
+		}
+	}
+
+	PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL,
+		"MCLK dependency table is missing. This table is mandatory", return -1);
+	/* Initialize Mclk DPM table based on allow Mclk values */
+	data->dpm_table.mclk_table.count = 0;
+	for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
+		if (i == 0 || data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count-1].value !=
+			allowed_vdd_mclk_table->entries[i].clk) {
+			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value =
+				allowed_vdd_mclk_table->entries[i].clk;
+			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = 1; /*(i==0) ? 1 : 0; */
+			data->dpm_table.mclk_table.count++;
+		}
+	}
+
+	/* Initialize Vddc DPM table based on allow Vddc values.  And populate corresponding std values. */
+	for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
+		data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddc;
+		/* tonga_hwmgr->dpm_table.VddcTable.dpm_levels[i].param1 = stdVoltageTable->entries[i].Leakage; */
+		/* param1 is for corresponding std voltage */
+		data->dpm_table.vddc_table.dpm_levels[i].enabled = 1;
+	}
+	data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count;
+
+	if (NULL != allowed_vdd_mclk_table) {
+		/* Initialize Vddci DPM table based on allow Mclk values */
+		for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
+			data->dpm_table.vdd_ci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddci;
+			data->dpm_table.vdd_ci_table.dpm_levels[i].enabled = 1;
+			data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].mvdd;
+			data->dpm_table.mvdd_table.dpm_levels[i].enabled = 1;
+		}
+		data->dpm_table.vdd_ci_table.count = allowed_vdd_mclk_table->count;
+		data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count;
+	}
+
+	/* setup PCIE gen speed levels*/
+	tonga_setup_default_pcie_tables(hwmgr);
+
+	/* save a copy of the default DPM table*/
+	memcpy(&(data->golden_dpm_table), &(data->dpm_table), sizeof(struct tonga_dpm_table));
+
+	return 0;
+}
+
+int tonga_populate_smc_initial_state(struct pp_hwmgr *hwmgr,
+		const struct tonga_power_state *bootState)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint8_t count, level;
+
+	count = (uint8_t) (pptable_info->vdd_dep_on_sclk->count);
+	for (level = 0; level < count; level++) {
+		if (pptable_info->vdd_dep_on_sclk->entries[level].clk >=
+			bootState->performance_levels[0].engine_clock) {
+			data->smc_state_table.GraphicsBootLevel = level;
+			break;
+		}
+	}
+
+	count = (uint8_t) (pptable_info->vdd_dep_on_mclk->count);
+	for (level = 0; level < count; level++) {
+		if (pptable_info->vdd_dep_on_mclk->entries[level].clk >=
+			bootState->performance_levels[0].memory_clock) {
+			data->smc_state_table.MemoryBootLevel = level;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Initializes the SMC table and uploads it
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @param    pInput  the pointer to input data (PowerState)
+ * @return   always 0
+ */
+int tonga_init_smc_table(struct pp_hwmgr *hwmgr)
+{
+	int result;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	SMU72_Discrete_DpmTable  *table = &(data->smc_state_table);
+	const phw_tonga_ulv_parm *ulv = &(data->ulv);
+	uint8_t i;
+	PECI_RegistryValue reg_value;
+	pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
+
+	result = tonga_setup_default_dpm_tables(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to setup default DPM tables!", return result;);
+	memset(&(data->smc_state_table), 0x00, sizeof(data->smc_state_table));
+	if (TONGA_VOLTAGE_CONTROL_NONE != data->voltage_control) {
+		tonga_populate_smc_voltage_tables(hwmgr, table);
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_AutomaticDCTransition)) {
+		table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_StepVddc)) {
+		table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
+	}
+
+	if (data->is_memory_GDDR5) {
+		table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
+	}
+
+	i = PHM_READ_FIELD(hwmgr->device, CC_MC_MAX_CHANNEL, NOOFCHAN);
+
+	if (i == 1 || i == 0) {
+		table->SystemFlags |= PPSMC_SYSTEMFLAG_12CHANNEL;
+	}
+
+	if (ulv->ulv_supported && pptable_info->us_ulv_voltage_offset) {
+		PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize ULV state!", return result;);
+
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_ULV_PARAMETER, ulv->ch_ulv_parameter);
+	}
+
+	result = tonga_populate_smc_link_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize Link Level!", return result;);
+
+	result = tonga_populate_all_graphic_levels(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize Graphics Level!", return result;);
+
+	result = tonga_populate_all_memory_levels(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize Memory Level!", return result;);
+
+	result = tonga_populate_smv_acpi_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize ACPI Level!", return result;);
+
+	result = tonga_populate_smc_vce_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize VCE Level!", return result;);
+
+	result = tonga_populate_smc_acp_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize ACP Level!", return result;);
+
+	result = tonga_populate_smc_samu_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize SAMU Level!", return result;);
+
+	/* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */
+	/* need to populate the  ARB settings for the initial state. */
+	result = tonga_program_memory_timing_parameters(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to Write ARB settings for the initial state.", return result;);
+
+	result = tonga_populate_smc_uvd_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize UVD Level!", return result;);
+
+	result = tonga_populate_smc_boot_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize Boot Level!", return result;);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ClockStretcher)) {
+		result = tonga_populate_clock_stretcher_data_table(hwmgr);
+		PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to populate Clock Stretcher Data Table!", return result;);
+	}
+	table->GraphicsVoltageChangeEnable  = 1;
+	table->GraphicsThermThrottleEnable  = 1;
+	table->GraphicsInterval = 1;
+	table->VoltageInterval  = 1;
+	table->ThermalInterval  = 1;
+	table->TemperatureLimitHigh =
+		pptable_info->cac_dtp_table->usTargetOperatingTemp *
+		TONGA_Q88_FORMAT_CONVERSION_UNIT;
+	table->TemperatureLimitLow =
+		(pptable_info->cac_dtp_table->usTargetOperatingTemp - 1) *
+		TONGA_Q88_FORMAT_CONVERSION_UNIT;
+	table->MemoryVoltageChangeEnable  = 1;
+	table->MemoryInterval  = 1;
+	table->VoltageResponseTime  = 0;
+	table->PhaseResponseTime  = 0;
+	table->MemoryThermThrottleEnable  = 1;
+
+	/*
+	* Cail reads current link status and reports it as cap (we cannot change this due to some previous issues we had)
+	* SMC drops the link status to lowest level after enabling DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again
+	* but this time Cail reads current link status which was set to low by SMC and reports it as cap to powerplay
+	* To avoid it, we set PCIeBootLinkLevel to highest dpm level
+	*/
+	PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count),
+			"There must be 1 or more PCIE levels defined in PPTable.",
+			return -1);
+
+	table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count);
+
+	table->PCIeGenInterval  = 1;
+
+	result = tonga_populate_vr_config(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to populate VRConfig setting!", return result);
+
+	table->ThermGpio  = 17;
+	table->SclkStepSize = 0x4000;
+
+	reg_value = 0;
+	if ((0 == reg_value) &&
+		(0 == atomctrl_get_pp_assign_pin(hwmgr,
+			VDDC_VRHOT_GPIO_PINID, &gpio_pin_assignment))) {
+		table->VRHotGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_RegulatorHot);
+	} else {
+		table->VRHotGpio = TONGA_UNUSED_GPIO_PIN;
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_RegulatorHot);
+	}
+
+	/* ACDC Switch GPIO */
+	reg_value = 0;
+	if ((0 == reg_value) &&
+		(0 == atomctrl_get_pp_assign_pin(hwmgr,
+			PP_AC_DC_SWITCH_GPIO_PINID, &gpio_pin_assignment))) {
+		table->AcDcGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_AutomaticDCTransition);
+	} else {
+		table->AcDcGpio = TONGA_UNUSED_GPIO_PIN;
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_AutomaticDCTransition);
+	}
+
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_Falcon_QuickTransition);
+
+	reg_value = 0;
+	if (1 == reg_value) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_AutomaticDCTransition);
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_Falcon_QuickTransition);
+	}
+
+	reg_value = 0;
+	if ((0 == reg_value) &&
+		(0 == atomctrl_get_pp_assign_pin(hwmgr,
+			THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin_assignment))) {
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ThermalOutGPIO);
+
+		table->ThermOutGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
+
+		table->ThermOutPolarity =
+			(0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) &
+			(1 << gpio_pin_assignment.uc_gpio_pin_bit_shift))) ? 1:0;
+
+		table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY;
+
+		/* if required, combine VRHot/PCC with thermal out GPIO*/
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_RegulatorHot) &&
+			phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_CombinePCCWithThermalSignal)){
+			table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT;
+		}
+	} else {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ThermalOutGPIO);
+
+		table->ThermOutGpio = 17;
+		table->ThermOutPolarity = 1;
+		table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE;
+	}
+
+	for (i = 0; i < SMU72_MAX_ENTRIES_SMIO; i++) {
+		table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
+	}
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
+	CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
+	CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
+	CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
+	CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
+
+	/* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
+	result = tonga_copy_bytes_to_smc(hwmgr->smumgr, data->dpm_table_start +
+										offsetof(SMU72_Discrete_DpmTable, SystemFlags),
+										(uint8_t *)&(table->SystemFlags),
+										sizeof(SMU72_Discrete_DpmTable)-3 * sizeof(SMU72_PIDController),
+										data->sram_end);
+
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to upload dpm data to SMC memory!", return result;);
+
+	return result;
+}
+
+/* Look up the voltaged based on DAL's requested level. and then send the requested VDDC voltage to SMC*/
+static void tonga_apply_dal_minimum_voltage_request(struct pp_hwmgr *hwmgr)
+{
+	return;
+}
+
+int tonga_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr)
+{
+	PPSMC_Result result;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	/* Apply minimum voltage based on DAL's request level */
+	tonga_apply_dal_minimum_voltage_request(hwmgr);
+
+	if (0 == data->sclk_dpm_key_disabled) {
+		/* Checking if DPM is running.  If we discover hang because of this, we should skip this message.*/
+		if (0 != tonga_is_dpm_running(hwmgr))
+			printk(KERN_ERR "[ powerplay ] Trying to set Enable Mask when DPM is disabled \n");
+
+		if (0 != data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
+			result = smum_send_msg_to_smc_with_parameter(
+								hwmgr->smumgr,
+				(PPSMC_Msg)PPSMC_MSG_SCLKDPM_SetEnabledMask,
+				data->dpm_level_enable_mask.sclk_dpm_enable_mask);
+			PP_ASSERT_WITH_CODE((0 == result),
+				"Set Sclk Dpm enable Mask failed", return -1);
+		}
+	}
+
+	if (0 == data->mclk_dpm_key_disabled) {
+		/* Checking if DPM is running.  If we discover hang because of this, we should skip this message.*/
+		if (0 != tonga_is_dpm_running(hwmgr))
+			printk(KERN_ERR "[ powerplay ] Trying to set Enable Mask when DPM is disabled \n");
+
+		if (0 != data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
+			result = smum_send_msg_to_smc_with_parameter(
+								hwmgr->smumgr,
+				(PPSMC_Msg)PPSMC_MSG_MCLKDPM_SetEnabledMask,
+				data->dpm_level_enable_mask.mclk_dpm_enable_mask);
+			PP_ASSERT_WITH_CODE((0 == result),
+				"Set Mclk Dpm enable Mask failed", return -1);
+		}
+	}
+
+	return 0;
+}
+
+
+int tonga_force_dpm_highest(struct pp_hwmgr *hwmgr)
+{
+	uint32_t level, tmp;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	if (0 == data->pcie_dpm_key_disabled) {
+		/* PCIE */
+		if (data->dpm_level_enable_mask.pcie_dpm_enable_mask != 0) {
+			level = 0;
+			tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask;
+			while (tmp >>= 1)
+				level++ ;
+
+			if (0 != level) {
+				PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_pcie(hwmgr, level)),
+					"force highest pcie dpm state failed!", return -1);
+			}
+		}
+	}
+
+	if (0 == data->sclk_dpm_key_disabled) {
+		/* SCLK */
+		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask != 0) {
+			level = 0;
+			tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask;
+			while (tmp >>= 1)
+				level++ ;
+
+			if (0 != level) {
+				PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state(hwmgr, level)),
+					"force highest sclk dpm state failed!", return -1);
+				if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
+					CGS_IND_REG__SMC, TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX) != level)
+					printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \
+						Curr_Sclk_Index does not match the level \n");
+
+			}
+		}
+	}
+
+	if (0 == data->mclk_dpm_key_disabled) {
+		/* MCLK */
+		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask != 0) {
+			level = 0;
+			tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask;
+			while (tmp >>= 1)
+				level++ ;
+
+			if (0 != level) {
+				PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_mclk(hwmgr, level)),
+					"force highest mclk dpm state failed!", return -1);
+				if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+					TARGET_AND_CURRENT_PROFILE_INDEX, CURR_MCLK_INDEX) != level)
+					printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \
+						Curr_Mclk_Index does not match the level \n");
+			}
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Find the MC microcode version and store it in the HwMgr struct
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_get_mc_microcode_version (struct pp_hwmgr *hwmgr)
+{
+	cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F);
+
+	hwmgr->microcode_version_info.MC = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA);
+
+	return 0;
+}
+
+/**
+ * Initialize Dynamic State Adjustment Rule Settings
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ */
+int tonga_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr)
+{
+	uint32_t table_size;
+	struct phm_clock_voltage_dependency_table *table_clk_vlt;
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	hwmgr->dyn_state.mclk_sclk_ratio = 4;
+	hwmgr->dyn_state.sclk_mclk_delta = 15000;      /* 150 MHz */
+	hwmgr->dyn_state.vddc_vddci_delta = 200;       /* 200mV */
+
+	/* initialize vddc_dep_on_dal_pwrl table */
+	table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record);
+	table_clk_vlt = (struct phm_clock_voltage_dependency_table *)kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == table_clk_vlt) {
+		printk(KERN_ERR "[ powerplay ] Can not allocate space for vddc_dep_on_dal_pwrl! \n");
+		return -ENOMEM;
+	} else {
+		table_clk_vlt->count = 4;
+		table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW;
+		table_clk_vlt->entries[0].v = 0;
+		table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW;
+		table_clk_vlt->entries[1].v = 720;
+		table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL;
+		table_clk_vlt->entries[2].v = 810;
+		table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE;
+		table_clk_vlt->entries[3].v = 900;
+		pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
+		hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
+	}
+
+	return 0;
+}
+
+static int tonga_set_private_var_based_on_pptale(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
+		pptable_info->vdd_dep_on_sclk;
+	phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
+		pptable_info->vdd_dep_on_mclk;
+
+	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL,
+		"VDD dependency on SCLK table is missing. 	\
+		This table is mandatory", return -1);
+	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
+		"VDD dependency on SCLK table has to have is missing. 	\
+		This table is mandatory", return -1);
+
+	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL,
+		"VDD dependency on MCLK table is missing. 	\
+		This table is mandatory", return -1);
+	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
+		"VDD dependency on MCLK table has to have is missing.	 \
+		This table is mandatory", return -1);
+
+	data->min_vddc_in_pp_table = (uint16_t)allowed_sclk_vdd_table->entries[0].vddc;
+	data->max_vddc_in_pp_table = (uint16_t)allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
+
+	pptable_info->max_clock_voltage_on_ac.sclk =
+		allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
+	pptable_info->max_clock_voltage_on_ac.mclk =
+		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
+	pptable_info->max_clock_voltage_on_ac.vddc =
+		allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
+	pptable_info->max_clock_voltage_on_ac.vddci =
+		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
+
+	hwmgr->dyn_state.max_clock_voltage_on_ac.sclk =
+		pptable_info->max_clock_voltage_on_ac.sclk;
+	hwmgr->dyn_state.max_clock_voltage_on_ac.mclk =
+		pptable_info->max_clock_voltage_on_ac.mclk;
+	hwmgr->dyn_state.max_clock_voltage_on_ac.vddc =
+		pptable_info->max_clock_voltage_on_ac.vddc;
+	hwmgr->dyn_state.max_clock_voltage_on_ac.vddci =
+		pptable_info->max_clock_voltage_on_ac.vddci;
+
+	return 0;
+}
+
+int tonga_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	int result = 1;
+
+	PP_ASSERT_WITH_CODE (0 == tonga_is_dpm_running(hwmgr),
+		"Trying to Unforce DPM when DPM is disabled. Returning without sending SMC message.",
+							return result);
+
+	if (0 == data->pcie_dpm_key_disabled) {
+		PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(
+							     hwmgr->smumgr,
+					PPSMC_MSG_PCIeDPM_UnForceLevel)),
+					   "unforce pcie level failed!",
+								return -1);
+	}
+
+	result = tonga_upload_dpm_level_enable_mask(hwmgr);
+
+	return result;
+}
+
+static uint32_t tonga_get_lowest_enable_level(
+				struct pp_hwmgr *hwmgr, uint32_t level_mask)
+{
+	uint32_t level = 0;
+
+	while (0 == (level_mask & (1 << level)))
+		level++;
+
+	return level;
+}
+
+static int tonga_force_dpm_lowest(struct pp_hwmgr *hwmgr)
+{
+	uint32_t level;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	if (0 == data->pcie_dpm_key_disabled) {
+		/* PCIE */
+		if (data->dpm_level_enable_mask.pcie_dpm_enable_mask != 0) {
+			level = tonga_get_lowest_enable_level(hwmgr,
+							      data->dpm_level_enable_mask.pcie_dpm_enable_mask);
+			PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_pcie(hwmgr, level)),
+					    "force lowest pcie dpm state failed!", return -1);
+		}
+	}
+
+	if (0 == data->sclk_dpm_key_disabled) {
+		/* SCLK */
+		if (0 != data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
+			level = tonga_get_lowest_enable_level(hwmgr,
+							      data->dpm_level_enable_mask.sclk_dpm_enable_mask);
+
+			PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state(hwmgr, level)),
+					    "force sclk dpm state failed!", return -1);
+
+			if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
+							 CGS_IND_REG__SMC, TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX) != level)
+				printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index.	\
+				Curr_Sclk_Index does not match the level \n");
+		}
+	}
+
+	if (0 == data->mclk_dpm_key_disabled) {
+		/* MCLK */
+		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask != 0) {
+			level = tonga_get_lowest_enable_level(hwmgr,
+							      data->dpm_level_enable_mask.mclk_dpm_enable_mask);
+			PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_mclk(hwmgr, level)),
+					    "force lowest mclk dpm state failed!", return -1);
+			if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+							 TARGET_AND_CURRENT_PROFILE_INDEX, CURR_MCLK_INDEX) != level)
+				printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \
+						Curr_Mclk_Index does not match the level \n");
+		}
+	}
+
+	return 0;
+}
+
+static int tonga_patch_voltage_dependency_tables_with_lookup_table(struct pp_hwmgr *hwmgr)
+{
+	uint8_t entryId;
+	uint8_t voltageId;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk;
+	phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk;
+	phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
+
+	if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) {
+		for (entryId = 0; entryId < sclk_table->count; ++entryId) {
+			voltageId = sclk_table->entries[entryId].vddInd;
+			sclk_table->entries[entryId].vddgfx =
+				pptable_info->vddgfx_lookup_table->entries[voltageId].us_vdd;
+		}
+	} else {
+		for (entryId = 0; entryId < sclk_table->count; ++entryId) {
+			voltageId = sclk_table->entries[entryId].vddInd;
+			sclk_table->entries[entryId].vddc =
+				pptable_info->vddc_lookup_table->entries[voltageId].us_vdd;
+		}
+	}
+
+	for (entryId = 0; entryId < mclk_table->count; ++entryId) {
+		voltageId = mclk_table->entries[entryId].vddInd;
+		mclk_table->entries[entryId].vddc =
+			pptable_info->vddc_lookup_table->entries[voltageId].us_vdd;
+	}
+
+	for (entryId = 0; entryId < mm_table->count; ++entryId) {
+		voltageId = mm_table->entries[entryId].vddcInd;
+		mm_table->entries[entryId].vddc =
+			pptable_info->vddc_lookup_table->entries[voltageId].us_vdd;
+	}
+
+	return 0;
+
+}
+
+static int tonga_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr)
+{
+	uint8_t entryId;
+	phm_ppt_v1_voltage_lookup_record v_record;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk;
+	phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk;
+
+	if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) {
+		for (entryId = 0; entryId < sclk_table->count; ++entryId) {
+			if (sclk_table->entries[entryId].vdd_offset & (1 << 15))
+				v_record.us_vdd = sclk_table->entries[entryId].vddgfx +
+					sclk_table->entries[entryId].vdd_offset - 0xFFFF;
+			else
+				v_record.us_vdd = sclk_table->entries[entryId].vddgfx +
+					sclk_table->entries[entryId].vdd_offset;
+
+			sclk_table->entries[entryId].vddc =
+				v_record.us_cac_low = v_record.us_cac_mid =
+				v_record.us_cac_high = v_record.us_vdd;
+
+			tonga_add_voltage(hwmgr, pptable_info->vddc_lookup_table, &v_record);
+		}
+
+		for (entryId = 0; entryId < mclk_table->count; ++entryId) {
+			if (mclk_table->entries[entryId].vdd_offset & (1 << 15))
+				v_record.us_vdd = mclk_table->entries[entryId].vddc +
+					mclk_table->entries[entryId].vdd_offset - 0xFFFF;
+			else
+				v_record.us_vdd = mclk_table->entries[entryId].vddc +
+					mclk_table->entries[entryId].vdd_offset;
+
+			mclk_table->entries[entryId].vddgfx = v_record.us_cac_low =
+				v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd;
+			tonga_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record);
+		}
+	}
+
+	return 0;
+
+}
+
+static int tonga_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr)
+{
+	uint32_t entryId;
+	phm_ppt_v1_voltage_lookup_record v_record;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
+
+	if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) {
+		for (entryId = 0; entryId < mm_table->count; entryId++) {
+			if (mm_table->entries[entryId].vddgfx_offset & (1 << 15))
+				v_record.us_vdd = mm_table->entries[entryId].vddc +
+					mm_table->entries[entryId].vddgfx_offset - 0xFFFF;
+			else
+				v_record.us_vdd = mm_table->entries[entryId].vddc +
+					mm_table->entries[entryId].vddgfx_offset;
+
+			/* Add the calculated VDDGFX to the VDDGFX lookup table */
+			mm_table->entries[entryId].vddgfx = v_record.us_cac_low =
+				v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd;
+			tonga_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record);
+		}
+	}
+	return 0;
+}
+
+
+/**
+ * Change virtual leakage voltage to actual value.
+ *
+ * @param     hwmgr  the address of the powerplay hardware manager.
+ * @param     pointer to changing voltage
+ * @param     pointer to leakage table
+ */
+static void tonga_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr,
+		uint16_t *voltage, phw_tonga_leakage_voltage *pLeakageTable)
+{
+	uint32_t leakage_index;
+
+	/* search for leakage voltage ID 0xff01 ~ 0xff08 */
+	for (leakage_index = 0; leakage_index < pLeakageTable->count; leakage_index++) {
+		/* if this voltage matches a leakage voltage ID */
+		/* patch with actual leakage voltage */
+		if (pLeakageTable->leakage_id[leakage_index] == *voltage) {
+			*voltage = pLeakageTable->actual_voltage[leakage_index];
+			break;
+		}
+	}
+
+	if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
+		printk(KERN_ERR "[ powerplay ] Voltage value looks like a Leakage ID but it's not patched \n");
+}
+
+/**
+ * Patch voltage lookup table by EVV leakages.
+ *
+ * @param     hwmgr  the address of the powerplay hardware manager.
+ * @param     pointer to voltage lookup table
+ * @param     pointer to leakage table
+ * @return     always 0
+ */
+static int tonga_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_voltage_lookup_table *lookup_table,
+		phw_tonga_leakage_voltage *pLeakageTable)
+{
+	uint32_t i;
+
+	for (i = 0; i < lookup_table->count; i++) {
+		tonga_patch_with_vdd_leakage(hwmgr,
+			&lookup_table->entries[i].us_vdd, pLeakageTable);
+	}
+
+	return 0;
+}
+
+static int tonga_patch_clock_voltage_lomits_with_vddc_leakage(struct pp_hwmgr *hwmgr,
+		phw_tonga_leakage_voltage *pLeakageTable, uint16_t *Vddc)
+{
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	tonga_patch_with_vdd_leakage(hwmgr, (uint16_t *)Vddc, pLeakageTable);
+	hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
+		pptable_info->max_clock_voltage_on_dc.vddc;
+
+	return 0;
+}
+
+static int tonga_patch_clock_voltage_limits_with_vddgfx_leakage(
+		struct pp_hwmgr *hwmgr, phw_tonga_leakage_voltage *pLeakageTable,
+		uint16_t *Vddgfx)
+{
+	tonga_patch_with_vdd_leakage(hwmgr, (uint16_t *)Vddgfx, pLeakageTable);
+	return 0;
+}
+
+int tonga_sort_lookup_table(struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_voltage_lookup_table *lookup_table)
+{
+	uint32_t table_size, i, j;
+	phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record;
+	table_size = lookup_table->count;
+
+	PP_ASSERT_WITH_CODE(0 != lookup_table->count,
+		"Lookup table is empty", return -1);
+
+	/* Sorting voltages */
+	for (i = 0; i < table_size - 1; i++) {
+		for (j = i + 1; j > 0; j--) {
+			if (lookup_table->entries[j].us_vdd < lookup_table->entries[j-1].us_vdd) {
+				tmp_voltage_lookup_record = lookup_table->entries[j-1];
+				lookup_table->entries[j-1] = lookup_table->entries[j];
+				lookup_table->entries[j] = tmp_voltage_lookup_record;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int tonga_complete_dependency_tables(struct pp_hwmgr *hwmgr)
+{
+	int result = 0;
+	int tmp_result;
+	tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) {
+		tmp_result = tonga_patch_lookup_table_with_leakage(hwmgr,
+			pptable_info->vddgfx_lookup_table, &(data->vddcgfx_leakage));
+		if (tmp_result != 0)
+			result = tmp_result;
+
+		tmp_result = tonga_patch_clock_voltage_limits_with_vddgfx_leakage(hwmgr,
+			&(data->vddcgfx_leakage), &pptable_info->max_clock_voltage_on_dc.vddgfx);
+		if (tmp_result != 0)
+			result = tmp_result;
+	} else {
+		tmp_result = tonga_patch_lookup_table_with_leakage(hwmgr,
+			pptable_info->vddc_lookup_table, &(data->vddc_leakage));
+		if (tmp_result != 0)
+			result = tmp_result;
+
+		tmp_result = tonga_patch_clock_voltage_lomits_with_vddc_leakage(hwmgr,
+			&(data->vddc_leakage), &pptable_info->max_clock_voltage_on_dc.vddc);
+		if (tmp_result != 0)
+			result = tmp_result;
+	}
+
+	tmp_result = tonga_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
+	if (tmp_result != 0)
+		result = tmp_result;
+
+	tmp_result = tonga_calc_voltage_dependency_tables(hwmgr);
+	if (tmp_result != 0)
+		result = tmp_result;
+
+	tmp_result = tonga_calc_mm_voltage_dependency_table(hwmgr);
+	if (tmp_result != 0)
+		result = tmp_result;
+
+	tmp_result = tonga_sort_lookup_table(hwmgr, pptable_info->vddgfx_lookup_table);
+	if (tmp_result != 0)
+		result = tmp_result;
+
+	tmp_result = tonga_sort_lookup_table(hwmgr, pptable_info->vddc_lookup_table);
+	if (tmp_result != 0)
+		result = tmp_result;
+
+	return result;
+}
+
+int tonga_init_sclk_threshold(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	data->low_sclk_interrupt_threshold = 0;
+
+	return 0;
+}
+
+int tonga_setup_asic_task(struct pp_hwmgr *hwmgr)
+{
+	int tmp_result, result = 0;
+
+	tmp_result = tonga_read_clock_registers(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to read clock registers!", result = tmp_result);
+
+	tmp_result = tonga_get_memory_type(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to get memory type!", result = tmp_result);
+
+	tmp_result = tonga_enable_acpi_power_management(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to enable ACPI power management!", result = tmp_result);
+
+	tmp_result = tonga_init_power_gate_state(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to init power gate state!", result = tmp_result);
+
+	tmp_result = tonga_get_mc_microcode_version(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to get MC microcode version!", result = tmp_result);
+
+	tmp_result = tonga_init_sclk_threshold(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to init sclk threshold!", result = tmp_result);
+
+	return result;
+}
+
+/**
+ * Enable voltage control
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_enable_voltage_control(struct pp_hwmgr *hwmgr)
+{
+	/* enable voltage control */
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1);
+
+	return 0;
+}
+
+/**
+ * Checks if we want to support voltage control
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ */
+bool cf_tonga_voltage_control(const struct pp_hwmgr *hwmgr)
+{
+	const struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	return(TONGA_VOLTAGE_CONTROL_NONE != data->voltage_control);
+}
+
+/*---------------------------MC----------------------------*/
+
+uint8_t tonga_get_memory_modile_index(struct pp_hwmgr *hwmgr)
+{
+	return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16));
+}
+
+bool tonga_check_s0_mc_reg_index(uint16_t inReg, uint16_t *outReg)
+{
+	bool result = 1;
+
+	switch (inReg) {
+	case  mmMC_SEQ_RAS_TIMING:
+		*outReg = mmMC_SEQ_RAS_TIMING_LP;
+		break;
+
+	case  mmMC_SEQ_DLL_STBY:
+		*outReg = mmMC_SEQ_DLL_STBY_LP;
+		break;
+
+	case  mmMC_SEQ_G5PDX_CMD0:
+		*outReg = mmMC_SEQ_G5PDX_CMD0_LP;
+		break;
+
+	case  mmMC_SEQ_G5PDX_CMD1:
+		*outReg = mmMC_SEQ_G5PDX_CMD1_LP;
+		break;
+
+	case  mmMC_SEQ_G5PDX_CTRL:
+		*outReg = mmMC_SEQ_G5PDX_CTRL_LP;
+		break;
+
+	case mmMC_SEQ_CAS_TIMING:
+		*outReg = mmMC_SEQ_CAS_TIMING_LP;
+		break;
+
+	case mmMC_SEQ_MISC_TIMING:
+		*outReg = mmMC_SEQ_MISC_TIMING_LP;
+		break;
+
+	case mmMC_SEQ_MISC_TIMING2:
+		*outReg = mmMC_SEQ_MISC_TIMING2_LP;
+		break;
+
+	case mmMC_SEQ_PMG_DVS_CMD:
+		*outReg = mmMC_SEQ_PMG_DVS_CMD_LP;
+		break;
+
+	case mmMC_SEQ_PMG_DVS_CTL:
+		*outReg = mmMC_SEQ_PMG_DVS_CTL_LP;
+		break;
+
+	case mmMC_SEQ_RD_CTL_D0:
+		*outReg = mmMC_SEQ_RD_CTL_D0_LP;
+		break;
+
+	case mmMC_SEQ_RD_CTL_D1:
+		*outReg = mmMC_SEQ_RD_CTL_D1_LP;
+		break;
+
+	case mmMC_SEQ_WR_CTL_D0:
+		*outReg = mmMC_SEQ_WR_CTL_D0_LP;
+		break;
+
+	case mmMC_SEQ_WR_CTL_D1:
+		*outReg = mmMC_SEQ_WR_CTL_D1_LP;
+		break;
+
+	case mmMC_PMG_CMD_EMRS:
+		*outReg = mmMC_SEQ_PMG_CMD_EMRS_LP;
+		break;
+
+	case mmMC_PMG_CMD_MRS:
+		*outReg = mmMC_SEQ_PMG_CMD_MRS_LP;
+		break;
+
+	case mmMC_PMG_CMD_MRS1:
+		*outReg = mmMC_SEQ_PMG_CMD_MRS1_LP;
+		break;
+
+	case mmMC_SEQ_PMG_TIMING:
+		*outReg = mmMC_SEQ_PMG_TIMING_LP;
+		break;
+
+	case mmMC_PMG_CMD_MRS2:
+		*outReg = mmMC_SEQ_PMG_CMD_MRS2_LP;
+		break;
+
+	case mmMC_SEQ_WR_CTL_2:
+		*outReg = mmMC_SEQ_WR_CTL_2_LP;
+		break;
+
+	default:
+		result = 0;
+		break;
+	}
+
+	return result;
+}
+
+int tonga_set_s0_mc_reg_index(phw_tonga_mc_reg_table *table)
+{
+	uint32_t i;
+	uint16_t address;
+
+	for (i = 0; i < table->last; i++) {
+		table->mc_reg_address[i].s0 =
+			tonga_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address)
+			? address : table->mc_reg_address[i].s1;
+	}
+	return 0;
+}
+
+int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, phw_tonga_mc_reg_table *ni_table)
+{
+	uint8_t i, j;
+
+	PP_ASSERT_WITH_CODE((table->last <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
+		"Invalid VramInfo table.", return -1);
+	PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES),
+		"Invalid VramInfo table.", return -1);
+
+	for (i = 0; i < table->last; i++) {
+		ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
+	}
+	ni_table->last = table->last;
+
+	for (i = 0; i < table->num_entries; i++) {
+		ni_table->mc_reg_table_entry[i].mclk_max =
+			table->mc_reg_table_entry[i].mclk_max;
+		for (j = 0; j < table->last; j++) {
+			ni_table->mc_reg_table_entry[i].mc_data[j] =
+				table->mc_reg_table_entry[i].mc_data[j];
+		}
+	}
+
+	ni_table->num_entries = table->num_entries;
+
+	return 0;
+}
+
+/**
+ * VBIOS omits some information to reduce size, we need to recover them here.
+ * 1.   when we see mmMC_SEQ_MISC1, bit[31:16] EMRS1, need to be write to  mmMC_PMG_CMD_EMRS /_LP[15:0].
+ *      Bit[15:0] MRS, need to be update mmMC_PMG_CMD_MRS/_LP[15:0]
+ * 2.   when we see mmMC_SEQ_RESERVE_M, bit[15:0] EMRS2, need to be write to mmMC_PMG_CMD_MRS1/_LP[15:0].
+ * 3.   need to set these data for each clock range
+ *
+ * @param    hwmgr the address of the powerplay hardware manager.
+ * @param    table the address of MCRegTable
+ * @return   always 0
+ */
+int tonga_set_mc_special_registers(struct pp_hwmgr *hwmgr, phw_tonga_mc_reg_table *table)
+{
+	uint8_t i, j, k;
+	uint32_t temp_reg;
+	const tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	for (i = 0, j = table->last; i < table->last; i++) {
+		PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
+			"Invalid VramInfo table.", return -1);
+		switch (table->mc_reg_address[i].s1) {
+		/*
+		* mmMC_SEQ_MISC1, bit[31:16] EMRS1, need to be write to  mmMC_PMG_CMD_EMRS /_LP[15:0].
+		* Bit[15:0] MRS, need to be update mmMC_PMG_CMD_MRS/_LP[15:0]
+		*/
+		case mmMC_SEQ_MISC1:
+			temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS);
+			table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS;
+			table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP;
+			for (k = 0; k < table->num_entries; k++) {
+				table->mc_reg_table_entry[k].mc_data[j] =
+					((temp_reg & 0xffff0000)) |
+					((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
+			}
+			j++;
+			PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
+				"Invalid VramInfo table.", return -1);
+
+			temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS);
+			table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS;
+			table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP;
+			for (k = 0; k < table->num_entries; k++) {
+				table->mc_reg_table_entry[k].mc_data[j] =
+					(temp_reg & 0xffff0000) |
+					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
+
+				if (!data->is_memory_GDDR5) {
+					table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
+				}
+			}
+			j++;
+			PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
+				"Invalid VramInfo table.", return -1);
+
+			if (!data->is_memory_GDDR5) {
+				table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD;
+				table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD;
+				for (k = 0; k < table->num_entries; k++) {
+					table->mc_reg_table_entry[k].mc_data[j] =
+						(table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
+				}
+				j++;
+				PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
+					"Invalid VramInfo table.", return -1);
+			}
+
+			break;
+
+		case mmMC_SEQ_RESERVE_M:
+			temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1);
+			table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1;
+			table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP;
+			for (k = 0; k < table->num_entries; k++) {
+				table->mc_reg_table_entry[k].mc_data[j] =
+					(temp_reg & 0xffff0000) |
+					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
+			}
+			j++;
+			PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
+				"Invalid VramInfo table.", return -1);
+			break;
+
+		default:
+			break;
+		}
+
+	}
+
+	table->last = j;
+
+	return 0;
+}
+
+int tonga_set_valid_flag(phw_tonga_mc_reg_table *table)
+{
+	uint8_t i, j;
+	for (i = 0; i < table->last; i++) {
+		for (j = 1; j < table->num_entries; j++) {
+			if (table->mc_reg_table_entry[j-1].mc_data[i] !=
+				table->mc_reg_table_entry[j].mc_data[i]) {
+				table->validflag |= (1<<i);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
+{
+	int result;
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+	pp_atomctrl_mc_reg_table *table;
+	phw_tonga_mc_reg_table *ni_table = &data->tonga_mc_reg_table;
+	uint8_t module_index = tonga_get_memory_modile_index(hwmgr);
+
+	table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL);
+
+	if (NULL == table)
+		return -ENOMEM;
+
+	/* Program additional LP registers that are no longer programmed by VBIOS */
+	cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2));
+	cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2));
+
+	memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table));
+
+	result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table);
+
+	if (0 == result)
+		result = tonga_copy_vbios_smc_reg_table(table, ni_table);
+
+	if (0 == result) {
+		tonga_set_s0_mc_reg_index(ni_table);
+		result = tonga_set_mc_special_registers(hwmgr, ni_table);
+	}
+
+	if (0 == result)
+		tonga_set_valid_flag(ni_table);
+
+	kfree(table);
+	return result;
+}
+
+/*
+* Copy one arb setting to another and then switch the active set.
+* arbFreqSrc and arbFreqDest is one of the MC_CG_ARB_FREQ_Fx constants.
+*/
+int tonga_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr,
+		uint32_t arbFreqSrc, uint32_t arbFreqDest)
+{
+	uint32_t mc_arb_dram_timing;
+	uint32_t mc_arb_dram_timing2;
+	uint32_t burst_time;
+	uint32_t mc_cg_config;
+
+	switch (arbFreqSrc) {
+	case MC_CG_ARB_FREQ_F0:
+		mc_arb_dram_timing  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
+		mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
+		burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
+		break;
+
+	case MC_CG_ARB_FREQ_F1:
+		mc_arb_dram_timing  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1);
+		mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1);
+		burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1);
+		break;
+
+	default:
+		return -1;
+	}
+
+	switch (arbFreqDest) {
+	case MC_CG_ARB_FREQ_F0:
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing);
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
+		PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time);
+		break;
+
+	case MC_CG_ARB_FREQ_F1:
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
+		PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time);
+		break;
+
+	default:
+		return -1;
+	}
+
+	mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG);
+	mc_cg_config |= 0x0000000F;
+	cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config);
+	PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arbFreqDest);
+
+	return 0;
+}
+
+/**
+ * Initial switch from ARB F0->F1
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ * This function is to be called from the SetPowerState table.
+ */
+int tonga_initial_switch_from_arb_f0_to_f1(struct pp_hwmgr *hwmgr)
+{
+	return tonga_copy_and_switch_arb_sets(hwmgr, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
+}
+
+/**
+ * Initialize the ARB DRAM timing table's index field.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_init_arb_table_index(struct pp_hwmgr *hwmgr)
+{
+	const tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	uint32_t tmp;
+	int result;
+
+	/*
+	* This is a read-modify-write on the first byte of the ARB table.
+	* The first byte in the SMU72_Discrete_MCArbDramTimingTable structure is the field 'current'.
+	* This solution is ugly, but we never write the whole table only individual fields in it.
+	* In reality this field should not be in that structure but in a soft register.
+	*/
+	result = tonga_read_smc_sram_dword(hwmgr->smumgr,
+				data->arb_table_start, &tmp, data->sram_end);
+
+	if (0 != result)
+		return result;
+
+	tmp &= 0x00FFFFFF;
+	tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24;
+
+	return tonga_write_smc_sram_dword(hwmgr->smumgr,
+			data->arb_table_start,  tmp, data->sram_end);
+}
+
+int tonga_populate_mc_reg_address(struct pp_hwmgr *hwmgr, SMU72_Discrete_MCRegisters *mc_reg_table)
+{
+	const struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	uint32_t i, j;
+
+	for (i = 0, j = 0; j < data->tonga_mc_reg_table.last; j++) {
+		if (data->tonga_mc_reg_table.validflag & 1<<j) {
+			PP_ASSERT_WITH_CODE(i < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE,
+				"Index of mc_reg_table->address[] array out of boundary", return -1);
+			mc_reg_table->address[i].s0 =
+				PP_HOST_TO_SMC_US(data->tonga_mc_reg_table.mc_reg_address[j].s0);
+			mc_reg_table->address[i].s1 =
+				PP_HOST_TO_SMC_US(data->tonga_mc_reg_table.mc_reg_address[j].s1);
+			i++;
+		}
+	}
+
+	mc_reg_table->last = (uint8_t)i;
+
+	return 0;
+}
+
+/*convert register values from driver to SMC format */
+void tonga_convert_mc_registers(
+	const phw_tonga_mc_reg_entry * pEntry,
+	SMU72_Discrete_MCRegisterSet *pData,
+	uint32_t numEntries, uint32_t validflag)
+{
+	uint32_t i, j;
+
+	for (i = 0, j = 0; j < numEntries; j++) {
+		if (validflag & 1<<j) {
+			pData->value[i] = PP_HOST_TO_SMC_UL(pEntry->mc_data[j]);
+			i++;
+		}
+	}
+}
+
+/* find the entry in the memory range table, then populate the value to SMC's tonga_mc_reg_table */
+int tonga_convert_mc_reg_table_entry_to_smc(
+		struct pp_hwmgr *hwmgr,
+		const uint32_t memory_clock,
+		SMU72_Discrete_MCRegisterSet *mc_reg_table_data
+		)
+{
+	const tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	uint32_t i = 0;
+
+	for (i = 0; i < data->tonga_mc_reg_table.num_entries; i++) {
+		if (memory_clock <=
+			data->tonga_mc_reg_table.mc_reg_table_entry[i].mclk_max) {
+			break;
+		}
+	}
+
+	if ((i == data->tonga_mc_reg_table.num_entries) && (i > 0))
+		--i;
+
+	tonga_convert_mc_registers(&data->tonga_mc_reg_table.mc_reg_table_entry[i],
+		mc_reg_table_data, data->tonga_mc_reg_table.last, data->tonga_mc_reg_table.validflag);
+
+	return 0;
+}
+
+int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr,
+		SMU72_Discrete_MCRegisters *mc_reg_table)
+{
+	int result = 0;
+	tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	int res;
+	uint32_t i;
+
+	for (i = 0; i < data->dpm_table.mclk_table.count; i++) {
+		res = tonga_convert_mc_reg_table_entry_to_smc(
+				hwmgr,
+				data->dpm_table.mclk_table.dpm_levels[i].value,
+				&mc_reg_table->data[i]
+				);
+
+		if (0 != res)
+			result = res;
+	}
+
+	return result;
+}
+
+int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr)
+{
+	int result;
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	memset(&data->mc_reg_table, 0x00, sizeof(SMU72_Discrete_MCRegisters));
+	result = tonga_populate_mc_reg_address(hwmgr, &(data->mc_reg_table));
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize MCRegTable for the MC register addresses!", return result;);
+
+	result = tonga_convert_mc_reg_table_to_smc(hwmgr, &data->mc_reg_table);
+	PP_ASSERT_WITH_CODE(0 == result,
+		"Failed to initialize MCRegTable for driver state!", return result;);
+
+	return tonga_copy_bytes_to_smc(hwmgr->smumgr, data->mc_reg_table_start,
+			(uint8_t *)&data->mc_reg_table, sizeof(SMU72_Discrete_MCRegisters), data->sram_end);
+}
+
+/**
+ * Programs static screed detection parameters
+ *
+ * @param   hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_program_static_screen_threshold_parameters(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	/* Set static screen threshold unit*/
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
+		CGS_IND_REG__SMC, CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT,
+		data->static_screen_threshold_unit);
+	/* Set static screen threshold*/
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
+		CGS_IND_REG__SMC, CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD,
+		data->static_screen_threshold);
+
+	return 0;
+}
+
+/**
+ * Setup display gap for glitch free memory clock switching.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_enable_display_gap(struct pp_hwmgr *hwmgr)
+{
+	uint32_t display_gap = cgs_read_ind_register(hwmgr->device,
+							CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL);
+
+	display_gap = PHM_SET_FIELD(display_gap,
+					CG_DISPLAY_GAP_CNTL, DISP_GAP, DISPLAY_GAP_IGNORE);
+
+	display_gap = PHM_SET_FIELD(display_gap,
+					CG_DISPLAY_GAP_CNTL, DISP_GAP_MCHG, DISPLAY_GAP_VBLANK);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+		ixCG_DISPLAY_GAP_CNTL, display_gap);
+
+	return 0;
+}
+
+/**
+ * Programs activity state transition voting clients
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int tonga_program_voting_clients(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
+
+	/* Clear reset for voting clients before enabling DPM */
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+		SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0);
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+		SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+		ixCG_FREQ_TRAN_VOTING_0, data->voting_rights_clients0);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+		ixCG_FREQ_TRAN_VOTING_1, data->voting_rights_clients1);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+		ixCG_FREQ_TRAN_VOTING_2, data->voting_rights_clients2);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+		ixCG_FREQ_TRAN_VOTING_3, data->voting_rights_clients3);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+		ixCG_FREQ_TRAN_VOTING_4, data->voting_rights_clients4);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+		ixCG_FREQ_TRAN_VOTING_5, data->voting_rights_clients5);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+		ixCG_FREQ_TRAN_VOTING_6, data->voting_rights_clients6);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+		ixCG_FREQ_TRAN_VOTING_7, data->voting_rights_clients7);
+
+	return 0;
+}
+
+
+int tonga_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
+{
+	int tmp_result, result = 0;
+
+	tmp_result = tonga_check_for_dpm_stopped(hwmgr);
+
+	if (cf_tonga_voltage_control(hwmgr)) {
+		tmp_result = tonga_enable_voltage_control(hwmgr);
+		PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable voltage control!", result = tmp_result);
+
+		tmp_result = tonga_construct_voltage_tables(hwmgr);
+		PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to contruct voltage tables!", result = tmp_result);
+	}
+
+	tmp_result = tonga_initialize_mc_reg_table(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to initialize MC reg table!", result = tmp_result);
+
+	tmp_result = tonga_program_static_screen_threshold_parameters(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to program static screen threshold parameters!", result = tmp_result);
+
+	tmp_result = tonga_enable_display_gap(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to enable display gap!", result = tmp_result);
+
+	tmp_result = tonga_program_voting_clients(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to program voting clients!", result = tmp_result);
+
+	tmp_result = tonga_process_firmware_header(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to process firmware header!", result = tmp_result);
+
+	tmp_result = tonga_initial_switch_from_arb_f0_to_f1(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to initialize switch from ArbF0 to F1!", result = tmp_result);
+
+	tmp_result = tonga_init_smc_table(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to initialize SMC table!", result = tmp_result);
+
+	tmp_result = tonga_init_arb_table_index(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to initialize ARB table index!", result = tmp_result);
+
+	tmp_result = tonga_populate_initial_mc_reg_table(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to populate initialize MC Reg table!", result = tmp_result);
+
+	tmp_result = tonga_notify_smc_display_change(hwmgr, false);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to notify no display!", result = tmp_result);
+
+	/* enable SCLK control */
+	tmp_result = tonga_enable_sclk_control(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to enable SCLK control!", result = tmp_result);
+
+	/* enable DPM */
+	tmp_result = tonga_start_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to start DPM!", result = tmp_result);
+
+	return result;
+}
+
+int tonga_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
+{
+	int tmp_result, result = 0;
+
+	tmp_result = tonga_check_for_dpm_running(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"SMC is still running!", return 0);
+
+	tmp_result = tonga_stop_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to stop DPM!", result = tmp_result);
+
+	tmp_result = tonga_reset_to_default(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+		"Failed to reset to default!", result = tmp_result);
+
+	return result;
+}
+
+int tonga_reset_asic_tasks(struct pp_hwmgr *hwmgr)
+{
+	int result;
+
+	result = tonga_set_boot_state(hwmgr);
+	if (0 != result)
+		printk(KERN_ERR "[ powerplay ] Failed to reset asic via set boot state! \n");
+
+	return result;
+}
+
+int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
+{
+	if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) {
+		kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
+		hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
+	}
+
+	if (NULL != hwmgr->backend) {
+		kfree(hwmgr->backend);
+		hwmgr->backend = NULL;
+	}
+
+	return 0;
+}
+
+/**
+ * Initializes the Volcanic Islands Hardware Manager
+ *
+ * @param   hwmgr the address of the powerplay hardware manager.
+ * @return   1 if success; otherwise appropriate error code.
+ */
+int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+{
+	int result = 0;
+	SMU72_Discrete_DpmTable  *table = NULL;
+	tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	phw_tonga_ulv_parm *ulv;
+
+	PP_ASSERT_WITH_CODE((NULL != hwmgr),
+		"Invalid Parameter!", return -1;);
+
+	data->dll_defaule_on = 0;
+	data->sram_end = SMC_RAM_END;
+
+	data->activity_target[0] = PPTONGA_TARGETACTIVITY_DFLT;
+	data->activity_target[1] = PPTONGA_TARGETACTIVITY_DFLT;
+	data->activity_target[2] = PPTONGA_TARGETACTIVITY_DFLT;
+	data->activity_target[3] = PPTONGA_TARGETACTIVITY_DFLT;
+	data->activity_target[4] = PPTONGA_TARGETACTIVITY_DFLT;
+	data->activity_target[5] = PPTONGA_TARGETACTIVITY_DFLT;
+	data->activity_target[6] = PPTONGA_TARGETACTIVITY_DFLT;
+	data->activity_target[7] = PPTONGA_TARGETACTIVITY_DFLT;
+
+	data->vddc_vddci_delta = VDDC_VDDCI_DELTA;
+	data->vddc_vddgfx_delta = VDDC_VDDGFX_DELTA;
+	data->mclk_activity_target = PPTONGA_MCLK_TARGETACTIVITY_DFLT;
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_DisableVoltageIsland);
+
+	data->sclk_dpm_key_disabled = 0;
+	data->mclk_dpm_key_disabled = 0;
+	data->pcie_dpm_key_disabled = 0;
+	data->pcc_monitor_enabled = 0;
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_UnTabledHardwareInterface);
+
+	data->gpio_debug = 0;
+	data->engine_clock_data = 0;
+	data->memory_clock_data = 0;
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_DynamicPatchPowerState);
+
+	/* need to set voltage control types before EVV patching*/
+	data->voltage_control = TONGA_VOLTAGE_CONTROL_NONE;
+	data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_NONE;
+	data->vdd_gfx_control = TONGA_VOLTAGE_CONTROL_NONE;
+	data->mvdd_control = TONGA_VOLTAGE_CONTROL_NONE;
+
+	if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+				VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) {
+		data->voltage_control = TONGA_VOLTAGE_CONTROL_BY_SVID2;
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ControlVDDGFX)) {
+		if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+			VOLTAGE_TYPE_VDDGFX, VOLTAGE_OBJ_SVID2)) {
+			data->vdd_gfx_control = TONGA_VOLTAGE_CONTROL_BY_SVID2;
+		}
+	}
+
+	if (TONGA_VOLTAGE_CONTROL_NONE == data->vdd_gfx_control) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ControlVDDGFX);
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_EnableMVDDControl)) {
+		if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+					VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT)) {
+			data->mvdd_control = TONGA_VOLTAGE_CONTROL_BY_GPIO;
+		}
+	}
+
+	if (TONGA_VOLTAGE_CONTROL_NONE == data->mvdd_control) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_EnableMVDDControl);
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ControlVDDCI)) {
+		if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+					VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
+			data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_BY_GPIO;
+		else if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+						VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2))
+			data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_BY_SVID2;
+	}
+
+	if (TONGA_VOLTAGE_CONTROL_NONE == data->vdd_ci_control)
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_ControlVDDCI);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_TablelessHardwareInterface);
+
+	if (pptable_info->cac_dtp_table->usClockStretchAmount != 0)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ClockStretcher);
+
+	/* Initializes DPM default values*/
+	tonga_initialize_dpm_defaults(hwmgr);
+
+	/* Get leakage voltage based on leakage ID.*/
+	PP_ASSERT_WITH_CODE((0 == tonga_get_evv_voltage(hwmgr)),
+		"Get EVV Voltage Failed.  Abort Driver loading!", return -1);
+
+	tonga_complete_dependency_tables(hwmgr);
+
+	/* Parse pptable data read from VBIOS*/
+	tonga_set_private_var_based_on_pptale(hwmgr);
+
+	/* ULV Support*/
+	ulv = &(data->ulv);
+	ulv->ulv_supported = 0;
+
+	/* Initalize Dynamic State Adjustment Rule Settings*/
+	result = tonga_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
+	if (result)
+		printk(KERN_ERR "[ powerplay ] tonga_initializa_dynamic_state_adjustment_rule_settings failed!\n");
+	data->uvd_enabled = 0;
+
+	table = &(data->smc_state_table);
+
+	/*
+	* if ucGPIO_ID=VDDC_PCC_GPIO_PINID in GPIO_LUTable,
+	* Peak Current Control feature is enabled and we should program PCC HW register
+	*/
+	if (0 == atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) {
+		uint32_t temp_reg = cgs_read_ind_register(hwmgr->device,
+										CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL);
+
+		switch (gpio_pin_assignment.uc_gpio_pin_bit_shift) {
+		case 0:
+			temp_reg = PHM_SET_FIELD(temp_reg,
+				CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x1);
+			break;
+		case 1:
+			temp_reg = PHM_SET_FIELD(temp_reg,
+				CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x2);
+			break;
+		case 2:
+			temp_reg = PHM_SET_FIELD(temp_reg,
+				CNB_PWRMGT_CNTL, GNB_SLOW, 0x1);
+			break;
+		case 3:
+			temp_reg = PHM_SET_FIELD(temp_reg,
+				CNB_PWRMGT_CNTL, FORCE_NB_PS1, 0x1);
+			break;
+		case 4:
+			temp_reg = PHM_SET_FIELD(temp_reg,
+				CNB_PWRMGT_CNTL, DPM_ENABLED, 0x1);
+			break;
+		default:
+			printk(KERN_ERR "[ powerplay ] Failed to setup PCC HW register!	\
+				Wrong GPIO assigned for VDDC_PCC_GPIO_PINID! \n");
+			break;
+		}
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCNB_PWRMGT_CNTL, temp_reg);
+	}
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_EnableSMU7ThermalManagement);
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_SMU7);
+
+	data->vddc_phase_shed_control = 0;
+
+	if (0 == result) {
+		struct cgs_system_info sys_info = {0};
+
+		data->is_tlu_enabled = 0;
+		hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
+			TONGA_MAX_HARDWARE_POWERLEVELS;
+		hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
+		hwmgr->platform_descriptor.minimumClocksReductionPercentage  = 50;
+
+		sys_info.size = sizeof(struct cgs_system_info);
+		sys_info.info_id = CGS_SYSTEM_INFO_PCIE_GEN_INFO;
+		result = cgs_query_system_info(hwmgr->device, &sys_info);
+		if (result)
+			data->pcie_gen_cap = 0x30007;
+		else
+			data->pcie_gen_cap = (uint32_t)sys_info.value;
+		if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
+			data->pcie_spc_cap = 20;
+		sys_info.size = sizeof(struct cgs_system_info);
+		sys_info.info_id = CGS_SYSTEM_INFO_PCIE_MLW;
+		result = cgs_query_system_info(hwmgr->device, &sys_info);
+		if (result)
+			data->pcie_lane_cap = 0x2f0000;
+		else
+			data->pcie_lane_cap = (uint32_t)sys_info.value;
+	} else {
+		/* Ignore return value in here, we are cleaning up a mess. */
+		tonga_hwmgr_backend_fini(hwmgr);
+	}
+
+	return result;
+}
+
+static int tonga_force_dpm_level(struct pp_hwmgr *hwmgr,
+		enum amd_dpm_forced_level level)
+{
+	int ret = 0;
+
+	switch (level) {
+	case AMD_DPM_FORCED_LEVEL_HIGH:
+		ret = tonga_force_dpm_highest(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	case AMD_DPM_FORCED_LEVEL_LOW:
+		ret = tonga_force_dpm_lowest(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	case AMD_DPM_FORCED_LEVEL_AUTO:
+		ret = tonga_unforce_dpm_levels(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	default:
+		break;
+	}
+
+	hwmgr->dpm_level = level;
+	return ret;
+}
+
+static int tonga_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+				struct pp_power_state  *prequest_ps,
+			const struct pp_power_state *pcurrent_ps)
+{
+	struct tonga_power_state *tonga_ps =
+				cast_phw_tonga_power_state(&prequest_ps->hardware);
+
+	uint32_t sclk;
+	uint32_t mclk;
+	struct PP_Clocks minimum_clocks = {0};
+	bool disable_mclk_switching;
+	bool disable_mclk_switching_for_frame_lock;
+	struct cgs_display_info info = {0};
+	const struct phm_clock_and_voltage_limits *max_limits;
+	uint32_t i;
+	tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	int32_t count;
+	int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
+
+	data->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label);
+
+	PP_ASSERT_WITH_CODE(tonga_ps->performance_level_count == 2,
+				 "VI should always have 2 performance levels",
+				 );
+
+	max_limits = (PP_PowerSource_AC == hwmgr->power_source) ?
+			&(hwmgr->dyn_state.max_clock_voltage_on_ac) :
+			&(hwmgr->dyn_state.max_clock_voltage_on_dc);
+
+	if (PP_PowerSource_DC == hwmgr->power_source) {
+		for (i = 0; i < tonga_ps->performance_level_count; i++) {
+			if (tonga_ps->performance_levels[i].memory_clock > max_limits->mclk)
+				tonga_ps->performance_levels[i].memory_clock = max_limits->mclk;
+			if (tonga_ps->performance_levels[i].engine_clock > max_limits->sclk)
+				tonga_ps->performance_levels[i].engine_clock = max_limits->sclk;
+		}
+	}
+
+	tonga_ps->vce_clocks.EVCLK = hwmgr->vce_arbiter.evclk;
+	tonga_ps->vce_clocks.ECCLK = hwmgr->vce_arbiter.ecclk;
+
+	tonga_ps->acp_clk = hwmgr->acp_arbiter.acpclk;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	/*TO DO result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/
+
+	/* TO DO GetMinClockSettings(hwmgr->pPECI, &minimum_clocks); */
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) {
+
+		max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
+		stable_pstate_sclk = (max_limits->sclk * 75) / 100;
+
+		for (count = pptable_info->vdd_dep_on_sclk->count-1; count >= 0; count--) {
+			if (stable_pstate_sclk >= pptable_info->vdd_dep_on_sclk->entries[count].clk) {
+				stable_pstate_sclk = pptable_info->vdd_dep_on_sclk->entries[count].clk;
+				break;
+			}
+		}
+
+		if (count < 0)
+			stable_pstate_sclk = pptable_info->vdd_dep_on_sclk->entries[0].clk;
+
+		stable_pstate_mclk = max_limits->mclk;
+
+		minimum_clocks.engineClock = stable_pstate_sclk;
+		minimum_clocks.memoryClock = stable_pstate_mclk;
+	}
+
+	if (minimum_clocks.engineClock < hwmgr->gfx_arbiter.sclk)
+		minimum_clocks.engineClock = hwmgr->gfx_arbiter.sclk;
+
+	if (minimum_clocks.memoryClock < hwmgr->gfx_arbiter.mclk)
+		minimum_clocks.memoryClock = hwmgr->gfx_arbiter.mclk;
+
+	tonga_ps->sclk_threshold = hwmgr->gfx_arbiter.sclk_threshold;
+
+	if (0 != hwmgr->gfx_arbiter.sclk_over_drive) {
+		PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.sclk_over_drive <= hwmgr->platform_descriptor.overdriveLimit.engineClock),
+					"Overdrive sclk exceeds limit",
+					hwmgr->gfx_arbiter.sclk_over_drive = hwmgr->platform_descriptor.overdriveLimit.engineClock);
+
+		if (hwmgr->gfx_arbiter.sclk_over_drive >= hwmgr->gfx_arbiter.sclk)
+			tonga_ps->performance_levels[1].engine_clock = hwmgr->gfx_arbiter.sclk_over_drive;
+	}
+
+	if (0 != hwmgr->gfx_arbiter.mclk_over_drive) {
+		PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.mclk_over_drive <= hwmgr->platform_descriptor.overdriveLimit.memoryClock),
+			"Overdrive mclk exceeds limit",
+			hwmgr->gfx_arbiter.mclk_over_drive = hwmgr->platform_descriptor.overdriveLimit.memoryClock);
+
+		if (hwmgr->gfx_arbiter.mclk_over_drive >= hwmgr->gfx_arbiter.mclk)
+			tonga_ps->performance_levels[1].memory_clock = hwmgr->gfx_arbiter.mclk_over_drive;
+	}
+
+	disable_mclk_switching_for_frame_lock = phm_cap_enabled(
+				    hwmgr->platform_descriptor.platformCaps,
+				    PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
+
+	disable_mclk_switching = (1 < info.display_count) ||
+				    disable_mclk_switching_for_frame_lock;
+
+	sclk  = tonga_ps->performance_levels[0].engine_clock;
+	mclk  = tonga_ps->performance_levels[0].memory_clock;
+
+	if (disable_mclk_switching)
+		mclk  = tonga_ps->performance_levels[tonga_ps->performance_level_count - 1].memory_clock;
+
+	if (sclk < minimum_clocks.engineClock)
+		sclk = (minimum_clocks.engineClock > max_limits->sclk) ? max_limits->sclk : minimum_clocks.engineClock;
+
+	if (mclk < minimum_clocks.memoryClock)
+		mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? max_limits->mclk : minimum_clocks.memoryClock;
+
+	tonga_ps->performance_levels[0].engine_clock = sclk;
+	tonga_ps->performance_levels[0].memory_clock = mclk;
+
+	tonga_ps->performance_levels[1].engine_clock =
+		(tonga_ps->performance_levels[1].engine_clock >= tonga_ps->performance_levels[0].engine_clock) ?
+			      tonga_ps->performance_levels[1].engine_clock :
+			      tonga_ps->performance_levels[0].engine_clock;
+
+	if (disable_mclk_switching) {
+		if (mclk < tonga_ps->performance_levels[1].memory_clock)
+			mclk = tonga_ps->performance_levels[1].memory_clock;
+
+		tonga_ps->performance_levels[0].memory_clock = mclk;
+		tonga_ps->performance_levels[1].memory_clock = mclk;
+	} else {
+		if (tonga_ps->performance_levels[1].memory_clock < tonga_ps->performance_levels[0].memory_clock)
+			tonga_ps->performance_levels[1].memory_clock = tonga_ps->performance_levels[0].memory_clock;
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) {
+		for (i=0; i < tonga_ps->performance_level_count; i++) {
+			tonga_ps->performance_levels[i].engine_clock = stable_pstate_sclk;
+			tonga_ps->performance_levels[i].memory_clock = stable_pstate_mclk;
+			tonga_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max;
+			tonga_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max;
+		}
+	}
+
+	return 0;
+}
+
+int tonga_get_power_state_size(struct pp_hwmgr *hwmgr)
+{
+	return sizeof(struct tonga_power_state);
+}
+
+static int tonga_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
+{
+	struct pp_power_state  *ps;
+	struct tonga_power_state  *tonga_ps;
+
+	if (hwmgr == NULL)
+		return -EINVAL;
+
+	ps = hwmgr->request_ps;
+
+	if (ps == NULL)
+		return -EINVAL;
+
+	tonga_ps = cast_phw_tonga_power_state(&ps->hardware);
+
+	if (low)
+		return tonga_ps->performance_levels[0].memory_clock;
+	else
+		return tonga_ps->performance_levels[tonga_ps->performance_level_count-1].memory_clock;
+}
+
+static int tonga_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
+{
+	struct pp_power_state  *ps;
+	struct tonga_power_state  *tonga_ps;
+
+	if (hwmgr == NULL)
+		return -EINVAL;
+
+	ps = hwmgr->request_ps;
+
+	if (ps == NULL)
+		return -EINVAL;
+
+	tonga_ps = cast_phw_tonga_power_state(&ps->hardware);
+
+	if (low)
+		return tonga_ps->performance_levels[0].engine_clock;
+	else
+		return tonga_ps->performance_levels[tonga_ps->performance_level_count-1].engine_clock;
+}
+
+static uint16_t tonga_get_current_pcie_speed(
+						   struct pp_hwmgr *hwmgr)
+{
+	uint32_t speed_cntl = 0;
+
+	speed_cntl = cgs_read_ind_register(hwmgr->device,
+						   CGS_IND_REG__PCIE,
+						   ixPCIE_LC_SPEED_CNTL);
+	return((uint16_t)PHM_GET_FIELD(speed_cntl,
+			PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE));
+}
+
+static int tonga_get_current_pcie_lane_number(
+						   struct pp_hwmgr *hwmgr)
+{
+	uint32_t link_width;
+
+	link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device,
+							CGS_IND_REG__PCIE,
+						  PCIE_LC_LINK_WIDTH_CNTL,
+							LC_LINK_WIDTH_RD);
+
+	PP_ASSERT_WITH_CODE((7 >= link_width),
+			"Invalid PCIe lane width!", return 0);
+
+	return decode_pcie_lane_width(link_width);
+}
+
+static int tonga_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
+					struct pp_hw_power_state *hw_ps)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	struct tonga_power_state *ps = (struct tonga_power_state *)hw_ps;
+	ATOM_FIRMWARE_INFO_V2_2 *fw_info;
+	uint16_t size;
+	uint8_t frev, crev;
+	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+
+	/* First retrieve the Boot clocks and VDDC from the firmware info table.
+	 * We assume here that fw_info is unchanged if this call fails.
+	 */
+	fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)cgs_atom_get_data_table(
+			hwmgr->device, index,
+			&size, &frev, &crev);
+	if (!fw_info)
+		/* During a test, there is no firmware info table. */
+		return 0;
+
+	/* Patch the state. */
+	data->vbios_boot_state.sclk_bootup_value  = le32_to_cpu(fw_info->ulDefaultEngineClock);
+	data->vbios_boot_state.mclk_bootup_value  = le32_to_cpu(fw_info->ulDefaultMemoryClock);
+	data->vbios_boot_state.mvdd_bootup_value  = le16_to_cpu(fw_info->usBootUpMVDDCVoltage);
+	data->vbios_boot_state.vddc_bootup_value  = le16_to_cpu(fw_info->usBootUpVDDCVoltage);
+	data->vbios_boot_state.vddci_bootup_value = le16_to_cpu(fw_info->usBootUpVDDCIVoltage);
+	data->vbios_boot_state.pcie_gen_bootup_value = tonga_get_current_pcie_speed(hwmgr);
+	data->vbios_boot_state.pcie_lane_bootup_value =
+			(uint16_t)tonga_get_current_pcie_lane_number(hwmgr);
+
+	/* set boot power state */
+	ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value;
+	ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value;
+	ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value;
+	ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value;
+
+	return 0;
+}
+
+static int tonga_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
+		void *state, struct pp_power_state *power_state,
+		void *pp_table, uint32_t classification_flag)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	struct tonga_power_state  *tonga_ps =
+			(struct tonga_power_state *)(&(power_state->hardware));
+
+	struct tonga_performance_level *performance_level;
+
+	ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state;
+
+	ATOM_Tonga_POWERPLAYTABLE *powerplay_table =
+			(ATOM_Tonga_POWERPLAYTABLE *)pp_table;
+
+	ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table =
+			(ATOM_Tonga_SCLK_Dependency_Table *)
+			(((unsigned long)powerplay_table) +
+			le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
+
+	ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
+			(ATOM_Tonga_MCLK_Dependency_Table *)
+			(((unsigned long)powerplay_table) +
+			le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
+
+	/* The following fields are not initialized here: id orderedList allStatesList */
+	power_state->classification.ui_label =
+			(le16_to_cpu(state_entry->usClassification) &
+			ATOM_PPLIB_CLASSIFICATION_UI_MASK) >>
+			ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
+	power_state->classification.flags = classification_flag;
+	/* NOTE: There is a classification2 flag in BIOS that is not being used right now */
+
+	power_state->classification.temporary_state = false;
+	power_state->classification.to_be_deleted = false;
+
+	power_state->validation.disallowOnDC =
+			(0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & ATOM_Tonga_DISALLOW_ON_DC));
+
+	power_state->pcie.lanes = 0;
+
+	power_state->display.disableFrameModulation = false;
+	power_state->display.limitRefreshrate = false;
+	power_state->display.enableVariBright =
+			(0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & ATOM_Tonga_ENABLE_VARIBRIGHT));
+
+	power_state->validation.supportedPowerLevels = 0;
+	power_state->uvd_clocks.VCLK = 0;
+	power_state->uvd_clocks.DCLK = 0;
+	power_state->temperatures.min = 0;
+	power_state->temperatures.max = 0;
+
+	performance_level = &(tonga_ps->performance_levels
+			[tonga_ps->performance_level_count++]);
+
+	PP_ASSERT_WITH_CODE(
+			(tonga_ps->performance_level_count < SMU72_MAX_LEVELS_GRAPHICS),
+			"Performance levels exceeds SMC limit!",
+			return -1);
+
+	PP_ASSERT_WITH_CODE(
+			(tonga_ps->performance_level_count <=
+					hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),
+			"Performance levels exceeds Driver limit!",
+			return -1);
+
+	/* Performance levels are arranged from low to high. */
+	performance_level->memory_clock =
+				le32_to_cpu(mclk_dep_table->entries[state_entry->ucMemoryClockIndexLow].ulMclk);
+
+	performance_level->engine_clock =
+				le32_to_cpu(sclk_dep_table->entries[state_entry->ucEngineClockIndexLow].ulSclk);
+
+	performance_level->pcie_gen = get_pcie_gen_support(
+							data->pcie_gen_cap,
+					     state_entry->ucPCIEGenLow);
+
+	performance_level->pcie_lane = get_pcie_lane_support(
+						    data->pcie_lane_cap,
+					   state_entry->ucPCIELaneHigh);
+
+	performance_level =
+			&(tonga_ps->performance_levels[tonga_ps->performance_level_count++]);
+
+	performance_level->memory_clock =
+				le32_to_cpu(mclk_dep_table->entries[state_entry->ucMemoryClockIndexHigh].ulMclk);
+
+	performance_level->engine_clock =
+				le32_to_cpu(sclk_dep_table->entries[state_entry->ucEngineClockIndexHigh].ulSclk);
+
+	performance_level->pcie_gen = get_pcie_gen_support(
+							data->pcie_gen_cap,
+					    state_entry->ucPCIEGenHigh);
+
+	performance_level->pcie_lane = get_pcie_lane_support(
+						    data->pcie_lane_cap,
+					   state_entry->ucPCIELaneHigh);
+
+	return 0;
+}
+
+static int tonga_get_pp_table_entry(struct pp_hwmgr *hwmgr,
+		    unsigned long entry_index, struct pp_power_state *ps)
+{
+	int result;
+	struct tonga_power_state *tonga_ps;
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
+					   table_info->vdd_dep_on_mclk;
+
+	ps->hardware.magic = PhwTonga_Magic;
+
+	tonga_ps = cast_phw_tonga_power_state(&(ps->hardware));
+
+	result = tonga_get_powerplay_table_entry(hwmgr, entry_index, ps,
+			tonga_get_pp_table_entry_callback_func);
+
+	/* This is the earliest time we have all the dependency table and the VBIOS boot state
+	 * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state
+	 * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state
+	 */
+	if (dep_mclk_table != NULL && dep_mclk_table->count == 1) {
+		if (dep_mclk_table->entries[0].clk !=
+				data->vbios_boot_state.mclk_bootup_value)
+			printk(KERN_ERR "Single MCLK entry VDDCI/MCLK dependency table "
+					"does not match VBIOS boot MCLK level");
+		if (dep_mclk_table->entries[0].vddci !=
+				data->vbios_boot_state.vddci_bootup_value)
+			printk(KERN_ERR "Single VDDCI entry VDDCI/MCLK dependency table "
+					"does not match VBIOS boot VDDCI level");
+	}
+
+	/* set DC compatible flag if this state supports DC */
+	if (!ps->validation.disallowOnDC)
+		tonga_ps->dc_compatible = true;
+
+	if (ps->classification.flags & PP_StateClassificationFlag_ACPI)
+		data->acpi_pcie_gen = tonga_ps->performance_levels[0].pcie_gen;
+	else if (ps->classification.flags & PP_StateClassificationFlag_Boot) {
+		if (data->bacos.best_match == 0xffff) {
+			/* For V.I. use boot state as base BACO state */
+			data->bacos.best_match = PP_StateClassificationFlag_Boot;
+			data->bacos.performance_level = tonga_ps->performance_levels[0];
+		}
+	}
+
+	tonga_ps->uvd_clocks.VCLK = ps->uvd_clocks.VCLK;
+	tonga_ps->uvd_clocks.DCLK = ps->uvd_clocks.DCLK;
+
+	if (!result) {
+		uint32_t i;
+
+		switch (ps->classification.ui_label) {
+		case PP_StateUILabel_Performance:
+			data->use_pcie_performance_levels = true;
+
+			for (i = 0; i < tonga_ps->performance_level_count; i++) {
+				if (data->pcie_gen_performance.max <
+						tonga_ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_performance.max =
+							tonga_ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_gen_performance.min >
+						tonga_ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_performance.min =
+							tonga_ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_lane_performance.max <
+						tonga_ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_performance.max =
+							tonga_ps->performance_levels[i].pcie_lane;
+
+				if (data->pcie_lane_performance.min >
+						tonga_ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_performance.min =
+							tonga_ps->performance_levels[i].pcie_lane;
+			}
+			break;
+		case PP_StateUILabel_Battery:
+			data->use_pcie_power_saving_levels = true;
+
+			for (i = 0; i < tonga_ps->performance_level_count; i++) {
+				if (data->pcie_gen_power_saving.max <
+						tonga_ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_power_saving.max =
+							tonga_ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_gen_power_saving.min >
+						tonga_ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_power_saving.min =
+							tonga_ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_lane_power_saving.max <
+						tonga_ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_power_saving.max =
+							tonga_ps->performance_levels[i].pcie_lane;
+
+				if (data->pcie_lane_power_saving.min >
+						tonga_ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_power_saving.min =
+							tonga_ps->performance_levels[i].pcie_lane;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	return 0;
+}
+
+static void
+tonga_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m)
+{
+	uint32_t sclk, mclk, activity_percent;
+	uint32_t offset;
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetSclkFrequency));
+
+	sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
+
+	smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetMclkFrequency));
+
+	mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
+	seq_printf(m, "\n [  mclk  ]: %u MHz\n\n [  sclk  ]: %u MHz\n", mclk/100, sclk/100);
+
+
+	offset = data->soft_regs_start + offsetof(SMU72_SoftRegisters, AverageGraphicsActivity);
+	activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset);
+	activity_percent += 0x80;
+	activity_percent >>= 8;
+
+	seq_printf(m, "\n [GPU load]: %u%%\n\n", activity_percent > 100 ? 100 : activity_percent);
+
+}
+
+static int tonga_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
+	const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state);
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	struct tonga_single_dpm_table *psclk_table = &(data->dpm_table.sclk_table);
+	uint32_t sclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].engine_clock;
+	struct tonga_single_dpm_table *pmclk_table = &(data->dpm_table.mclk_table);
+	uint32_t mclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].memory_clock;
+	struct PP_Clocks min_clocks = {0};
+	uint32_t i;
+	struct cgs_display_info info = {0};
+
+	data->need_update_smu7_dpm_table = 0;
+
+	for (i = 0; i < psclk_table->count; i++) {
+		if (sclk == psclk_table->dpm_levels[i].value)
+			break;
+	}
+
+	if (i >= psclk_table->count)
+		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
+	else {
+	/* TODO: Check SCLK in DAL's minimum clocks in case DeepSleep divider update is required.*/
+		if(data->display_timing.min_clock_insr != min_clocks.engineClockInSR)
+			data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK;
+	}
+
+	for (i=0; i < pmclk_table->count; i++) {
+		if (mclk == pmclk_table->dpm_levels[i].value)
+			break;
+	}
+
+	if (i >= pmclk_table->count)
+		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	if (data->display_timing.num_existing_displays != info.display_count)
+		data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK;
+
+	return 0;
+}
+
+static uint16_t tonga_get_maximum_link_speed(struct pp_hwmgr *hwmgr, const struct tonga_power_state *hw_ps)
+{
+	uint32_t i;
+	uint32_t sclk, max_sclk = 0;
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	struct tonga_dpm_table *pdpm_table = &data->dpm_table;
+
+	for (i = 0; i < hw_ps->performance_level_count; i++) {
+		sclk = hw_ps->performance_levels[i].engine_clock;
+		if (max_sclk < sclk)
+			max_sclk = sclk;
+	}
+
+	for (i = 0; i < pdpm_table->sclk_table.count; i++) {
+		if (pdpm_table->sclk_table.dpm_levels[i].value == max_sclk)
+			return (uint16_t) ((i >= pdpm_table->pcie_speed_table.count) ?
+					pdpm_table->pcie_speed_table.dpm_levels[pdpm_table->pcie_speed_table.count-1].value :
+					pdpm_table->pcie_speed_table.dpm_levels[i].value);
+	}
+
+	return 0;
+}
+
+static int tonga_request_link_speed_change_before_state_change(struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	const struct tonga_power_state *tonga_nps = cast_const_phw_tonga_power_state(states->pnew_state);
+	const struct tonga_power_state *tonga_cps = cast_const_phw_tonga_power_state(states->pcurrent_state);
+
+	uint16_t target_link_speed = tonga_get_maximum_link_speed(hwmgr, tonga_nps);
+	uint16_t current_link_speed;
+
+	if (data->force_pcie_gen == PP_PCIEGenInvalid)
+		current_link_speed = tonga_get_maximum_link_speed(hwmgr, tonga_cps);
+	else
+		current_link_speed = data->force_pcie_gen;
+
+	data->force_pcie_gen = PP_PCIEGenInvalid;
+	data->pspp_notify_required = false;
+	if (target_link_speed > current_link_speed) {
+		switch(target_link_speed) {
+		case PP_PCIEGen3:
+			if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN3, false))
+				break;
+			data->force_pcie_gen = PP_PCIEGen2;
+			if (current_link_speed == PP_PCIEGen2)
+				break;
+		case PP_PCIEGen2:
+			if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN2, false))
+				break;
+		default:
+			data->force_pcie_gen = tonga_get_current_pcie_speed(hwmgr);
+			break;
+		}
+	} else {
+		if (target_link_speed < current_link_speed)
+			data->pspp_notify_required = true;
+	}
+
+	return 0;
+}
+
+static int tonga_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	if (0 == data->need_update_smu7_dpm_table)
+		return 0;
+
+	if ((0 == data->sclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table &
+		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
+		PP_ASSERT_WITH_CODE(
+			true == tonga_is_dpm_running(hwmgr),
+			"Trying to freeze SCLK DPM when DPM is disabled",
+			);
+		PP_ASSERT_WITH_CODE(
+			0 == smum_send_msg_to_smc(hwmgr->smumgr,
+					  PPSMC_MSG_SCLKDPM_FreezeLevel),
+			"Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!",
+			return -1);
+	}
+
+	if ((0 == data->mclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table &
+		 DPMTABLE_OD_UPDATE_MCLK)) {
+		PP_ASSERT_WITH_CODE(true == tonga_is_dpm_running(hwmgr),
+			"Trying to freeze MCLK DPM when DPM is disabled",
+			);
+		PP_ASSERT_WITH_CODE(
+			0 == smum_send_msg_to_smc(hwmgr->smumgr,
+							PPSMC_MSG_MCLKDPM_FreezeLevel),
+			"Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!",
+			return -1);
+	}
+
+	return 0;
+}
+
+static int tonga_populate_and_upload_sclk_mclk_dpm_levels(struct pp_hwmgr *hwmgr, const void *input)
+{
+	int result = 0;
+
+	const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
+	const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state);
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	uint32_t sclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].engine_clock;
+	uint32_t mclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].memory_clock;
+	struct tonga_dpm_table *pdpm_table = &data->dpm_table;
+
+	struct tonga_dpm_table *pgolden_dpm_table = &data->golden_dpm_table;
+	uint32_t dpm_count, clock_percent;
+	uint32_t i;
+
+	if (0 == data->need_update_smu7_dpm_table)
+		return 0;
+
+	if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) {
+		pdpm_table->sclk_table.dpm_levels[pdpm_table->sclk_table.count-1].value = sclk;
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinACSupport) ||
+		    phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinDCSupport)) {
+		/* Need to do calculation based on the golden DPM table
+		 * as the Heatmap GPU Clock axis is also based on the default values
+		 */
+			PP_ASSERT_WITH_CODE(
+				(pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value != 0),
+				"Divide by 0!",
+				return -1);
+			dpm_count = pdpm_table->sclk_table.count < 2 ? 0 : pdpm_table->sclk_table.count-2;
+			for (i = dpm_count; i > 1; i--) {
+				if (sclk > pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value) {
+					clock_percent = ((sclk - pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value)*100) /
+							pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value;
+
+					pdpm_table->sclk_table.dpm_levels[i].value =
+							pgolden_dpm_table->sclk_table.dpm_levels[i].value +
+							(pgolden_dpm_table->sclk_table.dpm_levels[i].value * clock_percent)/100;
+
+				} else if (pgolden_dpm_table->sclk_table.dpm_levels[pdpm_table->sclk_table.count-1].value > sclk) {
+					clock_percent = ((pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value - sclk)*100) /
+								pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value;
+
+					pdpm_table->sclk_table.dpm_levels[i].value =
+							pgolden_dpm_table->sclk_table.dpm_levels[i].value -
+							(pgolden_dpm_table->sclk_table.dpm_levels[i].value * clock_percent)/100;
+				} else
+					pdpm_table->sclk_table.dpm_levels[i].value =
+							pgolden_dpm_table->sclk_table.dpm_levels[i].value;
+			}
+		}
+	}
+
+	if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
+		pdpm_table->mclk_table.dpm_levels[pdpm_table->mclk_table.count-1].value = mclk;
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinACSupport) ||
+			phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinDCSupport)) {
+
+			PP_ASSERT_WITH_CODE(
+					(pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value != 0),
+					"Divide by 0!",
+					return -1);
+			dpm_count = pdpm_table->mclk_table.count < 2? 0 : pdpm_table->mclk_table.count-2;
+			for (i = dpm_count; i > 1; i--) {
+				if (mclk > pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value) {
+						clock_percent = ((mclk - pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value)*100) /
+								    pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value;
+
+						pdpm_table->mclk_table.dpm_levels[i].value =
+										pgolden_dpm_table->mclk_table.dpm_levels[i].value +
+										(pgolden_dpm_table->mclk_table.dpm_levels[i].value * clock_percent)/100;
+
+				} else if (pgolden_dpm_table->mclk_table.dpm_levels[pdpm_table->mclk_table.count-1].value > mclk) {
+						clock_percent = ((pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value - mclk)*100) /
+								    pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value;
+
+						pdpm_table->mclk_table.dpm_levels[i].value =
+									pgolden_dpm_table->mclk_table.dpm_levels[i].value -
+									(pgolden_dpm_table->mclk_table.dpm_levels[i].value * clock_percent)/100;
+				} else
+					pdpm_table->mclk_table.dpm_levels[i].value = pgolden_dpm_table->mclk_table.dpm_levels[i].value;
+			}
+		}
+	}
+
+	if (data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) {
+		result = tonga_populate_all_memory_levels(hwmgr);
+		PP_ASSERT_WITH_CODE((0 == result),
+			"Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
+			return result);
+	}
+
+	if (data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) {
+		/*populate MCLK dpm table to SMU7 */
+		result = tonga_populate_all_memory_levels(hwmgr);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
+				return result);
+	}
+
+	return result;
+}
+
+static	int tonga_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
+			  struct tonga_single_dpm_table * pdpm_table,
+			     uint32_t low_limit, uint32_t high_limit)
+{
+	uint32_t i;
+
+	for (i = 0; i < pdpm_table->count; i++) {
+		if ((pdpm_table->dpm_levels[i].value < low_limit) ||
+		    (pdpm_table->dpm_levels[i].value > high_limit))
+			pdpm_table->dpm_levels[i].enabled = false;
+		else
+			pdpm_table->dpm_levels[i].enabled = true;
+	}
+	return 0;
+}
+
+static int tonga_trim_dpm_states(struct pp_hwmgr *hwmgr, const struct tonga_power_state *hw_state)
+{
+	int result = 0;
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	uint32_t high_limit_count;
+
+	PP_ASSERT_WITH_CODE((hw_state->performance_level_count >= 1),
+				"power state did not have any performance level",
+				 return -1);
+
+	high_limit_count = (1 == hw_state->performance_level_count) ? 0: 1;
+
+	tonga_trim_single_dpm_states(hwmgr,
+					&(data->dpm_table.sclk_table),
+					hw_state->performance_levels[0].engine_clock,
+					hw_state->performance_levels[high_limit_count].engine_clock);
+
+	tonga_trim_single_dpm_states(hwmgr,
+						&(data->dpm_table.mclk_table),
+						hw_state->performance_levels[0].memory_clock,
+						hw_state->performance_levels[high_limit_count].memory_clock);
+
+	return result;
+}
+
+static int tonga_generate_dpm_level_enable_mask(struct pp_hwmgr *hwmgr, const void *input)
+{
+	int result;
+	const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state);
+
+	result = tonga_trim_dpm_states(hwmgr, tonga_ps);
+	if (0 != result)
+		return result;
+
+	data->dpm_level_enable_mask.sclk_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table);
+	data->dpm_level_enable_mask.mclk_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table);
+	data->last_mclk_dpm_enable_mask = data->dpm_level_enable_mask.mclk_dpm_enable_mask;
+	if (data->uvd_enabled)
+		data->dpm_level_enable_mask.mclk_dpm_enable_mask &= 0xFFFFFFFE;
+
+	data->dpm_level_enable_mask.pcie_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table);
+
+	return 0;
+}
+
+int tonga_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
+				  (PPSMC_Msg)PPSMC_MSG_VCEDPM_Enable :
+				  (PPSMC_Msg)PPSMC_MSG_VCEDPM_Disable);
+}
+
+int tonga_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
+				  (PPSMC_Msg)PPSMC_MSG_UVDDPM_Enable :
+				  (PPSMC_Msg)PPSMC_MSG_UVDDPM_Disable);
+}
+
+int tonga_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	uint32_t mm_boot_level_offset, mm_boot_level_value;
+	struct phm_ppt_v1_information *ptable_information = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (!bgate) {
+		data->smc_state_table.UvdBootLevel = (uint8_t) (ptable_information->mm_dep_table->count - 1);
+		mm_boot_level_offset = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, UvdBootLevel);
+		mm_boot_level_offset /= 4;
+		mm_boot_level_offset *= 4;
+		mm_boot_level_value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset);
+		mm_boot_level_value &= 0x00FFFFFF;
+		mm_boot_level_value |= data->smc_state_table.UvdBootLevel << 24;
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
+
+		if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM) ||
+		    phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_UVDDPM_SetEnabledMask,
+						(uint32_t)(1 << data->smc_state_table.UvdBootLevel));
+	}
+
+	return tonga_enable_disable_uvd_dpm(hwmgr, !bgate);
+}
+
+int tonga_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	const struct tonga_power_state *tonga_nps = cast_const_phw_tonga_power_state(states->pnew_state);
+	const struct tonga_power_state *tonga_cps = cast_const_phw_tonga_power_state(states->pcurrent_state);
+
+	uint32_t mm_boot_level_offset, mm_boot_level_value;
+	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (tonga_nps->vce_clocks.EVCLK > 0 && (tonga_cps == NULL || tonga_cps->vce_clocks.EVCLK == 0)) {
+		data->smc_state_table.VceBootLevel = (uint8_t) (pptable_info->mm_dep_table->count - 1);
+
+		mm_boot_level_offset = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, VceBootLevel);
+		mm_boot_level_offset /= 4;
+		mm_boot_level_offset *= 4;
+		mm_boot_level_value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset);
+		mm_boot_level_value &= 0xFF00FFFF;
+		mm_boot_level_value |= data->smc_state_table.VceBootLevel << 16;
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_VCEDPM_SetEnabledMask,
+				(uint32_t)(1 << data->smc_state_table.VceBootLevel));
+
+		tonga_enable_disable_vce_dpm(hwmgr, true);
+	} else if (tonga_nps->vce_clocks.EVCLK == 0 && tonga_cps != NULL && tonga_cps->vce_clocks.EVCLK > 0)
+		tonga_enable_disable_vce_dpm(hwmgr, false);
+
+	return 0;
+}
+
+static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	uint32_t address;
+	int32_t result;
+
+	if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK))
+		return 0;
+
+
+	memset(&data->mc_reg_table, 0, sizeof(SMU72_Discrete_MCRegisters));
+
+	result = tonga_convert_mc_reg_table_to_smc(hwmgr, &(data->mc_reg_table));
+
+	if(result != 0)
+		return result;
+
+
+	address = data->mc_reg_table_start + (uint32_t)offsetof(SMU72_Discrete_MCRegisters, data[0]);
+
+	return  tonga_copy_bytes_to_smc(hwmgr->smumgr, address,
+				 (uint8_t *)&data->mc_reg_table.data[0],
+				sizeof(SMU72_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count,
+				data->sram_end);
+}
+
+static int tonga_program_memory_timing_parameters_conditionally(struct pp_hwmgr *hwmgr)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	if (data->need_update_smu7_dpm_table &
+		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
+		return tonga_program_memory_timing_parameters(hwmgr);
+
+	return 0;
+}
+
+static int tonga_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+	if (0 == data->need_update_smu7_dpm_table)
+		return 0;
+
+	if ((0 == data->sclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table &
+		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
+
+		PP_ASSERT_WITH_CODE(true == tonga_is_dpm_running(hwmgr),
+			"Trying to Unfreeze SCLK DPM when DPM is disabled",
+			);
+		PP_ASSERT_WITH_CODE(
+			 0 == smum_send_msg_to_smc(hwmgr->smumgr,
+					 PPSMC_MSG_SCLKDPM_UnfreezeLevel),
+			"Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!",
+			return -1);
+	}
+
+	if ((0 == data->mclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) {
+
+		PP_ASSERT_WITH_CODE(
+				true == tonga_is_dpm_running(hwmgr),
+				"Trying to Unfreeze MCLK DPM when DPM is disabled",
+				);
+		PP_ASSERT_WITH_CODE(
+			 0 == smum_send_msg_to_smc(hwmgr->smumgr,
+					 PPSMC_MSG_SCLKDPM_UnfreezeLevel),
+		    "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!",
+		    return -1);
+	}
+
+	data->need_update_smu7_dpm_table = 0;
+
+	return 0;
+}
+
+static int tonga_notify_link_speed_change_after_state_change(struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state);
+	uint16_t target_link_speed = tonga_get_maximum_link_speed(hwmgr, tonga_ps);
+	uint8_t  request;
+
+	if (data->pspp_notify_required  ||
+	    data->pcie_performance_request) {
+		if (target_link_speed == PP_PCIEGen3)
+			request = PCIE_PERF_REQ_GEN3;
+		else if (target_link_speed == PP_PCIEGen2)
+			request = PCIE_PERF_REQ_GEN2;
+		else
+			request = PCIE_PERF_REQ_GEN1;
+
+		if(request == PCIE_PERF_REQ_GEN1 && tonga_get_current_pcie_speed(hwmgr) > 0) {
+			data->pcie_performance_request = false;
+			return 0;
+		}
+
+		if (0 != acpi_pcie_perf_request(hwmgr->device, request, false)) {
+			if (PP_PCIEGen2 == target_link_speed)
+				printk("PSPP request to switch to Gen2 from Gen3 Failed!");
+			else
+				printk("PSPP request to switch to Gen1 from Gen2 Failed!");
+		}
+	}
+
+	data->pcie_performance_request = false;
+	return 0;
+}
+
+static int tonga_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
+{
+	int tmp_result, result = 0;
+
+	tmp_result = tonga_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to find DPM states clocks in DPM table!", result = tmp_result);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest)) {
+		tmp_result = tonga_request_link_speed_change_before_state_change(hwmgr, input);
+		PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to request link speed change before state change!", result = tmp_result);
+	}
+
+	tmp_result = tonga_freeze_sclk_mclk_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to freeze SCLK MCLK DPM!", result = tmp_result);
+
+	tmp_result = tonga_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to populate and upload SCLK MCLK DPM levels!", result = tmp_result);
+
+	tmp_result = tonga_generate_dpm_level_enable_mask(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to generate DPM level enabled mask!", result = tmp_result);
+
+	tmp_result = tonga_update_vce_dpm(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to update VCE DPM!", result = tmp_result);
+
+	tmp_result = tonga_update_sclk_threshold(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to update SCLK threshold!", result = tmp_result);
+
+	tmp_result = tonga_update_and_upload_mc_reg_table(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to upload MC reg table!", result = tmp_result);
+
+	tmp_result = tonga_program_memory_timing_parameters_conditionally(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to program memory timing parameters!", result = tmp_result);
+
+	tmp_result = tonga_unfreeze_sclk_mclk_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to unfreeze SCLK MCLK DPM!", result = tmp_result);
+
+	tmp_result = tonga_upload_dpm_level_enable_mask(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to upload DPM level enabled mask!", result = tmp_result);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest)) {
+		tmp_result = tonga_notify_link_speed_change_after_state_change(hwmgr, input);
+		PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to notify link speed change after state change!", result = tmp_result);
+	}
+
+	return result;
+}
+
+/**
+*  Set maximum target operating fan output PWM
+*
+* @param    pHwMgr:  the address of the powerplay hardware manager.
+* @param    usMaxFanPwm:  max operating fan PWM in percents
+* @return   The response that came from the SMC.
+*/
+static int tonga_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm)
+{
+	hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm;
+
+	if (phm_is_hw_access_blocked(hwmgr))
+		return 0;
+
+	return (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm) ? 0 : -1);
+}
+
+int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
+{
+	uint32_t num_active_displays = 0;
+	struct cgs_display_info info = {0};
+	info.mode_info = NULL;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	num_active_displays = info.display_count;
+
+	if (num_active_displays > 1)  /* to do && (pHwMgr->pPECI->displayConfiguration.bMultiMonitorInSync != TRUE)) */
+		tonga_notify_smc_display_change(hwmgr, false);
+	else
+		tonga_notify_smc_display_change(hwmgr, true);
+
+	return 0;
+}
+
+/**
+* Programs the display gap
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always OK
+*/
+int tonga_program_display_gap(struct pp_hwmgr *hwmgr)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	uint32_t num_active_displays = 0;
+	uint32_t display_gap = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL);
+	uint32_t display_gap2;
+	uint32_t pre_vbi_time_in_us;
+	uint32_t frame_time_in_us;
+	uint32_t ref_clock;
+	uint32_t refresh_rate = 0;
+	struct cgs_display_info info = {0};
+	struct cgs_mode_info mode_info;
+
+	info.mode_info = &mode_info;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+	num_active_displays = info.display_count;
+
+	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, DISP_GAP, (num_active_displays > 0)? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL, display_gap);
+
+	ref_clock = mode_info.ref_clock;
+	refresh_rate = mode_info.refresh_rate;
+
+	if(0 == refresh_rate)
+		refresh_rate = 60;
+
+	frame_time_in_us = 1000000 / refresh_rate;
+
+	pre_vbi_time_in_us = frame_time_in_us - 200 - mode_info.vblank_time_us;
+	display_gap2 = pre_vbi_time_in_us * (ref_clock / 100);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + offsetof(SMU72_SoftRegisters, PreVBlankGap), 0x64);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + offsetof(SMU72_SoftRegisters, VBlankTimeout), (frame_time_in_us - pre_vbi_time_in_us));
+
+	if (num_active_displays == 1)
+		tonga_notify_smc_display_change(hwmgr, true);
+
+	return 0;
+}
+
+int tonga_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
+{
+
+	tonga_program_display_gap(hwmgr);
+
+	/* to do PhwTonga_CacUpdateDisplayConfiguration(pHwMgr); */
+	return 0;
+}
+
+/**
+*  Set maximum target operating fan output RPM
+*
+* @param    pHwMgr:  the address of the powerplay hardware manager.
+* @param    usMaxFanRpm:  max operating fan RPM value.
+* @return   The response that came from the SMC.
+*/
+static int tonga_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm)
+{
+	hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = us_max_fan_pwm;
+
+	if (phm_is_hw_access_blocked(hwmgr))
+		return 0;
+
+	return (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanRpmMax, us_max_fan_pwm) ? 0 : -1);
+}
+
+uint32_t tonga_get_xclk(struct pp_hwmgr *hwmgr)
+{
+	uint32_t reference_clock;
+	uint32_t tc;
+	uint32_t divide;
+
+	ATOM_FIRMWARE_INFO *fw_info;
+	uint16_t size;
+	uint8_t frev, crev;
+	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+
+	tc = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_CLKPIN_CNTL_2, MUX_TCLK_TO_XCLK);
+
+	if (tc)
+		return TCLK;
+
+	fw_info = (ATOM_FIRMWARE_INFO *)cgs_atom_get_data_table(hwmgr->device, index,
+						  &size, &frev, &crev);
+
+	if (!fw_info)
+		return 0;
+
+	reference_clock = le16_to_cpu(fw_info->usMinPixelClockPLL_Output);
+
+	divide = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_CLKPIN_CNTL, XTALIN_DIVIDE);
+
+	if (0 != divide)
+		return reference_clock / 4;
+
+	return reference_clock;
+}
+
+int tonga_dpm_set_interrupt_state(void *private_data,
+					 unsigned src_id, unsigned type,
+					 int enabled)
+{
+	uint32_t cg_thermal_int;
+	struct pp_hwmgr *hwmgr = ((struct pp_eventmgr *)private_data)->hwmgr;
+
+	if (hwmgr == NULL)
+		return -EINVAL;
+
+	switch (type) {
+	case AMD_THERMAL_IRQ_LOW_TO_HIGH:
+		if (enabled) {
+			cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT);
+			cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
+		} else {
+			cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT);
+			cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
+		}
+		break;
+
+	case AMD_THERMAL_IRQ_HIGH_TO_LOW:
+		if (enabled) {
+			cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT);
+			cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
+		} else {
+			cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT);
+			cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+int tonga_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr,
+					const void *thermal_interrupt_info)
+{
+	int result;
+	const struct pp_interrupt_registration_info *info =
+			(const struct pp_interrupt_registration_info *)thermal_interrupt_info;
+
+	if (info == NULL)
+		return -EINVAL;
+
+	result = cgs_add_irq_source(hwmgr->device, 230, AMD_THERMAL_IRQ_LAST,
+				tonga_dpm_set_interrupt_state,
+				info->call_back, info->context);
+
+	if (result)
+		return -EINVAL;
+
+	result = cgs_add_irq_source(hwmgr->device, 231, AMD_THERMAL_IRQ_LAST,
+				tonga_dpm_set_interrupt_state,
+				info->call_back, info->context);
+
+	if (result)
+		return -EINVAL;
+
+	return 0;
+}
+
+bool tonga_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	bool is_update_required = false;
+	struct cgs_display_info info = {0,0,NULL};
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	if (data->display_timing.num_existing_displays != info.display_count)
+		is_update_required = true;
+/* TO DO NEED TO GET DEEP SLEEP CLOCK FROM DAL
+	if (phm_cap_enabled(hwmgr->hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
+		cgs_get_min_clock_settings(hwmgr->device, &min_clocks);
+		if(min_clocks.engineClockInSR != data->display_timing.minClockInSR)
+			is_update_required = true;
+*/
+	return is_update_required;
+}
+
+static inline bool tonga_are_power_levels_equal(const struct tonga_performance_level *pl1,
+							   const struct tonga_performance_level *pl2)
+{
+	return ((pl1->memory_clock == pl2->memory_clock) &&
+		  (pl1->engine_clock == pl2->engine_clock) &&
+		  (pl1->pcie_gen == pl2->pcie_gen) &&
+		  (pl1->pcie_lane == pl2->pcie_lane));
+}
+
+int tonga_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal)
+{
+	const struct tonga_power_state *psa = cast_const_phw_tonga_power_state(pstate1);
+	const struct tonga_power_state *psb = cast_const_phw_tonga_power_state(pstate2);
+	int i;
+
+	if (equal == NULL || psa == NULL || psb == NULL)
+		return -EINVAL;
+
+	/* If the two states don't even have the same number of performance levels they cannot be the same state. */
+	if (psa->performance_level_count != psb->performance_level_count) {
+		*equal = false;
+		return 0;
+	}
+
+	for (i = 0; i < psa->performance_level_count; i++) {
+		if (!tonga_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) {
+			/* If we have found even one performance level pair that is different the states are different. */
+			*equal = false;
+			return 0;
+		}
+	}
+
+	/* If all performance levels are the same try to use the UVD clocks to break the tie.*/
+	*equal = ((psa->uvd_clocks.VCLK == psb->uvd_clocks.VCLK) && (psa->uvd_clocks.DCLK == psb->uvd_clocks.DCLK));
+	*equal &= ((psa->vce_clocks.EVCLK == psb->vce_clocks.EVCLK) && (psa->vce_clocks.ECCLK == psb->vce_clocks.ECCLK));
+	*equal &= (psa->sclk_threshold == psb->sclk_threshold);
+	*equal &= (psa->acp_clk == psb->acp_clk);
+
+	return 0;
+}
+
+static int tonga_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
+{
+	if (mode) {
+		/* stop auto-manage */
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_MicrocodeFanControl))
+			tonga_fan_ctrl_stop_smc_fan_control(hwmgr);
+		tonga_fan_ctrl_set_static_mode(hwmgr, mode);
+	} else
+		/* restart auto-manage */
+		tonga_fan_ctrl_reset_fan_speed_to_default(hwmgr);
+
+	return 0;
+}
+
+static int tonga_get_fan_control_mode(struct pp_hwmgr *hwmgr)
+{
+	if (hwmgr->fan_ctrl_is_in_default_mode)
+		return hwmgr->fan_ctrl_default_mode;
+	else
+		return PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_FDO_CTRL2, FDO_PWM_MODE);
+}
+
+static const struct pp_hwmgr_func tonga_hwmgr_funcs = {
+	.backend_init = &tonga_hwmgr_backend_init,
+	.backend_fini = &tonga_hwmgr_backend_fini,
+	.asic_setup = &tonga_setup_asic_task,
+	.dynamic_state_management_enable = &tonga_enable_dpm_tasks,
+	.apply_state_adjust_rules = tonga_apply_state_adjust_rules,
+	.force_dpm_level = &tonga_force_dpm_level,
+	.power_state_set = tonga_set_power_state_tasks,
+	.get_power_state_size = tonga_get_power_state_size,
+	.get_mclk = tonga_dpm_get_mclk,
+	.get_sclk = tonga_dpm_get_sclk,
+	.patch_boot_state = tonga_dpm_patch_boot_state,
+	.get_pp_table_entry = tonga_get_pp_table_entry,
+	.get_num_of_pp_table_entries = tonga_get_number_of_powerplay_table_entries,
+	.print_current_perforce_level = tonga_print_current_perforce_level,
+	.powerdown_uvd = tonga_phm_powerdown_uvd,
+	.powergate_uvd = tonga_phm_powergate_uvd,
+	.powergate_vce = tonga_phm_powergate_vce,
+	.disable_clock_power_gating = tonga_phm_disable_clock_power_gating,
+	.notify_smc_display_config_after_ps_adjustment = tonga_notify_smc_display_config_after_ps_adjustment,
+	.display_config_changed = tonga_display_configuration_changed_task,
+	.set_max_fan_pwm_output = tonga_set_max_fan_pwm_output,
+	.set_max_fan_rpm_output = tonga_set_max_fan_rpm_output,
+	.get_temperature = tonga_thermal_get_temperature,
+	.stop_thermal_controller = tonga_thermal_stop_thermal_controller,
+	.get_fan_speed_info = tonga_fan_ctrl_get_fan_speed_info,
+	.get_fan_speed_percent = tonga_fan_ctrl_get_fan_speed_percent,
+	.set_fan_speed_percent = tonga_fan_ctrl_set_fan_speed_percent,
+	.reset_fan_speed_to_default = tonga_fan_ctrl_reset_fan_speed_to_default,
+	.get_fan_speed_rpm = tonga_fan_ctrl_get_fan_speed_rpm,
+	.set_fan_speed_rpm = tonga_fan_ctrl_set_fan_speed_rpm,
+	.uninitialize_thermal_controller = tonga_thermal_ctrl_uninitialize_thermal_controller,
+	.register_internal_thermal_interrupt = tonga_register_internal_thermal_interrupt,
+	.check_smc_update_required_for_display_configuration = tonga_check_smc_update_required_for_display_configuration,
+	.check_states_equal = tonga_check_states_equal,
+	.set_fan_control_mode = tonga_set_fan_control_mode,
+	.get_fan_control_mode = tonga_get_fan_control_mode,
+};
+
+int tonga_hwmgr_init(struct pp_hwmgr *hwmgr)
+{
+	tonga_hwmgr  *data;
+
+	data = kzalloc (sizeof(tonga_hwmgr), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+	memset(data, 0x00, sizeof(tonga_hwmgr));
+
+	hwmgr->backend = data;
+	hwmgr->hwmgr_func = &tonga_hwmgr_funcs;
+	hwmgr->pptable_func = &tonga_pptable_funcs;
+	pp_tonga_thermal_initialize(hwmgr);
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h
new file mode 100644
index 0000000..49168d2
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef TONGA_HWMGR_H
+#define TONGA_HWMGR_H
+
+#include "hwmgr.h"
+#include "smu72_discrete.h"
+#include "ppatomctrl.h"
+#include "ppinterrupt.h"
+#include "tonga_powertune.h"
+
+#define TONGA_MAX_HARDWARE_POWERLEVELS 2
+#define TONGA_DYNCLK_NUMBER_OF_TREND_COEFFICIENTS 15
+
+struct tonga_performance_level {
+	uint32_t	memory_clock;
+	uint32_t	engine_clock;
+	uint16_t    pcie_gen;
+	uint16_t    pcie_lane;
+};
+
+struct _phw_tonga_bacos {
+	uint32_t                          best_match;
+	uint32_t                          baco_flags;
+	struct tonga_performance_level		  performance_level;
+};
+typedef struct _phw_tonga_bacos phw_tonga_bacos;
+
+struct _phw_tonga_uvd_clocks {
+	uint32_t   VCLK;
+	uint32_t   DCLK;
+};
+
+typedef struct _phw_tonga_uvd_clocks phw_tonga_uvd_clocks;
+
+struct _phw_tonga_vce_clocks {
+	uint32_t   EVCLK;
+	uint32_t   ECCLK;
+};
+
+typedef struct _phw_tonga_vce_clocks phw_tonga_vce_clocks;
+
+struct tonga_power_state {
+	uint32_t                    magic;
+	phw_tonga_uvd_clocks        uvd_clocks;
+	phw_tonga_vce_clocks        vce_clocks;
+	uint32_t                    sam_clk;
+	uint32_t                    acp_clk;
+	uint16_t                    performance_level_count;
+	bool                        dc_compatible;
+	uint32_t                    sclk_threshold;
+	struct tonga_performance_level performance_levels[TONGA_MAX_HARDWARE_POWERLEVELS];
+};
+
+struct _phw_tonga_dpm_level {
+	bool  		enabled;
+	uint32_t    value;
+	uint32_t    param1;
+};
+typedef struct _phw_tonga_dpm_level phw_tonga_dpm_level;
+
+#define TONGA_MAX_DEEPSLEEP_DIVIDER_ID 5
+#define MAX_REGULAR_DPM_NUMBER 8
+#define TONGA_MINIMUM_ENGINE_CLOCK 2500
+
+struct tonga_single_dpm_table {
+	uint32_t count;
+	phw_tonga_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER];
+};
+
+struct tonga_dpm_table {
+	struct tonga_single_dpm_table  sclk_table;
+	struct tonga_single_dpm_table  mclk_table;
+	struct tonga_single_dpm_table  pcie_speed_table;
+	struct tonga_single_dpm_table  vddc_table;
+	struct tonga_single_dpm_table  vdd_gfx_table;
+	struct tonga_single_dpm_table  vdd_ci_table;
+	struct tonga_single_dpm_table  mvdd_table;
+};
+typedef struct _phw_tonga_dpm_table phw_tonga_dpm_table;
+
+
+struct _phw_tonga_clock_regisiters {
+	uint32_t  vCG_SPLL_FUNC_CNTL;
+	uint32_t  vCG_SPLL_FUNC_CNTL_2;
+	uint32_t  vCG_SPLL_FUNC_CNTL_3;
+	uint32_t  vCG_SPLL_FUNC_CNTL_4;
+	uint32_t  vCG_SPLL_SPREAD_SPECTRUM;
+	uint32_t  vCG_SPLL_SPREAD_SPECTRUM_2;
+	uint32_t  vDLL_CNTL;
+	uint32_t  vMCLK_PWRMGT_CNTL;
+	uint32_t  vMPLL_AD_FUNC_CNTL;
+	uint32_t  vMPLL_DQ_FUNC_CNTL;
+	uint32_t  vMPLL_FUNC_CNTL;
+	uint32_t  vMPLL_FUNC_CNTL_1;
+	uint32_t  vMPLL_FUNC_CNTL_2;
+	uint32_t  vMPLL_SS1;
+	uint32_t  vMPLL_SS2;
+};
+typedef struct _phw_tonga_clock_regisiters phw_tonga_clock_registers;
+
+struct _phw_tonga_voltage_smio_registers {
+	uint32_t vs0_vid_lower_smio_cntl;
+};
+typedef struct _phw_tonga_voltage_smio_registers phw_tonga_voltage_smio_registers;
+
+
+struct _phw_tonga_mc_reg_entry {
+	uint32_t mclk_max;
+	uint32_t mc_data[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE];
+};
+typedef struct _phw_tonga_mc_reg_entry phw_tonga_mc_reg_entry;
+
+struct _phw_tonga_mc_reg_table {
+	uint8_t   last;               /* number of registers*/
+	uint8_t   num_entries;        /* number of entries in mc_reg_table_entry used*/
+	uint16_t  validflag;          /* indicate the corresponding register is valid or not. 1: valid, 0: invalid. bit0->address[0], bit1->address[1], etc.*/
+	phw_tonga_mc_reg_entry    mc_reg_table_entry[MAX_AC_TIMING_ENTRIES];
+	SMU72_Discrete_MCRegisterAddress mc_reg_address[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE];
+};
+typedef struct _phw_tonga_mc_reg_table phw_tonga_mc_reg_table;
+
+#define DISABLE_MC_LOADMICROCODE   1
+#define DISABLE_MC_CFGPROGRAMMING  2
+
+/*Ultra Low Voltage parameter structure */
+struct _phw_tonga_ulv_parm{
+	bool	ulv_supported;
+	uint32_t   ch_ulv_parameter;
+	uint32_t   ulv_volt_change_delay;
+	struct tonga_performance_level   ulv_power_level;
+};
+typedef struct _phw_tonga_ulv_parm phw_tonga_ulv_parm;
+
+#define TONGA_MAX_LEAKAGE_COUNT  8
+
+struct _phw_tonga_leakage_voltage {
+	uint16_t  count;
+	uint16_t  leakage_id[TONGA_MAX_LEAKAGE_COUNT];
+	uint16_t  actual_voltage[TONGA_MAX_LEAKAGE_COUNT];
+};
+typedef struct _phw_tonga_leakage_voltage phw_tonga_leakage_voltage;
+
+struct _phw_tonga_display_timing {
+	uint32_t min_clock_insr;
+	uint32_t num_existing_displays;
+};
+typedef struct _phw_tonga_display_timing phw_tonga_display_timing;
+
+struct _phw_tonga_dpmlevel_enable_mask {
+	uint32_t uvd_dpm_enable_mask;
+	uint32_t vce_dpm_enable_mask;
+	uint32_t acp_dpm_enable_mask;
+	uint32_t samu_dpm_enable_mask;
+	uint32_t sclk_dpm_enable_mask;
+	uint32_t mclk_dpm_enable_mask;
+	uint32_t pcie_dpm_enable_mask;
+};
+typedef struct _phw_tonga_dpmlevel_enable_mask phw_tonga_dpmlevel_enable_mask;
+
+struct _phw_tonga_pcie_perf_range {
+	uint16_t max;
+	uint16_t min;
+};
+typedef struct _phw_tonga_pcie_perf_range phw_tonga_pcie_perf_range;
+
+struct _phw_tonga_vbios_boot_state {
+	uint16_t					mvdd_bootup_value;
+	uint16_t					vddc_bootup_value;
+	uint16_t					vddci_bootup_value;
+	uint16_t					vddgfx_bootup_value;
+	uint32_t					sclk_bootup_value;
+	uint32_t					mclk_bootup_value;
+	uint16_t					pcie_gen_bootup_value;
+	uint16_t					pcie_lane_bootup_value;
+};
+typedef struct _phw_tonga_vbios_boot_state phw_tonga_vbios_boot_state;
+
+#define DPMTABLE_OD_UPDATE_SCLK     0x00000001
+#define DPMTABLE_OD_UPDATE_MCLK     0x00000002
+#define DPMTABLE_UPDATE_SCLK        0x00000004
+#define DPMTABLE_UPDATE_MCLK        0x00000008
+
+/* We need to review which fields are needed. */
+/* This is mostly a copy of the RV7xx/Evergreen structure which is close, but not identical to the N.Islands one. */
+struct tonga_hwmgr {
+	struct tonga_dpm_table               dpm_table;
+	struct tonga_dpm_table               golden_dpm_table;
+
+	uint32_t                           voting_rights_clients0;
+	uint32_t                           voting_rights_clients1;
+	uint32_t                           voting_rights_clients2;
+	uint32_t                           voting_rights_clients3;
+	uint32_t                           voting_rights_clients4;
+	uint32_t                           voting_rights_clients5;
+	uint32_t                           voting_rights_clients6;
+	uint32_t                           voting_rights_clients7;
+	uint32_t                           static_screen_threshold_unit;
+	uint32_t                           static_screen_threshold;
+	uint32_t                           voltage_control;
+	uint32_t                           vdd_gfx_control;
+
+	uint32_t                           vddc_vddci_delta;
+	uint32_t                           vddc_vddgfx_delta;
+
+	struct pp_interrupt_registration_info    internal_high_thermal_interrupt_info;
+	struct pp_interrupt_registration_info    internal_low_thermal_interrupt_info;
+	struct pp_interrupt_registration_info    smc_to_host_interrupt_info;
+	uint32_t                          active_auto_throttle_sources;
+
+	struct pp_interrupt_registration_info    external_throttle_interrupt;
+	irq_handler_func_t             external_throttle_callback;
+	void                             *external_throttle_context;
+
+	struct pp_interrupt_registration_info    ctf_interrupt_info;
+	irq_handler_func_t             ctf_callback;
+	void                             *ctf_context;
+
+	phw_tonga_clock_registers      	  clock_registers;
+	phw_tonga_voltage_smio_registers  voltage_smio_registers;
+
+	bool                         	is_memory_GDDR5;
+	uint16_t                          acpi_vddc;
+	bool                         	pspp_notify_required;        /* Flag to indicate if PSPP notification to SBIOS is required */
+	uint16_t                          force_pcie_gen;            /* The forced PCI-E speed if not 0xffff */
+	uint16_t                          acpi_pcie_gen;             /* The PCI-E speed at ACPI time */
+	uint32_t                           pcie_gen_cap;             /* The PCI-E speed capabilities bitmap from CAIL */
+	uint32_t                           pcie_lane_cap;            /* The PCI-E lane capabilities bitmap from CAIL */
+	uint32_t                           pcie_spc_cap;             /* Symbol Per Clock Capabilities from registry */
+	phw_tonga_leakage_voltage       	vddc_leakage;            /* The Leakage VDDC supported (based on leakage ID).*/
+	phw_tonga_leakage_voltage       	vddcgfx_leakage;         /* The Leakage VDDC supported (based on leakage ID). */
+	phw_tonga_leakage_voltage       	vddci_leakage;           /* The Leakage VDDCI supported (based on leakage ID). */
+
+	uint32_t                           mvdd_control;
+	uint32_t                           vddc_mask_low;
+	uint32_t                           mvdd_mask_low;
+	uint16_t                          max_vddc_in_pp_table;        /* the maximum VDDC value in the powerplay table*/
+	uint16_t                          min_vddc_in_pp_table;
+	uint16_t                          max_vddci_in_pp_table;       /* the maximum VDDCI value in the powerplay table */
+	uint16_t                          min_vddci_in_pp_table;
+	uint32_t                           mclk_strobe_mode_threshold;
+	uint32_t                           mclk_stutter_mode_threshold;
+	uint32_t                           mclk_edc_enable_threshold;
+	uint32_t                           mclk_edc_wr_enable_threshold;
+	bool                         	is_uvd_enabled;
+	bool                         	is_xdma_enabled;
+	phw_tonga_vbios_boot_state      vbios_boot_state;
+
+	bool                         battery_state;
+	bool                         is_tlu_enabled;
+	bool                         pcie_performance_request;
+
+	/* -------------- SMC SRAM Address of firmware header tables ----------------*/
+	uint32_t                           sram_end;                 /* The first address after the SMC SRAM. */
+	uint32_t                           dpm_table_start;          /* The start of the dpm table in the SMC SRAM. */
+	uint32_t                           soft_regs_start;          /* The start of the soft registers in the SMC SRAM. */
+	uint32_t                           mc_reg_table_start;       /* The start of the mc register table in the SMC SRAM. */
+	uint32_t                           fan_table_start;          /* The start of the fan table in the SMC SRAM. */
+	uint32_t                           arb_table_start;          /* The start of the ARB setting table in the SMC SRAM. */
+	SMU72_Discrete_DpmTable         smc_state_table;             /* The carbon copy of the SMC state table. */
+	SMU72_Discrete_MCRegisters      mc_reg_table;
+	SMU72_Discrete_Ulv              ulv_setting;                 /* The carbon copy of ULV setting. */
+	/* -------------- Stuff originally coming from Evergreen --------------------*/
+	phw_tonga_mc_reg_table			tonga_mc_reg_table;
+	uint32_t                         vdd_ci_control;
+	pp_atomctrl_voltage_table        vddc_voltage_table;
+	pp_atomctrl_voltage_table        vddci_voltage_table;
+	pp_atomctrl_voltage_table        vddgfx_voltage_table;
+	pp_atomctrl_voltage_table        mvdd_voltage_table;
+
+	uint32_t                           mgcg_cgtt_local2;
+	uint32_t                           mgcg_cgtt_local3;
+	uint32_t                           gpio_debug;
+	uint32_t							mc_micro_code_feature;
+	uint32_t							highest_mclk;
+	uint16_t                          acpi_vdd_ci;
+	uint8_t                           mvdd_high_index;
+	uint8_t                           mvdd_low_index;
+	bool                         dll_defaule_on;
+	bool                         performance_request_registered;
+
+	/* ----------------- Low Power Features ---------------------*/
+	phw_tonga_bacos					bacos;
+	phw_tonga_ulv_parm              ulv;
+	/* ----------------- CAC Stuff ---------------------*/
+	uint32_t					cac_table_start;
+	bool                         cac_configuration_required;    /* TRUE if PP_CACConfigurationRequired == 1 */
+	bool                         driver_calculate_cac_leakage;  /* TRUE if PP_DriverCalculateCACLeakage == 1 */
+	bool                         cac_enabled;
+	/* ----------------- DPM2 Parameters ---------------------*/
+	uint32_t					power_containment_features;
+	bool                         enable_bapm_feature;
+	bool                         enable_tdc_limit_feature;
+	bool                         enable_pkg_pwr_tracking_feature;
+	bool                         disable_uvd_power_tune_feature;
+	phw_tonga_pt_defaults           *power_tune_defaults;
+	SMU72_Discrete_PmFuses           power_tune_table;
+	uint32_t                           ul_dte_tj_offset;             /* Fudge factor in DPM table to correct HW DTE errors */
+	uint32_t                           fast_watemark_threshold;      /* use fast watermark if clock is equal or above this. In percentage of the target high sclk. */
+
+	/* ----------------- Phase Shedding ---------------------*/
+	bool                         vddc_phase_shed_control;
+	/* --------------------- DI/DT --------------------------*/
+	phw_tonga_display_timing       display_timing;
+	/* --------- ReadRegistry data for memory and engine clock margins ---- */
+	uint32_t                           engine_clock_data;
+	uint32_t                           memory_clock_data;
+	/* -------- Thermal Temperature Setting --------------*/
+	phw_tonga_dpmlevel_enable_mask     dpm_level_enable_mask;
+	uint32_t                           need_update_smu7_dpm_table;
+	uint32_t                           sclk_dpm_key_disabled;
+	uint32_t                           mclk_dpm_key_disabled;
+	uint32_t                           pcie_dpm_key_disabled;
+	uint32_t                           min_engine_clocks; /* used to store the previous dal min sclock */
+	phw_tonga_pcie_perf_range       pcie_gen_performance;
+	phw_tonga_pcie_perf_range       pcie_lane_performance;
+	phw_tonga_pcie_perf_range       pcie_gen_power_saving;
+	phw_tonga_pcie_perf_range       pcie_lane_power_saving;
+	bool                            use_pcie_performance_levels;
+	bool                            use_pcie_power_saving_levels;
+	uint32_t                           activity_target[SMU72_MAX_LEVELS_GRAPHICS]; /* percentage value from 0-100, default 50 */
+	uint32_t                           mclk_activity_target;
+	uint32_t                           low_sclk_interrupt_threshold;
+	uint32_t                           last_mclk_dpm_enable_mask;
+	bool								uvd_enabled;
+	uint32_t                           pcc_monitor_enabled;
+
+	/* --------- Power Gating States ------------*/
+	bool                           uvd_power_gated;  /* 1: gated, 0:not gated */
+	bool                           vce_power_gated;  /* 1: gated, 0:not gated */
+	bool                           samu_power_gated; /* 1: gated, 0:not gated */
+	bool                           acp_power_gated;  /* 1: gated, 0:not gated */
+	bool                           pg_acp_init;
+
+};
+
+typedef struct tonga_hwmgr tonga_hwmgr;
+
+#define TONGA_DPM2_NEAR_TDP_DEC          10
+#define TONGA_DPM2_ABOVE_SAFE_INC        5
+#define TONGA_DPM2_BELOW_SAFE_INC        20
+
+#define TONGA_DPM2_LTA_WINDOW_SIZE       7  /* Log2 of the LTA window size (l2numWin_TDP). Eg. If LTA windows size is 128, then this value should be Log2(128) = 7. */
+
+#define TONGA_DPM2_LTS_TRUNCATE          0
+
+#define TONGA_DPM2_TDP_SAFE_LIMIT_PERCENT            80  /* Maximum 100 */
+
+#define TONGA_DPM2_MAXPS_PERCENT_H                   90  /* Maximum 0xFF */
+#define TONGA_DPM2_MAXPS_PERCENT_M                   90  /* Maximum 0xFF */
+
+#define TONGA_DPM2_PWREFFICIENCYRATIO_MARGIN         50
+
+#define TONGA_DPM2_SQ_RAMP_MAX_POWER                 0x3FFF
+#define TONGA_DPM2_SQ_RAMP_MIN_POWER                 0x12
+#define TONGA_DPM2_SQ_RAMP_MAX_POWER_DELTA           0x15
+#define TONGA_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE  0x1E
+#define TONGA_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO  0xF
+
+#define TONGA_VOLTAGE_CONTROL_NONE                   0x0
+#define TONGA_VOLTAGE_CONTROL_BY_GPIO                0x1
+#define TONGA_VOLTAGE_CONTROL_BY_SVID2               0x2
+#define TONGA_VOLTAGE_CONTROL_MERGED                 0x3
+
+#define TONGA_Q88_FORMAT_CONVERSION_UNIT             256 /*To convert to Q8.8 format for firmware */
+
+#define TONGA_UNUSED_GPIO_PIN                        0x7F
+
+#define PP_HOST_TO_SMC_UL(X) cpu_to_be32(X)
+#define PP_SMC_TO_HOST_UL(X) be32_to_cpu(X)
+
+#define PP_HOST_TO_SMC_US(X) cpu_to_be16(X)
+#define PP_SMC_TO_HOST_US(X) be16_to_cpu(X)
+
+#define CONVERT_FROM_HOST_TO_SMC_UL(X) ((X) = PP_HOST_TO_SMC_UL(X))
+#define CONVERT_FROM_SMC_TO_HOST_UL(X) ((X) = PP_SMC_TO_HOST_UL(X))
+
+#define CONVERT_FROM_HOST_TO_SMC_US(X) ((X) = PP_HOST_TO_SMC_US(X))
+
+int tonga_hwmgr_init(struct pp_hwmgr *hwmgr);
+int tonga_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input);
+int tonga_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate);
+int tonga_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable);
+int tonga_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable);
+uint32_t tonga_get_xclk(struct pp_hwmgr *hwmgr);
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.h
new file mode 100644
index 0000000..8e6670b
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef TONGA_POWERTUNE_H
+#define TONGA_POWERTUNE_H
+
+enum _phw_tonga_ptc_config_reg_type {
+	TONGA_CONFIGREG_MMR = 0,
+	TONGA_CONFIGREG_SMC_IND,
+	TONGA_CONFIGREG_DIDT_IND,
+	TONGA_CONFIGREG_CACHE,
+
+	TONGA_CONFIGREG_MAX
+};
+typedef enum _phw_tonga_ptc_config_reg_type phw_tonga_ptc_config_reg_type;
+
+/* PowerContainment Features */
+#define POWERCONTAINMENT_FEATURE_BAPM            0x00000001
+#define POWERCONTAINMENT_FEATURE_TDCLimit        0x00000002
+#define POWERCONTAINMENT_FEATURE_PkgPwrLimit     0x00000004
+
+struct _phw_tonga_pt_config_reg {
+	uint32_t                           Offset;
+	uint32_t                           Mask;
+	uint32_t                           Shift;
+	uint32_t                           Value;
+	phw_tonga_ptc_config_reg_type     Type;
+};
+typedef struct _phw_tonga_pt_config_reg phw_tonga_pt_config_reg;
+
+struct _phw_tonga_pt_defaults {
+	uint8_t   svi_load_line_en;
+	uint8_t   svi_load_line_vddC;
+	uint8_t   tdc_vddc_throttle_release_limit_perc;
+	uint8_t   tdc_mawt;
+	uint8_t   tdc_waterfall_ctl;
+	uint8_t   dte_ambient_temp_base;
+	uint32_t  display_cac;
+	uint32_t  bamp_temp_gradient;
+	uint16_t  bapmti_r[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS];
+	uint16_t  bapmti_rc[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS];
+};
+typedef struct _phw_tonga_pt_defaults phw_tonga_pt_defaults;
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h
new file mode 100644
index 0000000..9a4456e
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h
@@ -0,0 +1,406 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef TONGA_PPTABLE_H
+#define TONGA_PPTABLE_H
+
+/** \file
+ * This is a PowerPlay table header file
+ */
+#pragma pack(push, 1)
+
+#include "hwmgr.h"
+
+#define ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f
+#define ATOM_TONGA_PP_FANPARAMETERS_NOFAN                                 0x80    /* No fan is connected to this controller. */
+
+#define ATOM_TONGA_PP_THERMALCONTROLLER_NONE      0
+#define ATOM_TONGA_PP_THERMALCONTROLLER_LM96163   17
+#define ATOM_TONGA_PP_THERMALCONTROLLER_TONGA     21
+#define ATOM_TONGA_PP_THERMALCONTROLLER_FIJI      22
+
+/*
+ * Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal.
+ * We probably should reserve the bit 0x80 for this use.
+ * To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here).
+ * The driver can pick the correct internal controller based on the ASIC.
+ */
+
+#define ATOM_TONGA_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL   0x89    /* ADT7473 Fan Control + Internal Thermal Controller */
+#define ATOM_TONGA_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL   0x8D    /* EMC2103 Fan Control + Internal Thermal Controller */
+
+/*/* ATOM_TONGA_POWERPLAYTABLE::ulPlatformCaps */
+#define ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL              0x1            /* This cap indicates whether vddgfx will be a separated power rail. */
+#define ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY                   0x2            /* This cap indicates whether this is a mobile part and CCC need to show Powerplay page. */
+#define ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE            0x4            /* This cap indicates whether power source notificaiton is done by SBIOS directly. */
+#define ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND      0x8            /* Enable the option to overwrite voltage island feature to be disabled, regardless of VddGfx power rail support. */
+#define ____RETIRE16____                                0x10
+#define ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC                 0x20            /* This cap indicates whether power source notificaiton is done by GPIO directly. */
+#define ____RETIRE64____                                0x40
+#define ____RETIRE128____                               0x80
+#define ____RETIRE256____                              0x100
+#define ____RETIRE512____                              0x200
+#define ____RETIRE1024____                             0x400
+#define ____RETIRE2048____                             0x800
+#define ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL             0x1000            /* This cap indicates dynamic MVDD is required. Uncheck to disable it. */
+#define ____RETIRE2000____                            0x2000
+#define ____RETIRE4000____                            0x4000
+#define ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL            0x8000            /* This cap indicates dynamic VDDCI is required. Uncheck to disable it. */
+#define ____RETIRE10000____                          0x10000
+#define ATOM_TONGA_PP_PLATFORM_CAP_BACO                    0x20000            /* Enable to indicate the driver supports BACO state. */
+
+#define ATOM_TONGA_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17         0x100000     /* Enable to indicate the driver supports thermal2GPIO17. */
+#define ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL  0x1000000     /* Enable to indicate if thermal and PCC are sharing the same GPIO */
+#define ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE       0x2000000
+
+/* ATOM_PPLIB_NONCLOCK_INFO::usClassification */
+#define ATOM_PPLIB_CLASSIFICATION_UI_MASK               0x0007
+#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT              0
+#define ATOM_PPLIB_CLASSIFICATION_UI_NONE               0
+#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY            1
+#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED           3
+#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE        5
+/* 2, 4, 6, 7 are reserved */
+
+#define ATOM_PPLIB_CLASSIFICATION_BOOT                  0x0008
+#define ATOM_PPLIB_CLASSIFICATION_THERMAL               0x0010
+#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE    0x0020
+#define ATOM_PPLIB_CLASSIFICATION_REST                  0x0040
+#define ATOM_PPLIB_CLASSIFICATION_FORCED                0x0080
+#define ATOM_PPLIB_CLASSIFICATION_ACPI                  0x1000
+
+/* ATOM_PPLIB_NONCLOCK_INFO::usClassification2 */
+#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001
+
+#define ATOM_Tonga_DISALLOW_ON_DC                       0x00004000
+#define ATOM_Tonga_ENABLE_VARIBRIGHT                    0x00008000
+
+#define ATOM_Tonga_TABLE_REVISION_TONGA                 7
+
+typedef struct _ATOM_Tonga_POWERPLAYTABLE {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+
+	UCHAR  ucTableRevision;
+	USHORT usTableSize;						/*the size of header structure */
+
+	ULONG	ulGoldenPPID;
+	ULONG	ulGoldenRevision;
+	USHORT	usFormatID;
+
+	USHORT	usVoltageTime;					 /*in microseconds */
+	ULONG	ulPlatformCaps;					  /*See ATOM_Tonga_CAPS_* */
+
+	ULONG	ulMaxODEngineClock; 			   /*For Overdrive.  */
+	ULONG	ulMaxODMemoryClock; 			   /*For Overdrive. */
+
+	USHORT	usPowerControlLimit;
+	USHORT	usUlvVoltageOffset;				  /*in mv units */
+
+	USHORT	usStateArrayOffset;				  /*points to ATOM_Tonga_State_Array */
+	USHORT	usFanTableOffset;				  /*points to ATOM_Tonga_Fan_Table */
+	USHORT	usThermalControllerOffset;		   /*points to ATOM_Tonga_Thermal_Controller */
+	USHORT	usReserv;						   /*CustomThermalPolicy removed for Tonga. Keep this filed as reserved. */
+
+	USHORT	usMclkDependencyTableOffset;	   /*points to ATOM_Tonga_MCLK_Dependency_Table */
+	USHORT	usSclkDependencyTableOffset;	   /*points to ATOM_Tonga_SCLK_Dependency_Table */
+	USHORT	usVddcLookupTableOffset;		   /*points to ATOM_Tonga_Voltage_Lookup_Table */
+	USHORT	usVddgfxLookupTableOffset; 		/*points to ATOM_Tonga_Voltage_Lookup_Table */
+
+	USHORT	usMMDependencyTableOffset;		  /*points to ATOM_Tonga_MM_Dependency_Table */
+
+	USHORT	usVCEStateTableOffset;			   /*points to ATOM_Tonga_VCE_State_Table; */
+
+	USHORT	usPPMTableOffset;				  /*points to ATOM_Tonga_PPM_Table */
+	USHORT	usPowerTuneTableOffset;			  /*points to ATOM_PowerTune_Table */
+
+	USHORT	usHardLimitTableOffset; 		   /*points to ATOM_Tonga_Hard_Limit_Table */
+
+	USHORT	usPCIETableOffset;				  /*points to ATOM_Tonga_PCIE_Table */
+
+	USHORT	usGPIOTableOffset;				  /*points to ATOM_Tonga_GPIO_Table */
+
+	USHORT	usReserved[6];					   /*TODO: modify reserved size to fit structure aligning */
+} ATOM_Tonga_POWERPLAYTABLE;
+
+typedef struct _ATOM_Tonga_State {
+	UCHAR  ucEngineClockIndexHigh;
+	UCHAR  ucEngineClockIndexLow;
+
+	UCHAR  ucMemoryClockIndexHigh;
+	UCHAR  ucMemoryClockIndexLow;
+
+	UCHAR  ucPCIEGenLow;
+	UCHAR  ucPCIEGenHigh;
+
+	UCHAR  ucPCIELaneLow;
+	UCHAR  ucPCIELaneHigh;
+
+	USHORT usClassification;
+	ULONG ulCapsAndSettings;
+	USHORT usClassification2;
+	UCHAR  ucUnused[4];
+} ATOM_Tonga_State;
+
+typedef struct _ATOM_Tonga_State_Array {
+	UCHAR ucRevId;
+	UCHAR ucNumEntries;		/* Number of entries. */
+	ATOM_Tonga_State states[1];	/* Dynamically allocate entries. */
+} ATOM_Tonga_State_Array;
+
+typedef struct _ATOM_Tonga_MCLK_Dependency_Record {
+	UCHAR  ucVddcInd;	/* Vddc voltage */
+	USHORT usVddci;
+	USHORT usVddgfxOffset;	/* Offset relative to Vddc voltage */
+	USHORT usMvdd;
+	ULONG ulMclk;
+	USHORT usReserved;
+} ATOM_Tonga_MCLK_Dependency_Record;
+
+typedef struct _ATOM_Tonga_MCLK_Dependency_Table {
+	UCHAR ucRevId;
+	UCHAR ucNumEntries; 										/* Number of entries. */
+	ATOM_Tonga_MCLK_Dependency_Record entries[1];				/* Dynamically allocate entries. */
+} ATOM_Tonga_MCLK_Dependency_Table;
+
+typedef struct _ATOM_Tonga_SCLK_Dependency_Record {
+	UCHAR  ucVddInd;											/* Base voltage */
+	USHORT usVddcOffset;										/* Offset relative to base voltage */
+	ULONG ulSclk;
+	USHORT usEdcCurrent;
+	UCHAR  ucReliabilityTemperature;
+	UCHAR  ucCKSVOffsetandDisable;							  /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */
+} ATOM_Tonga_SCLK_Dependency_Record;
+
+typedef struct _ATOM_Tonga_SCLK_Dependency_Table {
+	UCHAR ucRevId;
+	UCHAR ucNumEntries; 										/* Number of entries. */
+	ATOM_Tonga_SCLK_Dependency_Record entries[1];				 /* Dynamically allocate entries. */
+} ATOM_Tonga_SCLK_Dependency_Table;
+
+typedef struct _ATOM_Tonga_PCIE_Record {
+	UCHAR ucPCIEGenSpeed;
+	UCHAR usPCIELaneWidth;
+	UCHAR ucReserved[2];
+} ATOM_Tonga_PCIE_Record;
+
+typedef struct _ATOM_Tonga_PCIE_Table {
+	UCHAR ucRevId;
+	UCHAR ucNumEntries; 										/* Number of entries. */
+	ATOM_Tonga_PCIE_Record entries[1];							/* Dynamically allocate entries. */
+} ATOM_Tonga_PCIE_Table;
+
+typedef struct _ATOM_Tonga_MM_Dependency_Record {
+	UCHAR   ucVddcInd;											 /* VDDC voltage */
+	USHORT  usVddgfxOffset;									  /* Offset relative to VDDC voltage */
+	ULONG  ulDClk;												/* UVD D-clock */
+	ULONG  ulVClk;												/* UVD V-clock */
+	ULONG  ulEClk;												/* VCE clock */
+	ULONG  ulAClk;												/* ACP clock */
+	ULONG  ulSAMUClk;											/* SAMU clock */
+} ATOM_Tonga_MM_Dependency_Record;
+
+typedef struct _ATOM_Tonga_MM_Dependency_Table {
+	UCHAR ucRevId;
+	UCHAR ucNumEntries; 										/* Number of entries. */
+	ATOM_Tonga_MM_Dependency_Record entries[1]; 			   /* Dynamically allocate entries. */
+} ATOM_Tonga_MM_Dependency_Table;
+
+typedef struct _ATOM_Tonga_Voltage_Lookup_Record {
+	USHORT usVdd;											   /* Base voltage */
+	USHORT usCACLow;
+	USHORT usCACMid;
+	USHORT usCACHigh;
+} ATOM_Tonga_Voltage_Lookup_Record;
+
+typedef struct _ATOM_Tonga_Voltage_Lookup_Table {
+	UCHAR ucRevId;
+	UCHAR ucNumEntries; 										/* Number of entries. */
+	ATOM_Tonga_Voltage_Lookup_Record entries[1];				/* Dynamically allocate entries. */
+} ATOM_Tonga_Voltage_Lookup_Table;
+
+typedef struct _ATOM_Tonga_Fan_Table {
+	UCHAR   ucRevId;						 /* Change this if the table format changes or version changes so that the other fields are not the same. */
+	UCHAR   ucTHyst;						 /* Temperature hysteresis. Integer. */
+	USHORT  usTMin; 						 /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */
+	USHORT  usTMed; 						 /* The middle temperature where we change slopes. */
+	USHORT  usTHigh;						 /* The high point above TMed for adjusting the second slope. */
+	USHORT  usPWMMin;						 /* The minimum PWM value in percent (0.01% increments). */
+	USHORT  usPWMMed;						 /* The PWM value (in percent) at TMed. */
+	USHORT  usPWMHigh;						 /* The PWM value at THigh. */
+	USHORT  usTMax; 						 /* The max temperature */
+	UCHAR   ucFanControlMode;				  /* Legacy or Fuzzy Fan mode */
+	USHORT  usFanPWMMax;					  /* Maximum allowed fan power in percent */
+	USHORT  usFanOutputSensitivity;		  /* Sensitivity of fan reaction to temepature changes */
+	USHORT  usFanRPMMax;					  /* The default value in RPM */
+	ULONG  ulMinFanSCLKAcousticLimit;	   /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */
+	UCHAR   ucTargetTemperature;			 /* Advanced fan controller target temperature. */
+	UCHAR   ucMinimumPWMLimit; 			  /* The minimum PWM that the advanced fan controller can set.	This should be set to the highest PWM that will run the fan at its lowest RPM. */
+	USHORT  usReserved;
+} ATOM_Tonga_Fan_Table;
+
+typedef struct _ATOM_Fiji_Fan_Table {
+	UCHAR   ucRevId;						 /* Change this if the table format changes or version changes so that the other fields are not the same. */
+	UCHAR   ucTHyst;						 /* Temperature hysteresis. Integer. */
+	USHORT  usTMin; 						 /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */
+	USHORT  usTMed; 						 /* The middle temperature where we change slopes. */
+	USHORT  usTHigh;						 /* The high point above TMed for adjusting the second slope. */
+	USHORT  usPWMMin;						 /* The minimum PWM value in percent (0.01% increments). */
+	USHORT  usPWMMed;						 /* The PWM value (in percent) at TMed. */
+	USHORT  usPWMHigh;						 /* The PWM value at THigh. */
+	USHORT  usTMax; 						 /* The max temperature */
+	UCHAR   ucFanControlMode;				  /* Legacy or Fuzzy Fan mode */
+	USHORT  usFanPWMMax;					  /* Maximum allowed fan power in percent */
+	USHORT  usFanOutputSensitivity;		  /* Sensitivity of fan reaction to temepature changes */
+	USHORT  usFanRPMMax;					  /* The default value in RPM */
+	ULONG  ulMinFanSCLKAcousticLimit;		/* Minimum Fan Controller SCLK Frequency Acoustic Limit. */
+	UCHAR   ucTargetTemperature;			 /* Advanced fan controller target temperature. */
+	UCHAR   ucMinimumPWMLimit; 			  /* The minimum PWM that the advanced fan controller can set.	This should be set to the highest PWM that will run the fan at its lowest RPM. */
+	USHORT  usFanGainEdge;
+	USHORT  usFanGainHotspot;
+	USHORT  usFanGainLiquid;
+	USHORT  usFanGainVrVddc;
+	USHORT  usFanGainVrMvdd;
+	USHORT  usFanGainPlx;
+	USHORT  usFanGainHbm;
+	USHORT  usReserved;
+} ATOM_Fiji_Fan_Table;
+
+typedef struct _ATOM_Tonga_Thermal_Controller {
+	UCHAR ucRevId;
+	UCHAR ucType;		   /* one of ATOM_TONGA_PP_THERMALCONTROLLER_* */
+	UCHAR ucI2cLine;		/* as interpreted by DAL I2C */
+	UCHAR ucI2cAddress;
+	UCHAR ucFanParameters;	/* Fan Control Parameters. */
+	UCHAR ucFanMinRPM; 	 /* Fan Minimum RPM (hundreds) -- for display purposes only. */
+	UCHAR ucFanMaxRPM; 	 /* Fan Maximum RPM (hundreds) -- for display purposes only. */
+	UCHAR ucReserved;
+	UCHAR ucFlags;		   /* to be defined */
+} ATOM_Tonga_Thermal_Controller;
+
+typedef struct _ATOM_Tonga_VCE_State_Record {
+	UCHAR  ucVCEClockIndex;	/*index into usVCEDependencyTableOffset of 'ATOM_Tonga_MM_Dependency_Table' type */
+	UCHAR  ucFlag;		/* 2 bits indicates memory p-states */
+	UCHAR  ucSCLKIndex;		/*index into ATOM_Tonga_SCLK_Dependency_Table */
+	UCHAR  ucMCLKIndex;		/*index into ATOM_Tonga_MCLK_Dependency_Table */
+} ATOM_Tonga_VCE_State_Record;
+
+typedef struct _ATOM_Tonga_VCE_State_Table {
+	UCHAR ucRevId;
+	UCHAR ucNumEntries;
+	ATOM_Tonga_VCE_State_Record entries[1];
+} ATOM_Tonga_VCE_State_Table;
+
+typedef struct _ATOM_Tonga_PowerTune_Table {
+	UCHAR  ucRevId;
+	USHORT usTDP;
+	USHORT usConfigurableTDP;
+	USHORT usTDC;
+	USHORT usBatteryPowerLimit;
+	USHORT usSmallPowerLimit;
+	USHORT usLowCACLeakage;
+	USHORT usHighCACLeakage;
+	USHORT usMaximumPowerDeliveryLimit;
+	USHORT usTjMax;
+	USHORT usPowerTuneDataSetID;
+	USHORT usEDCLimit;
+	USHORT usSoftwareShutdownTemp;
+	USHORT usClockStretchAmount;
+	USHORT usReserve[2];
+} ATOM_Tonga_PowerTune_Table;
+
+typedef struct _ATOM_Fiji_PowerTune_Table {
+	UCHAR  ucRevId;
+	USHORT usTDP;
+	USHORT usConfigurableTDP;
+	USHORT usTDC;
+	USHORT usBatteryPowerLimit;
+	USHORT usSmallPowerLimit;
+	USHORT usLowCACLeakage;
+	USHORT usHighCACLeakage;
+	USHORT usMaximumPowerDeliveryLimit;
+	USHORT usTjMax;  /* For Fiji, this is also usTemperatureLimitEdge; */
+	USHORT usPowerTuneDataSetID;
+	USHORT usEDCLimit;
+	USHORT usSoftwareShutdownTemp;
+	USHORT usClockStretchAmount;
+	USHORT usTemperatureLimitHotspot;  /*The following are added for Fiji */
+	USHORT usTemperatureLimitLiquid1;
+	USHORT usTemperatureLimitLiquid2;
+	USHORT usTemperatureLimitVrVddc;
+	USHORT usTemperatureLimitVrMvdd;
+	USHORT usTemperatureLimitPlx;
+	UCHAR  ucLiquid1_I2C_address;  /*Liquid */
+	UCHAR  ucLiquid2_I2C_address;
+	UCHAR  ucLiquid_I2C_Line;
+	UCHAR  ucVr_I2C_address;	/*VR */
+	UCHAR  ucVr_I2C_Line;
+	UCHAR  ucPlx_I2C_address;  /*PLX */
+	UCHAR  ucPlx_I2C_Line;
+	USHORT usReserved;
+} ATOM_Fiji_PowerTune_Table;
+
+#define ATOM_PPM_A_A    1
+#define ATOM_PPM_A_I    2
+typedef struct _ATOM_Tonga_PPM_Table {
+	UCHAR   ucRevId;
+	UCHAR   ucPpmDesign;		  /*A+I or A+A */
+	USHORT  usCpuCoreNumber;
+	ULONG  ulPlatformTDP;
+	ULONG  ulSmallACPlatformTDP;
+	ULONG  ulPlatformTDC;
+	ULONG  ulSmallACPlatformTDC;
+	ULONG  ulApuTDP;
+	ULONG  ulDGpuTDP;
+	ULONG  ulDGpuUlvPower;
+	ULONG  ulTjmax;
+} ATOM_Tonga_PPM_Table;
+
+typedef struct _ATOM_Tonga_Hard_Limit_Record {
+	ULONG  ulSCLKLimit;
+	ULONG  ulMCLKLimit;
+	USHORT  usVddcLimit;
+	USHORT  usVddciLimit;
+	USHORT  usVddgfxLimit;
+} ATOM_Tonga_Hard_Limit_Record;
+
+typedef struct _ATOM_Tonga_Hard_Limit_Table {
+	UCHAR ucRevId;
+	UCHAR ucNumEntries;
+	ATOM_Tonga_Hard_Limit_Record entries[1];
+} ATOM_Tonga_Hard_Limit_Table;
+
+typedef struct _ATOM_Tonga_GPIO_Table {
+	UCHAR  ucRevId;
+	UCHAR  ucVRHotTriggeredSclkDpmIndex;		/* If VRHot signal is triggered SCLK will be limited to this DPM level */
+	UCHAR  ucReserve[5];
+} ATOM_Tonga_GPIO_Table;
+
+typedef struct _PPTable_Generic_SubTable_Header {
+	UCHAR  ucRevId;
+} PPTable_Generic_SubTable_Header;
+
+
+#pragma pack(pop)
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c
new file mode 100644
index 0000000..34f4bef
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c
@@ -0,0 +1,1142 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+
+#include "tonga_processpptables.h"
+#include "ppatomctrl.h"
+#include "atombios.h"
+#include "pp_debug.h"
+#include "hwmgr.h"
+#include "cgs_common.h"
+#include "tonga_pptable.h"
+
+/**
+ * Private Function used during initialization.
+ * @param hwmgr Pointer to the hardware manager.
+ * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE).
+ * @param cap Which capability to set/reset.
+ */
+static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap)
+{
+	if (setIt)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
+	else
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
+}
+
+
+/**
+ * Private Function used during initialization.
+ * @param hwmgr Pointer to the hardware manager.
+ * @param powerplay_caps the bit array (from BIOS) of capability bits.
+ * @exception the current implementation always returns 1.
+ */
+static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
+{
+	PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE16____),
+		"ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue);
+	PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE64____),
+		"ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue);
+	PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE512____),
+		"ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue);
+	PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE1024____),
+		"ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue);
+	PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE2048____),
+		"ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue);
+
+	set_hw_cap(
+			hwmgr,
+			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY),
+			PHM_PlatformCaps_PowerPlaySupport
+		  );
+
+	set_hw_cap(
+			hwmgr,
+			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
+			PHM_PlatformCaps_BiosPowerSourceControl
+		  );
+
+	set_hw_cap(
+			hwmgr,
+			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC),
+			PHM_PlatformCaps_AutomaticDCTransition
+		  );
+
+	set_hw_cap(
+			hwmgr,
+			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL),
+			PHM_PlatformCaps_EnableMVDDControl
+		  );
+
+	set_hw_cap(
+			hwmgr,
+			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL),
+			PHM_PlatformCaps_ControlVDDCI
+		  );
+
+	set_hw_cap(
+			hwmgr,
+			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL),
+			PHM_PlatformCaps_ControlVDDGFX
+		  );
+
+	set_hw_cap(
+			hwmgr,
+			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO),
+			PHM_PlatformCaps_BACO
+		  );
+
+	set_hw_cap(
+			hwmgr,
+			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND),
+			PHM_PlatformCaps_DisableVoltageIsland
+		  );
+
+	set_hw_cap(
+			hwmgr,
+			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
+			PHM_PlatformCaps_CombinePCCWithThermalSignal
+		  );
+
+	set_hw_cap(
+			hwmgr,
+			0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
+			PHM_PlatformCaps_LoadPostProductionFirmware
+		  );
+
+	return 0;
+}
+
+/**
+ * Private Function to get the PowerPlay Table Address.
+ */
+const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
+{
+	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
+
+	u16 size;
+	u8 frev, crev;
+	void *table_address;
+
+	table_address = (ATOM_Tonga_POWERPLAYTABLE *)
+		cgs_atom_get_data_table(hwmgr->device, index, &size, &frev, &crev);
+
+	hwmgr->soft_pp_table = table_address;	/*Cache the result in RAM.*/
+
+	return table_address;
+}
+
+static int get_vddc_lookup_table(
+		struct pp_hwmgr	*hwmgr,
+		phm_ppt_v1_voltage_lookup_table	**lookup_table,
+		const ATOM_Tonga_Voltage_Lookup_Table	*vddc_lookup_pp_tables,
+		uint32_t	max_levels
+		)
+{
+	uint32_t table_size, i;
+	phm_ppt_v1_voltage_lookup_table *table;
+
+	PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries),
+		"Invalid CAC Leakage PowerPlay Table!", return 1);
+
+	table_size = sizeof(uint32_t) +
+		sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels;
+
+	table = (phm_ppt_v1_voltage_lookup_table *)
+		kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == table)
+		return -ENOMEM;
+
+	memset(table, 0x00, table_size);
+
+	table->count = vddc_lookup_pp_tables->ucNumEntries;
+
+	for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) {
+		table->entries[i].us_calculated = 0;
+		table->entries[i].us_vdd =
+			vddc_lookup_pp_tables->entries[i].usVdd;
+		table->entries[i].us_cac_low =
+			vddc_lookup_pp_tables->entries[i].usCACLow;
+		table->entries[i].us_cac_mid =
+			vddc_lookup_pp_tables->entries[i].usCACMid;
+		table->entries[i].us_cac_high =
+			vddc_lookup_pp_tables->entries[i].usCACHigh;
+	}
+
+	*lookup_table = table;
+
+	return 0;
+}
+
+/**
+ * Private Function used during initialization.
+ * Initialize Platform Power Management Parameter table
+ * @param hwmgr Pointer to the hardware manager.
+ * @param atom_ppm_table Pointer to PPM table in VBIOS
+ */
+static int get_platform_power_management_table(
+		struct pp_hwmgr *hwmgr,
+		ATOM_Tonga_PPM_Table *atom_ppm_table)
+{
+	struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL);
+	struct phm_ppt_v1_information *pp_table_information =
+		(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (NULL == ptr)
+		return -ENOMEM;
+
+	ptr->ppm_design
+		= atom_ppm_table->ucPpmDesign;
+	ptr->cpu_core_number
+		= atom_ppm_table->usCpuCoreNumber;
+	ptr->platform_tdp
+		= atom_ppm_table->ulPlatformTDP;
+	ptr->small_ac_platform_tdp
+		= atom_ppm_table->ulSmallACPlatformTDP;
+	ptr->platform_tdc
+		= atom_ppm_table->ulPlatformTDC;
+	ptr->small_ac_platform_tdc
+		= atom_ppm_table->ulSmallACPlatformTDC;
+	ptr->apu_tdp
+		= atom_ppm_table->ulApuTDP;
+	ptr->dgpu_tdp
+		= atom_ppm_table->ulDGpuTDP;
+	ptr->dgpu_ulv_power
+		= atom_ppm_table->ulDGpuUlvPower;
+	ptr->tj_max
+		= atom_ppm_table->ulTjmax;
+
+	pp_table_information->ppm_parameter_table = ptr;
+
+	return 0;
+}
+
+/**
+ * Private Function used during initialization.
+ * Initialize TDP limits for DPM2
+ * @param hwmgr Pointer to the hardware manager.
+ * @param powerplay_table Pointer to the PowerPlay Table.
+ */
+static int init_dpm_2_parameters(
+		struct pp_hwmgr *hwmgr,
+		const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
+		)
+{
+	int result = 0;
+	struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	ATOM_Tonga_PPM_Table *atom_ppm_table;
+	uint32_t disable_ppm = 0;
+	uint32_t disable_power_control = 0;
+
+	pp_table_information->us_ulv_voltage_offset =
+		le16_to_cpu(powerplay_table->usUlvVoltageOffset);
+
+	pp_table_information->ppm_parameter_table = NULL;
+	pp_table_information->vddc_lookup_table = NULL;
+	pp_table_information->vddgfx_lookup_table = NULL;
+	/* TDP limits */
+	hwmgr->platform_descriptor.TDPODLimit =
+		le16_to_cpu(powerplay_table->usPowerControlLimit);
+	hwmgr->platform_descriptor.TDPAdjustment = 0;
+	hwmgr->platform_descriptor.VidAdjustment = 0;
+	hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
+	hwmgr->platform_descriptor.VidMinLimit = 0;
+	hwmgr->platform_descriptor.VidMaxLimit = 1500000;
+	hwmgr->platform_descriptor.VidStep = 6250;
+
+	disable_power_control = 0;
+	if (0 == disable_power_control) {
+		/* enable TDP overdrive (PowerControl) feature as well if supported */
+		if (hwmgr->platform_descriptor.TDPODLimit != 0)
+			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PowerControl);
+	}
+
+	if (0 != powerplay_table->usVddcLookupTableOffset) {
+		const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable =
+			(ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) +
+			le16_to_cpu(powerplay_table->usVddcLookupTableOffset));
+
+		result = get_vddc_lookup_table(hwmgr,
+			&pp_table_information->vddc_lookup_table, pVddcCACTable, 16);
+	}
+
+	if (0 != powerplay_table->usVddgfxLookupTableOffset) {
+		const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable =
+			(ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) +
+			le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset));
+
+		result = get_vddc_lookup_table(hwmgr,
+			&pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16);
+	}
+
+	disable_ppm = 0;
+	if (0 == disable_ppm) {
+		atom_ppm_table = (ATOM_Tonga_PPM_Table *)
+			(((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset));
+
+		if (0 != powerplay_table->usPPMTableOffset) {
+			if (1 == get_platform_power_management_table(hwmgr, atom_ppm_table)) {
+				phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_EnablePlatformPowerManagement);
+			}
+		}
+	}
+
+	return result;
+}
+
+static int get_valid_clk(
+		struct pp_hwmgr *hwmgr,
+		struct phm_clock_array **clk_table,
+		const phm_ppt_v1_clock_voltage_dependency_table  * clk_volt_pp_table
+		)
+{
+	uint32_t table_size, i;
+	struct phm_clock_array *table;
+
+	PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count),
+		"Invalid PowerPlay Table!", return -1);
+
+	table_size = sizeof(uint32_t) +
+		sizeof(uint32_t) * clk_volt_pp_table->count;
+
+	table = (struct phm_clock_array *)kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == table)
+		return -ENOMEM;
+
+	memset(table, 0x00, table_size);
+
+	table->count = (uint32_t)clk_volt_pp_table->count;
+
+	for (i = 0; i < table->count; i++)
+		table->values[i] = (uint32_t)clk_volt_pp_table->entries[i].clk;
+
+	*clk_table = table;
+
+	return 0;
+}
+
+static int get_hard_limits(
+		struct pp_hwmgr *hwmgr,
+		struct phm_clock_and_voltage_limits *limits,
+		const ATOM_Tonga_Hard_Limit_Table * limitable
+		)
+{
+	PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1);
+
+	/* currently we always take entries[0] parameters */
+	limits->sclk = (uint32_t)limitable->entries[0].ulSCLKLimit;
+	limits->mclk = (uint32_t)limitable->entries[0].ulMCLKLimit;
+	limits->vddc = (uint16_t)limitable->entries[0].usVddcLimit;
+	limits->vddci = (uint16_t)limitable->entries[0].usVddciLimit;
+	limits->vddgfx = (uint16_t)limitable->entries[0].usVddgfxLimit;
+
+	return 0;
+}
+
+static int get_mclk_voltage_dependency_table(
+		struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table,
+		const ATOM_Tonga_MCLK_Dependency_Table * mclk_dep_table
+		)
+{
+	uint32_t table_size, i;
+	phm_ppt_v1_clock_voltage_dependency_table *mclk_table;
+
+	PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries),
+		"Invalid PowerPlay Table!", return -1);
+
+	table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
+		* mclk_dep_table->ucNumEntries;
+
+	mclk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
+		kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == mclk_table)
+		return -ENOMEM;
+
+	memset(mclk_table, 0x00, table_size);
+
+	mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries;
+
+	for (i = 0; i < mclk_dep_table->ucNumEntries; i++) {
+		mclk_table->entries[i].vddInd =
+			mclk_dep_table->entries[i].ucVddcInd;
+		mclk_table->entries[i].vdd_offset =
+			mclk_dep_table->entries[i].usVddgfxOffset;
+		mclk_table->entries[i].vddci =
+			mclk_dep_table->entries[i].usVddci;
+		mclk_table->entries[i].mvdd =
+			mclk_dep_table->entries[i].usMvdd;
+		mclk_table->entries[i].clk =
+			mclk_dep_table->entries[i].ulMclk;
+	}
+
+	*pp_tonga_mclk_dep_table = mclk_table;
+
+	return 0;
+}
+
+static int get_sclk_voltage_dependency_table(
+		struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table,
+		const ATOM_Tonga_SCLK_Dependency_Table * sclk_dep_table
+		)
+{
+	uint32_t table_size, i;
+	phm_ppt_v1_clock_voltage_dependency_table *sclk_table;
+
+	PP_ASSERT_WITH_CODE((0 != sclk_dep_table->ucNumEntries),
+		"Invalid PowerPlay Table!", return -1);
+
+	table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
+		* sclk_dep_table->ucNumEntries;
+
+	sclk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
+		kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == sclk_table)
+		return -ENOMEM;
+
+	memset(sclk_table, 0x00, table_size);
+
+	sclk_table->count = (uint32_t)sclk_dep_table->ucNumEntries;
+
+	for (i = 0; i < sclk_dep_table->ucNumEntries; i++) {
+		sclk_table->entries[i].vddInd =
+			sclk_dep_table->entries[i].ucVddInd;
+		sclk_table->entries[i].vdd_offset =
+			sclk_dep_table->entries[i].usVddcOffset;
+		sclk_table->entries[i].clk =
+			sclk_dep_table->entries[i].ulSclk;
+		sclk_table->entries[i].cks_enable =
+			(((sclk_dep_table->entries[i].ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
+		sclk_table->entries[i].cks_voffset =
+			(sclk_dep_table->entries[i].ucCKSVOffsetandDisable & 0x7F);
+	}
+
+	*pp_tonga_sclk_dep_table = sclk_table;
+
+	return 0;
+}
+
+static int get_pcie_table(
+		struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_pcie_table **pp_tonga_pcie_table,
+		const ATOM_Tonga_PCIE_Table * atom_pcie_table
+		)
+{
+	uint32_t table_size, i, pcie_count;
+	phm_ppt_v1_pcie_table *pcie_table;
+	struct phm_ppt_v1_information *pp_table_information =
+		(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	PP_ASSERT_WITH_CODE((0 != atom_pcie_table->ucNumEntries),
+		"Invalid PowerPlay Table!", return -1);
+
+	table_size = sizeof(uint32_t) +
+		sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries;
+
+	pcie_table = (phm_ppt_v1_pcie_table *)kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == pcie_table)
+		return -ENOMEM;
+
+	memset(pcie_table, 0x00, table_size);
+
+	/*
+	* Make sure the number of pcie entries are less than or equal to sclk dpm levels.
+	* Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
+	*/
+	pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
+	if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
+		pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
+	else
+		printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
+		Disregarding the excess entries... \n");
+
+	pcie_table->count = pcie_count;
+
+	for (i = 0; i < pcie_count; i++) {
+		pcie_table->entries[i].gen_speed =
+			atom_pcie_table->entries[i].ucPCIEGenSpeed;
+		pcie_table->entries[i].lane_width =
+			atom_pcie_table->entries[i].usPCIELaneWidth;
+	}
+
+	*pp_tonga_pcie_table = pcie_table;
+
+	return 0;
+}
+
+static int get_cac_tdp_table(
+		struct pp_hwmgr *hwmgr,
+		struct phm_cac_tdp_table **cac_tdp_table,
+		const PPTable_Generic_SubTable_Header * table
+		)
+{
+	uint32_t table_size;
+	struct phm_cac_tdp_table *tdp_table;
+
+	table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table);
+	tdp_table = kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == tdp_table)
+		return -ENOMEM;
+
+	memset(tdp_table, 0x00, table_size);
+
+	hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == hwmgr->dyn_state.cac_dtp_table)
+		return -ENOMEM;
+
+	memset(hwmgr->dyn_state.cac_dtp_table, 0x00, table_size);
+
+	if (table->ucRevId < 3) {
+		const ATOM_Tonga_PowerTune_Table *tonga_table =
+			(ATOM_Tonga_PowerTune_Table *)table;
+		tdp_table->usTDP = tonga_table->usTDP;
+		tdp_table->usConfigurableTDP =
+			tonga_table->usConfigurableTDP;
+		tdp_table->usTDC = tonga_table->usTDC;
+		tdp_table->usBatteryPowerLimit =
+			tonga_table->usBatteryPowerLimit;
+		tdp_table->usSmallPowerLimit =
+			tonga_table->usSmallPowerLimit;
+		tdp_table->usLowCACLeakage =
+			tonga_table->usLowCACLeakage;
+		tdp_table->usHighCACLeakage =
+			tonga_table->usHighCACLeakage;
+		tdp_table->usMaximumPowerDeliveryLimit =
+			tonga_table->usMaximumPowerDeliveryLimit;
+		tdp_table->usDefaultTargetOperatingTemp =
+			tonga_table->usTjMax;
+		tdp_table->usTargetOperatingTemp =
+			tonga_table->usTjMax; /*Set the initial temp to the same as default */
+		tdp_table->usPowerTuneDataSetID =
+			tonga_table->usPowerTuneDataSetID;
+		tdp_table->usSoftwareShutdownTemp =
+			tonga_table->usSoftwareShutdownTemp;
+		tdp_table->usClockStretchAmount =
+			tonga_table->usClockStretchAmount;
+	} else {   /* Fiji and newer */
+		const ATOM_Fiji_PowerTune_Table *fijitable =
+			(ATOM_Fiji_PowerTune_Table *)table;
+		tdp_table->usTDP = fijitable->usTDP;
+		tdp_table->usConfigurableTDP = fijitable->usConfigurableTDP;
+		tdp_table->usTDC = fijitable->usTDC;
+		tdp_table->usBatteryPowerLimit = fijitable->usBatteryPowerLimit;
+		tdp_table->usSmallPowerLimit = fijitable->usSmallPowerLimit;
+		tdp_table->usLowCACLeakage = fijitable->usLowCACLeakage;
+		tdp_table->usHighCACLeakage = fijitable->usHighCACLeakage;
+		tdp_table->usMaximumPowerDeliveryLimit =
+			fijitable->usMaximumPowerDeliveryLimit;
+		tdp_table->usDefaultTargetOperatingTemp =
+			fijitable->usTjMax;
+		tdp_table->usTargetOperatingTemp =
+			fijitable->usTjMax; /*Set the initial temp to the same as default */
+		tdp_table->usPowerTuneDataSetID =
+			fijitable->usPowerTuneDataSetID;
+		tdp_table->usSoftwareShutdownTemp =
+			fijitable->usSoftwareShutdownTemp;
+		tdp_table->usClockStretchAmount =
+			fijitable->usClockStretchAmount;
+		tdp_table->usTemperatureLimitHotspot =
+			fijitable->usTemperatureLimitHotspot;
+		tdp_table->usTemperatureLimitLiquid1 =
+			fijitable->usTemperatureLimitLiquid1;
+		tdp_table->usTemperatureLimitLiquid2 =
+			fijitable->usTemperatureLimitLiquid2;
+		tdp_table->usTemperatureLimitVrVddc =
+			fijitable->usTemperatureLimitVrVddc;
+		tdp_table->usTemperatureLimitVrMvdd =
+			fijitable->usTemperatureLimitVrMvdd;
+		tdp_table->usTemperatureLimitPlx =
+			fijitable->usTemperatureLimitPlx;
+		tdp_table->ucLiquid1_I2C_address =
+			fijitable->ucLiquid1_I2C_address;
+		tdp_table->ucLiquid2_I2C_address =
+			fijitable->ucLiquid2_I2C_address;
+		tdp_table->ucLiquid_I2C_Line =
+			fijitable->ucLiquid_I2C_Line;
+		tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address;
+		tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line;
+		tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address;
+		tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line;
+	}
+
+	*cac_tdp_table = tdp_table;
+
+	return 0;
+}
+
+static int get_mm_clock_voltage_table(
+		struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table,
+		const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table
+		)
+{
+	uint32_t table_size, i;
+	const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record;
+	phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table;
+
+	PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries),
+		"Invalid PowerPlay Table!", return -1);
+	table_size = sizeof(uint32_t) +
+		sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record)
+		* mm_dependency_table->ucNumEntries;
+	mm_table = (phm_ppt_v1_mm_clock_voltage_dependency_table *)
+		kzalloc(table_size, GFP_KERNEL);
+
+	if (NULL == mm_table)
+		return -ENOMEM;
+
+	memset(mm_table, 0x00, table_size);
+
+	mm_table->count = mm_dependency_table->ucNumEntries;
+
+	for (i = 0; i < mm_dependency_table->ucNumEntries; i++) {
+		mm_dependency_record = &mm_dependency_table->entries[i];
+		mm_table->entries[i].vddcInd = mm_dependency_record->ucVddcInd;
+		mm_table->entries[i].vddgfx_offset = mm_dependency_record->usVddgfxOffset;
+		mm_table->entries[i].aclk = mm_dependency_record->ulAClk;
+		mm_table->entries[i].samclock = mm_dependency_record->ulSAMUClk;
+		mm_table->entries[i].eclk = mm_dependency_record->ulEClk;
+		mm_table->entries[i].vclk = mm_dependency_record->ulVClk;
+		mm_table->entries[i].dclk = mm_dependency_record->ulDClk;
+	}
+
+	*tonga_mm_table = mm_table;
+
+	return 0;
+}
+
+/**
+ * Private Function used during initialization.
+ * Initialize clock voltage dependency
+ * @param hwmgr Pointer to the hardware manager.
+ * @param powerplay_table Pointer to the PowerPlay Table.
+ */
+static int init_clock_voltage_dependency(
+		struct pp_hwmgr *hwmgr,
+		const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
+		)
+{
+	int result = 0;
+	struct phm_ppt_v1_information *pp_table_information =
+		(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table =
+		(const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) +
+		le16_to_cpu(powerplay_table->usMMDependencyTableOffset));
+	const PPTable_Generic_SubTable_Header *pPowerTuneTable =
+		(const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
+		le16_to_cpu(powerplay_table->usPowerTuneTableOffset));
+	const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
+		(const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) +
+		le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
+	const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table =
+		(const ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long) powerplay_table) +
+		le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
+	const ATOM_Tonga_Hard_Limit_Table *pHardLimits =
+		(const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) +
+		le16_to_cpu(powerplay_table->usHardLimitTableOffset));
+	const ATOM_Tonga_PCIE_Table *pcie_table =
+		(const ATOM_Tonga_PCIE_Table *)(((unsigned long) powerplay_table) +
+		le16_to_cpu(powerplay_table->usPCIETableOffset));
+
+	pp_table_information->vdd_dep_on_sclk = NULL;
+	pp_table_information->vdd_dep_on_mclk = NULL;
+	pp_table_information->mm_dep_table = NULL;
+	pp_table_information->pcie_table = NULL;
+
+	if (powerplay_table->usMMDependencyTableOffset != 0)
+		result = get_mm_clock_voltage_table(hwmgr,
+		&pp_table_information->mm_dep_table, mm_dependency_table);
+
+	if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0)
+		result = get_cac_tdp_table(hwmgr,
+		&pp_table_information->cac_dtp_table, pPowerTuneTable);
+
+	if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0)
+		result = get_sclk_voltage_dependency_table(hwmgr,
+		&pp_table_information->vdd_dep_on_sclk, sclk_dep_table);
+
+	if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0)
+		result = get_mclk_voltage_dependency_table(hwmgr,
+		&pp_table_information->vdd_dep_on_mclk, mclk_dep_table);
+
+	if (result == 0 && powerplay_table->usPCIETableOffset != 0)
+		result = get_pcie_table(hwmgr,
+		&pp_table_information->pcie_table, pcie_table);
+
+	if (result == 0 && powerplay_table->usHardLimitTableOffset != 0)
+		result = get_hard_limits(hwmgr,
+		&pp_table_information->max_clock_voltage_on_dc, pHardLimits);
+
+	hwmgr->dyn_state.max_clock_voltage_on_dc.sclk =
+		pp_table_information->max_clock_voltage_on_dc.sclk;
+	hwmgr->dyn_state.max_clock_voltage_on_dc.mclk =
+		pp_table_information->max_clock_voltage_on_dc.mclk;
+	hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
+		pp_table_information->max_clock_voltage_on_dc.vddc;
+	hwmgr->dyn_state.max_clock_voltage_on_dc.vddci =
+		pp_table_information->max_clock_voltage_on_dc.vddci;
+
+	if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk)
+		&& (0 != pp_table_information->vdd_dep_on_mclk->count))
+		result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values,
+		pp_table_information->vdd_dep_on_mclk);
+
+	if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk)
+		&& (0 != pp_table_information->vdd_dep_on_sclk->count))
+		result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values,
+		pp_table_information->vdd_dep_on_sclk);
+
+	return result;
+}
+
+/** Retrieves the (signed) Overdrive limits from VBIOS.
+ * The max engine clock, memory clock and max temperature come from the firmware info table.
+ *
+ * The information is placed into the platform descriptor.
+ *
+ * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated.
+ * @param powerplay_table the address of the PowerPlay table.
+ *
+ * @return 1 as long as the firmware info table was present and of a supported version.
+ */
+static int init_over_drive_limits(
+		struct pp_hwmgr *hwmgr,
+		const ATOM_Tonga_POWERPLAYTABLE *powerplay_table)
+{
+	hwmgr->platform_descriptor.overdriveLimit.engineClock =
+		le16_to_cpu(powerplay_table->ulMaxODEngineClock);
+	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
+		le16_to_cpu(powerplay_table->ulMaxODMemoryClock);
+
+	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
+	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
+	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
+
+	if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 \
+		&& hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0) {
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ACOverdriveSupport);
+	}
+
+	return 0;
+}
+
+/**
+ * Private Function used during initialization.
+ * Inspect the PowerPlay table for obvious signs of corruption.
+ * @param hwmgr Pointer to the hardware manager.
+ * @param powerplay_table Pointer to the PowerPlay Table.
+ * @exception This implementation always returns 1.
+ */
+static int init_thermal_controller(
+		struct pp_hwmgr *hwmgr,
+		const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
+		)
+{
+	const PPTable_Generic_SubTable_Header *fan_table;
+	ATOM_Tonga_Thermal_Controller *thermal_controller;
+
+	thermal_controller = (ATOM_Tonga_Thermal_Controller *)
+		(((unsigned long)powerplay_table) +
+		le16_to_cpu(powerplay_table->usThermalControllerOffset));
+	PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset),
+		"Thermal controller table not set!", return -1);
+
+	hwmgr->thermal_controller.ucType = thermal_controller->ucType;
+	hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine;
+	hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress;
+
+	hwmgr->thermal_controller.fanInfo.bNoFan =
+		(0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN));
+
+	hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
+		thermal_controller->ucFanParameters &
+		ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
+
+	hwmgr->thermal_controller.fanInfo.ulMinRPM
+		= thermal_controller->ucFanMinRPM * 100UL;
+	hwmgr->thermal_controller.fanInfo.ulMaxRPM
+		= thermal_controller->ucFanMaxRPM * 100UL;
+
+	set_hw_cap(
+			hwmgr,
+			ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
+			PHM_PlatformCaps_ThermalController
+		  );
+
+	if (0 == powerplay_table->usFanTableOffset)
+		return 0;
+
+	fan_table = (const PPTable_Generic_SubTable_Header *)
+		(((unsigned long)powerplay_table) +
+		le16_to_cpu(powerplay_table->usFanTableOffset));
+
+	PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset),
+		"Fan table not set!", return -1);
+	PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId),
+		"Unsupported fan table format!", return -1);
+
+	hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay
+		= 100000;
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_MicrocodeFanControl);
+
+	if (fan_table->ucRevId < 8) {
+		const ATOM_Tonga_Fan_Table *tonga_fan_table =
+			(ATOM_Tonga_Fan_Table *)fan_table;
+		hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
+			= tonga_fan_table->ucTHyst;
+		hwmgr->thermal_controller.advanceFanControlParameters.usTMin
+			= tonga_fan_table->usTMin;
+		hwmgr->thermal_controller.advanceFanControlParameters.usTMed
+			= tonga_fan_table->usTMed;
+		hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
+			= tonga_fan_table->usTHigh;
+		hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
+			= tonga_fan_table->usPWMMin;
+		hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
+			= tonga_fan_table->usPWMMed;
+		hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
+			= tonga_fan_table->usPWMHigh;
+		hwmgr->thermal_controller.advanceFanControlParameters.usTMax
+			= 10900;                  /* hard coded */
+		hwmgr->thermal_controller.advanceFanControlParameters.usTMax
+			= tonga_fan_table->usTMax;
+		hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
+			= tonga_fan_table->ucFanControlMode;
+		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
+			= tonga_fan_table->usFanPWMMax;
+		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
+			= 4836;
+		hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
+			= tonga_fan_table->usFanOutputSensitivity;
+		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
+			= tonga_fan_table->usFanRPMMax;
+		hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
+			= (tonga_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places.  SMC wants MHz. */
+		hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
+			= tonga_fan_table->ucTargetTemperature;
+		hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
+			= tonga_fan_table->ucMinimumPWMLimit;
+	} else {
+		const ATOM_Fiji_Fan_Table *fiji_fan_table =
+			(ATOM_Fiji_Fan_Table *)fan_table;
+		hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
+			= fiji_fan_table->ucTHyst;
+		hwmgr->thermal_controller.advanceFanControlParameters.usTMin
+			= fiji_fan_table->usTMin;
+		hwmgr->thermal_controller.advanceFanControlParameters.usTMed
+			= fiji_fan_table->usTMed;
+		hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
+			= fiji_fan_table->usTHigh;
+		hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
+			= fiji_fan_table->usPWMMin;
+		hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
+			= fiji_fan_table->usPWMMed;
+		hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
+			= fiji_fan_table->usPWMHigh;
+		hwmgr->thermal_controller.advanceFanControlParameters.usTMax
+			= fiji_fan_table->usTMax;
+		hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
+			= fiji_fan_table->ucFanControlMode;
+		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
+			= fiji_fan_table->usFanPWMMax;
+		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
+			= 4836;
+		hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
+			= fiji_fan_table->usFanOutputSensitivity;
+		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
+			= fiji_fan_table->usFanRPMMax;
+		hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
+			= (fiji_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places.  SMC wants MHz. */
+		hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
+			= fiji_fan_table->ucTargetTemperature;
+		hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
+			= fiji_fan_table->ucMinimumPWMLimit;
+
+		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge
+			= fiji_fan_table->usFanGainEdge;
+		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot
+			= fiji_fan_table->usFanGainHotspot;
+		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid
+			= fiji_fan_table->usFanGainLiquid;
+		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc
+			= fiji_fan_table->usFanGainVrVddc;
+		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd
+			= fiji_fan_table->usFanGainVrMvdd;
+		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx
+			= fiji_fan_table->usFanGainPlx;
+		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm
+			= fiji_fan_table->usFanGainHbm;
+	}
+
+	return 0;
+}
+
+/**
+ * Private Function used during initialization.
+ * Inspect the PowerPlay table for obvious signs of corruption.
+ * @param hwmgr Pointer to the hardware manager.
+ * @param powerplay_table Pointer to the PowerPlay Table.
+ * @exception 2 if the powerplay table is incorrect.
+ */
+static int check_powerplay_tables(
+		struct pp_hwmgr *hwmgr,
+		const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
+		)
+{
+	const ATOM_Tonga_State_Array *state_arrays;
+
+	state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)powerplay_table) +
+		le16_to_cpu(powerplay_table->usStateArrayOffset));
+
+	PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA <=
+		powerplay_table->sHeader.ucTableFormatRevision),
+		"Unsupported PPTable format!", return -1);
+	PP_ASSERT_WITH_CODE((0 != powerplay_table->usStateArrayOffset),
+		"State table is not set!", return -1);
+	PP_ASSERT_WITH_CODE((0 < powerplay_table->sHeader.usStructureSize),
+		"Invalid PowerPlay Table!", return -1);
+	PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries),
+		"Invalid PowerPlay Table!", return -1);
+
+	return 0;
+}
+
+int tonga_pp_tables_initialize(struct pp_hwmgr *hwmgr)
+{
+	int result = 0;
+	const ATOM_Tonga_POWERPLAYTABLE *powerplay_table;
+
+	hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL);
+
+	PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable),
+			    "Failed to allocate hwmgr->pptable!", return -ENOMEM);
+
+	memset(hwmgr->pptable, 0x00, sizeof(struct phm_ppt_v1_information));
+
+	powerplay_table = get_powerplay_table(hwmgr);
+
+	PP_ASSERT_WITH_CODE((NULL != powerplay_table),
+		"Missing PowerPlay Table!", return -1);
+
+	result = check_powerplay_tables(hwmgr, powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "check_powerplay_tables failed", return result);
+
+	result = set_platform_caps(hwmgr,
+				   le32_to_cpu(powerplay_table->ulPlatformCaps));
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "set_platform_caps failed", return result);
+
+	result = init_thermal_controller(hwmgr, powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "init_thermal_controller failed", return result);
+
+	result = init_over_drive_limits(hwmgr, powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "init_over_drive_limits failed", return result);
+
+	result = init_clock_voltage_dependency(hwmgr, powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "init_clock_voltage_dependency failed", return result);
+
+	result = init_dpm_2_parameters(hwmgr, powerplay_table);
+
+	PP_ASSERT_WITH_CODE((result == 0),
+			    "init_dpm_2_parameters failed", return result);
+
+	return result;
+}
+
+int tonga_pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
+{
+	int result = 0;
+	struct phm_ppt_v1_information *pp_table_information =
+		(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (NULL != hwmgr->soft_pp_table) {
+		kfree(hwmgr->soft_pp_table);
+		hwmgr->soft_pp_table = NULL;
+	}
+
+	if (NULL != pp_table_information->vdd_dep_on_sclk)
+		pp_table_information->vdd_dep_on_sclk = NULL;
+
+	if (NULL != pp_table_information->vdd_dep_on_mclk)
+		pp_table_information->vdd_dep_on_mclk = NULL;
+
+	if (NULL != pp_table_information->valid_mclk_values)
+		pp_table_information->valid_mclk_values = NULL;
+
+	if (NULL != pp_table_information->valid_sclk_values)
+		pp_table_information->valid_sclk_values = NULL;
+
+	if (NULL != pp_table_information->vddc_lookup_table)
+		pp_table_information->vddc_lookup_table = NULL;
+
+	if (NULL != pp_table_information->vddgfx_lookup_table)
+		pp_table_information->vddgfx_lookup_table = NULL;
+
+	if (NULL != pp_table_information->mm_dep_table)
+		pp_table_information->mm_dep_table = NULL;
+
+	if (NULL != pp_table_information->cac_dtp_table)
+		pp_table_information->cac_dtp_table = NULL;
+
+	if (NULL != hwmgr->dyn_state.cac_dtp_table)
+		hwmgr->dyn_state.cac_dtp_table = NULL;
+
+	if (NULL != pp_table_information->ppm_parameter_table)
+		pp_table_information->ppm_parameter_table = NULL;
+
+	if (NULL != pp_table_information->pcie_table)
+		pp_table_information->pcie_table = NULL;
+
+	if (NULL != hwmgr->pptable) {
+		kfree(hwmgr->pptable);
+		hwmgr->pptable = NULL;
+	}
+
+	return result;
+}
+
+const struct pp_table_func tonga_pptable_funcs = {
+	.pptable_init = tonga_pp_tables_initialize,
+	.pptable_fini = tonga_pp_tables_uninitialize,
+};
+
+int tonga_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr)
+{
+	const ATOM_Tonga_State_Array * state_arrays;
+	const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
+
+	PP_ASSERT_WITH_CODE((NULL != pp_table),
+			"Missing PowerPlay Table!", return -1);
+	PP_ASSERT_WITH_CODE((pp_table->sHeader.ucTableFormatRevision >=
+			ATOM_Tonga_TABLE_REVISION_TONGA),
+			"Incorrect PowerPlay table revision!", return -1);
+
+	state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) +
+			le16_to_cpu(pp_table->usStateArrayOffset));
+
+	return (uint32_t)(state_arrays->ucNumEntries);
+}
+
+/**
+* Private function to convert flags stored in the BIOS to software flags in PowerPlay.
+*/
+static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr,
+		uint16_t classification, uint16_t classification2)
+{
+	uint32_t result = 0;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
+		result |= PP_StateClassificationFlag_Boot;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
+		result |= PP_StateClassificationFlag_Thermal;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
+		result |= PP_StateClassificationFlag_LimitedPowerSource;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
+		result |= PP_StateClassificationFlag_Rest;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
+		result |= PP_StateClassificationFlag_Forced;
+
+	if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
+		result |= PP_StateClassificationFlag_ACPI;
+
+	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
+		result |= PP_StateClassificationFlag_LimitedPowerSource_2;
+
+	return result;
+}
+
+/**
+* Create a Power State out of an entry in the PowerPlay table.
+* This function is called by the hardware back-end.
+* @param hwmgr Pointer to the hardware manager.
+* @param entry_index The index of the entry to be extracted from the table.
+* @param power_state The address of the PowerState instance being created.
+* @return -1 if the entry cannot be retrieved.
+*/
+int tonga_get_powerplay_table_entry(struct pp_hwmgr *hwmgr,
+		uint32_t entry_index, struct pp_power_state *power_state,
+		int (*call_back_func)(struct pp_hwmgr *, void *,
+				struct pp_power_state *, void *, uint32_t))
+{
+	int result = 0;
+	const ATOM_Tonga_State_Array * state_arrays;
+	const ATOM_Tonga_State *state_entry;
+	const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
+
+	PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;);
+	power_state->classification.bios_index = entry_index;
+
+	if (pp_table->sHeader.ucTableFormatRevision >=
+			ATOM_Tonga_TABLE_REVISION_TONGA) {
+		state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) +
+				le16_to_cpu(pp_table->usStateArrayOffset));
+
+		PP_ASSERT_WITH_CODE((0 < pp_table->usStateArrayOffset),
+				"Invalid PowerPlay Table State Array Offset.", return -1);
+		PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries),
+				"Invalid PowerPlay Table State Array.", return -1);
+		PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries),
+				"Invalid PowerPlay Table State Array Entry.", return -1);
+
+		state_entry = &(state_arrays->states[entry_index]);
+
+		result = call_back_func(hwmgr, (void *)state_entry, power_state,
+				(void *)pp_table,
+				make_classification_flags(hwmgr,
+					le16_to_cpu(state_entry->usClassification),
+					le16_to_cpu(state_entry->usClassification2)));
+	}
+
+	if (!result && (power_state->classification.flags &
+			PP_StateClassificationFlag_Boot))
+		result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware));
+
+	return result;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.h
new file mode 100644
index 0000000..d24b888
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef TONGA_PROCESSPPTABLES_H
+#define TONGA_PROCESSPPTABLES_H
+
+#include "hwmgr.h"
+
+extern const struct pp_table_func tonga_pptable_funcs;
+extern int tonga_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr);
+extern int tonga_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, uint32_t entry_index,
+		struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *,
+				struct pp_power_state *, void *, uint32_t));
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.c
new file mode 100644
index 0000000..a188174
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.c
@@ -0,0 +1,590 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <asm/div64.h>
+#include "tonga_thermal.h"
+#include "tonga_hwmgr.h"
+#include "tonga_smumgr.h"
+#include "tonga_ppsmc.h"
+#include "smu/smu_7_1_2_d.h"
+#include "smu/smu_7_1_2_sh_mask.h"
+
+/**
+* Get Fan Speed Control Parameters.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pSpeed is the address of the structure where the result is to be placed.
+* @exception Always succeeds except if we cannot zero out the output structure.
+*/
+int tonga_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info)
+{
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	fan_speed_info->supports_percent_read = true;
+	fan_speed_info->supports_percent_write = true;
+	fan_speed_info->min_percent = 0;
+	fan_speed_info->max_percent = 100;
+
+	if (0 != hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) {
+		fan_speed_info->supports_rpm_read = true;
+		fan_speed_info->supports_rpm_write = true;
+		fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM;
+		fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM;
+	} else {
+		fan_speed_info->min_rpm = 0;
+		fan_speed_info->max_rpm = 0;
+	}
+
+	return 0;
+}
+
+/**
+* Get Fan Speed in percent.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pSpeed is the address of the structure where the result is to be placed.
+* @exception Fails is the 100% setting appears to be 0.
+*/
+int tonga_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed)
+{
+	uint32_t duty100;
+	uint32_t duty;
+	uint64_t tmp64;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100);
+	duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_STATUS, FDO_PWM_DUTY);
+
+	if (0 == duty100)
+		return -EINVAL;
+
+
+	tmp64 = (uint64_t)duty * 100;
+	do_div(tmp64, duty100);
+	*speed = (uint32_t)tmp64;
+
+	if (*speed > 100)
+		*speed = 100;
+
+	return 0;
+}
+
+/**
+* Get Fan Speed in RPM.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    speed is the address of the structure where the result is to be placed.
+* @exception Returns not supported if no fan is found or if pulses per revolution are not set
+*/
+int tonga_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
+{
+	return 0;
+}
+
+/**
+* Set Fan Speed Control to static mode, so that the user can decide what speed to use.
+* @param    hwmgr  the address of the powerplay hardware manager.
+*           mode    the fan control mode, 0 default, 1 by percent, 5, by RPM
+* @exception Should always succeed.
+*/
+int tonga_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
+{
+
+	if (hwmgr->fan_ctrl_is_in_default_mode) {
+		hwmgr->fan_ctrl_default_mode = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, FDO_PWM_MODE);
+		hwmgr->tmin = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TMIN);
+		hwmgr->fan_ctrl_is_in_default_mode = false;
+	}
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TMIN, 0);
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, FDO_PWM_MODE, mode);
+
+	return 0;
+}
+
+/**
+* Reset Fan Speed Control to default mode.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @exception Should always succeed.
+*/
+int tonga_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
+{
+	if (!hwmgr->fan_ctrl_is_in_default_mode) {
+		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode);
+		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TMIN, hwmgr->tmin);
+		hwmgr->fan_ctrl_is_in_default_mode = true;
+	}
+
+	return 0;
+}
+
+int tonga_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
+{
+	int result;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ODFuzzyFanControlSupport)) {
+		cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_FUZZY);
+		result = (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl) == 0) ?  0 : -EINVAL;
+/*
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_FanSpeedInTableIsRPM))
+			hwmgr->set_max_fan_rpm_output(hwmgr, hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM);
+		else
+			hwmgr->set_max_fan_pwm_output(hwmgr, hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM);
+*/
+	} else {
+		cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_TABLE);
+		result = (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl) == 0) ?  0 : -EINVAL;
+	}
+/* TO DO FOR SOME DEVICE ID 0X692b, send this msg return invalid command.
+	if (result == 0 && hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature != 0)
+		result = (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanTemperatureTarget, \
+								hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature) ? 0 : -EINVAL);
+*/
+	return result;
+}
+
+
+int tonga_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
+{
+	return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl) == 0) ?  0 : -EINVAL;
+}
+
+/**
+* Set Fan Speed in percent.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    speed is the percentage value (0% - 100%) to be set.
+* @exception Fails is the 100% setting appears to be 0.
+*/
+int tonga_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed)
+{
+	uint32_t duty100;
+	uint32_t duty;
+	uint64_t tmp64;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return -EINVAL;
+
+	if (speed > 100)
+		speed = 100;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl))
+		tonga_fan_ctrl_stop_smc_fan_control(hwmgr);
+
+	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100);
+
+	if (0 == duty100)
+		return -EINVAL;
+
+	tmp64 = (uint64_t)speed * 100;
+	do_div(tmp64, duty100);
+	duty = (uint32_t)tmp64;
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL0, FDO_STATIC_DUTY, duty);
+
+	return tonga_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+}
+
+/**
+* Reset Fan Speed to default.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @exception Always succeeds.
+*/
+int tonga_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
+{
+	int result;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) {
+		result = tonga_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+		if (0 == result)
+			result = tonga_fan_ctrl_start_smc_fan_control(hwmgr);
+	} else
+		result = tonga_fan_ctrl_set_default_mode(hwmgr);
+
+	return result;
+}
+
+/**
+* Set Fan Speed in RPM.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    speed is the percentage value (min - max) to be set.
+* @exception Fails is the speed not lie between min and max.
+*/
+int tonga_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
+{
+	return 0;
+}
+
+/**
+* Reads the remote temperature from the SIslands thermal controller.
+*
+* @param    hwmgr The address of the hardware manager.
+*/
+int tonga_thermal_get_temperature(struct pp_hwmgr *hwmgr)
+{
+	int temp;
+
+	temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_STATUS, CTF_TEMP);
+
+/* Bit 9 means the reading is lower than the lowest usable value. */
+	if (0 != (0x200 & temp))
+		temp = TONGA_THERMAL_MAXIMUM_TEMP_READING;
+	else
+		temp = (temp & 0x1ff);
+
+	temp = temp * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+	return temp;
+}
+
+/**
+* Set the requested temperature range for high and low alert signals
+*
+* @param    hwmgr The address of the hardware manager.
+* @param    range Temperature range to be programmed for high and low alert signals
+* @exception PP_Result_BadInput if the input data is not valid.
+*/
+static int tonga_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, uint32_t low_temp, uint32_t high_temp)
+{
+	uint32_t low = TONGA_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+	uint32_t high = TONGA_THERMAL_MAXIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+	if (low < low_temp)
+		low = low_temp;
+	if (high > high_temp)
+		high = high_temp;
+
+	if (low > high)
+		return -EINVAL;
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL, DIG_THERM_DPM, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+
+	return 0;
+}
+
+/**
+* Programs thermal controller one-time setting registers
+*
+* @param    hwmgr The address of the hardware manager.
+*/
+static int tonga_thermal_initialize(struct pp_hwmgr *hwmgr)
+{
+	if (0 != hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution)
+		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+						CG_TACH_CTRL, EDGE_PER_REV,
+						hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution - 1);
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28);
+
+	return 0;
+}
+
+/**
+* Enable thermal alerts on the RV770 thermal controller.
+*
+* @param    hwmgr The address of the hardware manager.
+*/
+static int tonga_thermal_enable_alert(struct pp_hwmgr *hwmgr)
+{
+	uint32_t alert;
+
+	alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK);
+	alert &= ~(TONGA_THERMAL_HIGH_ALERT_MASK | TONGA_THERMAL_LOW_ALERT_MASK);
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK, alert);
+
+	/* send message to SMU to enable internal thermal interrupts */
+	return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Enable) == 0) ? 0 : -1;
+}
+
+/**
+* Disable thermal alerts on the RV770 thermal controller.
+* @param    hwmgr The address of the hardware manager.
+*/
+static int tonga_thermal_disable_alert(struct pp_hwmgr *hwmgr)
+{
+	uint32_t alert;
+
+	alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK);
+	alert |= (TONGA_THERMAL_HIGH_ALERT_MASK | TONGA_THERMAL_LOW_ALERT_MASK);
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK, alert);
+
+	/* send message to SMU to disable internal thermal interrupts */
+	return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Disable) == 0) ? 0 : -1;
+}
+
+/**
+* Uninitialize the thermal controller.
+* Currently just disables alerts.
+* @param    hwmgr The address of the hardware manager.
+*/
+int tonga_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
+{
+	int result = tonga_thermal_disable_alert(hwmgr);
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		tonga_fan_ctrl_set_default_mode(hwmgr);
+
+	return result;
+}
+
+/**
+* Set up the fan table to control the fan using the SMC.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from set temperature range routine
+*/
+int tf_tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result)
+{
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+	SMU72_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
+	uint32_t duty100;
+	uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
+	uint16_t fdo_min, slope1, slope2;
+	uint32_t reference_clock;
+	int res;
+	uint64_t tmp64;
+
+	if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl))
+		return 0;
+
+	if (0 == data->fan_table_start) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
+		return 0;
+	}
+
+	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100);
+
+	if (0 == duty100) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
+		return 0;
+	}
+
+	tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100;
+	do_div(tmp64, 10000);
+	fdo_min = (uint16_t)tmp64;
+
+	t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
+	t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
+
+	pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
+	pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
+
+	slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
+	slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
+
+	fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100);
+	fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100);
+	fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100);
+
+	fan_table.Slope1 = cpu_to_be16(slope1);
+	fan_table.Slope2 = cpu_to_be16(slope2);
+
+	fan_table.FdoMin = cpu_to_be16(fdo_min);
+
+	fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst);
+
+	fan_table.HystUp = cpu_to_be16(1);
+
+	fan_table.HystSlope = cpu_to_be16(1);
+
+	fan_table.TempRespLim = cpu_to_be16(5);
+
+	reference_clock = tonga_get_xclk(hwmgr);
+
+	fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600);
+
+	fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
+
+	fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL);
+
+	fan_table.FanControl_GL_Flag = 1;
+
+	res = tonga_copy_bytes_to_smc(hwmgr->smumgr, data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), data->sram_end);
+/* TO DO FOR SOME DEVICE ID 0X692b, send this msg return invalid command.
+	if (res == 0 && hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit != 0)
+		res = (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanMinPwm, \
+						hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit) ? 0 : -1);
+
+	if (res == 0 && hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit != 0)
+		res = (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanSclkTarget, \
+					hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit) ? 0 : -1);
+
+	if (0 != res)
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
+*/
+	return 0;
+}
+
+/**
+* Start the fan control on the SMC.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from set temperature range routine
+*/
+int tf_tonga_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result)
+{
+/* If the fantable setup has failed we could have disabled PHM_PlatformCaps_MicrocodeFanControl even after this function was included in the table.
+ * Make sure that we still think controlling the fan is OK.
+*/
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) {
+		tonga_fan_ctrl_start_smc_fan_control(hwmgr);
+		tonga_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+	}
+
+	return 0;
+}
+
+/**
+* Set temperature range for high and low alerts
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from set temperature range routine
+*/
+int tf_tonga_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result)
+{
+	struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input;
+
+	if (range == NULL)
+		return -EINVAL;
+
+	return tonga_thermal_set_temperature_range(hwmgr, range->min, range->max);
+}
+
+/**
+* Programs one-time setting registers
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from initialize thermal controller routine
+*/
+int tf_tonga_thermal_initialize(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result)
+{
+    return tonga_thermal_initialize(hwmgr);
+}
+
+/**
+* Enable high and low alerts
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from enable alert routine
+*/
+int tf_tonga_thermal_enable_alert(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result)
+{
+	return tonga_thermal_enable_alert(hwmgr);
+}
+
+/**
+* Disable high and low alerts
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from disable alert routine
+*/
+static int tf_tonga_thermal_disable_alert(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result)
+{
+	return tonga_thermal_disable_alert(hwmgr);
+}
+
+static struct phm_master_table_item tonga_thermal_start_thermal_controller_master_list[] = {
+	{ NULL, tf_tonga_thermal_initialize },
+	{ NULL, tf_tonga_thermal_set_temperature_range },
+	{ NULL, tf_tonga_thermal_enable_alert },
+/* We should restrict performance levels to low before we halt the SMC.
+ * On the other hand we are still in boot state when we do this so it would be pointless.
+ * If this assumption changes we have to revisit this table.
+ */
+	{ NULL, tf_tonga_thermal_setup_fan_table},
+	{ NULL, tf_tonga_thermal_start_smc_fan_control},
+	{ NULL, NULL }
+};
+
+static struct phm_master_table_header tonga_thermal_start_thermal_controller_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	tonga_thermal_start_thermal_controller_master_list
+};
+
+static struct phm_master_table_item tonga_thermal_set_temperature_range_master_list[] = {
+	{ NULL, tf_tonga_thermal_disable_alert},
+	{ NULL, tf_tonga_thermal_set_temperature_range},
+	{ NULL, tf_tonga_thermal_enable_alert},
+	{ NULL, NULL }
+};
+
+struct phm_master_table_header tonga_thermal_set_temperature_range_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	tonga_thermal_set_temperature_range_master_list
+};
+
+int tonga_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
+{
+	if (!hwmgr->thermal_controller.fanInfo.bNoFan)
+		tonga_fan_ctrl_set_default_mode(hwmgr);
+	return 0;
+}
+
+/**
+* Initializes the thermal controller related functions in the Hardware Manager structure.
+* @param    hwmgr The address of the hardware manager.
+* @exception Any error code from the low-level communication.
+*/
+int pp_tonga_thermal_initialize(struct pp_hwmgr *hwmgr)
+{
+	int result;
+
+	result = phm_construct_table(hwmgr, &tonga_thermal_set_temperature_range_master, &(hwmgr->set_temperature_range));
+
+	if (0 == result) {
+		result = phm_construct_table(hwmgr,
+						&tonga_thermal_start_thermal_controller_master,
+						&(hwmgr->start_thermal_controller));
+		if (0 != result)
+			phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range));
+	}
+
+	if (0 == result)
+		hwmgr->fan_ctrl_is_in_default_mode = true;
+	return result;
+}
+
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.h
new file mode 100644
index 0000000..aa335f2
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef TONGA_THERMAL_H
+#define TONGA_THERMAL_H
+
+#include "hwmgr.h"
+
+#define TONGA_THERMAL_HIGH_ALERT_MASK         0x1
+#define TONGA_THERMAL_LOW_ALERT_MASK          0x2
+
+#define TONGA_THERMAL_MINIMUM_TEMP_READING    -256
+#define TONGA_THERMAL_MAXIMUM_TEMP_READING    255
+
+#define TONGA_THERMAL_MINIMUM_ALERT_TEMP      0
+#define TONGA_THERMAL_MAXIMUM_ALERT_TEMP      255
+
+#define FDO_PWM_MODE_STATIC  1
+#define FDO_PWM_MODE_STATIC_RPM 5
+
+
+extern int tf_tonga_thermal_initialize(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result);
+extern int tf_tonga_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result);
+extern int tf_tonga_thermal_enable_alert(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result);
+
+extern int tonga_thermal_get_temperature(struct pp_hwmgr *hwmgr);
+extern int tonga_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
+extern int tonga_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info);
+extern int tonga_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed);
+extern int tonga_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr);
+extern int tonga_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode);
+extern int tonga_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed);
+extern int tonga_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr);
+extern int pp_tonga_thermal_initialize(struct pp_hwmgr *hwmgr);
+extern int tonga_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr);
+extern int tonga_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed);
+extern int tonga_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed);
+extern int tonga_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
new file mode 100644
index 0000000..e61a3e6
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _AMD_POWERPLAY_H_
+#define _AMD_POWERPLAY_H_
+
+#include <linux/seq_file.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include "amd_shared.h"
+#include "cgs_common.h"
+
+enum amd_pp_event {
+	AMD_PP_EVENT_INITIALIZE = 0,
+	AMD_PP_EVENT_UNINITIALIZE,
+	AMD_PP_EVENT_POWER_SOURCE_CHANGE,
+	AMD_PP_EVENT_SUSPEND,
+	AMD_PP_EVENT_RESUME,
+	AMD_PP_EVENT_ENTER_REST_STATE,
+	AMD_PP_EVENT_EXIT_REST_STATE,
+	AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE,
+	AMD_PP_EVENT_THERMAL_NOTIFICATION,
+	AMD_PP_EVENT_VBIOS_NOTIFICATION,
+	AMD_PP_EVENT_ENTER_THERMAL_STATE,
+	AMD_PP_EVENT_EXIT_THERMAL_STATE,
+	AMD_PP_EVENT_ENTER_FORCED_STATE,
+	AMD_PP_EVENT_EXIT_FORCED_STATE,
+	AMD_PP_EVENT_ENTER_EXCLUSIVE_MODE,
+	AMD_PP_EVENT_EXIT_EXCLUSIVE_MODE,
+	AMD_PP_EVENT_ENTER_SCREEN_SAVER,
+	AMD_PP_EVENT_EXIT_SCREEN_SAVER,
+	AMD_PP_EVENT_VPU_RECOVERY_BEGIN,
+	AMD_PP_EVENT_VPU_RECOVERY_END,
+	AMD_PP_EVENT_ENABLE_POWER_PLAY,
+	AMD_PP_EVENT_DISABLE_POWER_PLAY,
+	AMD_PP_EVENT_CHANGE_POWER_SOURCE_UI_LABEL,
+	AMD_PP_EVENT_ENABLE_USER2D_PERFORMANCE,
+	AMD_PP_EVENT_DISABLE_USER2D_PERFORMANCE,
+	AMD_PP_EVENT_ENABLE_USER3D_PERFORMANCE,
+	AMD_PP_EVENT_DISABLE_USER3D_PERFORMANCE,
+	AMD_PP_EVENT_ENABLE_OVER_DRIVE_TEST,
+	AMD_PP_EVENT_DISABLE_OVER_DRIVE_TEST,
+	AMD_PP_EVENT_ENABLE_REDUCED_REFRESH_RATE,
+	AMD_PP_EVENT_DISABLE_REDUCED_REFRESH_RATE,
+	AMD_PP_EVENT_ENABLE_GFX_CLOCK_GATING,
+	AMD_PP_EVENT_DISABLE_GFX_CLOCK_GATING,
+	AMD_PP_EVENT_ENABLE_CGPG,
+	AMD_PP_EVENT_DISABLE_CGPG,
+	AMD_PP_EVENT_ENTER_TEXT_MODE,
+	AMD_PP_EVENT_EXIT_TEXT_MODE,
+	AMD_PP_EVENT_VIDEO_START,
+	AMD_PP_EVENT_VIDEO_STOP,
+	AMD_PP_EVENT_ENABLE_USER_STATE,
+	AMD_PP_EVENT_DISABLE_USER_STATE,
+	AMD_PP_EVENT_READJUST_POWER_STATE,
+	AMD_PP_EVENT_START_INACTIVITY,
+	AMD_PP_EVENT_STOP_INACTIVITY,
+	AMD_PP_EVENT_LINKED_ADAPTERS_READY,
+	AMD_PP_EVENT_ADAPTER_SAFE_TO_DISABLE,
+	AMD_PP_EVENT_COMPLETE_INIT,
+	AMD_PP_EVENT_CRITICAL_THERMAL_FAULT,
+	AMD_PP_EVENT_BACKLIGHT_CHANGED,
+	AMD_PP_EVENT_ENABLE_VARI_BRIGHT,
+	AMD_PP_EVENT_DISABLE_VARI_BRIGHT,
+	AMD_PP_EVENT_ENABLE_VARI_BRIGHT_ON_POWER_XPRESS,
+	AMD_PP_EVENT_DISABLE_VARI_BRIGHT_ON_POWER_XPRESS,
+	AMD_PP_EVENT_SET_VARI_BRIGHT_LEVEL,
+	AMD_PP_EVENT_VARI_BRIGHT_MONITOR_MEASUREMENT,
+	AMD_PP_EVENT_SCREEN_ON,
+	AMD_PP_EVENT_SCREEN_OFF,
+	AMD_PP_EVENT_PRE_DISPLAY_CONFIG_CHANGE,
+	AMD_PP_EVENT_ENTER_ULP_STATE,
+	AMD_PP_EVENT_EXIT_ULP_STATE,
+	AMD_PP_EVENT_REGISTER_IP_STATE,
+	AMD_PP_EVENT_UNREGISTER_IP_STATE,
+	AMD_PP_EVENT_ENTER_MGPU_MODE,
+	AMD_PP_EVENT_EXIT_MGPU_MODE,
+	AMD_PP_EVENT_ENTER_MULTI_GPU_MODE,
+	AMD_PP_EVENT_PRE_SUSPEND,
+	AMD_PP_EVENT_PRE_RESUME,
+	AMD_PP_EVENT_ENTER_BACOS,
+	AMD_PP_EVENT_EXIT_BACOS,
+	AMD_PP_EVENT_RESUME_BACO,
+	AMD_PP_EVENT_RESET_BACO,
+	AMD_PP_EVENT_PRE_DISPLAY_PHY_ACCESS,
+	AMD_PP_EVENT_POST_DISPLAY_PHY_CCESS,
+	AMD_PP_EVENT_START_COMPUTE_APPLICATION,
+	AMD_PP_EVENT_STOP_COMPUTE_APPLICATION,
+	AMD_PP_EVENT_REDUCE_POWER_LIMIT,
+	AMD_PP_EVENT_ENTER_FRAME_LOCK,
+	AMD_PP_EVENT_EXIT_FRAME_LOOCK,
+	AMD_PP_EVENT_LONG_IDLE_REQUEST_BACO,
+	AMD_PP_EVENT_LONG_IDLE_ENTER_BACO,
+	AMD_PP_EVENT_LONG_IDLE_EXIT_BACO,
+	AMD_PP_EVENT_HIBERNATE,
+	AMD_PP_EVENT_CONNECTED_STANDBY,
+	AMD_PP_EVENT_ENTER_SELF_REFRESH,
+	AMD_PP_EVENT_EXIT_SELF_REFRESH,
+	AMD_PP_EVENT_START_AVFS_BTC,
+	AMD_PP_EVENT_MAX
+};
+
+enum amd_dpm_forced_level {
+	AMD_DPM_FORCED_LEVEL_AUTO = 0,
+	AMD_DPM_FORCED_LEVEL_LOW = 1,
+	AMD_DPM_FORCED_LEVEL_HIGH = 2,
+};
+
+struct amd_pp_init {
+	struct cgs_device *device;
+	uint32_t chip_family;
+	uint32_t chip_id;
+	uint32_t rev_id;
+};
+enum amd_pp_display_config_type{
+	AMD_PP_DisplayConfigType_None = 0,
+	AMD_PP_DisplayConfigType_DP54 ,
+	AMD_PP_DisplayConfigType_DP432 ,
+	AMD_PP_DisplayConfigType_DP324 ,
+	AMD_PP_DisplayConfigType_DP27,
+	AMD_PP_DisplayConfigType_DP243,
+	AMD_PP_DisplayConfigType_DP216,
+	AMD_PP_DisplayConfigType_DP162,
+	AMD_PP_DisplayConfigType_HDMI6G ,
+	AMD_PP_DisplayConfigType_HDMI297 ,
+	AMD_PP_DisplayConfigType_HDMI162,
+	AMD_PP_DisplayConfigType_LVDS,
+	AMD_PP_DisplayConfigType_DVI,
+	AMD_PP_DisplayConfigType_WIRELESS,
+	AMD_PP_DisplayConfigType_VGA
+};
+
+struct single_display_configuration
+{
+	uint32_t controller_index;
+	uint32_t controller_id;
+	uint32_t signal_type;
+	uint32_t display_state;
+	/* phy id for the primary internal transmitter */
+	uint8_t primary_transmitter_phyi_d;
+	/* bitmap with the active lanes */
+	uint8_t primary_transmitter_active_lanemap;
+	/* phy id for the secondary internal transmitter (for dual-link dvi) */
+	uint8_t secondary_transmitter_phy_id;
+	/* bitmap with the active lanes */
+	uint8_t secondary_transmitter_active_lanemap;
+	/* misc phy settings for SMU. */
+	uint32_t config_flags;
+	uint32_t display_type;
+	uint32_t view_resolution_cx;
+	uint32_t view_resolution_cy;
+	enum amd_pp_display_config_type displayconfigtype;
+	uint32_t vertical_refresh; /* for active display */
+};
+
+#define MAX_NUM_DISPLAY 32
+
+struct amd_pp_display_configuration {
+	bool nb_pstate_switch_disable;/* controls NB PState switch */
+	bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */
+	bool cpu_pstate_disable;
+	uint32_t cpu_pstate_separation_time;
+
+	uint32_t num_display;  /* total number of display*/
+	uint32_t num_path_including_non_display;
+	uint32_t crossfire_display_index;
+	uint32_t min_mem_set_clock;
+	uint32_t min_core_set_clock;
+	/* unit 10KHz x bit*/
+	uint32_t min_bus_bandwidth;
+	/* minimum required stutter sclk, in 10khz uint32_t ulMinCoreSetClk;*/
+	uint32_t min_core_set_clock_in_sr;
+
+	struct single_display_configuration displays[MAX_NUM_DISPLAY];
+
+	uint32_t vrefresh; /* for active display*/
+
+	uint32_t min_vblank_time; /* for active display*/
+	bool multi_monitor_in_sync;
+	/* Controller Index of primary display - used in MCLK SMC switching hang
+	 * SW Workaround*/
+	uint32_t crtc_index;
+	/* htotal*1000/pixelclk - used in MCLK SMC switching hang SW Workaround*/
+	uint32_t line_time_in_us;
+	bool invalid_vblank_time;
+
+	uint32_t display_clk;
+	/*
+	 * for given display configuration if multimonitormnsync == false then
+	 * Memory clock DPMS with this latency or below is allowed, DPMS with
+	 * higher latency not allowed.
+	 */
+	uint32_t dce_tolerable_mclk_in_active_latency;
+};
+
+struct amd_pp_dal_clock_info {
+	uint32_t	engine_max_clock;
+	uint32_t	memory_max_clock;
+	uint32_t	level;
+};
+
+enum {
+	PP_GROUP_UNKNOWN = 0,
+	PP_GROUP_GFX = 1,
+	PP_GROUP_SYS,
+	PP_GROUP_MAX
+};
+
+#define PP_GROUP_MASK        0xF0000000
+#define PP_GROUP_SHIFT       28
+
+#define PP_BLOCK_MASK        0x0FFFFF00
+#define PP_BLOCK_SHIFT       8
+
+#define PP_BLOCK_GFX_CG         0x01
+#define PP_BLOCK_GFX_MG         0x02
+#define PP_BLOCK_SYS_BIF        0x01
+#define PP_BLOCK_SYS_MC         0x02
+#define PP_BLOCK_SYS_ROM        0x04
+#define PP_BLOCK_SYS_DRM        0x08
+#define PP_BLOCK_SYS_HDP        0x10
+#define PP_BLOCK_SYS_SDMA       0x20
+
+#define PP_STATE_MASK           0x0000000F
+#define PP_STATE_SHIFT          0
+#define PP_STATE_SUPPORT_MASK   0x000000F0
+#define PP_STATE_SUPPORT_SHIFT  0
+
+#define PP_STATE_CG             0x01
+#define PP_STATE_LS             0x02
+#define PP_STATE_DS             0x04
+#define PP_STATE_SD             0x08
+#define PP_STATE_SUPPORT_CG     0x10
+#define PP_STATE_SUPPORT_LS     0x20
+#define PP_STATE_SUPPORT_DS     0x40
+#define PP_STATE_SUPPORT_SD     0x80
+
+#define PP_CG_MSG_ID(group, block, support, state) (group << PP_GROUP_SHIFT |\
+								block << PP_BLOCK_SHIFT |\
+								support << PP_STATE_SUPPORT_SHIFT |\
+								state << PP_STATE_SHIFT)
+
+struct amd_powerplay_funcs {
+	int (*get_temperature)(void *handle);
+	int (*load_firmware)(void *handle);
+	int (*wait_for_fw_loading_complete)(void *handle);
+	int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level);
+	enum amd_dpm_forced_level (*get_performance_level)(void *handle);
+	enum amd_pm_state_type (*get_current_power_state)(void *handle);
+	int (*get_sclk)(void *handle, bool low);
+	int (*get_mclk)(void *handle, bool low);
+	int (*powergate_vce)(void *handle, bool gate);
+	int (*powergate_uvd)(void *handle, bool gate);
+	int (*dispatch_tasks)(void *handle, enum amd_pp_event event_id,
+				   void *input, void *output);
+	void (*print_current_performance_level)(void *handle,
+						      struct seq_file *m);
+	int (*set_fan_control_mode)(void *handle, uint32_t mode);
+	int (*get_fan_control_mode)(void *handle);
+	int (*set_fan_speed_percent)(void *handle, uint32_t percent);
+	int (*get_fan_speed_percent)(void *handle, uint32_t *speed);
+};
+
+struct amd_powerplay {
+	void *pp_handle;
+	const struct amd_ip_funcs *ip_funcs;
+	const struct amd_powerplay_funcs *pp_funcs;
+};
+
+int amd_powerplay_init(struct amd_pp_init *pp_init,
+		       struct amd_powerplay *amd_pp);
+int amd_powerplay_fini(void *handle);
+
+int amd_powerplay_display_configuration_change(void *handle, const void *input);
+
+int amd_powerplay_get_display_power_level(void *handle,
+		struct amd_pp_dal_clock_info *output);
+
+
+#endif /* _AMD_POWERPLAY_H_ */
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h
similarity index 98%
rename from drivers/gpu/drm/amd/amdgpu/cz_ppsmc.h
rename to drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h
index 273616a..9b69878 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_ppsmc.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h
@@ -164,6 +164,7 @@
 #define PPSMC_MSG_SetLoggerAddressHigh        ((uint16_t) 0x26C)
 #define PPSMC_MSG_SetLoggerAddressLow         ((uint16_t) 0x26D)
 #define PPSMC_MSG_SetWatermarkFrequency       ((uint16_t) 0x26E)
+#define PPSMC_MSG_SetDisplaySizePowerParams   ((uint16_t) 0x26F)
 
 /* REMOVE LATER*/
 #define PPSMC_MSG_DPM_ForceState              ((uint16_t) 0x104)
diff --git a/drivers/gpu/drm/amd/powerplay/inc/eventmanager.h b/drivers/gpu/drm/amd/powerplay/inc/eventmanager.h
new file mode 100644
index 0000000..b9d84de
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/eventmanager.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _EVENT_MANAGER_H_
+#define _EVENT_MANAGER_H_
+
+#include "power_state.h"
+#include "pp_power_source.h"
+#include "hardwaremanager.h"
+#include "pp_asicblocks.h"
+
+struct pp_eventmgr;
+enum amd_pp_event;
+
+enum PEM_EventDataValid {
+	PEM_EventDataValid_RequestedStateID = 0,
+	PEM_EventDataValid_RequestedUILabel,
+	PEM_EventDataValid_NewPowerState,
+	PEM_EventDataValid_RequestedPowerSource,
+	PEM_EventDataValid_RequestedClocks,
+	PEM_EventDataValid_CurrentTemperature,
+	PEM_EventDataValid_AsicBlocks,
+	PEM_EventDataValid_ODParameters,
+	PEM_EventDataValid_PXAdapterPrefs,
+	PEM_EventDataValid_PXUserPrefs,
+	PEM_EventDataValid_PXSwitchReason,
+	PEM_EventDataValid_PXSwitchPhase,
+	PEM_EventDataValid_HdVideo,
+	PEM_EventDataValid_BacklightLevel,
+	PEM_EventDatavalid_VariBrightParams,
+	PEM_EventDataValid_VariBrightLevel,
+	PEM_EventDataValid_VariBrightImmediateChange,
+	PEM_EventDataValid_PercentWhite,
+	PEM_EventDataValid_SdVideo,
+	PEM_EventDataValid_HTLinkChangeReason,
+	PEM_EventDataValid_HWBlocks,
+	PEM_EventDataValid_RequestedThermalState,
+	PEM_EventDataValid_MvcVideo,
+	PEM_EventDataValid_Max
+};
+
+typedef enum PEM_EventDataValid PEM_EventDataValid;
+
+/* Number of bits in ULONG variable */
+#define PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD (sizeof(unsigned long)*8)
+
+/* Number of ULONG entries used by event data valid bits */
+#define PEM_MAX_NUM_EVENTDATAVALID_ULONG_ENTRIES                                 \
+		((PEM_EventDataValid_Max + PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD - 1) /  \
+		PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD)
+
+static inline void pem_set_event_data_valid(unsigned long *fields, PEM_EventDataValid valid_field)
+{
+	fields[valid_field / PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD] |=
+		(1UL << (valid_field % PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD));
+}
+
+static inline void pem_unset_event_data_valid(unsigned long *fields, PEM_EventDataValid valid_field)
+{
+	fields[valid_field / PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD] &=
+		~(1UL << (valid_field % PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD));
+}
+
+static inline unsigned long pem_is_event_data_valid(const unsigned long *fields, PEM_EventDataValid valid_field)
+{
+	return fields[valid_field / PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD] &
+		(1UL << (valid_field % PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD));
+}
+
+struct pem_event_data {
+	unsigned long	valid_fields[100];
+	unsigned long   requested_state_id;
+	enum PP_StateUILabel requested_ui_label;
+	struct pp_power_state  *pnew_power_state;
+	enum pp_power_source  requested_power_source;
+	struct PP_Clocks       requested_clocks;
+	bool         skip_state_adjust_rules;
+	struct phm_asic_blocks  asic_blocks;
+	/* to doPP_ThermalState requestedThermalState;
+	enum ThermalStateRequestSrc requestThermalStateSrc;
+	PP_Temperature  currentTemperature;*/
+
+};
+
+int pem_handle_event(struct pp_eventmgr *eventmgr, enum amd_pp_event event,
+		     struct pem_event_data *event_data);
+
+bool pem_is_hw_access_blocked(struct pp_eventmgr *eventmgr);
+
+#endif /* _EVENT_MANAGER_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h b/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h
new file mode 100644
index 0000000..10437dc
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _EVENTMGR_H_
+#define _EVENTMGR_H_
+
+#include <linux/mutex.h>
+#include "pp_instance.h"
+#include "hardwaremanager.h"
+#include "eventmanager.h"
+#include "pp_feature.h"
+#include "pp_power_source.h"
+#include "power_state.h"
+
+typedef int (*pem_event_action)(struct pp_eventmgr *eventmgr,
+				struct pem_event_data *event_data);
+
+struct action_chain {
+	const char *description;  /* action chain description for debugging purpose */
+	const pem_event_action **action_chain; /* pointer to chain of event actions */
+};
+
+struct pem_power_source_ui_state_info {
+	enum PP_StateUILabel current_ui_label;
+	enum PP_StateUILabel default_ui_lable;
+	unsigned long    configurable_ui_mapping;
+};
+
+struct pp_clock_range {
+	uint32_t min_sclk_khz;
+	uint32_t max_sclk_khz;
+
+	uint32_t min_mclk_khz;
+	uint32_t max_mclk_khz;
+
+	uint32_t min_vclk_khz;
+	uint32_t max_vclk_khz;
+
+	uint32_t min_dclk_khz;
+	uint32_t max_dclk_khz;
+
+	uint32_t min_aclk_khz;
+	uint32_t max_aclk_khz;
+
+	uint32_t min_eclk_khz;
+	uint32_t max_eclk_khz;
+};
+
+enum pp_state {
+	UNINITIALIZED,
+	INACTIVE,
+	ACTIVE
+};
+
+enum pp_ring_index {
+	PP_RING_TYPE_GFX_INDEX = 0,
+	PP_RING_TYPE_DMA_INDEX,
+	PP_RING_TYPE_DMA1_INDEX,
+	PP_RING_TYPE_UVD_INDEX,
+	PP_RING_TYPE_VCE0_INDEX,
+	PP_RING_TYPE_VCE1_INDEX,
+	PP_RING_TYPE_CP1_INDEX,
+	PP_RING_TYPE_CP2_INDEX,
+	PP_NUM_RINGS,
+};
+
+struct pp_request {
+	uint32_t flags;
+	uint32_t sclk;
+	uint32_t sclk_throttle;
+	uint32_t mclk;
+	uint32_t vclk;
+	uint32_t dclk;
+	uint32_t eclk;
+	uint32_t aclk;
+	uint32_t iclk;
+	uint32_t vp8clk;
+	uint32_t rsv[32];
+};
+
+struct pp_eventmgr {
+	struct pp_hwmgr	*hwmgr;
+	struct pp_smumgr *smumgr;
+
+	struct pp_feature_info features[PP_Feature_Max];
+	const struct action_chain *event_chain[AMD_PP_EVENT_MAX];
+	struct phm_platform_descriptor   *platform_descriptor;
+	struct pp_clock_range clock_range;
+	enum pp_power_source  current_power_source;
+	struct pem_power_source_ui_state_info  ui_state_info[PP_PowerSource_Max];
+	enum pp_state states[PP_NUM_RINGS];
+	struct pp_request hi_req;
+	struct list_head context_list;
+	struct mutex lock;
+	bool  block_adjust_power_state;
+	bool enable_cg;
+	bool enable_gfx_cgpg;
+	int (*pp_eventmgr_init)(struct pp_eventmgr *eventmgr);
+	void (*pp_eventmgr_fini)(struct pp_eventmgr *eventmgr);
+};
+
+int eventmgr_init(struct pp_instance *handle);
+int eventmgr_fini(struct pp_eventmgr *eventmgr);
+
+#endif /* _EVENTMGR_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h
new file mode 100644
index 0000000..7ae4945
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+
+#ifndef _FIJI_PP_SMC_H_
+#define _FIJI_PP_SMC_H_
+
+#pragma pack(push, 1)
+
+#define PPSMC_SWSTATE_FLAG_DC                           0x01
+#define PPSMC_SWSTATE_FLAG_UVD                          0x02
+#define PPSMC_SWSTATE_FLAG_VCE                          0x04
+
+#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL             0x00
+#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL             0x01
+#define PPSMC_THERMAL_PROTECT_TYPE_NONE                 0xff
+
+#define PPSMC_SYSTEMFLAG_GPIO_DC                        0x01
+#define PPSMC_SYSTEMFLAG_STEPVDDC                       0x02
+#define PPSMC_SYSTEMFLAG_GDDR5                          0x04
+
+#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP               0x08
+
+#define PPSMC_SYSTEMFLAG_REGULATOR_HOT                  0x10
+#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG           0x20
+
+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK              0x07
+#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK     0x08
+
+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE   0x00
+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE  0x01
+
+/* Defines for DPM 2.0 */
+#define PPSMC_DPM2FLAGS_TDPCLMP                         0x01
+#define PPSMC_DPM2FLAGS_PWRSHFT                         0x02
+#define PPSMC_DPM2FLAGS_OCP                             0x04
+
+/* Defines for display watermark level */
+#define PPSMC_DISPLAY_WATERMARK_LOW                     0
+#define PPSMC_DISPLAY_WATERMARK_HIGH                    1
+
+/* In the HW performance level's state flags: */
+#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP    0x01
+#define PPSMC_STATEFLAG_POWERBOOST         0x02
+#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04
+#define PPSMC_STATEFLAG_POWERSHIFT         0x08
+#define PPSMC_STATEFLAG_SLOW_READ_MARGIN   0x10
+#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20
+#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS   0x40
+
+/* Fan control algorithm: */
+#define FDO_MODE_HARDWARE 0
+#define FDO_MODE_PIECE_WISE_LINEAR 1
+
+enum FAN_CONTROL {
+  FAN_CONTROL_FUZZY,
+  FAN_CONTROL_TABLE
+};
+
+/* Gemini Modes*/
+#define PPSMC_GeminiModeNone   0  /*Single GPU board*/
+#define PPSMC_GeminiModeMaster 1  /*Master GPU on a Gemini board*/
+#define PPSMC_GeminiModeSlave  2  /*Slave GPU on a Gemini board*/
+
+
+/* Return codes for driver to SMC communication. */
+#define PPSMC_Result_OK             ((uint16_t)0x01)
+#define PPSMC_Result_NoMore         ((uint16_t)0x02)
+
+#define PPSMC_Result_NotNow         ((uint16_t)0x03)
+
+#define PPSMC_Result_Failed         ((uint16_t)0xFF)
+#define PPSMC_Result_UnknownCmd     ((uint16_t)0xFE)
+#define PPSMC_Result_UnknownVT      ((uint16_t)0xFD)
+
+#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x))
+
+
+#define PPSMC_MSG_Halt                      ((uint16_t)0x10)
+#define PPSMC_MSG_Resume                    ((uint16_t)0x11)
+#define PPSMC_MSG_EnableDPMLevel            ((uint16_t)0x12)
+#define PPSMC_MSG_ZeroLevelsDisabled        ((uint16_t)0x13)
+#define PPSMC_MSG_OneLevelsDisabled         ((uint16_t)0x14)
+#define PPSMC_MSG_TwoLevelsDisabled         ((uint16_t)0x15)
+#define PPSMC_MSG_EnableThermalInterrupt    ((uint16_t)0x16)
+#define PPSMC_MSG_RunningOnAC               ((uint16_t)0x17)
+#define PPSMC_MSG_LevelUp                   ((uint16_t)0x18)
+#define PPSMC_MSG_LevelDown                 ((uint16_t)0x19)
+#define PPSMC_MSG_ResetDPMCounters          ((uint16_t)0x1a)
+#define PPSMC_MSG_SwitchToSwState           ((uint16_t)0x20)
+
+#define PPSMC_MSG_SwitchToSwStateLast       ((uint16_t)0x3f)
+#define PPSMC_MSG_SwitchToInitialState      ((uint16_t)0x40)
+#define PPSMC_MSG_NoForcedLevel             ((uint16_t)0x41)
+#define PPSMC_MSG_ForceHigh                 ((uint16_t)0x42)
+#define PPSMC_MSG_ForceMediumOrHigh         ((uint16_t)0x43)
+
+#define PPSMC_MSG_SwitchToMinimumPower      ((uint16_t)0x51)
+#define PPSMC_MSG_ResumeFromMinimumPower    ((uint16_t)0x52)
+#define PPSMC_MSG_EnableCac                 ((uint16_t)0x53)
+#define PPSMC_MSG_DisableCac                ((uint16_t)0x54)
+#define PPSMC_DPMStateHistoryStart          ((uint16_t)0x55)
+#define PPSMC_DPMStateHistoryStop           ((uint16_t)0x56)
+#define PPSMC_CACHistoryStart               ((uint16_t)0x57)
+#define PPSMC_CACHistoryStop                ((uint16_t)0x58)
+#define PPSMC_TDPClampingActive             ((uint16_t)0x59)
+#define PPSMC_TDPClampingInactive           ((uint16_t)0x5A)
+#define PPSMC_StartFanControl               ((uint16_t)0x5B)
+#define PPSMC_StopFanControl                ((uint16_t)0x5C)
+#define PPSMC_NoDisplay                     ((uint16_t)0x5D)
+#define PPSMC_HasDisplay                    ((uint16_t)0x5E)
+#define PPSMC_MSG_UVDPowerOFF               ((uint16_t)0x60)
+#define PPSMC_MSG_UVDPowerON                ((uint16_t)0x61)
+#define PPSMC_MSG_EnableULV                 ((uint16_t)0x62)
+#define PPSMC_MSG_DisableULV                ((uint16_t)0x63)
+#define PPSMC_MSG_EnterULV                  ((uint16_t)0x64)
+#define PPSMC_MSG_ExitULV                   ((uint16_t)0x65)
+#define PPSMC_PowerShiftActive              ((uint16_t)0x6A)
+#define PPSMC_PowerShiftInactive            ((uint16_t)0x6B)
+#define PPSMC_OCPActive                     ((uint16_t)0x6C)
+#define PPSMC_OCPInactive                   ((uint16_t)0x6D)
+#define PPSMC_CACLongTermAvgEnable          ((uint16_t)0x6E)
+#define PPSMC_CACLongTermAvgDisable         ((uint16_t)0x6F)
+#define PPSMC_MSG_InferredStateSweep_Start  ((uint16_t)0x70)
+#define PPSMC_MSG_InferredStateSweep_Stop   ((uint16_t)0x71)
+#define PPSMC_MSG_SwitchToLowestInfState    ((uint16_t)0x72)
+#define PPSMC_MSG_SwitchToNonInfState       ((uint16_t)0x73)
+#define PPSMC_MSG_AllStateSweep_Start       ((uint16_t)0x74)
+#define PPSMC_MSG_AllStateSweep_Stop        ((uint16_t)0x75)
+#define PPSMC_MSG_SwitchNextLowerInfState   ((uint16_t)0x76)
+#define PPSMC_MSG_SwitchNextHigherInfState  ((uint16_t)0x77)
+#define PPSMC_MSG_MclkRetrainingTest        ((uint16_t)0x78)
+#define PPSMC_MSG_ForceTDPClamping          ((uint16_t)0x79)
+#define PPSMC_MSG_CollectCAC_PowerCorreln   ((uint16_t)0x7A)
+#define PPSMC_MSG_CollectCAC_WeightCalib    ((uint16_t)0x7B)
+#define PPSMC_MSG_CollectCAC_SQonly         ((uint16_t)0x7C)
+#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D)
+
+#define PPSMC_MSG_ExtremitiesTest_Start     ((uint16_t)0x7E)
+#define PPSMC_MSG_ExtremitiesTest_Stop      ((uint16_t)0x7F)
+#define PPSMC_FlushDataCache                ((uint16_t)0x80)
+#define PPSMC_FlushInstrCache               ((uint16_t)0x81)
+
+#define PPSMC_MSG_SetEnabledLevels          ((uint16_t)0x82)
+#define PPSMC_MSG_SetForcedLevels           ((uint16_t)0x83)
+
+#define PPSMC_MSG_ResetToDefaults           ((uint16_t)0x84)
+
+#define PPSMC_MSG_SetForcedLevelsAndJump      ((uint16_t)0x85)
+#define PPSMC_MSG_SetCACHistoryMode           ((uint16_t)0x86)
+#define PPSMC_MSG_EnableDTE                   ((uint16_t)0x87)
+#define PPSMC_MSG_DisableDTE                  ((uint16_t)0x88)
+
+#define PPSMC_MSG_SmcSpaceSetAddress          ((uint16_t)0x89)
+
+#define PPSMC_MSG_BREAK                       ((uint16_t)0xF8)
+
+/* Trinity Specific Messages*/
+#define PPSMC_MSG_Test                        ((uint16_t) 0x100)
+#define PPSMC_MSG_DPM_Voltage_Pwrmgt          ((uint16_t) 0x101)
+#define PPSMC_MSG_DPM_Config                  ((uint16_t) 0x102)
+#define PPSMC_MSG_PM_Controller_Start         ((uint16_t) 0x103)
+#define PPSMC_MSG_DPM_ForceState              ((uint16_t) 0x104)
+#define PPSMC_MSG_PG_PowerDownSIMD            ((uint16_t) 0x105)
+#define PPSMC_MSG_PG_PowerUpSIMD              ((uint16_t) 0x106)
+#define PPSMC_MSG_PM_Controller_Stop          ((uint16_t) 0x107)
+#define PPSMC_MSG_PG_SIMD_Config              ((uint16_t) 0x108)
+#define PPSMC_MSG_Voltage_Cntl_Enable         ((uint16_t) 0x109)
+#define PPSMC_MSG_Thermal_Cntl_Enable         ((uint16_t) 0x10a)
+#define PPSMC_MSG_Reset_Service               ((uint16_t) 0x10b)
+#define PPSMC_MSG_VCEPowerOFF                 ((uint16_t) 0x10e)
+#define PPSMC_MSG_VCEPowerON                  ((uint16_t) 0x10f)
+#define PPSMC_MSG_DPM_Disable_VCE_HS          ((uint16_t) 0x110)
+#define PPSMC_MSG_DPM_Enable_VCE_HS           ((uint16_t) 0x111)
+#define PPSMC_MSG_DPM_N_LevelsDisabled        ((uint16_t) 0x112)
+#define PPSMC_MSG_DCEPowerOFF                 ((uint16_t) 0x113)
+#define PPSMC_MSG_DCEPowerON                  ((uint16_t) 0x114)
+#define PPSMC_MSG_PCIE_DDIPowerDown           ((uint16_t) 0x117)
+#define PPSMC_MSG_PCIE_DDIPowerUp             ((uint16_t) 0x118)
+#define PPSMC_MSG_PCIE_CascadePLLPowerDown    ((uint16_t) 0x119)
+#define PPSMC_MSG_PCIE_CascadePLLPowerUp      ((uint16_t) 0x11a)
+#define PPSMC_MSG_SYSPLLPowerOff              ((uint16_t) 0x11b)
+#define PPSMC_MSG_SYSPLLPowerOn               ((uint16_t) 0x11c)
+#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint16_t) 0x11d)
+#define PPSMC_MSG_DCE_AllowVoltageAdjustment  ((uint16_t) 0x11e)
+#define PPSMC_MSG_DISPLAYPHYStatusNotify      ((uint16_t) 0x11f)
+#define PPSMC_MSG_EnableBAPM                  ((uint16_t) 0x120)
+#define PPSMC_MSG_DisableBAPM                 ((uint16_t) 0x121)
+#define PPSMC_MSG_Spmi_Enable                 ((uint16_t) 0x122)
+#define PPSMC_MSG_Spmi_Timer                  ((uint16_t) 0x123)
+#define PPSMC_MSG_LCLK_DPM_Config             ((uint16_t) 0x124)
+#define PPSMC_MSG_VddNB_Request               ((uint16_t) 0x125)
+#define PPSMC_MSG_PCIE_DDIPhyPowerDown        ((uint32_t) 0x126)
+#define PPSMC_MSG_PCIE_DDIPhyPowerUp          ((uint32_t) 0x127)
+#define PPSMC_MSG_MCLKDPM_Config              ((uint16_t) 0x128)
+
+#define PPSMC_MSG_UVDDPM_Config               ((uint16_t) 0x129)
+#define PPSMC_MSG_VCEDPM_Config               ((uint16_t) 0x12A)
+#define PPSMC_MSG_ACPDPM_Config               ((uint16_t) 0x12B)
+#define PPSMC_MSG_SAMUDPM_Config              ((uint16_t) 0x12C)
+#define PPSMC_MSG_UVDDPM_SetEnabledMask       ((uint16_t) 0x12D)
+#define PPSMC_MSG_VCEDPM_SetEnabledMask       ((uint16_t) 0x12E)
+#define PPSMC_MSG_ACPDPM_SetEnabledMask       ((uint16_t) 0x12F)
+#define PPSMC_MSG_SAMUDPM_SetEnabledMask      ((uint16_t) 0x130)
+#define PPSMC_MSG_MCLKDPM_ForceState          ((uint16_t) 0x131)
+#define PPSMC_MSG_MCLKDPM_NoForcedLevel       ((uint16_t) 0x132)
+#define PPSMC_MSG_Thermal_Cntl_Disable        ((uint16_t) 0x133)
+#define PPSMC_MSG_SetTDPLimit                 ((uint16_t) 0x134)
+#define PPSMC_MSG_Voltage_Cntl_Disable        ((uint16_t) 0x135)
+#define PPSMC_MSG_PCIeDPM_Enable              ((uint16_t) 0x136)
+#define PPSMC_MSG_ACPPowerOFF                 ((uint16_t) 0x137)
+#define PPSMC_MSG_ACPPowerON                  ((uint16_t) 0x138)
+#define PPSMC_MSG_SAMPowerOFF                 ((uint16_t) 0x139)
+#define PPSMC_MSG_SAMPowerON                  ((uint16_t) 0x13a)
+#define PPSMC_MSG_SDMAPowerOFF                ((uint16_t) 0x13b)
+#define PPSMC_MSG_SDMAPowerON                 ((uint16_t) 0x13c)
+#define PPSMC_MSG_PCIeDPM_Disable             ((uint16_t) 0x13d)
+#define PPSMC_MSG_IOMMUPowerOFF               ((uint16_t) 0x13e)
+#define PPSMC_MSG_IOMMUPowerON                ((uint16_t) 0x13f)
+#define PPSMC_MSG_NBDPM_Enable                ((uint16_t) 0x140)
+#define PPSMC_MSG_NBDPM_Disable               ((uint16_t) 0x141)
+#define PPSMC_MSG_NBDPM_ForceNominal          ((uint16_t) 0x142)
+#define PPSMC_MSG_NBDPM_ForcePerformance      ((uint16_t) 0x143)
+#define PPSMC_MSG_NBDPM_UnForce               ((uint16_t) 0x144)
+#define PPSMC_MSG_SCLKDPM_SetEnabledMask      ((uint16_t) 0x145)
+#define PPSMC_MSG_MCLKDPM_SetEnabledMask      ((uint16_t) 0x146)
+#define PPSMC_MSG_PCIeDPM_ForceLevel          ((uint16_t) 0x147)
+#define PPSMC_MSG_PCIeDPM_UnForceLevel        ((uint16_t) 0x148)
+#define PPSMC_MSG_EnableACDCGPIOInterrupt     ((uint16_t) 0x149)
+#define PPSMC_MSG_EnableVRHotGPIOInterrupt    ((uint16_t) 0x14a)
+#define PPSMC_MSG_SwitchToAC                  ((uint16_t) 0x14b)
+
+#define PPSMC_MSG_XDMAPowerOFF                ((uint16_t) 0x14c)
+#define PPSMC_MSG_XDMAPowerON                 ((uint16_t) 0x14d)
+
+#define PPSMC_MSG_DPM_Enable                  ((uint16_t) 0x14e)
+#define PPSMC_MSG_DPM_Disable                 ((uint16_t) 0x14f)
+#define PPSMC_MSG_MCLKDPM_Enable              ((uint16_t) 0x150)
+#define PPSMC_MSG_MCLKDPM_Disable             ((uint16_t) 0x151)
+#define PPSMC_MSG_LCLKDPM_Enable              ((uint16_t) 0x152)
+#define PPSMC_MSG_LCLKDPM_Disable             ((uint16_t) 0x153)
+#define PPSMC_MSG_UVDDPM_Enable               ((uint16_t) 0x154)
+#define PPSMC_MSG_UVDDPM_Disable              ((uint16_t) 0x155)
+#define PPSMC_MSG_SAMUDPM_Enable              ((uint16_t) 0x156)
+#define PPSMC_MSG_SAMUDPM_Disable             ((uint16_t) 0x157)
+#define PPSMC_MSG_ACPDPM_Enable               ((uint16_t) 0x158)
+#define PPSMC_MSG_ACPDPM_Disable              ((uint16_t) 0x159)
+#define PPSMC_MSG_VCEDPM_Enable               ((uint16_t) 0x15a)
+#define PPSMC_MSG_VCEDPM_Disable              ((uint16_t) 0x15b)
+#define PPSMC_MSG_LCLKDPM_SetEnabledMask      ((uint16_t) 0x15c)
+#define PPSMC_MSG_DPM_FPS_Mode                ((uint16_t) 0x15d)
+#define PPSMC_MSG_DPM_Activity_Mode           ((uint16_t) 0x15e)
+#define PPSMC_MSG_VddC_Request                ((uint16_t) 0x15f)
+#define PPSMC_MSG_MCLKDPM_GetEnabledMask      ((uint16_t) 0x160)
+#define PPSMC_MSG_LCLKDPM_GetEnabledMask      ((uint16_t) 0x161)
+#define PPSMC_MSG_SCLKDPM_GetEnabledMask      ((uint16_t) 0x162)
+#define PPSMC_MSG_UVDDPM_GetEnabledMask       ((uint16_t) 0x163)
+#define PPSMC_MSG_SAMUDPM_GetEnabledMask      ((uint16_t) 0x164)
+#define PPSMC_MSG_ACPDPM_GetEnabledMask       ((uint16_t) 0x165)
+#define PPSMC_MSG_VCEDPM_GetEnabledMask       ((uint16_t) 0x166)
+#define PPSMC_MSG_PCIeDPM_SetEnabledMask      ((uint16_t) 0x167)
+#define PPSMC_MSG_PCIeDPM_GetEnabledMask      ((uint16_t) 0x168)
+#define PPSMC_MSG_TDCLimitEnable              ((uint16_t) 0x169)
+#define PPSMC_MSG_TDCLimitDisable             ((uint16_t) 0x16a)
+#define PPSMC_MSG_DPM_AutoRotate_Mode         ((uint16_t) 0x16b)
+#define PPSMC_MSG_DISPCLK_FROM_FCH            ((uint16_t) 0x16c)
+#define PPSMC_MSG_DISPCLK_FROM_DFS            ((uint16_t) 0x16d)
+#define PPSMC_MSG_DPREFCLK_FROM_FCH           ((uint16_t) 0x16e)
+#define PPSMC_MSG_DPREFCLK_FROM_DFS           ((uint16_t) 0x16f)
+#define PPSMC_MSG_PmStatusLogStart            ((uint16_t) 0x170)
+#define PPSMC_MSG_PmStatusLogSample           ((uint16_t) 0x171)
+#define PPSMC_MSG_SCLK_AutoDPM_ON             ((uint16_t) 0x172)
+#define PPSMC_MSG_MCLK_AutoDPM_ON             ((uint16_t) 0x173)
+#define PPSMC_MSG_LCLK_AutoDPM_ON             ((uint16_t) 0x174)
+#define PPSMC_MSG_UVD_AutoDPM_ON              ((uint16_t) 0x175)
+#define PPSMC_MSG_SAMU_AutoDPM_ON             ((uint16_t) 0x176)
+#define PPSMC_MSG_ACP_AutoDPM_ON              ((uint16_t) 0x177)
+#define PPSMC_MSG_VCE_AutoDPM_ON              ((uint16_t) 0x178)
+#define PPSMC_MSG_PCIe_AutoDPM_ON             ((uint16_t) 0x179)
+#define PPSMC_MSG_MASTER_AutoDPM_ON           ((uint16_t) 0x17a)
+#define PPSMC_MSG_MASTER_AutoDPM_OFF          ((uint16_t) 0x17b)
+#define PPSMC_MSG_DYNAMICDISPPHYPOWER         ((uint16_t) 0x17c)
+#define PPSMC_MSG_CAC_COLLECTION_ON           ((uint16_t) 0x17d)
+#define PPSMC_MSG_CAC_COLLECTION_OFF          ((uint16_t) 0x17e)
+#define PPSMC_MSG_CAC_CORRELATION_ON          ((uint16_t) 0x17f)
+#define PPSMC_MSG_CAC_CORRELATION_OFF         ((uint16_t) 0x180)
+#define PPSMC_MSG_PM_STATUS_TO_DRAM_ON        ((uint16_t) 0x181)
+#define PPSMC_MSG_PM_STATUS_TO_DRAM_OFF       ((uint16_t) 0x182)
+#define PPSMC_MSG_ALLOW_LOWSCLK_INTERRUPT     ((uint16_t) 0x184)
+#define PPSMC_MSG_PkgPwrLimitEnable           ((uint16_t) 0x185)
+#define PPSMC_MSG_PkgPwrLimitDisable          ((uint16_t) 0x186)
+#define PPSMC_MSG_PkgPwrSetLimit              ((uint16_t) 0x187)
+#define PPSMC_MSG_OverDriveSetTargetTdp       ((uint16_t) 0x188)
+#define PPSMC_MSG_SCLKDPM_FreezeLevel         ((uint16_t) 0x189)
+#define PPSMC_MSG_SCLKDPM_UnfreezeLevel       ((uint16_t) 0x18A)
+#define PPSMC_MSG_MCLKDPM_FreezeLevel         ((uint16_t) 0x18B)
+#define PPSMC_MSG_MCLKDPM_UnfreezeLevel       ((uint16_t) 0x18C)
+#define PPSMC_MSG_START_DRAM_LOGGING          ((uint16_t) 0x18D)
+#define PPSMC_MSG_STOP_DRAM_LOGGING           ((uint16_t) 0x18E)
+#define PPSMC_MSG_MASTER_DeepSleep_ON         ((uint16_t) 0x18F)
+#define PPSMC_MSG_MASTER_DeepSleep_OFF        ((uint16_t) 0x190)
+#define PPSMC_MSG_Remove_DC_Clamp             ((uint16_t) 0x191)
+#define PPSMC_MSG_DisableACDCGPIOInterrupt    ((uint16_t) 0x192)
+#define PPSMC_MSG_OverrideVoltageControl_SetVddc       ((uint16_t) 0x193)
+#define PPSMC_MSG_OverrideVoltageControl_SetVddci      ((uint16_t) 0x194)
+#define PPSMC_MSG_SetVidOffset_1              ((uint16_t) 0x195)
+#define PPSMC_MSG_SetVidOffset_2              ((uint16_t) 0x207)
+#define PPSMC_MSG_GetVidOffset_1              ((uint16_t) 0x196)
+#define PPSMC_MSG_GetVidOffset_2              ((uint16_t) 0x208)
+#define PPSMC_MSG_THERMAL_OVERDRIVE_Enable    ((uint16_t) 0x197)
+#define PPSMC_MSG_THERMAL_OVERDRIVE_Disable   ((uint16_t) 0x198)
+#define PPSMC_MSG_SetTjMax                    ((uint16_t) 0x199)
+#define PPSMC_MSG_SetFanPwmMax                ((uint16_t) 0x19A)
+#define PPSMC_MSG_WaitForMclkSwitchFinish     ((uint16_t) 0x19B)
+#define PPSMC_MSG_ENABLE_THERMAL_DPM          ((uint16_t) 0x19C)
+#define PPSMC_MSG_DISABLE_THERMAL_DPM         ((uint16_t) 0x19D)
+
+#define PPSMC_MSG_API_GetSclkFrequency        ((uint16_t) 0x200)
+#define PPSMC_MSG_API_GetMclkFrequency        ((uint16_t) 0x201)
+#define PPSMC_MSG_API_GetSclkBusy             ((uint16_t) 0x202)
+#define PPSMC_MSG_API_GetMclkBusy             ((uint16_t) 0x203)
+#define PPSMC_MSG_API_GetAsicPower            ((uint16_t) 0x204)
+#define PPSMC_MSG_SetFanRpmMax                ((uint16_t) 0x205)
+#define PPSMC_MSG_SetFanSclkTarget            ((uint16_t) 0x206)
+#define PPSMC_MSG_SetFanMinPwm                ((uint16_t) 0x209)
+#define PPSMC_MSG_SetFanTemperatureTarget     ((uint16_t) 0x20A)
+
+#define PPSMC_MSG_BACO_StartMonitor           ((uint16_t) 0x240)
+#define PPSMC_MSG_BACO_Cancel                 ((uint16_t) 0x241)
+#define PPSMC_MSG_EnableVddGfx                ((uint16_t) 0x242)
+#define PPSMC_MSG_DisableVddGfx               ((uint16_t) 0x243)
+#define PPSMC_MSG_UcodeAddressLow             ((uint16_t) 0x244)
+#define PPSMC_MSG_UcodeAddressHigh            ((uint16_t) 0x245)
+#define PPSMC_MSG_UcodeLoadStatus             ((uint16_t) 0x246)
+
+#define PPSMC_MSG_DRV_DRAM_ADDR_HI            ((uint16_t) 0x250)
+#define PPSMC_MSG_DRV_DRAM_ADDR_LO            ((uint16_t) 0x251)
+#define PPSMC_MSG_SMU_DRAM_ADDR_HI            ((uint16_t) 0x252)
+#define PPSMC_MSG_SMU_DRAM_ADDR_LO            ((uint16_t) 0x253)
+#define PPSMC_MSG_LoadUcodes                  ((uint16_t) 0x254)
+#define PPSMC_MSG_PowerStateNotify            ((uint16_t) 0x255)
+#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_HI      ((uint16_t) 0x256)
+#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_LO      ((uint16_t) 0x257)
+#define PPSMC_MSG_VBIOS_DRAM_ADDR_HI          ((uint16_t) 0x258)
+#define PPSMC_MSG_VBIOS_DRAM_ADDR_LO          ((uint16_t) 0x259)
+#define PPSMC_MSG_LoadVBios                   ((uint16_t) 0x25A)
+#define PPSMC_MSG_GetUcodeVersion             ((uint16_t) 0x25B)
+#define DMCUSMC_MSG_PSREntry                  ((uint16_t) 0x25C)
+#define DMCUSMC_MSG_PSRExit                   ((uint16_t) 0x25D)
+#define PPSMC_MSG_EnableClockGatingFeature    ((uint16_t) 0x260)
+#define PPSMC_MSG_DisableClockGatingFeature   ((uint16_t) 0x261)
+#define PPSMC_MSG_IsDeviceRunning             ((uint16_t) 0x262)
+#define PPSMC_MSG_LoadMetaData                ((uint16_t) 0x263)
+#define PPSMC_MSG_TMON_AutoCaliberate_Enable  ((uint16_t) 0x264)
+#define PPSMC_MSG_TMON_AutoCaliberate_Disable ((uint16_t) 0x265)
+#define PPSMC_MSG_GetTelemetry1Slope          ((uint16_t) 0x266)
+#define PPSMC_MSG_GetTelemetry1Offset         ((uint16_t) 0x267)
+#define PPSMC_MSG_GetTelemetry2Slope          ((uint16_t) 0x268)
+#define PPSMC_MSG_GetTelemetry2Offset         ((uint16_t) 0x269)
+#define PPSMC_MSG_EnableAvfs                  ((uint16_t) 0x26A)
+#define PPSMC_MSG_DisableAvfs                 ((uint16_t) 0x26B)
+#define PPSMC_MSG_PerformBtc                  ((uint16_t) 0x26C)
+#define PPSMC_MSG_GetHbmCode                  ((uint16_t) 0x26D)
+#define PPSMC_MSG_GetVrVddcTemperature        ((uint16_t) 0x26E)
+#define PPSMC_MSG_GetVrMvddTemperature        ((uint16_t) 0x26F)
+#define PPSMC_MSG_GetLiquidTemperature        ((uint16_t) 0x270)
+#define PPSMC_MSG_GetPlxTemperature           ((uint16_t) 0x271)
+#define PPSMC_MSG_RequestI2CControl           ((uint16_t) 0x272)
+#define PPSMC_MSG_ReleaseI2CControl           ((uint16_t) 0x273)
+#define PPSMC_MSG_LedConfig                   ((uint16_t) 0x274)
+#define PPSMC_MSG_SetHbmFanCode               ((uint16_t) 0x275)
+#define PPSMC_MSG_SetHbmThrottleCode          ((uint16_t) 0x276)
+
+#define PPSMC_MSG_GetEnabledPsm               ((uint16_t) 0x400)
+#define PPSMC_MSG_AgmStartPsm                 ((uint16_t) 0x401)
+#define PPSMC_MSG_AgmReadPsm                  ((uint16_t) 0x402)
+#define PPSMC_MSG_AgmResetPsm                 ((uint16_t) 0x403)
+#define PPSMC_MSG_ReadVftCell                 ((uint16_t) 0x404)
+
+/* AVFS Only - Remove Later */
+#define PPSMC_MSG_VftTableIsValid             ((uint16_t) 0x666)
+
+/* If the SMC firmware has an event status soft register this is what the individual bits mean.*/
+#define PPSMC_EVENT_STATUS_THERMAL          0x00000001
+#define PPSMC_EVENT_STATUS_REGULATORHOT     0x00000002
+#define PPSMC_EVENT_STATUS_DC               0x00000004
+
+typedef uint16_t PPSMC_Msg;
+
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h b/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h
new file mode 100644
index 0000000..0262ad3
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h
@@ -0,0 +1,10299 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _FIJI_PWRVIRUS_H_
+#define _FIJI_PWRVIRUS_H_
+
+#define mmCP_HYP_MEC1_UCODE_ADDR	0xf81a
+#define mmCP_HYP_MEC1_UCODE_DATA	0xf81b
+#define mmCP_HYP_MEC2_UCODE_ADDR	0xf81c
+#define mmCP_HYP_MEC2_UCODE_DATA	0xf81d
+
+enum PWR_Command
+{
+   PwrCmdNull = 0,
+   PwrCmdWrite,
+   PwrCmdEnd,
+   PwrCmdMax
+};
+typedef enum PWR_Command PWR_Command;
+
+struct PWR_Command_Table
+{
+   PWR_Command        command;
+   ULONG              data;
+   ULONG              reg;
+};
+typedef struct PWR_Command_Table PWR_Command_Table;
+
+#define PWR_VIRUS_TABLE_SIZE  10243
+static PWR_Command_Table PwrVirusTable[PWR_VIRUS_TABLE_SIZE] =
+{
+    { PwrCmdWrite, 0x100100b6, mmPCIE_INDEX                               },
+    { PwrCmdWrite, 0x00000000, mmPCIE_DATA                                },
+    { PwrCmdWrite, 0x100100b6, mmPCIE_INDEX                               },
+    { PwrCmdWrite, 0x0300078c, mmPCIE_DATA                                },
+    { PwrCmdWrite, 0x00000000, mmBIF_CLK_CTRL                             },
+    { PwrCmdWrite, 0x00000001, mmBIF_CLK_CTRL                             },
+    { PwrCmdWrite, 0x00000000, mmBIF_CLK_CTRL                             },
+    { PwrCmdWrite, 0x00000003, mmBIF_FB_EN                                },
+    { PwrCmdWrite, 0x00000000, mmBIF_FB_EN                                },
+    { PwrCmdWrite, 0x00000001, mmBIF_DOORBELL_APER_EN                     },
+    { PwrCmdWrite, 0x00000000, mmBIF_DOORBELL_APER_EN                     },
+    { PwrCmdWrite, 0x014000c0, mmPCIE_INDEX                               },
+    { PwrCmdWrite, 0x00000000, mmPCIE_DATA                                },
+    { PwrCmdWrite, 0x014000c0, mmPCIE_INDEX                               },
+    { PwrCmdWrite, 0x22000000, mmPCIE_DATA                                },
+    { PwrCmdWrite, 0x014000c0, mmPCIE_INDEX                               },
+    { PwrCmdWrite, 0x00000000, mmPCIE_DATA                                },
+    /*
+    { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION                        },
+    { PwrCmdWrite, 0x00000000, mmMC_CITF_CNTL                             },
+    { PwrCmdWrite, 0x00000000, mmMC_VM_FB_LOCATION                        },
+    { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION                        },
+    { PwrCmdWrite, 0x00000000, mmMC_VM_FB_LOCATION                        },
+    { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION                        },
+    { PwrCmdWrite, 0x00000000, mmMC_VM_FB_OFFSET                          },*/
+    { PwrCmdWrite, 0x00000000, mmRLC_CSIB_ADDR_LO                         },
+    { PwrCmdWrite, 0x00000000, mmRLC_CSIB_ADDR_HI                         },
+    { PwrCmdWrite, 0x00000000, mmRLC_CSIB_LENGTH                          },
+    /*
+    { PwrCmdWrite, 0x00000000, mmMC_VM_MX_L1_TLB_CNTL                     },
+    { PwrCmdWrite, 0x00000001, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR           },
+    { PwrCmdWrite, 0x00000000, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR          },
+    { PwrCmdWrite, 0x00000000, mmMC_VM_FB_LOCATION                        },
+    { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION                        },*/
+    { PwrCmdWrite, 0x00000000, mmVM_CONTEXT0_CNTL                         },
+    { PwrCmdWrite, 0x00000000, mmVM_CONTEXT1_CNTL                         },
+    /*
+    { PwrCmdWrite, 0x00000000, mmMC_VM_AGP_BASE                           },
+    { PwrCmdWrite, 0x00000002, mmMC_VM_AGP_BOT                            },
+    { PwrCmdWrite, 0x00000000, mmMC_VM_AGP_TOP                            },*/
+    { PwrCmdWrite, 0x04000000, mmATC_VM_APERTURE0_LOW_ADDR                },
+    { PwrCmdWrite, 0x0400ff20, mmATC_VM_APERTURE0_HIGH_ADDR               },
+    { PwrCmdWrite, 0x00000002, mmATC_VM_APERTURE0_CNTL                    },
+    { PwrCmdWrite, 0x0000ffff, mmATC_VM_APERTURE0_CNTL2                   },
+    { PwrCmdWrite, 0x00000001, mmATC_VM_APERTURE1_LOW_ADDR                },
+    { PwrCmdWrite, 0x00000000, mmATC_VM_APERTURE1_HIGH_ADDR               },
+    { PwrCmdWrite, 0x00000000, mmATC_VM_APERTURE1_CNTL                    },
+    { PwrCmdWrite, 0x00000000, mmATC_VM_APERTURE1_CNTL2                   },
+    //{ PwrCmdWrite, 0x00000000, mmMC_ARB_RAMCFG                            },
+    { PwrCmdWrite, 0x12011003, mmGB_ADDR_CONFIG                           },
+    { PwrCmdWrite, 0x00800010, mmGB_TILE_MODE0                            },
+    { PwrCmdWrite, 0x00800810, mmGB_TILE_MODE1                            },
+    { PwrCmdWrite, 0x00801010, mmGB_TILE_MODE2                            },
+    { PwrCmdWrite, 0x00801810, mmGB_TILE_MODE3                            },
+    { PwrCmdWrite, 0x00802810, mmGB_TILE_MODE4                            },
+    { PwrCmdWrite, 0x00802808, mmGB_TILE_MODE5                            },
+    { PwrCmdWrite, 0x00802814, mmGB_TILE_MODE6                            },
+    { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE7                            },
+    { PwrCmdWrite, 0x00000004, mmGB_TILE_MODE8                            },
+    { PwrCmdWrite, 0x02000008, mmGB_TILE_MODE9                            },
+    { PwrCmdWrite, 0x02000010, mmGB_TILE_MODE10                           },
+    { PwrCmdWrite, 0x06000014, mmGB_TILE_MODE11                           },
+    { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE12                           },
+    { PwrCmdWrite, 0x02400008, mmGB_TILE_MODE13                           },
+    { PwrCmdWrite, 0x02400010, mmGB_TILE_MODE14                           },
+    { PwrCmdWrite, 0x02400030, mmGB_TILE_MODE15                           },
+    { PwrCmdWrite, 0x06400014, mmGB_TILE_MODE16                           },
+    { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE17                           },
+    { PwrCmdWrite, 0x0040000c, mmGB_TILE_MODE18                           },
+    { PwrCmdWrite, 0x0100000c, mmGB_TILE_MODE19                           },
+    { PwrCmdWrite, 0x0100001c, mmGB_TILE_MODE20                           },
+    { PwrCmdWrite, 0x01000034, mmGB_TILE_MODE21                           },
+    { PwrCmdWrite, 0x01000024, mmGB_TILE_MODE22                           },
+    { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE23                           },
+    { PwrCmdWrite, 0x0040001c, mmGB_TILE_MODE24                           },
+    { PwrCmdWrite, 0x01000020, mmGB_TILE_MODE25                           },
+    { PwrCmdWrite, 0x01000038, mmGB_TILE_MODE26                           },
+    { PwrCmdWrite, 0x02c00008, mmGB_TILE_MODE27                           },
+    { PwrCmdWrite, 0x02c00010, mmGB_TILE_MODE28                           },
+    { PwrCmdWrite, 0x06c00014, mmGB_TILE_MODE29                           },
+    { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE30                           },
+    { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE31                           },
+    { PwrCmdWrite, 0x000000a8, mmGB_MACROTILE_MODE0                       },
+    { PwrCmdWrite, 0x000000a4, mmGB_MACROTILE_MODE1                       },
+    { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE2                       },
+    { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE3                       },
+    { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE4                       },
+    { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE5                       },
+    { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE6                       },
+    { PwrCmdWrite, 0x00000000, mmGB_MACROTILE_MODE7                       },
+    { PwrCmdWrite, 0x000000ee, mmGB_MACROTILE_MODE8                       },
+    { PwrCmdWrite, 0x000000ea, mmGB_MACROTILE_MODE9                       },
+    { PwrCmdWrite, 0x000000e9, mmGB_MACROTILE_MODE10                      },
+    { PwrCmdWrite, 0x000000e5, mmGB_MACROTILE_MODE11                      },
+    { PwrCmdWrite, 0x000000e4, mmGB_MACROTILE_MODE12                      },
+    { PwrCmdWrite, 0x000000e0, mmGB_MACROTILE_MODE13                      },
+    { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE14                      },
+    { PwrCmdWrite, 0x00000000, mmGB_MACROTILE_MODE15                      },
+    { PwrCmdWrite, 0x00900000, mmHDP_NONSURFACE_BASE                      },
+    { PwrCmdWrite, 0x00008000, mmHDP_NONSURFACE_INFO                      },
+    { PwrCmdWrite, 0x3fffffff, mmHDP_NONSURFACE_SIZE                      },
+    { PwrCmdWrite, 0x00000003, mmBIF_FB_EN                                },
+    //{ PwrCmdWrite, 0x00000000, mmMC_VM_FB_OFFSET                          },
+    { PwrCmdWrite, 0x00000000, mmSRBM_CNTL                                },
+    { PwrCmdWrite, 0x00020000, mmSRBM_CNTL                                },
+    { PwrCmdWrite, 0x80000000, mmATC_VMID0_PASID_MAPPING                  },
+    { PwrCmdWrite, 0x00000000, mmATC_VMID_PASID_MAPPING_UPDATE_STATUS     },
+    { PwrCmdWrite, 0x00000000, mmRLC_CNTL                                 },
+    { PwrCmdWrite, 0x00000000, mmRLC_CNTL                                 },
+    { PwrCmdWrite, 0x00000000, mmRLC_CNTL                                 },
+    { PwrCmdWrite, 0xe0000000, mmGRBM_GFX_INDEX                           },
+    { PwrCmdWrite, 0x00000000, mmCGTS_TCC_DISABLE                         },
+    { PwrCmdWrite, 0x00000000, mmTCP_ADDR_CONFIG                          },
+    { PwrCmdWrite, 0x000000ff, mmTCP_ADDR_CONFIG                          },
+    { PwrCmdWrite, 0x76543210, mmTCP_CHAN_STEER_LO                        },
+    { PwrCmdWrite, 0xfedcba98, mmTCP_CHAN_STEER_HI                        },
+    { PwrCmdWrite, 0x00000000, mmDB_DEBUG2                                },
+    { PwrCmdWrite, 0x00000000, mmDB_DEBUG                                 },
+    { PwrCmdWrite, 0x00002b16, mmCP_QUEUE_THRESHOLDS                      },
+    { PwrCmdWrite, 0x00006030, mmCP_MEQ_THRESHOLDS                        },
+    { PwrCmdWrite, 0x01000104, mmSPI_CONFIG_CNTL_1                        },
+    { PwrCmdWrite, 0x98184020, mmPA_SC_FIFO_SIZE                          },
+    { PwrCmdWrite, 0x00000001, mmVGT_NUM_INSTANCES                        },
+    { PwrCmdWrite, 0x00000000, mmCP_PERFMON_CNTL                          },
+    { PwrCmdWrite, 0x01180000, mmSQ_CONFIG                                },
+    { PwrCmdWrite, 0x00000000, mmVGT_CACHE_INVALIDATION                   },
+    { PwrCmdWrite, 0x00000000, mmSQ_THREAD_TRACE_BASE                     },
+    { PwrCmdWrite, 0x0000df80, mmSQ_THREAD_TRACE_MASK                     },
+    { PwrCmdWrite, 0x02249249, mmSQ_THREAD_TRACE_MODE                     },
+    { PwrCmdWrite, 0x00000000, mmPA_SC_LINE_STIPPLE_STATE                 },
+    { PwrCmdWrite, 0x00000000, mmCB_PERFCOUNTER0_SELECT1                  },
+    { PwrCmdWrite, 0x06000100, mmCGTT_VGT_CLK_CTRL                        },
+    { PwrCmdWrite, 0x00000007, mmPA_CL_ENHANCE                            },
+    { PwrCmdWrite, 0x00000001, mmPA_SC_ENHANCE                            },
+    { PwrCmdWrite, 0x00ffffff, mmPA_SC_FORCE_EOV_MAX_CNTS                 },
+    { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000010, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000020, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000030, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000040, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000050, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000060, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000070, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000080, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000090, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x000000a0, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x000000b0, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x000000c0, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x000000d0, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x000000e0, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x000000f0, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmRLC_PG_CNTL                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS2                             },
+    { PwrCmdWrite, 0x15000000, mmCP_ME_CNTL                               },
+    { PwrCmdWrite, 0x50000000, mmCP_MEC_CNTL                              },
+    { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x0000000e, mmSH_MEM_APE1_BASE                         },
+    { PwrCmdWrite, 0x0000020d, mmSH_MEM_APE1_LIMIT                        },
+    { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG                            },
+    { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_RB_VMID                               },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmRLC_CNTL                                 },
+    { PwrCmdWrite, 0x00000000, mmRLC_CNTL                                 },
+    { PwrCmdWrite, 0x00000000, mmRLC_SRM_CNTL                             },
+    { PwrCmdWrite, 0x00000002, mmRLC_SRM_CNTL                             },
+    { PwrCmdWrite, 0x00000000, mmCP_ME_CNTL                               },
+    { PwrCmdWrite, 0x15000000, mmCP_ME_CNTL                               },
+    { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL                              },
+    { PwrCmdWrite, 0x50000000, mmCP_MEC_CNTL                              },
+    { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+    { PwrCmdWrite, 0x0840800a, mmCP_RB0_CNTL                              },
+    { PwrCmdWrite, 0xf30fff0f, mmTCC_CTRL                                 },
+    { PwrCmdWrite, 0x00000002, mmTCC_EXE_DISABLE                          },
+    { PwrCmdWrite, 0x000000ff, mmTCP_ADDR_CONFIG                          },
+    { PwrCmdWrite, 0x540ff000, mmCP_CPC_IC_BASE_LO                        },
+    { PwrCmdWrite, 0x000000b4, mmCP_CPC_IC_BASE_HI                        },
+    { PwrCmdWrite, 0x00010000, mmCP_HYP_MEC1_UCODE_ADDR                   },
+    { PwrCmdWrite, 0x00041b75, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000710e8, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000910dd, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000a1081, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000b016f, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000c0e3c, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000d10ec, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000e0188, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00101b5d, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00150a6c, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00170c5e, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x001d0c8c, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x001e0cfe, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00221408, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00370d7b, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00390dcb, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x003c142f, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x003f0b27, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00400e63, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00500f62, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00460fa7, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00490fa7, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x005811d4, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00680ad6, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00760b00, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00780b0c, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00790af7, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x007d1aba, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x007e1abe, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00591260, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x005a12fb, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00861ac7, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x008c1b01, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x008d1b34, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a014b9, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a1152e, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a216fb, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a41890, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a31906, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a50b14, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00621387, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x005c0b27, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00160a75, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00010000, mmCP_HYP_MEC2_UCODE_ADDR                   },
+    { PwrCmdWrite, 0x00041b75, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000710e8, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000910dd, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000a1081, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000b016f, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000c0e3c, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000d10ec, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000e0188, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00101b5d, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00150a6c, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00170c5e, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x001d0c8c, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x001e0cfe, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00221408, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00370d7b, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00390dcb, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x003c142f, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x003f0b27, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00400e63, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00500f62, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00460fa7, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00490fa7, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x005811d4, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00680ad6, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00760b00, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00780b0c, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00790af7, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x007d1aba, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x007e1abe, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00591260, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x005a12fb, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00861ac7, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x008c1b01, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x008d1b34, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a014b9, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a1152e, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a216fb, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a41890, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a31906, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00a50b14, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00621387, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x005c0b27, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x00160a75, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+    { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+    { PwrCmdWrite, 0x540fe800, mmCP_DFY_ADDR_LO                           },
+    { PwrCmdWrite, 0x7e000200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e020201, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e040204, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e060205, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x54106f00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000400b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00004000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00804fac, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+    { PwrCmdWrite, 0x540fef00, mmCP_DFY_ADDR_LO                           },
+    { PwrCmdWrite, 0xc0031502, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00001e00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+    { PwrCmdWrite, 0x540ff000, mmCP_DFY_ADDR_LO                           },
+    { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000145, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc810000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdcc10000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdd010000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdd810000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4080061, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24ccffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3cd08000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9500fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1cd0ffcf, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d018001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4140004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x050c0019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x84c00000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000023, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000067, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000006a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000006d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000079, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000084, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000008f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000099, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800000a0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800000af, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4080007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x388c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x08880002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98800003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000002d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28080001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d808001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24cc0700, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113255, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d10ffdf, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x10cc0014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d10c017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d0d000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14cc0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000005d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14d00011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9500fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c01b10, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00e0080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00e0800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x280c0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x280c0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x280c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000069, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28080001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ca88004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800079, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc00006f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28180080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d10c017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97400001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc810000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd4c0380, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdcc0388, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55dc0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdcc038c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce0c0390, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce0c0394, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce4c0398, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56640020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce4c039c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce8c03a0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56a80020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce8c03a4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcecc03a8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcecc03ac, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf0c03b0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57300020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf0c03b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf4c03b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57740020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf4c03bc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf8c03c0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57b80020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf8c03c4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfcc03c8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57fc0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfcc03cc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c0fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05dc002f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc12009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d200a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc012009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25e01c00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12200013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25e40300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25e800c0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25ec003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e25c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eae400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de5c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xddc10000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31100006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9500007b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc1c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc1c200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4df0388, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4d7038c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d5dc01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4e30390, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4d70394, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d62001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4e70398, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4d7039c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d66401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4eb03a0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4d703a4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d6a801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4ef03a8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4d703ac, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d6ec01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4f303b0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4d703b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d73001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4f703b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4d703bc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d77401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4fb03c0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4d703c4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d7b801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4ff03c8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4d703cc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d7fc01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4d70380, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4080001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1c88001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc0e0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c0000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc01e3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3cd00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95000008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0085, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc006a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc01e3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3cd00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900fffa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4080001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1c88001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400051, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04180018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aac0027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce813265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd80002f1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04080002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x08880001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080230, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080228, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000367, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9880fff3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04080010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x08880001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd80c0309, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd80c0319, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9880fffc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00e0100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d0003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d4001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x155c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05e80180, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x202c003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc410001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000031, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900091a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05280196, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d4fe04, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800001b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000032b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000350, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000352, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000035f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000701, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000047c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000019f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc419325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d98001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd81325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4140004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0044, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27fc0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9400036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15540008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd40005b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd40005d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840006d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11540015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19a4003c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1998003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1af0007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1264001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15dc000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d65400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a38003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd5c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7df1c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800045, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411326a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc415326b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc419326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d326d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425326e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293279, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd000056, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800058, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00059, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x259c8000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce40005a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29988000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd000073, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411326f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17300019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25140fff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800003a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001b6d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4153279, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd00005f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000075, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26f00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15100010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d190004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd000035, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000035, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1af07fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04340022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4412e01, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0434001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdf030000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4412e40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c031, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43dc031, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04343000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf413267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd1c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45dc0160, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc810001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b4c0057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f4f400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55180020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x248dfffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc12e00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1af4007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33740003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26d80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1ae8003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9680000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26680001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce413277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253348, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce413348, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253348, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b400003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x958000d8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000315, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04303000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26680001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800041, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1714000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25540800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x459801b0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d77400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x199c01e2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e5e4002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3e5c0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3e540002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1334e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01334f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd413350, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813351, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd881334d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193273, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3275, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3271, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113270, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4153274, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50cc0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cdcc011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05900008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd00006a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc0006b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3272, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d594002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc12e23, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd012e24, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc12e25, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15540002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b340057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b280213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980198, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55e40020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd40000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd40000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x20cc003c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc13249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113274, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdd430000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc01e0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29dc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2d540002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x078c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07d40000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001239, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04f80000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x057c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc414000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd5c005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840007c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400069, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c018a6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4412e22, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800007c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c018a2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd4c005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9680fffc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800002e3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd0c002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9680fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800002e3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000069, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013273, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013275, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9540188f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc013cfff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd0c009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc13249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9680000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x38d00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04cc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdcc30000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c01882, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000304, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840002f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0016, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0016, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x49980198, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55e40020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x459801a0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000329, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc812e00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16ec001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1998003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00031, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce00000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a18003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d43c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4093249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1888003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc419324c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x259c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1598001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c0000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14d80011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24dc00ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31e00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31dc0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580fff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95801827, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840002f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14dc0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c0fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800006d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32200002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a0000ad, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04080000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27fc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c0015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1af4003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9740004d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4080060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ca88005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24880001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f4b4009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97400046, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313274, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d33400c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97400009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28240100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a4004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400079, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1eecffdd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf013273, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf013275, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800003c3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc429326f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aa80030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28240001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a8004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800035, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3272, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x10cc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19e80042, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc0006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e8e800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de9c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3271, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293270, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50cc0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ce8c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd30011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11e80007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd300001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b30003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4240059, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1660001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e320009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0328000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e72400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0430000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02ac000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d310002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa87600, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd0c011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd0c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280222, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4280058, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x22ec003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013273, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce813275, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800007b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8380018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57b00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04343108, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc429325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c3000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13740008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2374007e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32a80003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18ec0057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e40213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc0199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cecc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ce4c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800003e7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980104, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x49980104, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800003f2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000448, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c0016, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c0016, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c0015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf813279, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf41326e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01326d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c0000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x254c0700, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x10cc0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a641fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0726, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a640200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1237b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8813260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4240033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4280034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xde430000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce40000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c01755, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9680000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce80000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xde830000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce80000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c0174c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4393265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bb80040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf813265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100044, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19180024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x551c003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000043d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00c8000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840006c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28200000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000043f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x282000f0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113255, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000053, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x195c00e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2555fff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0360001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32200002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc5e124dc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef6c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e624001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80fff9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2555fff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3255, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353259, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980158, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x49980158, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980170, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16200010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc429324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd000008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d43c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x195400e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1154000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18dc00e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05e80488, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d0006c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18f807f0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e40077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18ec0199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000048e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000494, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800004de, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000685, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000686, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800006ac, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1ccc001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1264000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d79400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e7a400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52a8001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15180001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d69401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x202c007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95000008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aec0028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d325c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800004cc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc419324e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26e8003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aec003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12f4000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d324d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d75401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d290004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f8f4001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f52800f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50e00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800004d1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d0dc002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x6665fc00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e5e401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da1c011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd140000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a644000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f534002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x6665fc00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e76401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800004d7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aec003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3257, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213259, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12f4000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d75401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52200002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da1c011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd140000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a644000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x202c003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x259c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15980004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05e804e3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800004e7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800004f0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000505, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc435325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x277401ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf41325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9640fff4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17e00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd84131db, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26edf000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8413260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05a80507, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000050c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000528, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000057d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800005c2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800005f3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c004d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00063b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801326f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000624, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1be00fe4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce413260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000066, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400068, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c004d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400067, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00063b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801326f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000624, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c0060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ed6c005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113271, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4153270, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193272, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3273, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d51401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113274, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213275, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253276, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400061, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2730000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7db1800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05dc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00062, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd000063, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000064, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400065, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b700057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b680213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x46ec0188, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17e00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26e01000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9c131fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x191807e4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x192007ec, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x69dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de20014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x561c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013344, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc13345, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425334d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc419334e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d334f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213350, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253351, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x46ec01b0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800068, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2010007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1910003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9500fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd00001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc410000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd00001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc410000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2010003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x191807e4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9540000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013344, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013345, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180050, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0052, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280042, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813273, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc13275, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000068, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400067, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07d40000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00124f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x057c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x46ec0190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4153249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2154003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bd800e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd9c005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd80005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420004d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e1e000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd413249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01326f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28340001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f598004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800035, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1be800e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce80005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801327a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800005f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000075, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800007f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424004c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41326e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28240100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a4004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400079, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc435325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x277401ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41325e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf41325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xda000068, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9540002d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425334d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc419334e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d334f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213350, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253351, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x46ec01b0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1be000e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0360001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc63124dc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef6c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80fff9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fc14001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x194c1c03, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc0003b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c002d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000697, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420004a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x194c00e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc0005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c004c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431326d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27301fff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce00005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cf0c00d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25100007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31100005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900008e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000075e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x202c007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a9feff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d30b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce813265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00ac006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00e0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28880700, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c0006de, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14cc0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x30d4000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x10cc0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41530b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19980028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800006c8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8380023, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fa38011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x282c2002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd3800025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x202400d0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28240006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d8003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840003c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd81a2a4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c0000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420004a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x194c00e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc0005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c004c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431326d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27301fff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce00005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cf0c00d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000712, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x194c1c03, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc0003b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c002d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05e80714, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000071c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000720, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000747, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000071d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800007c4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000732, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000745, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000744, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000072e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c0000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a64008c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce413265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b301fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000075e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c0fff1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000723, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41f02f1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000743, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8813247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd000008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c0ffde, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000072e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd84131db, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8413260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c3000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc8000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c004a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x195800e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd80005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418004c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd81326e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc0005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dd7fff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc13265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51e00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e1a001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x46200200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04283247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1af80057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1af40213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f6f400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2000025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc6990000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x329c325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x329c3269, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x329c3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc01defff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d8009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000078a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25980000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fff2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03e7ff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f3f0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1f30001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf013249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03e4000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013255, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d30b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bf0003a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000b80, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x203c003a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300700, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf0130b7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x46200008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2000025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4080007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x259c0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31dc0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c3000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18ec0057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e40213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc0199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cecc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ce4c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000448, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31980002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19580066, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0120001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11980003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da18001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1c200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d24db, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd0c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd9c005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40fff8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580137b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00ee000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1c200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113269, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19080070, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x190c00e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2510003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2518000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05a80809, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000080e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000080f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000898, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000946, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800009e1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04a80811, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000815, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000834, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3045, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1c091, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31300021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd84002f1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293059, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56a8001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000241, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000084a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43130b6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02f0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec130b6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4252087, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5668001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a80005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd80130b6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000084a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431ecaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02e0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec130b6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd80130b6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31300021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd84002f1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293059, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56a8001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00021d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c0005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001a41, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43b02f1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec80278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56f00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf080280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8813247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd80802e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31100011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x950001fa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02e0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aec0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc01c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0180001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11a40006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de6000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x10e40008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e2e000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d10ffdf, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2110003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013255, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d10ff9e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0245301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801325f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0121fff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29108eff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0127ff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0131fff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801326d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801326e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013279, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x08cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0100010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd2400c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0180003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd1c002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04a8089a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000089e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800008fa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000945, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000945, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31300022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x459801e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2738000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8300011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8340011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9740002f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13b80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc79d3300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc7a13301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8393300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0260001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce793301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x964012a4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c028009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800008d2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce40001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x242c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06ec0400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02620c0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41c078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce81c080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01c082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57240020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41c083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0260400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eae8001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f2f0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800008d2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdf93300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce393301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000903, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31240022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ec30011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32f80000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x67180001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0bfc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd981325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000915, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9c1325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0fff6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f818001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001606, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d838001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3259, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16240014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a2801f0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e2a000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e5e400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013259, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00075e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4af0228, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x66d80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1330000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13f40014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07fc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33e80010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9680ffec, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04a80948, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000094c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000099b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800009e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800009e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x459801e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2738000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8300011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8340011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9740002c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13b80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc79d3300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc7a13301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8393300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0260001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce793301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x964011fe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c028009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000978, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce40001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x242c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06ec0400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0260010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41c078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01c080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57240020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41c081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce81c082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0260800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eae8001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f2f0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000978, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdf93300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce393301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dda801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e838011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001802, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x469c0390, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4240011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4280011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c0014df, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31280014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce8802ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800062, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31280034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04a809e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800009ec, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a45, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a59, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a59, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b30258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4a70250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x53300020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e72401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x66740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97400041, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04383000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4393267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b38007e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33b40003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b400003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x4598001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9740002f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf4002eb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf4002ec, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf4002ed, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf4002ee, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04382000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001715, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04382000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0ffbc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431ecaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a55, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43130b6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x233c0032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc130b6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf0130b6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49302ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04180001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5198001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193269, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2598000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd80002f1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013268, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x53b8001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7db9801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000a5e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c01106, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc412e01, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc412e02, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc412e03, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c010fd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50640020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ce4c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc80c0072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x58e801fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18dc01e2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e5e4002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3e5c0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3e540002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000aa2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9540000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x44cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55900020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4140011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000aa2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x44cc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd812e01, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd012e02, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd412e03, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc410001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4140028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95000005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1e64001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14d00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ab1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a0010ac, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd880003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c0003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc010ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d403f7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d0cc009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41b0367, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d958004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d85800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc1e0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d001fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05280adc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000af1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000adf, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ae7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000ace, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd8d2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d803f7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc010ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d0cc009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11940014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29544001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29544003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000af4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd44d2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd44dc000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d0003c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95000006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000ace, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd8d2c00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000b0a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd44d2c00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28148004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d800ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4593240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c0105e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x199c0034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313255, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef3400c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14e80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a8000af, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c01043, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18a01fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3620005c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a00000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2464003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc6290ce7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16ac001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ac003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ee6c00d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a00fff8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000367, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9640102e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x199c0037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19a00035, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c0005d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16f8001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9780000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc035f0ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e764009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19b401f8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13740008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e76400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce413248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x199c0034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1ae4003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000b7c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aec003c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19a4003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12ec001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02e4000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc01e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13fc0018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dbd800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d98ff15, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x592c00fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd80000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12e00016, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x592c007e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12e00015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11a0000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1264001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1620000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12e4001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5924007e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19a4003c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013257, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd413258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc429325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00fdb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9780f5ca, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001b6d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d324e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431324d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07740003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x269c003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e5e4004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f67000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f674002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x53740002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef6c011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1ab42010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1ab8c006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16a8000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a80800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b740000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf40001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000bec, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000b47, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b34060b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04340100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ec00ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03a8004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef6c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f3b000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc410001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc415325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18580037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x262001ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d15400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d54001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a80004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14f00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd280200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd680208, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcda80210, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b400014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a80004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc6930200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc6970208, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc69b0210, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd900003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd940003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9000040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9400040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14fc0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24f800ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33b80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d83c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4093249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1888003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc419324c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x259c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1598001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00016, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14d80011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24e000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x321c0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580ffee, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c30, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9480000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800f29, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800f23, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800f1a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9600f502, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c0f500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000f05, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1f30001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16e4001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9640f4f4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc434000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33740002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b40f4f1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aec003c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12ec001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02e4000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12780001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bb80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00ac005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00e0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc8000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28884900, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ff3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400ee1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c40a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c40c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c40d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d0007f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15580010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x255400ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01c411, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd81c40f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41c40e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c410, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e80033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18ec0034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c414, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c415, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd81c413, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41c412, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18dc0032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c030011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c038011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431c417, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc435c416, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439c419, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43dc418, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf413261, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf013262, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13263, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf813264, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18dc0030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d77000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000cd6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51b80020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x53300020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f97801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f37001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f3b000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000cd6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ca7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18dc0031, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc435c40b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9740fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4280032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f8cc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000cf4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc032800b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d42011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24cc007f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd4c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800e6c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x596001fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12200009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ce0c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x505c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50600020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc0001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd140001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8240010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e5e800c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x122c0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000d1f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8240010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x566c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce413261, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13262, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b740008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x566c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce413261, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec13262, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f8cc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000d57, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0328009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04143000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd413267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e51001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4153267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d2d0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19640057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19580213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19600199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da6400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1000025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04142000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd413267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4153267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d40030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d80034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05280d83, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c424001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000d8a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000d95, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000db1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000d95, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000dbc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11540010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e010001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d75400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4610000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580f3d8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000016, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x526c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e80058, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e2ec01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c00072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5ae0073a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ea2800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580f3c6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc3a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80fffb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980fff5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16200002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01c405, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd441c406, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580f3b1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439c409, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11540010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29540002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4610000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580f3a5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00da7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5aac007e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12d80017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56a00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e82400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e58c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19d4003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28182002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc011000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c908009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x20880188, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x54ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x20240090, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28240004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000016, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf80003a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd901a2a4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1624001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd841325f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000039, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc429325f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ac0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ac0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b301ff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9680000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400039, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c0001a2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1910003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2220003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e2a000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000039, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18dc003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d40030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18fc0034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24e8000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80e71, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000edd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000e91, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000e91, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ea1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000eaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000e7c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000e7f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000e7f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000e87, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000e8f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9e001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a200008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213262, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253261, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a200008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213264, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253263, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e82005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51e00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da1801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1800072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8180072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x59a001fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12200009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ea2800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15980002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd81c400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421c401, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400041, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425c401, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac2580, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac260c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac0800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac0828, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac2440, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac2390, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac0093, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac31dc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac31e6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ede, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39ac7c06, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db07c00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39acc337, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db0c330, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39acc335, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db0c336, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39ac9002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db09001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39ac9012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db09011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39acec70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db0ec6f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc5a10000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc5a50000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05280eea, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ef1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000efe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f11, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f2e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000efe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f1f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0f26f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e80058, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7daec01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c00072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5af8073a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eba800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0f25c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15980002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd81c405, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01c406, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41c406, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0f24e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439c409, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40f247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0f240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac2580, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac260c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac0800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac0828, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac2440, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac2390, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac0093, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac31dc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31ac31e6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ef2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39ac7c06, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db07c00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39acc337, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db0c330, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39acc335, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db0c336, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39acec70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db0ec6f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39ac9002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db09002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39ac9012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3db09012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ef1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc434000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b740008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b780001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c1325e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf80001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c034001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c038001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e0007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32240003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32240000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01c080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41c081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f88, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51640020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e52401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2400072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce81c080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56ac0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26f0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01c081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1af000fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1334000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24e02000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f63400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e00074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32240003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32240000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd81c082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc1c083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000f9d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51e40020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e5a401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2400072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce81c082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56ac0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26f0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01c083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1af000fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13380016, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e00039, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12200019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e0007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1220001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e00074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12200014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf81c078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc1c084, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18dc003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31140005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31140006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05280fb7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28140002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000fc2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000fd1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ff2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ff2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e80039, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52a8003b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d69401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd140004b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc414000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04180001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d958004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800035, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9500000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x159c0011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x259800ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31a00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31a40001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e25800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c0fff5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580fff4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000fef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411326f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d100010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01326f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc011000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33b40003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97400003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0340008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000ffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c908009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x282c2002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x208801a8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x20240030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28340000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x507c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d7d401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x557c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28342002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000102f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1cccfe08, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00b33, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840003c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da2400f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da28002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e1ac002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d2ac002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3ef40010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b40f11d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf81325e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xde410000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdcc10000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdd010000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdd810000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xddc10000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xde010000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c024001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8100086, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5510003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001075, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4140025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d15800f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d15c002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d520002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cde0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3e20001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c0030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1325e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001071, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00b01, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc200000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc1c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc240000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc240000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc40003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4080029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18a400e5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12500009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x248c0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x200c006d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd0c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x200c0228, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd0c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc410002b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18881fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d4072c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc00d1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd4c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3094000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x38d80000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x311c0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x30940007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1620001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000023, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800010c4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00041, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418002c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x259c007f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19a00030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc0001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400023, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800010cb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x199c0fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc0001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400023, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800010cb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000023, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000aac, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc434002e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2020002c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17780001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07a810d8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000104c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc400040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x200c007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28240007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xde430000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x192400fd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06681110, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19180070, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19100078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18f40058, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5978073a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001117, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001118, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000112d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001130, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001133, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24ec0f00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32ec0600, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24ec0f00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32ec0600, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc81c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00116b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02a0200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e8e8009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x22a8003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x22a80074, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2774001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13740014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eb6800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25ecffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55700020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15f40010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13740002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x275c001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15dc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39e00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dc1c01e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05e40008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dc2001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05e40008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e62000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da58001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001165, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dc2001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e1a0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e0d000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95000007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e02401e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06640008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05d80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dc2401e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da58001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05e00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da2000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9600ffe6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00116b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce00001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce81c078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1c080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41c082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01c083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x22640435, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0528117e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x312c0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001185, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001182, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001182, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03a0400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1198001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d81c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc130b7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf8130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0049, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19a000e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29a80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de2c00c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421325e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26200010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc415326d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc420007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce40003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800011a3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d654001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41326d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c020001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4240081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4140025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800011b6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253279, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc415326d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2730003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3b380006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3f38000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800011b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800011b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0430000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb10004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e57000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e578002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d67c002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0be40001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d3a4002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x202c002c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421325e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26200010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3e640010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce81325e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc434002e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17780001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07a811cf, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00feb8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x954009a7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1c07c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c07d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c08c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c079, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01c07e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18f0012f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18f40612, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc00c1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cf7400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x39600004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0140004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11600001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18fc003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400041, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800011ee, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a6c003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800011e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428002c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ac007f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1ab00030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aac0fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001205, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11600001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0fffa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27fc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd841c07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc0078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ffbc00c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03a2800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801c07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03ae000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf81c200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03a0800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03ae000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf81c200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03a4000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x30d00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000052, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9640090f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1514001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19180038, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x30dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d324e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431324d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1ab0c006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000127f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d3258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313257, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353259, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc429325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1ab0c012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a0003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e624004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f67800f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04340000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x53740002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef6c011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1ab42010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16a8000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a80800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b740000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf40001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1514001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c0012e1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x964008d7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9800036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300677, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800012aa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b34060b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04340100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ec00ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03a8002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef6c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7edec00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f3b000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4140032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc410001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1858003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99800007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d0cc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d0006c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d407f0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2598003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d190004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d5d4001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d52000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800012d8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d514002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800012d8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193259, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d958001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd5c002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813259, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc1325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1ccc001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14f00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b40000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd980003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9c0003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9800040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd9c00040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33f80003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800051, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b74003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b4c00f8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50700020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04e81324, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50600020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x30e40004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d71401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x596401fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b74008d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e76400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a640000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000132c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000133b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001344, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42530b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a68003a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2024003a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25980700, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11980014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d19000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce4130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce40001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4240011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de6800f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffea, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce40001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8240011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de6800f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffe0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28182002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x20240030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b4c00f8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28340000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x507c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x30e40004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d7d401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x557c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28342002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf81a2a4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c007eb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d0d001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x591c01fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45140210, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x595801fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11980009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29dc0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc0001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1624001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400069, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a307fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x23304076, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc00e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x10cc0015, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x4514020c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a2001e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12200014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a204001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a64003c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1264001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15dc000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dcdc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e5dc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04340022, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4412e01, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0434001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdf030000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4412e40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c030, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41c031, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x248dfffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc12e00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc812e00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45140248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013257, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0434000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdb000024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45540008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013259, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0337fff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f220009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55300020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d01c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c01d0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06ec0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f01c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8240072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd240001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19682011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5a6c01fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12ec0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eeac00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aec0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99800007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdf830000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfa0000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4380007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17b80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d40038, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9540073d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18c80066, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x30880001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd910000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x4220000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24e80007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24ec0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc5310000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001465, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18f02011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5aec01fc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12ec0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aec0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a8146a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f1f0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f1b400f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001478, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f1b400e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001478, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f1b400c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f1b400d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f1b400f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f1b400e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f334002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97400014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000147b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b400012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e024001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000144a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fbfc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94800007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd910000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800014a9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0328007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03a0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf8130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd9c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45dc0390, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b380057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b340213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c424001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c428001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c42c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c430001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a0800fd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x109c000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd9c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc13265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce080228, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9880000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce480250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce880258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080230, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0ec75, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26180001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce480250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce880258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52a80020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x66580001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc80260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec80288, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf080290, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec80298, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf0802a0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf4802a8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc802b0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd80802b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x178c000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27b8003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cf8c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf8802c0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc802c8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf8802d0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf8802d8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25b8ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f0238, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24cc000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd2800c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc5230309, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e3a400c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001539, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd08034b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd880353, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49b0353, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f0228, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd14005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000154f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd080238, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd08034b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x08cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3d200008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd900309, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8100319, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04340801, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd910ce7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4190ce6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d918005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d918004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd810ce6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdd1054f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000156e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x090c0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdcd050e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x110c0014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc4001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41230a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41230b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41230c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc41230d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc480329, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc48032a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc4802e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000055, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f02e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d8003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09940001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x44100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580002c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x69100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000157f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4970290, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49b0288, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49b02a0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49f0298, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x041c0040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dcdc002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d924019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d26400c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0fffa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001579, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d010021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d914019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd480298, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd8802a0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x10d40010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12180016, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc51f0309, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d95800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d62000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd9c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdd00309, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce113320, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f02e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49b02b0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18dc01e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd9400e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c0001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800015aa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f0238, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4a302b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12240004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e5e400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4ab02a8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce4c0319, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d9d8002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ea14005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800015bc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e624004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d25000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0fff4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd0d3330, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce0802b8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd8802b0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4ab02e0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aa807f0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f02d0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49702d8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49b02c8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49f02c0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96800028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d4e000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9600000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d964002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d694001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cde4002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de94001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd64002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d694001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800015cd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d698002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd4802d8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x129c0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc50f0319, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11a0000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11140001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e1e000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1198000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd953300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e0e000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a8000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce953301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce100319, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b70280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73800a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x536c0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9780eb68, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001609, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x30b40000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b400011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b70258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b30250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x53780020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb3801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7faf8019, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x67b40001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x57b80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4bb0260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fab8001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf880260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x66f40001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97400005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4353247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f7f4009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b40fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fff7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x269c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a00018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12200003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a00060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x269c0018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a00007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a40060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11dc0006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12200006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de5c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b70228, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f514005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001644, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b30248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd080240, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f130005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001688, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04340801, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f130004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01051e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42d051f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ed2c005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26ec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96c0fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01051f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000055, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc5170309, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x195c07f0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x196007f6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04340000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04340001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x53740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x6b740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001665, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4a702a0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4ab0298, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f634014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e76401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56680020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8113320, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce480298, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce8802a0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc5170319, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b702b0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x255c000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f5f4001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8113330, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf4802b0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11340001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x195c07e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x196007ee, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8353300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e1e4001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8353301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce4802d0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8100309, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8100319, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc48f0250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd4c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x64d80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x54cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580005c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dc24001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd2000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3255, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7df5c00c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25980040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800016f1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a7003e6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a7000e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a700064, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800016df, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800016f2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940ff9c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd80802e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18fc0064, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00042, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dd9801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x45980400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b380057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b340213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14f4001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x192807fa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4bf0258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4a70250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x53fc0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e7e401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x667c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eebc00c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fff8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x43300007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x53300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7db30011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd3000025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc03ec005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bfca200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x192807fa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d1d0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2110007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x203c003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c0017f5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18fc01e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00185b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b40ffd5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0ea24, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14d4001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d52400e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49f0258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4a30250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400017, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d534002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4af0270, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dae4005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32e0001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec80270, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000174f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00178a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b40fff3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4ab0268, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7daa4005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32a0001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001765, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d1d0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2110007d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8013256, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c0017f2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4113248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b3034b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f13000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf013248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001855, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32a4001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd080260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce880268, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940ffc0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ec28001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32e0001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9640005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253255, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431324f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e72400c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a80040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9680fff7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aa4003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400049, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aa400e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32680003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a800046, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9640000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4293260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1aa400e4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32640004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800017e2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc027ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2e6400ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a4009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a800ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4240009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19e403e6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26680003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12a80004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19e400e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19e40064, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16a40005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06640003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce412082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a640003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800017d0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16a40005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce412082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ea64002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4292083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ea68005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a80ffdf, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26a400ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40ffca, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2024007b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800017e3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4a70280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4ab0278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7eae8014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56680020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce480278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce880280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec80270, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800017fe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800017fe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43b02eb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42302ec, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf813245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fa3801a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x47b8020c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x15e00008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1220000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2a206032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x513c001e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e3e001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000180f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b3c0077, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ff3000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd200000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd3800002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dc30001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc1e0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04380032, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf80000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc413248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3269, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27fc000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33fc0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4413249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0bfc0021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd441326a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x173c0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300303, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f3f0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ff3c004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13084, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001842, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4413249, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x23fc003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc1326d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0bb80026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdf830000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd441326e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4393265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1fb8ffc6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xddc30000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf813265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc0000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001852, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc0000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001878, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49f02e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c00018, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c0012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001878, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41f02ed, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42302ee, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e2a0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013084, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28340001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x313c0bcc, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x393c051f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3d3c050e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x393c0560, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3d3c054f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x393c1538, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3d3c1537, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b740800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e8007c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c42c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a8189a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800018c5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800018f2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d0007e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09240002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc42130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a24002c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2020002c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1198001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x10cc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14cc0004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7cd8c00a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc130b7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce0130b5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x5978073a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bb80002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf800024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9600e8a8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9640e8a5, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800018a9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc55b0309, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3d5c0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09780001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dad800c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0ffd2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580fff9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x442c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7df9c00c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c13260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd901325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940fff1, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x66d80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26240007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940fff7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc023007f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19e4003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7de1c009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dee000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96000007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c13260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd901325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x261c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99c0fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940fff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18e00064, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06281911, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14f4001d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24cc0003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001915, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x800019af, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001a2b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc48032b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc480333, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc48033b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc480343, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98800011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x46640400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04203000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b3c0057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b200213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e3e000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04180000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f438001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00068, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213254, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a1c003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00065, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e1e0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97800062, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x43bc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fcbc001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc7df032b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e1fc00c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0101, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c0102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001994, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001982, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00ffcb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc1325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001995, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc1325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98800009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x41bc0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x53fc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e7fc011, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd3c00025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0012, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x653c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dbd8001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940ff8f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc55b0309, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x3d5c0010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x05540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d91800c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580fff8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09780001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9580005d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200101, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400058, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dc24001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7df9c00c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95c00053, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e41c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a70003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a7000e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33240003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a400046, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1a7000e4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001a21, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f270009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x266400ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27240003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06640002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16700005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001a0f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x16700005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e730002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4252083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e724005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a40ffdf, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x267000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001a22, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940ff9f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001a31, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213246, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4253245, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e26401a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x46640400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04203000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce013267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4213267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b180057, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b200213, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e1a000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce000024, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800060, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4193247, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200101, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x30f00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95800056, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001aa2, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001a90, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf00325b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001aa3, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49b02e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99800005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd2400025, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x4664001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940ff9c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc49b02e9, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99800008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc430000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2b300008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf000013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x244c00ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc4c0200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc44f0200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc410000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc414000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d158010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x059cc000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccdd0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0037, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000049, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c003a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9500e69a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d0003b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d40021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd840004a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c003c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x14cc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c00028, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000033, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc438000b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x27fc0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd841c07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1bfc0078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7ffbc00c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x99000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0120840, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x282c0040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001ae8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0121841, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x282c001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01c07c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04200004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9ac0fffb, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801c07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8000034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940e66b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800004a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0036, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9900fffe, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18cc0021, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc00047, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc000046, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0039, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c003d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24d003ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d47fea, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x18d87ff4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd00004c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd40004e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd80004d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41c405, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01c406, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c406, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c406, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x295c0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8c1325e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcdc0001a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11980002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x4110000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0160800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7d15000a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0164010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41c078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c080, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd81c082, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc01c083, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01c084, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400048, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c003b, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801c40a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd901c40d, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801c410, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801c40e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd801c40f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc40c0040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9940ffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04140096, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1c400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc411c401, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9500fffa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424003e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04d00001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x11100002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd01c40c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0180034, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd81c411, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd841c414, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0a540001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcd41c412, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x2468000f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc419c416, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x41980003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc41c003f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7dda0001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x12200002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x10cc0002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xccc1c40c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd901c411, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce41c412, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xce292e40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc412e01, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc412e02, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc412e03, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc120000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x31144000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xcc3c000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x33f80003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x9780e601, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x188cfff0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x04e40002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400006, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x96400003, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80001b74, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+    { PwrCmdWrite, 0x54106500, mmCP_DFY_ADDR_LO                           },
+    { PwrCmdWrite, 0x7e000200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e020204, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc00a0505, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xbf8c007f, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb8900904, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb8911a04, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb8920304, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb8930b44, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x921c0d0c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x921c1c13, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x921d0c12, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x811c1d1c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x811c111c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x921cff1c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000400, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x921dff10, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000100, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x81181d1c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e040218, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+    { PwrCmdWrite, 0x54106900, mmCP_DFY_ADDR_LO                           },
+    { PwrCmdWrite, 0x7e080200, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x7e100204, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xbefc00ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00010000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x24200087, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x262200ff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000001f0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x20222282, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x28182111, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+    { PwrCmdWrite, 0x54116f00, mmCP_DFY_ADDR_LO                           },
+    { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb4540fe8, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000041, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000000c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x54116f00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb454105e, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000c0, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x54117300, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb4541065, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000500, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000001c, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x54117700, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb4541069, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000444, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x0000008a, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x54117b00, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+    { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL                              },
+    { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL                              },
+    { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x54116f00, mmCP_MQD_BASE_ADDR                         },
+    { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI                      },
+    { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI                        },
+    { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR                 },
+    { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI              },
+    { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE                  },
+    { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID                              },
+    { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL                        },
+    { PwrCmdWrite, 0x00000005, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x54117300, mmCP_MQD_BASE_ADDR                         },
+    { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI                      },
+    { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI                        },
+    { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR                 },
+    { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI              },
+    { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE                  },
+    { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID                              },
+    { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL                        },
+    { PwrCmdWrite, 0x00000006, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x54117700, mmCP_MQD_BASE_ADDR                         },
+    { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI                      },
+    { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI                        },
+    { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR                 },
+    { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI              },
+    { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE                  },
+    { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID                              },
+    { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL                        },
+    { PwrCmdWrite, 0x00000007, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x54117b00, mmCP_MQD_BASE_ADDR                         },
+    { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI                      },
+    { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI                        },
+    { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR                 },
+    { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI              },
+    { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE                  },
+    { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID                              },
+    { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL                        },
+    { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000104, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000204, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000304, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000404, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000504, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000604, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000704, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000005, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000105, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000205, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000305, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000405, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000505, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000605, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000705, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000006, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000106, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000206, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000306, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000406, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000506, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000606, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000706, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000007, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000107, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000207, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000307, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000407, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000507, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000607, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000707, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000008, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000108, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000208, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000308, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000408, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000508, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000608, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000708, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000009, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000109, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000209, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000309, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000409, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000509, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000609, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000709, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+    { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+    { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+    { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL                            },
+    { PwrCmdWrite, 0x01010101, mmCP_PQ_WPTR_POLL_CNTL1                    },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+    { PwrCmdEnd,   0x00000000, 0x00000000                                 },
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
new file mode 100644
index 0000000..91795ef
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _HARDWARE_MANAGER_H_
+#define _HARDWARE_MANAGER_H_
+
+
+
+struct pp_hwmgr;
+struct pp_hw_power_state;
+struct pp_power_state;
+enum amd_dpm_forced_level;
+struct PP_TemperatureRange;
+
+struct phm_fan_speed_info {
+	uint32_t min_percent;
+	uint32_t max_percent;
+	uint32_t min_rpm;
+	uint32_t max_rpm;
+	bool supports_percent_read;
+	bool supports_percent_write;
+	bool supports_rpm_read;
+	bool supports_rpm_write;
+};
+
+/* Automatic Power State Throttling */
+enum PHM_AutoThrottleSource
+{
+    PHM_AutoThrottleSource_Thermal,
+    PHM_AutoThrottleSource_External
+};
+
+typedef enum PHM_AutoThrottleSource PHM_AutoThrottleSource;
+
+enum phm_platform_caps {
+	PHM_PlatformCaps_AtomBiosPpV1 = 0,
+	PHM_PlatformCaps_PowerPlaySupport,
+	PHM_PlatformCaps_ACOverdriveSupport,
+	PHM_PlatformCaps_BacklightSupport,
+	PHM_PlatformCaps_ThermalController,
+	PHM_PlatformCaps_BiosPowerSourceControl,
+	PHM_PlatformCaps_DisableVoltageTransition,
+	PHM_PlatformCaps_DisableEngineTransition,
+	PHM_PlatformCaps_DisableMemoryTransition,
+	PHM_PlatformCaps_DynamicPowerManagement,
+	PHM_PlatformCaps_EnableASPML0s,
+	PHM_PlatformCaps_EnableASPML1,
+	PHM_PlatformCaps_OD5inACSupport,
+	PHM_PlatformCaps_OD5inDCSupport,
+	PHM_PlatformCaps_SoftStateOD5,
+	PHM_PlatformCaps_NoOD5Support,
+	PHM_PlatformCaps_ContinuousHardwarePerformanceRange,
+	PHM_PlatformCaps_ActivityReporting,
+	PHM_PlatformCaps_EnableBackbias,
+	PHM_PlatformCaps_OverdriveDisabledByPowerBudget,
+	PHM_PlatformCaps_ShowPowerBudgetWarning,
+	PHM_PlatformCaps_PowerBudgetWaiverAvailable,
+	PHM_PlatformCaps_GFXClockGatingSupport,
+	PHM_PlatformCaps_MMClockGatingSupport,
+	PHM_PlatformCaps_AutomaticDCTransition,
+	PHM_PlatformCaps_GeminiPrimary,
+	PHM_PlatformCaps_MemorySpreadSpectrumSupport,
+	PHM_PlatformCaps_EngineSpreadSpectrumSupport,
+	PHM_PlatformCaps_StepVddc,
+	PHM_PlatformCaps_DynamicPCIEGen2Support,
+	PHM_PlatformCaps_SMC,
+	PHM_PlatformCaps_FaultyInternalThermalReading,          /* Internal thermal controller reports faulty temperature value when DAC2 is active */
+	PHM_PlatformCaps_EnableVoltageControl,                  /* indicates voltage can be controlled */
+	PHM_PlatformCaps_EnableSideportControl,                 /* indicates Sideport can be controlled */
+	PHM_PlatformCaps_VideoPlaybackEEUNotification,          /* indicates EEU notification of video start/stop is required */
+	PHM_PlatformCaps_TurnOffPll_ASPML1,                     /* PCIE Turn Off PLL in ASPM L1 */
+	PHM_PlatformCaps_EnableHTLinkControl,                   /* indicates HT Link can be controlled by ACPI or CLMC overrided/automated mode. */
+	PHM_PlatformCaps_PerformanceStateOnly,                  /* indicates only performance power state to be used on current system. */
+	PHM_PlatformCaps_ExclusiveModeAlwaysHigh,               /* In Exclusive (3D) mode always stay in High state. */
+	PHM_PlatformCaps_DisableMGClockGating,                  /* to disable Medium Grain Clock Gating or not */
+	PHM_PlatformCaps_DisableMGCGTSSM,                       /* TO disable Medium Grain Clock Gating Shader Complex control */
+	PHM_PlatformCaps_UVDAlwaysHigh,                         /* In UVD mode always stay in High state */
+	PHM_PlatformCaps_DisablePowerGating,                    /* to disable power gating */
+	PHM_PlatformCaps_CustomThermalPolicy,                   /* indicates only performance power state to be used on current system. */
+	PHM_PlatformCaps_StayInBootState,                       /* Stay in Boot State, do not do clock/voltage or PCIe Lane and Gen switching (RV7xx and up). */
+	PHM_PlatformCaps_SMCAllowSeparateSWThermalState,        /* SMC use separate SW thermal state, instead of the default SMC thermal policy. */
+	PHM_PlatformCaps_MultiUVDStateSupport,                  /* Powerplay state table supports multi UVD states. */
+	PHM_PlatformCaps_EnableSCLKDeepSleepForUVD,             /* With HW ECOs, we don't need to disable SCLK Deep Sleep for UVD state. */
+	PHM_PlatformCaps_EnableMCUHTLinkControl,                /* Enable HT link control by MCU */
+	PHM_PlatformCaps_ABM,                                   /* ABM support.*/
+	PHM_PlatformCaps_KongThermalPolicy,                     /* A thermal policy specific for Kong */
+	PHM_PlatformCaps_SwitchVDDNB,                           /* if the users want to switch VDDNB */
+	PHM_PlatformCaps_ULPS,                                  /* support ULPS mode either through ACPI state or ULPS state */
+	PHM_PlatformCaps_NativeULPS,                            /* hardware capable of ULPS state (other than through the ACPI state) */
+	PHM_PlatformCaps_EnableMVDDControl,                     /* indicates that memory voltage can be controlled */
+	PHM_PlatformCaps_ControlVDDCI,                          /* Control VDDCI separately from VDDC. */
+	PHM_PlatformCaps_DisableDCODT,                          /* indicates if DC ODT apply or not */
+	PHM_PlatformCaps_DynamicACTiming,                       /* if the SMC dynamically re-programs MC SEQ register values */
+	PHM_PlatformCaps_EnableThermalIntByGPIO,                /* enable throttle control through GPIO */
+	PHM_PlatformCaps_BootStateOnAlert,                      /* Go to boot state on alerts, e.g. on an AC->DC transition. */
+	PHM_PlatformCaps_DontWaitForVBlankOnAlert,              /* Do NOT wait for VBLANK during an alert (e.g. AC->DC transition). */
+	PHM_PlatformCaps_Force3DClockSupport,                   /* indicates if the platform supports force 3D clock. */
+	PHM_PlatformCaps_MicrocodeFanControl,                   /* Fan is controlled by the SMC microcode. */
+	PHM_PlatformCaps_AdjustUVDPriorityForSP,
+	PHM_PlatformCaps_DisableLightSleep,                     /* Light sleep for evergreen family. */
+	PHM_PlatformCaps_DisableMCLS,                           /* MC Light sleep */
+	PHM_PlatformCaps_RegulatorHot,                          /* Enable throttling on 'regulator hot' events. */
+	PHM_PlatformCaps_BACO,                                  /* Support Bus Alive Chip Off mode */
+	PHM_PlatformCaps_DisableDPM,                            /* Disable DPM, supported from Llano */
+	PHM_PlatformCaps_DynamicM3Arbiter,                      /* support dynamically change m3 arbitor parameters */
+	PHM_PlatformCaps_SclkDeepSleep,                         /* support sclk deep sleep */
+	PHM_PlatformCaps_DynamicPatchPowerState,                /* this ASIC supports to patch power state dynamically */
+	PHM_PlatformCaps_ThermalAutoThrottling,                 /* enabling auto thermal throttling, */
+	PHM_PlatformCaps_SumoThermalPolicy,                     /* A thermal policy specific for Sumo */
+	PHM_PlatformCaps_PCIEPerformanceRequest,                /* support to change RC voltage */
+	PHM_PlatformCaps_BLControlledByGPU,                     /* support varibright */
+	PHM_PlatformCaps_PowerContainment,                      /* support DPM2 power containment (AKA TDP clamping) */
+	PHM_PlatformCaps_SQRamping,                             /* support DPM2 SQ power throttle */
+	PHM_PlatformCaps_CAC,                                   /* support Capacitance * Activity power estimation */
+	PHM_PlatformCaps_NIChipsets,                            /* Northern Island and beyond chipsets */
+	PHM_PlatformCaps_TrinityChipsets,                       /* Trinity chipset */
+	PHM_PlatformCaps_EvergreenChipsets,                     /* Evergreen family chipset */
+	PHM_PlatformCaps_PowerControl,                          /* Cayman and beyond chipsets */
+	PHM_PlatformCaps_DisableLSClockGating,                  /* to disable Light Sleep control for HDP memories */
+	PHM_PlatformCaps_BoostState,                            /* this ASIC supports boost state */
+	PHM_PlatformCaps_UserMaxClockForMultiDisplays,          /* indicates if max memory clock is used for all status when multiple displays are connected */
+	PHM_PlatformCaps_RegWriteDelay,                         /* indicates if back to back reg write delay is required */
+	PHM_PlatformCaps_NonABMSupportInPPLib,                  /* ABM is not supported in PPLIB, (moved from PPLIB to DAL) */
+	PHM_PlatformCaps_GFXDynamicMGPowerGating,               /* Enable Dynamic MG PowerGating on Trinity */
+	PHM_PlatformCaps_DisableSMUUVDHandshake,                /* Disable SMU UVD Handshake */
+	PHM_PlatformCaps_DTE,                                   /* Support Digital Temperature Estimation */
+	PHM_PlatformCaps_W5100Specifc_SmuSkipMsgDTE,            /* This is for the feature requested by David B., and Tonny W.*/
+	PHM_PlatformCaps_UVDPowerGating,                        /* enable UVD power gating, supported from Llano */
+	PHM_PlatformCaps_UVDDynamicPowerGating,                 /* enable UVD Dynamic power gating, supported from UVD5 */
+	PHM_PlatformCaps_VCEPowerGating,                        /* Enable VCE power gating, supported for TN and later ASICs */
+	PHM_PlatformCaps_SamuPowerGating,                       /* Enable SAMU power gating, supported for KV and later ASICs */
+	PHM_PlatformCaps_UVDDPM,                                /* UVD clock DPM */
+	PHM_PlatformCaps_VCEDPM,                                /* VCE clock DPM */
+	PHM_PlatformCaps_SamuDPM,                               /* SAMU clock DPM */
+	PHM_PlatformCaps_AcpDPM,                                /* ACP clock DPM */
+	PHM_PlatformCaps_SclkDeepSleepAboveLow,                 /* Enable SCLK Deep Sleep on all DPM states */
+	PHM_PlatformCaps_DynamicUVDState,                       /* Dynamic UVD State */
+	PHM_PlatformCaps_WantSAMClkWithDummyBackEnd,            /* Set SAM Clk With Dummy Back End */
+	PHM_PlatformCaps_WantUVDClkWithDummyBackEnd,            /* Set UVD Clk With Dummy Back End */
+	PHM_PlatformCaps_WantVCEClkWithDummyBackEnd,            /* Set VCE Clk With Dummy Back End */
+	PHM_PlatformCaps_WantACPClkWithDummyBackEnd,            /* Set SAM Clk With Dummy Back End */
+	PHM_PlatformCaps_OD6inACSupport,                        /* indicates that the ASIC/back end supports OD6 */
+	PHM_PlatformCaps_OD6inDCSupport,                        /* indicates that the ASIC/back end supports OD6 in DC */
+	PHM_PlatformCaps_EnablePlatformPowerManagement,         /* indicates that Platform Power Management feature is supported */
+	PHM_PlatformCaps_SurpriseRemoval,                       /* indicates that surprise removal feature is requested */
+	PHM_PlatformCaps_NewCACVoltage,                         /* indicates new CAC voltage table support */
+	PHM_PlatformCaps_DBRamping,                             /* for dI/dT feature */
+	PHM_PlatformCaps_TDRamping,                             /* for dI/dT feature */
+	PHM_PlatformCaps_TCPRamping,                            /* for dI/dT feature */
+	PHM_PlatformCaps_EnableSMU7ThermalManagement,           /* SMC will manage thermal events */
+	PHM_PlatformCaps_FPS,                                   /* FPS support */
+	PHM_PlatformCaps_ACP,                                   /* ACP support */
+	PHM_PlatformCaps_SclkThrottleLowNotification,           /* SCLK Throttle Low Notification */
+	PHM_PlatformCaps_XDMAEnabled,                           /* XDMA engine is enabled */
+	PHM_PlatformCaps_UseDummyBackEnd,                       /* use dummy back end */
+	PHM_PlatformCaps_EnableDFSBypass,                       /* Enable DFS bypass */
+	PHM_PlatformCaps_VddNBDirectRequest,
+	PHM_PlatformCaps_PauseMMSessions,
+	PHM_PlatformCaps_UnTabledHardwareInterface,             /* Tableless/direct call hardware interface for CI and newer ASICs */
+	PHM_PlatformCaps_SMU7,                                  /* indicates that vpuRecoveryBegin without SMU shutdown */
+	PHM_PlatformCaps_RevertGPIO5Polarity,                   /* indicates revert GPIO5 plarity table support */
+	PHM_PlatformCaps_Thermal2GPIO17,                        /* indicates thermal2GPIO17 table support */
+	PHM_PlatformCaps_ThermalOutGPIO,                        /* indicates ThermalOutGPIO support, pin number is assigned by VBIOS */
+	PHM_PlatformCaps_DisableMclkSwitchingForFrameLock,      /* Disable memory clock switch during Framelock */
+	PHM_PlatformCaps_VRHotGPIOConfigurable,                 /* indicates VR_HOT GPIO configurable */
+	PHM_PlatformCaps_TempInversion,                         /* enable Temp Inversion feature */
+	PHM_PlatformCaps_IOIC3,
+	PHM_PlatformCaps_ConnectedStandby,
+	PHM_PlatformCaps_EVV,
+	PHM_PlatformCaps_EnableLongIdleBACOSupport,
+	PHM_PlatformCaps_CombinePCCWithThermalSignal,
+	PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc,
+	PHM_PlatformCaps_StablePState,
+	PHM_PlatformCaps_OD6PlusinACSupport,
+	PHM_PlatformCaps_OD6PlusinDCSupport,
+	PHM_PlatformCaps_ODThermalLimitUnlock,
+	PHM_PlatformCaps_ReducePowerLimit,
+	PHM_PlatformCaps_ODFuzzyFanControlSupport,
+	PHM_PlatformCaps_GeminiRegulatorFanControlSupport,
+	PHM_PlatformCaps_ControlVDDGFX,
+	PHM_PlatformCaps_BBBSupported,
+	PHM_PlatformCaps_DisableVoltageIsland,
+	PHM_PlatformCaps_FanSpeedInTableIsRPM,
+	PHM_PlatformCaps_GFXClockGatingManagedInCAIL,
+	PHM_PlatformCaps_IcelandULPSSWWorkAround,
+	PHM_PlatformCaps_FPSEnhancement,
+	PHM_PlatformCaps_LoadPostProductionFirmware,
+	PHM_PlatformCaps_VpuRecoveryInProgress,
+	PHM_PlatformCaps_Falcon_QuickTransition,
+	PHM_PlatformCaps_AVFS,
+	PHM_PlatformCaps_ClockStretcher,
+	PHM_PlatformCaps_TablelessHardwareInterface,
+	PHM_PlatformCaps_EnableDriverEVV,
+	PHM_PlatformCaps_Max
+};
+
+#define PHM_MAX_NUM_CAPS_BITS_PER_FIELD (sizeof(uint32_t)*8)
+
+/* Number of uint32_t entries used by CAPS table */
+#define PHM_MAX_NUM_CAPS_ULONG_ENTRIES \
+	((PHM_PlatformCaps_Max + ((PHM_MAX_NUM_CAPS_BITS_PER_FIELD) - 1)) / (PHM_MAX_NUM_CAPS_BITS_PER_FIELD))
+
+struct pp_hw_descriptor {
+	uint32_t hw_caps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES];
+};
+
+enum PHM_PerformanceLevelDesignation {
+	PHM_PerformanceLevelDesignation_Activity,
+	PHM_PerformanceLevelDesignation_PowerContainment
+};
+
+typedef enum PHM_PerformanceLevelDesignation PHM_PerformanceLevelDesignation;
+
+struct PHM_PerformanceLevel {
+    uint32_t    coreClock;
+    uint32_t    memory_clock;
+    uint32_t  vddc;
+    uint32_t  vddci;
+    uint32_t    nonLocalMemoryFreq;
+    uint32_t nonLocalMemoryWidth;
+};
+
+typedef struct PHM_PerformanceLevel PHM_PerformanceLevel;
+
+/* Function for setting a platform cap */
+static inline void phm_cap_set(uint32_t *caps,
+			enum phm_platform_caps c)
+{
+	caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] |= (1UL <<
+			     (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1)));
+}
+
+static inline void phm_cap_unset(uint32_t *caps,
+			enum phm_platform_caps c)
+{
+	caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] &= ~(1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1)));
+}
+
+static inline bool phm_cap_enabled(const uint32_t *caps, enum phm_platform_caps c)
+{
+	return (0 != (caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] &
+		  (1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1)))));
+}
+
+#define PP_PCIEGenInvalid  0xffff
+enum PP_PCIEGen {
+    PP_PCIEGen1 = 0,                /* PCIE 1.0 - Transfer rate of 2.5 GT/s */
+    PP_PCIEGen2,                    /*PCIE 2.0 - Transfer rate of 5.0 GT/s */
+    PP_PCIEGen3                     /*PCIE 3.0 - Transfer rate of 8.0 GT/s */
+};
+
+typedef enum PP_PCIEGen PP_PCIEGen;
+
+#define PP_Min_PCIEGen     PP_PCIEGen1
+#define PP_Max_PCIEGen     PP_PCIEGen3
+#define PP_Min_PCIELane    1
+#define PP_Max_PCIELane    32
+
+enum phm_clock_Type {
+	PHM_DispClock = 1,
+	PHM_SClock,
+	PHM_MemClock
+};
+
+#define MAX_NUM_CLOCKS 16
+
+struct PP_Clocks {
+	uint32_t engineClock;
+	uint32_t memoryClock;
+	uint32_t BusBandwidth;
+	uint32_t engineClockInSR;
+};
+
+struct phm_platform_descriptor {
+	uint32_t platformCaps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES];
+	uint32_t vbiosInterruptId;
+	struct PP_Clocks overdriveLimit;
+	struct PP_Clocks clockStep;
+	uint32_t hardwareActivityPerformanceLevels;
+	uint32_t minimumClocksReductionPercentage;
+	uint32_t minOverdriveVDDC;
+	uint32_t maxOverdriveVDDC;
+	uint32_t overdriveVDDCStep;
+	uint32_t hardwarePerformanceLevels;
+	uint16_t powerBudget;
+	uint32_t TDPLimit;
+	uint32_t nearTDPLimit;
+	uint32_t nearTDPLimitAdjusted;
+	uint32_t SQRampingThreshold;
+	uint32_t CACLeakage;
+	uint16_t TDPODLimit;
+	uint32_t TDPAdjustment;
+	bool TDPAdjustmentPolarity;
+	uint16_t LoadLineSlope;
+	uint32_t  VidMinLimit;
+	uint32_t  VidMaxLimit;
+	uint32_t  VidStep;
+	uint32_t  VidAdjustment;
+	bool VidAdjustmentPolarity;
+};
+
+struct phm_clocks {
+	uint32_t num_of_entries;
+	uint32_t clock[MAX_NUM_CLOCKS];
+};
+
+enum PP_DAL_POWERLEVEL {
+	PP_DAL_POWERLEVEL_INVALID = 0,
+	PP_DAL_POWERLEVEL_ULTRALOW,
+	PP_DAL_POWERLEVEL_LOW,
+	PP_DAL_POWERLEVEL_NOMINAL,
+	PP_DAL_POWERLEVEL_PERFORMANCE,
+
+	PP_DAL_POWERLEVEL_0 = PP_DAL_POWERLEVEL_ULTRALOW,
+	PP_DAL_POWERLEVEL_1 = PP_DAL_POWERLEVEL_LOW,
+	PP_DAL_POWERLEVEL_2 = PP_DAL_POWERLEVEL_NOMINAL,
+	PP_DAL_POWERLEVEL_3 = PP_DAL_POWERLEVEL_PERFORMANCE,
+	PP_DAL_POWERLEVEL_4 = PP_DAL_POWERLEVEL_3+1,
+	PP_DAL_POWERLEVEL_5 = PP_DAL_POWERLEVEL_4+1,
+	PP_DAL_POWERLEVEL_6 = PP_DAL_POWERLEVEL_5+1,
+	PP_DAL_POWERLEVEL_7 = PP_DAL_POWERLEVEL_6+1,
+};
+
+
+extern int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr);
+extern int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate);
+extern int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate);
+extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr);
+extern int phm_setup_asic(struct pp_hwmgr *hwmgr);
+extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr);
+extern void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr);
+extern bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr);
+extern int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block);
+extern int phm_set_power_state(struct pp_hwmgr *hwmgr,
+		    const struct pp_hw_power_state *pcurrent_state,
+		 const struct pp_hw_power_state *pnew_power_state);
+
+extern int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+				   struct pp_power_state *adjusted_ps,
+			     const struct pp_power_state *current_ps);
+
+extern int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level);
+extern int phm_display_configuration_changed(struct pp_hwmgr *hwmgr);
+extern int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr);
+extern int phm_register_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *info);
+extern int phm_start_thermal_controller(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *temperature_range);
+extern int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr);
+extern bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr);
+
+extern int phm_check_states_equal(struct pp_hwmgr *hwmgr,
+				 const struct pp_hw_power_state *pstate1,
+				 const struct pp_hw_power_state *pstate2,
+				 bool *equal);
+
+extern int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr,
+		const struct amd_pp_display_configuration *display_config);
+
+extern int phm_get_dal_power_level(struct pp_hwmgr *hwmgr,
+		struct amd_pp_dal_clock_info*info);
+
+extern int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr);
+
+extern int phm_power_down_asic(struct pp_hwmgr *hwmgr);
+
+#endif /* _HARDWARE_MANAGER_H_ */
+
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
new file mode 100644
index 0000000..aeaa3db
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -0,0 +1,801 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _HWMGR_H_
+#define _HWMGR_H_
+
+#include <linux/seq_file.h>
+#include "amd_powerplay.h"
+#include "pp_instance.h"
+#include "hardwaremanager.h"
+#include "pp_power_source.h"
+#include "hwmgr_ppt.h"
+#include "ppatomctrl.h"
+#include "hwmgr_ppt.h"
+
+struct pp_instance;
+struct pp_hwmgr;
+struct pp_hw_power_state;
+struct pp_power_state;
+struct PP_VCEState;
+struct phm_fan_speed_info;
+struct pp_atomctrl_voltage_table;
+
+
+enum DISPLAY_GAP {
+	DISPLAY_GAP_VBLANK_OR_WM = 0,   /* Wait for vblank or MCHG watermark. */
+	DISPLAY_GAP_VBLANK       = 1,   /* Wait for vblank. */
+	DISPLAY_GAP_WATERMARK    = 2,   /* Wait for MCHG watermark. (Note that HW may deassert WM in VBI depending on DC_STUTTER_CNTL.) */
+	DISPLAY_GAP_IGNORE       = 3    /* Do not wait. */
+};
+typedef enum DISPLAY_GAP DISPLAY_GAP;
+
+
+struct vi_dpm_level {
+	bool enabled;
+	uint32_t value;
+	uint32_t param1;
+};
+
+struct vi_dpm_table {
+	uint32_t count;
+	struct vi_dpm_level dpm_level[1];
+};
+
+enum PP_Result {
+	PP_Result_TableImmediateExit = 0x13,
+};
+
+#define PCIE_PERF_REQ_REMOVE_REGISTRY   0
+#define PCIE_PERF_REQ_FORCE_LOWPOWER    1
+#define PCIE_PERF_REQ_GEN1         2
+#define PCIE_PERF_REQ_GEN2         3
+#define PCIE_PERF_REQ_GEN3         4
+
+enum PHM_BackEnd_Magic {
+	PHM_Dummy_Magic       = 0xAA5555AA,
+	PHM_RV770_Magic       = 0xDCBAABCD,
+	PHM_Kong_Magic        = 0x239478DF,
+	PHM_NIslands_Magic    = 0x736C494E,
+	PHM_Sumo_Magic        = 0x8339FA11,
+	PHM_SIslands_Magic    = 0x369431AC,
+	PHM_Trinity_Magic     = 0x96751873,
+	PHM_CIslands_Magic    = 0x38AC78B0,
+	PHM_Kv_Magic          = 0xDCBBABC0,
+	PHM_VIslands_Magic    = 0x20130307,
+	PHM_Cz_Magic          = 0x67DCBA25
+};
+
+
+#define PHM_PCIE_POWERGATING_TARGET_GFX            0
+#define PHM_PCIE_POWERGATING_TARGET_DDI            1
+#define PHM_PCIE_POWERGATING_TARGET_PLLCASCADE     2
+#define PHM_PCIE_POWERGATING_TARGET_PHY            3
+
+typedef int (*phm_table_function)(struct pp_hwmgr *hwmgr, void *input,
+				  void *output, void *storage, int result);
+
+typedef bool (*phm_check_function)(struct pp_hwmgr *hwmgr);
+
+struct phm_set_power_state_input {
+	const struct pp_hw_power_state *pcurrent_state;
+	const struct pp_hw_power_state *pnew_state;
+};
+
+struct phm_acp_arbiter {
+	uint32_t acpclk;
+};
+
+struct phm_uvd_arbiter {
+	uint32_t vclk;
+	uint32_t dclk;
+	uint32_t vclk_ceiling;
+	uint32_t dclk_ceiling;
+};
+
+struct phm_vce_arbiter {
+	uint32_t   evclk;
+	uint32_t   ecclk;
+};
+
+struct phm_gfx_arbiter {
+	uint32_t sclk;
+	uint32_t mclk;
+	uint32_t sclk_over_drive;
+	uint32_t mclk_over_drive;
+	uint32_t sclk_threshold;
+	uint32_t num_cus;
+};
+
+/* Entries in the master tables */
+struct phm_master_table_item {
+	phm_check_function isFunctionNeededInRuntimeTable;
+	phm_table_function tableFunction;
+};
+
+enum phm_master_table_flag {
+	PHM_MasterTableFlag_None         = 0,
+	PHM_MasterTableFlag_ExitOnError  = 1,
+};
+
+/* The header of the master tables */
+struct phm_master_table_header {
+	uint32_t storage_size;
+	uint32_t flags;
+	struct phm_master_table_item *master_list;
+};
+
+struct phm_runtime_table_header {
+	uint32_t storage_size;
+	bool exit_error;
+	phm_table_function *function_list;
+};
+
+struct phm_clock_array {
+	uint32_t count;
+	uint32_t values[1];
+};
+
+struct phm_clock_voltage_dependency_record {
+	uint32_t clk;
+	uint32_t v;
+};
+
+struct phm_vceclock_voltage_dependency_record {
+	uint32_t ecclk;
+	uint32_t evclk;
+	uint32_t v;
+};
+
+struct phm_uvdclock_voltage_dependency_record {
+	uint32_t vclk;
+	uint32_t dclk;
+	uint32_t v;
+};
+
+struct phm_samuclock_voltage_dependency_record {
+	uint32_t samclk;
+	uint32_t v;
+};
+
+struct phm_acpclock_voltage_dependency_record {
+	uint32_t acpclk;
+	uint32_t v;
+};
+
+struct phm_clock_voltage_dependency_table {
+	uint32_t count;										/* Number of entries. */
+	struct phm_clock_voltage_dependency_record entries[1];		/* Dynamically allocate count entries. */
+};
+
+struct phm_phase_shedding_limits_record {
+	uint32_t  Voltage;
+	uint32_t    Sclk;
+	uint32_t    Mclk;
+};
+
+
+extern int phm_dispatch_table(struct pp_hwmgr *hwmgr,
+			      struct phm_runtime_table_header *rt_table,
+			      void *input, void *output);
+
+extern int phm_construct_table(struct pp_hwmgr *hwmgr,
+			       struct phm_master_table_header *master_table,
+			       struct phm_runtime_table_header *rt_table);
+
+extern int phm_destroy_table(struct pp_hwmgr *hwmgr,
+			     struct phm_runtime_table_header *rt_table);
+
+
+struct phm_uvd_clock_voltage_dependency_record {
+	uint32_t vclk;
+	uint32_t dclk;
+	uint32_t v;
+};
+
+struct phm_uvd_clock_voltage_dependency_table {
+	uint8_t count;
+	struct phm_uvd_clock_voltage_dependency_record entries[1];
+};
+
+struct phm_acp_clock_voltage_dependency_record {
+	uint32_t acpclk;
+	uint32_t v;
+};
+
+struct phm_acp_clock_voltage_dependency_table {
+	uint32_t count;
+	struct phm_acp_clock_voltage_dependency_record entries[1];
+};
+
+struct phm_vce_clock_voltage_dependency_record {
+	uint32_t ecclk;
+	uint32_t evclk;
+	uint32_t v;
+};
+
+struct phm_phase_shedding_limits_table {
+	uint32_t                           count;
+	struct phm_phase_shedding_limits_record  entries[1];
+};
+
+struct phm_vceclock_voltage_dependency_table {
+	uint8_t count;                                    /* Number of entries. */
+	struct phm_vceclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
+};
+
+struct phm_uvdclock_voltage_dependency_table {
+	uint8_t count;                                    /* Number of entries. */
+	struct phm_uvdclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
+};
+
+struct phm_samuclock_voltage_dependency_table {
+	uint8_t count;                                    /* Number of entries. */
+	struct phm_samuclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
+};
+
+struct phm_acpclock_voltage_dependency_table {
+	uint32_t count;                                    /* Number of entries. */
+	struct phm_acpclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
+};
+
+struct phm_vce_clock_voltage_dependency_table {
+	uint8_t count;
+	struct phm_vce_clock_voltage_dependency_record entries[1];
+};
+
+struct pp_hwmgr_func {
+	int (*backend_init)(struct pp_hwmgr *hw_mgr);
+	int (*backend_fini)(struct pp_hwmgr *hw_mgr);
+	int (*asic_setup)(struct pp_hwmgr *hw_mgr);
+	int (*get_power_state_size)(struct pp_hwmgr *hw_mgr);
+
+	int (*apply_state_adjust_rules)(struct pp_hwmgr *hwmgr,
+				struct pp_power_state  *prequest_ps,
+			const struct pp_power_state *pcurrent_ps);
+
+	int (*force_dpm_level)(struct pp_hwmgr *hw_mgr,
+					enum amd_dpm_forced_level level);
+
+	int (*dynamic_state_management_enable)(
+						struct pp_hwmgr *hw_mgr);
+
+	int (*patch_boot_state)(struct pp_hwmgr *hwmgr,
+				     struct pp_hw_power_state *hw_ps);
+
+	int (*get_pp_table_entry)(struct pp_hwmgr *hwmgr,
+			    unsigned long, struct pp_power_state *);
+	int (*get_num_of_pp_table_entries)(struct pp_hwmgr *hwmgr);
+	int (*powerdown_uvd)(struct pp_hwmgr *hwmgr);
+	int (*powergate_vce)(struct pp_hwmgr *hwmgr, bool bgate);
+	int (*powergate_uvd)(struct pp_hwmgr *hwmgr, bool bgate);
+	int (*get_mclk)(struct pp_hwmgr *hwmgr, bool low);
+	int (*get_sclk)(struct pp_hwmgr *hwmgr, bool low);
+	int (*power_state_set)(struct pp_hwmgr *hwmgr,
+						const void *state);
+	void (*print_current_perforce_level)(struct pp_hwmgr *hwmgr,
+							struct seq_file *m);
+	int (*enable_clock_power_gating)(struct pp_hwmgr *hwmgr);
+	int (*notify_smc_display_config_after_ps_adjustment)(struct pp_hwmgr *hwmgr);
+	int (*display_config_changed)(struct pp_hwmgr *hwmgr);
+	int (*disable_clock_power_gating)(struct pp_hwmgr *hwmgr);
+	int (*update_clock_gatings)(struct pp_hwmgr *hwmgr,
+						const uint32_t *msg_id);
+	int (*set_max_fan_rpm_output)(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm);
+	int (*set_max_fan_pwm_output)(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm);
+	int (*get_temperature)(struct pp_hwmgr *hwmgr);
+	int (*stop_thermal_controller)(struct pp_hwmgr *hwmgr);
+	int (*get_fan_speed_info)(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info);
+	int (*set_fan_control_mode)(struct pp_hwmgr *hwmgr, uint32_t mode);
+	int (*get_fan_control_mode)(struct pp_hwmgr *hwmgr);
+	int (*set_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t percent);
+	int (*get_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t *speed);
+	int (*set_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t percent);
+	int (*get_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t *speed);
+	int (*reset_fan_speed_to_default)(struct pp_hwmgr *hwmgr);
+	int (*uninitialize_thermal_controller)(struct pp_hwmgr *hwmgr);
+	int (*register_internal_thermal_interrupt)(struct pp_hwmgr *hwmgr,
+					const void *thermal_interrupt_info);
+	bool (*check_smc_update_required_for_display_configuration)(struct pp_hwmgr *hwmgr);
+	int (*check_states_equal)(struct pp_hwmgr *hwmgr,
+					const struct pp_hw_power_state *pstate1,
+					const struct pp_hw_power_state *pstate2,
+					bool *equal);
+	int (*set_cpu_power_state)(struct pp_hwmgr *hwmgr);
+	int (*store_cc6_data)(struct pp_hwmgr *hwmgr, uint32_t separation_time,
+				bool cc6_disable, bool pstate_disable,
+				bool pstate_switch_disable);
+	int (*get_dal_power_level)(struct pp_hwmgr *hwmgr,
+				   struct amd_pp_dal_clock_info *info);
+	int (*power_off_asic)(struct pp_hwmgr *hwmgr);
+};
+
+struct pp_table_func {
+	int (*pptable_init)(struct pp_hwmgr *hw_mgr);
+	int (*pptable_fini)(struct pp_hwmgr *hw_mgr);
+	int (*pptable_get_number_of_vce_state_table_entries)(struct pp_hwmgr *hw_mgr);
+	int (*pptable_get_vce_state_table_entry)(
+						struct pp_hwmgr *hwmgr,
+						unsigned long i,
+						struct PP_VCEState *vce_state,
+						void **clock_info,
+						unsigned long *flag);
+};
+
+union phm_cac_leakage_record {
+	struct {
+		uint16_t Vddc;          /* in CI, we use it for StdVoltageHiSidd */
+		uint32_t Leakage;       /* in CI, we use it for StdVoltageLoSidd */
+	};
+	struct {
+		uint16_t Vddc1;
+		uint16_t Vddc2;
+		uint16_t Vddc3;
+	};
+};
+
+struct phm_cac_leakage_table {
+	uint32_t count;
+	union phm_cac_leakage_record entries[1];
+};
+
+struct phm_samu_clock_voltage_dependency_record {
+	uint32_t samclk;
+	uint32_t v;
+};
+
+
+struct phm_samu_clock_voltage_dependency_table {
+	uint8_t count;
+	struct phm_samu_clock_voltage_dependency_record entries[1];
+};
+
+struct phm_cac_tdp_table {
+	uint16_t usTDP;
+	uint16_t usConfigurableTDP;
+	uint16_t usTDC;
+	uint16_t usBatteryPowerLimit;
+	uint16_t usSmallPowerLimit;
+	uint16_t usLowCACLeakage;
+	uint16_t usHighCACLeakage;
+	uint16_t usMaximumPowerDeliveryLimit;
+	uint16_t usOperatingTempMinLimit;
+	uint16_t usOperatingTempMaxLimit;
+	uint16_t usOperatingTempStep;
+	uint16_t usOperatingTempHyst;
+	uint16_t usDefaultTargetOperatingTemp;
+	uint16_t usTargetOperatingTemp;
+	uint16_t usPowerTuneDataSetID;
+	uint16_t usSoftwareShutdownTemp;
+	uint16_t usClockStretchAmount;
+	uint16_t usTemperatureLimitHotspot;
+	uint16_t usTemperatureLimitLiquid1;
+	uint16_t usTemperatureLimitLiquid2;
+	uint16_t usTemperatureLimitVrVddc;
+	uint16_t usTemperatureLimitVrMvdd;
+	uint16_t usTemperatureLimitPlx;
+	uint8_t  ucLiquid1_I2C_address;
+	uint8_t  ucLiquid2_I2C_address;
+	uint8_t  ucLiquid_I2C_Line;
+	uint8_t  ucVr_I2C_address;
+	uint8_t  ucVr_I2C_Line;
+	uint8_t  ucPlx_I2C_address;
+	uint8_t  ucPlx_I2C_Line;
+};
+
+struct phm_ppm_table {
+	uint8_t   ppm_design;
+	uint16_t  cpu_core_number;
+	uint32_t  platform_tdp;
+	uint32_t  small_ac_platform_tdp;
+	uint32_t  platform_tdc;
+	uint32_t  small_ac_platform_tdc;
+	uint32_t  apu_tdp;
+	uint32_t  dgpu_tdp;
+	uint32_t  dgpu_ulv_power;
+	uint32_t  tj_max;
+};
+
+struct phm_vq_budgeting_record {
+	uint32_t ulCUs;
+	uint32_t ulSustainableSOCPowerLimitLow;
+	uint32_t ulSustainableSOCPowerLimitHigh;
+	uint32_t ulMinSclkLow;
+	uint32_t ulMinSclkHigh;
+	uint8_t  ucDispConfig;
+	uint32_t ulDClk;
+	uint32_t ulEClk;
+	uint32_t ulSustainableSclk;
+	uint32_t ulSustainableCUs;
+};
+
+struct phm_vq_budgeting_table {
+	uint8_t numEntries;
+	struct phm_vq_budgeting_record entries[1];
+};
+
+struct phm_clock_and_voltage_limits {
+	uint32_t sclk;
+	uint32_t mclk;
+	uint16_t vddc;
+	uint16_t vddci;
+	uint16_t vddgfx;
+};
+
+/* Structure to hold PPTable information */
+
+struct phm_ppt_v1_information {
+	struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_sclk;
+	struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_mclk;
+	struct phm_clock_array *valid_sclk_values;
+	struct phm_clock_array *valid_mclk_values;
+	struct phm_clock_and_voltage_limits max_clock_voltage_on_dc;
+	struct phm_clock_and_voltage_limits max_clock_voltage_on_ac;
+	struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl;
+	struct phm_ppm_table *ppm_parameter_table;
+	struct phm_cac_tdp_table *cac_dtp_table;
+	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_dep_table;
+	struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table;
+	struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table;
+	struct phm_ppt_v1_pcie_table *pcie_table;
+	uint16_t us_ulv_voltage_offset;
+};
+
+struct phm_dynamic_state_info {
+	struct phm_clock_voltage_dependency_table *vddc_dependency_on_sclk;
+	struct phm_clock_voltage_dependency_table *vddci_dependency_on_mclk;
+	struct phm_clock_voltage_dependency_table *vddc_dependency_on_mclk;
+	struct phm_clock_voltage_dependency_table *mvdd_dependency_on_mclk;
+	struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl;
+	struct phm_clock_array                    *valid_sclk_values;
+	struct phm_clock_array                    *valid_mclk_values;
+	struct phm_clock_and_voltage_limits       max_clock_voltage_on_dc;
+	struct phm_clock_and_voltage_limits       max_clock_voltage_on_ac;
+	uint32_t                                  mclk_sclk_ratio;
+	uint32_t                                  sclk_mclk_delta;
+	uint32_t                                  vddc_vddci_delta;
+	uint32_t                                  min_vddc_for_pcie_gen2;
+	struct phm_cac_leakage_table              *cac_leakage_table;
+	struct phm_phase_shedding_limits_table	  *vddc_phase_shed_limits_table;
+
+	struct phm_vce_clock_voltage_dependency_table
+					    *vce_clock_voltage_dependency_table;
+	struct phm_uvd_clock_voltage_dependency_table
+					    *uvd_clock_voltage_dependency_table;
+	struct phm_acp_clock_voltage_dependency_table
+					    *acp_clock_voltage_dependency_table;
+	struct phm_samu_clock_voltage_dependency_table
+					   *samu_clock_voltage_dependency_table;
+
+	struct phm_ppm_table                          *ppm_parameter_table;
+	struct phm_cac_tdp_table                      *cac_dtp_table;
+	struct phm_clock_voltage_dependency_table	  *vdd_gfx_dependency_on_sclk;
+	struct phm_vq_budgeting_table		  		  *vq_budgeting_table;
+};
+
+struct pp_fan_info {
+	bool bNoFan;
+	uint8_t   ucTachometerPulsesPerRevolution;
+	uint32_t   ulMinRPM;
+	uint32_t   ulMaxRPM;
+};
+
+struct pp_advance_fan_control_parameters {
+	uint16_t  usTMin;                          /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */
+	uint16_t  usTMed;                          /* The middle temperature where we change slopes. */
+	uint16_t  usTHigh;                         /* The high temperature for setting the second slope. */
+	uint16_t  usPWMMin;                        /* The minimum PWM value in percent (0.01% increments). */
+	uint16_t  usPWMMed;                        /* The PWM value (in percent) at TMed. */
+	uint16_t  usPWMHigh;                       /* The PWM value at THigh. */
+	uint8_t   ucTHyst;                         /* Temperature hysteresis. Integer. */
+	uint32_t   ulCycleDelay;                   /* The time between two invocations of the fan control routine in microseconds. */
+	uint16_t  usTMax;                          /* The max temperature */
+	uint8_t   ucFanControlMode;
+	uint16_t  usFanPWMMinLimit;
+	uint16_t  usFanPWMMaxLimit;
+	uint16_t  usFanPWMStep;
+	uint16_t  usDefaultMaxFanPWM;
+	uint16_t  usFanOutputSensitivity;
+	uint16_t  usDefaultFanOutputSensitivity;
+	uint16_t  usMaxFanPWM;                     /* The max Fan PWM value for Fuzzy Fan Control feature */
+	uint16_t  usFanRPMMinLimit;                /* Minimum limit range in percentage, need to calculate based on minRPM/MaxRpm */
+	uint16_t  usFanRPMMaxLimit;                /* Maximum limit range in percentage, usually set to 100% by default */
+	uint16_t  usFanRPMStep;                    /* Step increments/decerements, in percent */
+	uint16_t  usDefaultMaxFanRPM;              /* The max Fan RPM value for Fuzzy Fan Control feature, default from PPTable */
+	uint16_t  usMaxFanRPM;                     /* The max Fan RPM value for Fuzzy Fan Control feature, user defined */
+	uint16_t  usFanCurrentLow;                 /* Low current */
+	uint16_t  usFanCurrentHigh;                /* High current */
+	uint16_t  usFanRPMLow;                     /* Low RPM */
+	uint16_t  usFanRPMHigh;                    /* High RPM */
+	uint32_t   ulMinFanSCLKAcousticLimit;      /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */
+	uint8_t   ucTargetTemperature;             /* Advanced fan controller target temperature. */
+	uint8_t   ucMinimumPWMLimit;               /* The minimum PWM that the advanced fan controller can set.  This should be set to the highest PWM that will run the fan at its lowest RPM. */
+	uint16_t  usFanGainEdge;                   /* The following is added for Fiji */
+	uint16_t  usFanGainHotspot;
+	uint16_t  usFanGainLiquid;
+	uint16_t  usFanGainVrVddc;
+	uint16_t  usFanGainVrMvdd;
+	uint16_t  usFanGainPlx;
+	uint16_t  usFanGainHbm;
+};
+
+struct pp_thermal_controller_info {
+	uint8_t ucType;
+	uint8_t ucI2cLine;
+	uint8_t ucI2cAddress;
+	struct pp_fan_info fanInfo;
+	struct pp_advance_fan_control_parameters advanceFanControlParameters;
+};
+
+struct phm_microcode_version_info {
+	uint32_t SMC;
+	uint32_t DMCU;
+	uint32_t MC;
+	uint32_t NB;
+};
+
+/**
+ * The main hardware manager structure.
+ */
+struct pp_hwmgr {
+	uint32_t chip_family;
+	uint32_t chip_id;
+	uint32_t hw_revision;
+	uint32_t sub_sys_id;
+	uint32_t sub_vendor_id;
+
+	void *device;
+	struct pp_smumgr *smumgr;
+	const void *soft_pp_table;
+	bool need_pp_table_upload;
+	enum amd_dpm_forced_level dpm_level;
+	bool block_hw_access;
+	struct phm_gfx_arbiter gfx_arbiter;
+	struct phm_acp_arbiter acp_arbiter;
+	struct phm_uvd_arbiter uvd_arbiter;
+	struct phm_vce_arbiter vce_arbiter;
+	uint32_t usec_timeout;
+	void *pptable;
+	struct phm_platform_descriptor platform_descriptor;
+	void *backend;
+	enum PP_DAL_POWERLEVEL dal_power_level;
+	struct phm_dynamic_state_info dyn_state;
+	struct phm_runtime_table_header setup_asic;
+	struct phm_runtime_table_header power_down_asic;
+	struct phm_runtime_table_header disable_dynamic_state_management;
+	struct phm_runtime_table_header enable_dynamic_state_management;
+	struct phm_runtime_table_header set_power_state;
+	struct phm_runtime_table_header enable_clock_power_gatings;
+	struct phm_runtime_table_header display_configuration_changed;
+	struct phm_runtime_table_header start_thermal_controller;
+	struct phm_runtime_table_header set_temperature_range;
+	const struct pp_hwmgr_func *hwmgr_func;
+	const struct pp_table_func *pptable_func;
+	struct pp_power_state    *ps;
+	enum pp_power_source  power_source;
+	uint32_t num_ps;
+	struct pp_thermal_controller_info thermal_controller;
+	bool fan_ctrl_is_in_default_mode;
+	uint32_t fan_ctrl_default_mode;
+	uint32_t tmin;
+	struct phm_microcode_version_info microcode_version_info;
+	uint32_t ps_size;
+	struct pp_power_state    *current_ps;
+	struct pp_power_state    *request_ps;
+	struct pp_power_state    *boot_ps;
+	struct pp_power_state    *uvd_ps;
+	struct amd_pp_display_configuration display_config;
+};
+
+
+extern int hwmgr_init(struct amd_pp_init *pp_init,
+		      struct pp_instance *handle);
+
+extern int hwmgr_fini(struct pp_hwmgr *hwmgr);
+
+extern int hw_init_power_state_table(struct pp_hwmgr *hwmgr);
+
+extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index,
+				uint32_t value, uint32_t mask);
+
+extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr,
+				uint32_t index, uint32_t value, uint32_t mask);
+
+extern uint32_t phm_read_indirect_register(struct pp_hwmgr *hwmgr,
+		uint32_t indirect_port, uint32_t index);
+
+extern void phm_write_indirect_register(struct pp_hwmgr *hwmgr,
+		uint32_t indirect_port,
+		uint32_t index,
+		uint32_t value);
+
+extern void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr,
+				uint32_t indirect_port,
+				uint32_t index,
+				uint32_t value,
+				uint32_t mask);
+
+extern void phm_wait_for_indirect_register_unequal(
+				struct pp_hwmgr *hwmgr,
+				uint32_t indirect_port,
+				uint32_t index,
+				uint32_t value,
+				uint32_t mask);
+
+extern bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr);
+extern bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr);
+extern bool phm_cf_want_microcode_fan_ctrl(struct pp_hwmgr *hwmgr);
+
+extern int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table);
+extern int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table);
+extern int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table);
+extern int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_voltage_lookup_table *lookup_table);
+extern void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, struct pp_atomctrl_voltage_table *vol_table);
+extern int phm_reset_single_dpm_table(void *table, uint32_t count, int max);
+extern void phm_setup_pcie_table_entry(void *table, uint32_t index, uint32_t pcie_gen, uint32_t pcie_lanes);
+extern int32_t phm_get_dpm_level_enable_mask_value(void *table);
+extern uint8_t phm_get_voltage_index(struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage);
+extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci);
+extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level);
+extern int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table,
+								uint16_t virtual_voltage_id, int32_t *sclk);
+extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr);
+extern int phm_hwmgr_backend_fini(struct pp_hwmgr *hwmgr);
+extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask);
+
+
+#define PHM_ENTIRE_REGISTER_MASK 0xFFFFFFFFU
+
+#define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT
+#define PHM_FIELD_MASK(reg, field) reg##__##field##_MASK
+
+#define PHM_SET_FIELD(origval, reg, field, fieldval)	\
+	(((origval) & ~PHM_FIELD_MASK(reg, field)) |	\
+	 (PHM_FIELD_MASK(reg, field) & ((fieldval) << PHM_FIELD_SHIFT(reg, field))))
+
+#define PHM_GET_FIELD(value, reg, field)	\
+	(((value) & PHM_FIELD_MASK(reg, field)) >>	\
+	 PHM_FIELD_SHIFT(reg, field))
+
+
+#define PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, index, value, mask)	\
+	phm_wait_on_register(hwmgr, index, value, mask)
+
+#define PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, index, value, mask)	\
+	phm_wait_for_register_unequal(hwmgr, index, value, mask)
+
+#define PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask)	\
+	phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX, index, value, mask)
+
+#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask)	\
+	phm_wait_for_indirect_register_unequal(hwmgr, mm##port##_INDEX, index, value, mask)
+
+#define PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask)	\
+	phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX_0, index, value, mask)
+
+#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask)	\
+	phm_wait_for_indirect_register_unequal(hwmgr, mm##port##_INDEX_0, index, value, mask)
+
+/* Operations on named registers. */
+
+#define PHM_WAIT_REGISTER(hwmgr, reg, value, mask)	\
+	PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, mm##reg, value, mask)
+
+#define PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, value, mask)	\
+	PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, mm##reg, value, mask)
+
+#define PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, value, mask)	\
+	PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
+
+#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask)	\
+	PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
+
+#define PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, value, mask)	\
+	PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
+
+#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask)	\
+	PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
+
+/* Operations on named fields. */
+
+#define PHM_READ_FIELD(device, reg, field)	\
+	PHM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field)
+
+#define PHM_READ_INDIRECT_FIELD(device, port, reg, field)	\
+	PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg),	\
+			reg, field)
+
+#define PHM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field)	\
+	PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg),	\
+			reg, field)
+
+#define PHM_WRITE_FIELD(device, reg, field, fieldval)	\
+	cgs_write_register(device, mm##reg, PHM_SET_FIELD(	\
+				cgs_read_register(device, mm##reg), reg, field, fieldval))
+
+#define PHM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval)	\
+	cgs_write_ind_register(device, port, ix##reg,	\
+			PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg),	\
+				reg, field, fieldval))
+
+#define PHM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval)	\
+	cgs_write_ind_register(device, port, ix##reg,	\
+			PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg),	\
+				reg, field, fieldval))
+
+#define PHM_WAIT_FIELD(hwmgr, reg, field, fieldval)	\
+	PHM_WAIT_REGISTER(hwmgr, reg, (fieldval)	\
+			<< PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field))
+
+#define PHM_WAIT_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval)	\
+	PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval)	\
+			<< PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field))
+
+#define PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval)	\
+	PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval)	\
+			<< PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field))
+
+#define PHM_WAIT_FIELD_UNEQUAL(hwmgr, reg, field, fieldval)	\
+	PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, (fieldval)	\
+			<< PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field))
+
+#define PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval)	\
+	PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, (fieldval)	\
+			<< PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field))
+
+#define PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval)	\
+	PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, (fieldval)	\
+			<< PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field))
+
+/* Operations on arrays of registers & fields. */
+
+#define PHM_READ_ARRAY_REGISTER(device, reg, offset)	\
+	cgs_read_register(device, mm##reg + (offset))
+
+#define PHM_WRITE_ARRAY_REGISTER(device, reg, offset, value)	\
+	cgs_write_register(device, mm##reg + (offset), value)
+
+#define PHM_WAIT_ARRAY_REGISTER(hwmgr, reg, offset, value, mask)	\
+	PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, mm##reg + (offset), value, mask)
+
+#define PHM_WAIT_ARRAY_REGISTER_UNEQUAL(hwmgr, reg, offset, value, mask)	\
+	PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, mm##reg + (offset), value, mask)
+
+#define PHM_READ_ARRAY_FIELD(hwmgr, reg, offset, field) \
+	PHM_GET_FIELD(PHM_READ_ARRAY_REGISTER(hwmgr->device, reg, offset), reg, field)
+
+#define PHM_WRITE_ARRAY_FIELD(hwmgr, reg, offset, field, fieldvalue)	\
+	PHM_WRITE_ARRAY_REGISTER(hwmgr->device, reg, offset,	\
+			PHM_SET_FIELD(PHM_READ_ARRAY_REGISTER(hwmgr->device, reg, offset),	\
+				reg, field, fieldvalue))
+
+#define PHM_WAIT_ARRAY_FIELD(hwmgr, reg, offset, field, fieldvalue)	\
+	PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, mm##reg + (offset),	\
+			(fieldvalue) << PHM_FIELD_SHIFT(reg, field),	\
+			PHM_FIELD_MASK(reg, field))
+
+#define PHM_WAIT_ARRAY_FIELD_UNEQUAL(hwmgr, reg, offset, field, fieldvalue)	\
+	PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, mm##reg + (offset),	\
+			(fieldvalue) << PHM_FIELD_SHIFT(reg, field),	\
+			PHM_FIELD_MASK(reg, field))
+
+#endif /* _HWMGR_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/powerplay/inc/power_state.h
new file mode 100644
index 0000000..a3f0ce4
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/power_state.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef PP_POWERSTATE_H
+#define PP_POWERSTATE_H
+
+struct pp_hw_power_state {
+	unsigned int magic;
+};
+
+struct pp_power_state;
+
+
+#define PP_INVALID_POWER_STATE_ID (0)
+
+
+/*
+ * An item of a list containing Power States.
+ */
+
+struct PP_StateLinkedList {
+	struct pp_power_state *next;
+	struct pp_power_state *prev;
+};
+
+
+enum PP_StateUILabel {
+	PP_StateUILabel_None,
+	PP_StateUILabel_Battery,
+	PP_StateUILabel_MiddleLow,
+	PP_StateUILabel_Balanced,
+	PP_StateUILabel_MiddleHigh,
+	PP_StateUILabel_Performance,
+	PP_StateUILabel_BACO
+};
+
+enum PP_StateClassificationFlag {
+	PP_StateClassificationFlag_Boot                = 0x0001,
+	PP_StateClassificationFlag_Thermal             = 0x0002,
+	PP_StateClassificationFlag_LimitedPowerSource  = 0x0004,
+	PP_StateClassificationFlag_Rest                = 0x0008,
+	PP_StateClassificationFlag_Forced              = 0x0010,
+	PP_StateClassificationFlag_User3DPerformance   = 0x0020,
+	PP_StateClassificationFlag_User2DPerformance   = 0x0040,
+	PP_StateClassificationFlag_3DPerformance       = 0x0080,
+	PP_StateClassificationFlag_ACOverdriveTemplate   = 0x0100,
+	PP_StateClassificationFlag_Uvd                 = 0x0200,
+	PP_StateClassificationFlag_3DPerformanceLow    = 0x0400,
+	PP_StateClassificationFlag_ACPI                = 0x0800,
+	PP_StateClassificationFlag_HD2                 = 0x1000,
+	PP_StateClassificationFlag_UvdHD               = 0x2000,
+	PP_StateClassificationFlag_UvdSD               = 0x4000,
+	PP_StateClassificationFlag_UserDCPerformance    = 0x8000,
+	PP_StateClassificationFlag_DCOverdriveTemplate   = 0x10000,
+	PP_StateClassificationFlag_BACO                  = 0x20000,
+	PP_StateClassificationFlag_LimitedPowerSource_2  = 0x40000,
+	PP_StateClassificationFlag_ULV                   = 0x80000,
+	PP_StateClassificationFlag_UvdMVC               = 0x100000,
+};
+
+typedef unsigned int PP_StateClassificationFlags;
+
+struct PP_StateClassificationBlock {
+	enum PP_StateUILabel         ui_label;
+	enum PP_StateClassificationFlag  flags;
+	int                          bios_index;
+	bool                      temporary_state;
+	bool                      to_be_deleted;
+};
+
+struct PP_StatePcieBlock {
+	unsigned int lanes;
+};
+
+enum PP_RefreshrateSource {
+	PP_RefreshrateSource_EDID,
+	PP_RefreshrateSource_Explicit
+};
+
+struct PP_StateDisplayBlock {
+	bool              disableFrameModulation;
+	bool              limitRefreshrate;
+	enum PP_RefreshrateSource refreshrateSource;
+	int                  explicitRefreshrate;
+	int                  edidRefreshrateIndex;
+	bool              enableVariBright;
+};
+
+struct PP_StateMemroyBlock {
+	bool              dllOff;
+	uint8_t                 m3arb;
+	uint8_t                 unused[3];
+};
+
+struct PP_StateSoftwareAlgorithmBlock {
+	bool disableLoadBalancing;
+	bool enableSleepForTimestamps;
+};
+
+#define PP_TEMPERATURE_UNITS_PER_CENTIGRADES 1000
+
+/**
+ * Type to hold a temperature range.
+ */
+struct PP_TemperatureRange {
+	uint32_t min;
+	uint32_t max;
+};
+
+struct PP_StateValidationBlock {
+	bool singleDisplayOnly;
+	bool disallowOnDC;
+	uint8_t supportedPowerLevels;
+};
+
+struct PP_UVD_CLOCKS {
+	uint32_t VCLK;
+	uint32_t DCLK;
+};
+
+/**
+* Structure to hold a PowerPlay Power State.
+*/
+struct pp_power_state {
+	uint32_t                            id;
+	struct PP_StateLinkedList                  orderedList;
+	struct PP_StateLinkedList                  allStatesList;
+
+	struct PP_StateClassificationBlock         classification;
+	struct PP_StateValidationBlock             validation;
+	struct PP_StatePcieBlock                   pcie;
+	struct PP_StateDisplayBlock                display;
+	struct PP_StateMemroyBlock                 memory;
+	struct PP_TemperatureRange                 temperatures;
+	struct PP_StateSoftwareAlgorithmBlock      software;
+	struct PP_UVD_CLOCKS                       uvd_clocks;
+	struct pp_hw_power_state  hardware;
+};
+
+
+/*Structure to hold a VCE state entry*/
+struct PP_VCEState {
+	uint32_t evclk;
+	uint32_t ecclk;
+	uint32_t sclk;
+	uint32_t mclk;
+};
+
+enum PP_MMProfilingState {
+	PP_MMProfilingState_NA = 0,
+	PP_MMProfilingState_Started,
+	PP_MMProfilingState_Stopped
+};
+
+struct PP_Clock_Engine_Request {
+	unsigned long clientType;
+	unsigned long ctxid;
+	uint64_t  context_handle;
+	unsigned long sclk;
+	unsigned long sclkHardMin;
+	unsigned long mclk;
+	unsigned long iclk;
+	unsigned long evclk;
+	unsigned long ecclk;
+	unsigned long ecclkHardMin;
+	unsigned long vclk;
+	unsigned long dclk;
+	unsigned long samclk;
+	unsigned long acpclk;
+	unsigned long sclkOverdrive;
+	unsigned long mclkOverdrive;
+	unsigned long sclk_threshold;
+	unsigned long flag;
+	unsigned long vclk_ceiling;
+	unsigned long dclk_ceiling;
+	unsigned long num_cus;
+	unsigned long pmflag;
+	enum PP_MMProfilingState MMProfilingState;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h b/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h
new file mode 100644
index 0000000..3bd5e69
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+extern bool acpi_atcs_functions_supported(void *device,
+							uint32_t index);
+extern int acpi_pcie_perf_request(void *device,
+						uint8_t perf_req,
+						bool advertise);
diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h b/drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h
new file mode 100644
index 0000000..0c1593e
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef PP_ASICBLOCKS_H
+#define PP_ASICBLOCKS_H
+
+
+enum PHM_AsicBlock {
+	PHM_AsicBlock_GFX,
+	PHM_AsicBlock_UVD_MVC,
+	PHM_AsicBlock_UVD,
+	PHM_AsicBlock_UVD_HD,
+	PHM_AsicBlock_UVD_SD,
+	PHM_AsicBlock_Count
+};
+
+enum PHM_ClockGateSetting {
+	PHM_ClockGateSetting_StaticOn,
+	PHM_ClockGateSetting_StaticOff,
+	PHM_ClockGateSetting_Dynamic
+};
+
+struct phm_asic_blocks {
+	bool gfx : 1;
+	bool uvd : 1;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h
new file mode 100644
index 0000000..d7d83b7
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h
@@ -0,0 +1,47 @@
+
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef PP_DEBUG_H
+#define PP_DEBUG_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#define PP_ASSERT_WITH_CODE(cond, msg, code)	\
+	do {					\
+		if (!(cond)) {			\
+			printk("%s\n", msg);	\
+			code;			\
+		}				\
+	} while (0)
+
+
+#define PP_DBG_LOG(fmt, ...) \
+	do { \
+		if(0)printk(KERN_INFO "[ pp_dbg ] " fmt, ##__VA_ARGS__); \
+	} while (0)
+
+
+#endif /* PP_DEBUG_H */
+
diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_feature.h b/drivers/gpu/drm/amd/powerplay/inc/pp_feature.h
new file mode 100644
index 0000000..0faf6a2
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/pp_feature.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _PP_FEATURE_H_
+#define _PP_FEATURE_H_
+
+/**
+ * PowerPlay feature ids.
+ */
+enum pp_feature {
+	PP_Feature_PowerPlay = 0,
+	PP_Feature_User2DPerformance,
+	PP_Feature_User3DPerformance,
+	PP_Feature_VariBright,
+	PP_Feature_VariBrightOnPowerXpress,
+	PP_Feature_ReducedRefreshRate,
+	PP_Feature_GFXClockGating,
+	PP_Feature_OverdriveTest,
+	PP_Feature_OverDrive,
+	PP_Feature_PowerBudgetWaiver,
+	PP_Feature_PowerControl,
+	PP_Feature_PowerControl_2,
+	PP_Feature_MultiUVDState,
+	PP_Feature_Force3DClock,
+	PP_Feature_BACO,
+	PP_Feature_PowerDown,
+	PP_Feature_DynamicUVDState,
+	PP_Feature_VCEDPM,
+	PP_Feature_PPM,
+	PP_Feature_ACP_POWERGATING,
+	PP_Feature_FFC,
+	PP_Feature_FPS,
+	PP_Feature_ViPG,
+	PP_Feature_Max
+};
+
+/**
+ * Struct for PowerPlay feature info.
+ */
+struct pp_feature_info {
+	bool supported;               /* feature supported by PowerPlay */
+	bool enabled;                 /* feature enabled in PowerPlay */
+	bool enabled_default;        /* default enable status of the feature */
+	uint32_t version;             /* feature version */
+};
+
+#endif /* _PP_FEATURE_H_ */
diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h b/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h
new file mode 100644
index 0000000..4d8ed1f
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _PP_INSTANCE_H_
+#define _PP_INSTANCE_H_
+
+#include "smumgr.h"
+#include "hwmgr.h"
+#include "eventmgr.h"
+
+#define PP_VALID  0x1F1F1F1F
+
+struct pp_instance {
+	uint32_t pp_valid;
+	struct pp_smumgr *smu_mgr;
+	struct pp_hwmgr *hwmgr;
+	struct pp_eventmgr *eventmgr;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_power_source.h b/drivers/gpu/drm/amd/powerplay/inc/pp_power_source.h
new file mode 100644
index 0000000..b43315c
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/pp_power_source.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef PP_POWERSOURCE_H
+#define PP_POWERSOURCE_H
+
+enum pp_power_source {
+	PP_PowerSource_AC = 0,
+	PP_PowerSource_DC,
+	PP_PowerSource_LimitedPower,
+	PP_PowerSource_LimitedPower_2,
+	PP_PowerSource_Max
+};
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h b/drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h
new file mode 100644
index 0000000..c067e09
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _PP_INTERRUPT_H_
+#define _PP_INTERRUPT_H_
+
+enum amd_thermal_irq {
+	AMD_THERMAL_IRQ_LOW_TO_HIGH = 0,
+	AMD_THERMAL_IRQ_HIGH_TO_LOW,
+
+	AMD_THERMAL_IRQ_LAST
+};
+
+/* The type of the interrupt callback functions in PowerPlay */
+typedef int (*irq_handler_func_t)(void *private_data,
+				unsigned src_id, const uint32_t *iv_entry);
+
+/* Event Manager action chain list information */
+struct pp_interrupt_registration_info {
+	irq_handler_func_t call_back; /* Pointer to callback function */
+	void *context;                   /* Pointer to callback function context */
+	uint32_t src_id;               /* Registered interrupt id */
+	const uint32_t *iv_entry;
+};
+
+#endif /* _PP_INTERRUPT_H_ */
diff --git a/drivers/gpu/drm/amd/amdgpu/smu7.h b/drivers/gpu/drm/amd/powerplay/inc/smu7.h
similarity index 100%
rename from drivers/gpu/drm/amd/amdgpu/smu7.h
rename to drivers/gpu/drm/amd/powerplay/inc/smu7.h
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu72.h b/drivers/gpu/drm/amd/powerplay/inc/smu72.h
new file mode 100644
index 0000000..b73d6b5
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/smu72.h
@@ -0,0 +1,664 @@
+#ifndef SMU72_H
+#define SMU72_H
+
+#if !defined(SMC_MICROCODE)
+#pragma pack(push, 1)
+#endif
+
+#define SMU__NUM_SCLK_DPM_STATE  8
+#define SMU__NUM_MCLK_DPM_LEVELS 4
+#define SMU__NUM_LCLK_DPM_LEVELS 8
+#define SMU__NUM_PCIE_DPM_LEVELS 8
+
+enum SID_OPTION {
+	SID_OPTION_HI,
+	SID_OPTION_LO,
+	SID_OPTION_COUNT
+};
+
+enum Poly3rdOrderCoeff {
+	LEAKAGE_TEMPERATURE_SCALAR,
+	LEAKAGE_VOLTAGE_SCALAR,
+	DYNAMIC_VOLTAGE_SCALAR,
+	POLY_3RD_ORDER_COUNT
+};
+
+struct SMU7_Poly3rdOrder_Data {
+	int32_t a;
+	int32_t b;
+	int32_t c;
+	int32_t d;
+	uint8_t a_shift;
+	uint8_t b_shift;
+	uint8_t c_shift;
+	uint8_t x_shift;
+};
+
+typedef struct SMU7_Poly3rdOrder_Data SMU7_Poly3rdOrder_Data;
+
+struct Power_Calculator_Data {
+	uint16_t NoLoadVoltage;
+	uint16_t LoadVoltage;
+	uint16_t Resistance;
+	uint16_t Temperature;
+	uint16_t BaseLeakage;
+	uint16_t LkgTempScalar;
+	uint16_t LkgVoltScalar;
+	uint16_t LkgAreaScalar;
+	uint16_t LkgPower;
+	uint16_t DynVoltScalar;
+	uint32_t Cac;
+	uint32_t DynPower;
+	uint32_t TotalCurrent;
+	uint32_t TotalPower;
+};
+
+typedef struct Power_Calculator_Data PowerCalculatorData_t;
+
+struct Gc_Cac_Weight_Data {
+	uint8_t index;
+	uint32_t value;
+};
+
+typedef struct Gc_Cac_Weight_Data GcCacWeight_Data;
+
+
+typedef struct {
+	uint32_t high;
+	uint32_t low;
+} data_64_t;
+
+typedef struct {
+	data_64_t high;
+	data_64_t low;
+} data_128_t;
+
+#define SMU7_CONTEXT_ID_SMC        1
+#define SMU7_CONTEXT_ID_VBIOS      2
+
+#define SMU72_MAX_LEVELS_VDDC            16
+#define SMU72_MAX_LEVELS_VDDGFX          16
+#define SMU72_MAX_LEVELS_VDDCI           8
+#define SMU72_MAX_LEVELS_MVDD            4
+
+#define SMU_MAX_SMIO_LEVELS              4
+
+#define SMU72_MAX_LEVELS_GRAPHICS        SMU__NUM_SCLK_DPM_STATE   /* SCLK + SQ DPM + ULV */
+#define SMU72_MAX_LEVELS_MEMORY          SMU__NUM_MCLK_DPM_LEVELS   /* MCLK Levels DPM */
+#define SMU72_MAX_LEVELS_GIO             SMU__NUM_LCLK_DPM_LEVELS  /* LCLK Levels */
+#define SMU72_MAX_LEVELS_LINK            SMU__NUM_PCIE_DPM_LEVELS  /* PCIe speed and number of lanes. */
+#define SMU72_MAX_LEVELS_UVD             8   /* VCLK/DCLK levels for UVD. */
+#define SMU72_MAX_LEVELS_VCE             8   /* ECLK levels for VCE. */
+#define SMU72_MAX_LEVELS_ACP             8   /* ACLK levels for ACP. */
+#define SMU72_MAX_LEVELS_SAMU            8   /* SAMCLK levels for SAMU. */
+#define SMU72_MAX_ENTRIES_SMIO           32  /* Number of entries in SMIO table. */
+
+#define DPM_NO_LIMIT 0
+#define DPM_NO_UP 1
+#define DPM_GO_DOWN 2
+#define DPM_GO_UP 3
+
+#define SMU7_FIRST_DPM_GRAPHICS_LEVEL    0
+#define SMU7_FIRST_DPM_MEMORY_LEVEL      0
+
+#define GPIO_CLAMP_MODE_VRHOT      1
+#define GPIO_CLAMP_MODE_THERM      2
+#define GPIO_CLAMP_MODE_DC         4
+
+#define SCRATCH_B_TARG_PCIE_INDEX_SHIFT 0
+#define SCRATCH_B_TARG_PCIE_INDEX_MASK  (0x7<<SCRATCH_B_TARG_PCIE_INDEX_SHIFT)
+#define SCRATCH_B_CURR_PCIE_INDEX_SHIFT 3
+#define SCRATCH_B_CURR_PCIE_INDEX_MASK  (0x7<<SCRATCH_B_CURR_PCIE_INDEX_SHIFT)
+#define SCRATCH_B_TARG_UVD_INDEX_SHIFT  6
+#define SCRATCH_B_TARG_UVD_INDEX_MASK   (0x7<<SCRATCH_B_TARG_UVD_INDEX_SHIFT)
+#define SCRATCH_B_CURR_UVD_INDEX_SHIFT  9
+#define SCRATCH_B_CURR_UVD_INDEX_MASK   (0x7<<SCRATCH_B_CURR_UVD_INDEX_SHIFT)
+#define SCRATCH_B_TARG_VCE_INDEX_SHIFT  12
+#define SCRATCH_B_TARG_VCE_INDEX_MASK   (0x7<<SCRATCH_B_TARG_VCE_INDEX_SHIFT)
+#define SCRATCH_B_CURR_VCE_INDEX_SHIFT  15
+#define SCRATCH_B_CURR_VCE_INDEX_MASK   (0x7<<SCRATCH_B_CURR_VCE_INDEX_SHIFT)
+#define SCRATCH_B_TARG_ACP_INDEX_SHIFT  18
+#define SCRATCH_B_TARG_ACP_INDEX_MASK   (0x7<<SCRATCH_B_TARG_ACP_INDEX_SHIFT)
+#define SCRATCH_B_CURR_ACP_INDEX_SHIFT  21
+#define SCRATCH_B_CURR_ACP_INDEX_MASK   (0x7<<SCRATCH_B_CURR_ACP_INDEX_SHIFT)
+#define SCRATCH_B_TARG_SAMU_INDEX_SHIFT 24
+#define SCRATCH_B_TARG_SAMU_INDEX_MASK  (0x7<<SCRATCH_B_TARG_SAMU_INDEX_SHIFT)
+#define SCRATCH_B_CURR_SAMU_INDEX_SHIFT 27
+#define SCRATCH_B_CURR_SAMU_INDEX_MASK  (0x7<<SCRATCH_B_CURR_SAMU_INDEX_SHIFT)
+
+/* Virtualization Defines */
+#define CG_XDMA_MASK  0x1
+#define CG_XDMA_SHIFT 0
+#define CG_UVD_MASK   0x2
+#define CG_UVD_SHIFT  1
+#define CG_VCE_MASK   0x4
+#define CG_VCE_SHIFT  2
+#define CG_SAMU_MASK  0x8
+#define CG_SAMU_SHIFT 3
+#define CG_GFX_MASK   0x10
+#define CG_GFX_SHIFT  4
+#define CG_SDMA_MASK  0x20
+#define CG_SDMA_SHIFT 5
+#define CG_HDP_MASK   0x40
+#define CG_HDP_SHIFT  6
+#define CG_MC_MASK    0x80
+#define CG_MC_SHIFT   7
+#define CG_DRM_MASK   0x100
+#define CG_DRM_SHIFT  8
+#define CG_ROM_MASK   0x200
+#define CG_ROM_SHIFT  9
+#define CG_BIF_MASK   0x400
+#define CG_BIF_SHIFT  10
+
+#define SMU72_DTE_ITERATIONS 5
+#define SMU72_DTE_SOURCES 3
+#define SMU72_DTE_SINKS 1
+#define SMU72_NUM_CPU_TES 0
+#define SMU72_NUM_GPU_TES 1
+#define SMU72_NUM_NON_TES 2
+#define SMU72_DTE_FAN_SCALAR_MIN 0x100
+#define SMU72_DTE_FAN_SCALAR_MAX 0x166
+#define SMU72_DTE_FAN_TEMP_MAX 93
+#define SMU72_DTE_FAN_TEMP_MIN 83
+
+#if defined SMU__FUSION_ONLY
+#define SMU7_DTE_ITERATIONS 5
+#define SMU7_DTE_SOURCES 5
+#define SMU7_DTE_SINKS 3
+#define SMU7_NUM_CPU_TES 2
+#define SMU7_NUM_GPU_TES 1
+#define SMU7_NUM_NON_TES 2
+#endif
+
+struct SMU7_HystController_Data {
+	uint8_t waterfall_up;
+	uint8_t waterfall_down;
+	uint8_t waterfall_limit;
+	uint8_t spare;
+	uint16_t release_cnt;
+	uint16_t release_limit;
+};
+
+typedef struct SMU7_HystController_Data SMU7_HystController_Data;
+
+struct SMU72_PIDController {
+	uint32_t Ki;
+	int32_t LFWindupUpperLim;
+	int32_t LFWindupLowerLim;
+	uint32_t StatePrecision;
+	uint32_t LfPrecision;
+	uint32_t LfOffset;
+	uint32_t MaxState;
+	uint32_t MaxLfFraction;
+	uint32_t StateShift;
+};
+
+typedef struct SMU72_PIDController SMU72_PIDController;
+
+struct SMU7_LocalDpmScoreboard {
+	uint32_t PercentageBusy;
+
+	int32_t  PIDError;
+	int32_t  PIDIntegral;
+	int32_t  PIDOutput;
+
+	uint32_t SigmaDeltaAccum;
+	uint32_t SigmaDeltaOutput;
+	uint32_t SigmaDeltaLevel;
+
+	uint32_t UtilizationSetpoint;
+
+	uint8_t  TdpClampMode;
+	uint8_t  TdcClampMode;
+	uint8_t  ThermClampMode;
+	uint8_t  VoltageBusy;
+
+	int8_t   CurrLevel;
+	int8_t   TargLevel;
+	uint8_t  LevelChangeInProgress;
+	uint8_t  UpHyst;
+
+	uint8_t  DownHyst;
+	uint8_t  VoltageDownHyst;
+	uint8_t  DpmEnable;
+	uint8_t  DpmRunning;
+
+	uint8_t  DpmForce;
+	uint8_t  DpmForceLevel;
+	uint8_t  DisplayWatermark;
+	uint8_t  McArbIndex;
+
+	uint32_t MinimumPerfSclk;
+
+	uint8_t  AcpiReq;
+	uint8_t  AcpiAck;
+	uint8_t  GfxClkSlow;
+	uint8_t  GpioClampMode; /* bit0 = VRHOT: bit1 = THERM: bit2 = DC */
+
+	uint8_t  FpsFilterWeight;
+	uint8_t  EnabledLevelsChange;
+	uint8_t  DteClampMode;
+	uint8_t  FpsClampMode;
+
+	uint16_t LevelResidencyCounters[SMU72_MAX_LEVELS_GRAPHICS];
+	uint16_t LevelSwitchCounters[SMU72_MAX_LEVELS_GRAPHICS];
+
+	void     (*TargetStateCalculator)(uint8_t);
+	void     (*SavedTargetStateCalculator)(uint8_t);
+
+	uint16_t AutoDpmInterval;
+	uint16_t AutoDpmRange;
+
+	uint8_t  FpsEnabled;
+	uint8_t  MaxPerfLevel;
+	uint8_t  AllowLowClkInterruptToHost;
+	uint8_t  FpsRunning;
+
+	uint32_t MaxAllowedFrequency;
+
+	uint32_t FilteredSclkFrequency;
+	uint32_t LastSclkFrequency;
+	uint32_t FilteredSclkFrequencyCnt;
+};
+
+typedef struct SMU7_LocalDpmScoreboard SMU7_LocalDpmScoreboard;
+
+#define SMU7_MAX_VOLTAGE_CLIENTS 12
+
+typedef uint8_t (*VoltageChangeHandler_t)(uint16_t, uint8_t);
+
+struct SMU_VoltageLevel {
+	uint8_t Vddc;
+	uint8_t Vddci;
+	uint8_t VddGfx;
+	uint8_t Phases;
+};
+
+typedef struct SMU_VoltageLevel SMU_VoltageLevel;
+
+struct SMU7_VoltageScoreboard {
+	SMU_VoltageLevel CurrentVoltage;
+	SMU_VoltageLevel TargetVoltage;
+	uint16_t MaxVid;
+	uint8_t  HighestVidOffset;
+	uint8_t  CurrentVidOffset;
+
+	uint8_t  ControllerBusy;
+	uint8_t  CurrentVid;
+	uint8_t  CurrentVddciVid;
+	uint8_t  VddGfxShutdown; /* 0 = normal mode, 1 = shut down */
+
+	SMU_VoltageLevel RequestedVoltage[SMU7_MAX_VOLTAGE_CLIENTS];
+	uint8_t  EnabledRequest[SMU7_MAX_VOLTAGE_CLIENTS];
+
+	uint8_t  TargetIndex;
+	uint8_t  Delay;
+	uint8_t  ControllerEnable;
+	uint8_t  ControllerRunning;
+	uint16_t CurrentStdVoltageHiSidd;
+	uint16_t CurrentStdVoltageLoSidd;
+	uint8_t  OverrideVoltage;
+	uint8_t  VddcUseUlvOffset;
+	uint8_t  VddGfxUseUlvOffset;
+	uint8_t  padding;
+
+	VoltageChangeHandler_t ChangeVddc;
+	VoltageChangeHandler_t ChangeVddGfx;
+	VoltageChangeHandler_t ChangeVddci;
+	VoltageChangeHandler_t ChangePhase;
+	VoltageChangeHandler_t ChangeMvdd;
+
+	VoltageChangeHandler_t functionLinks[6];
+
+	uint8_t *VddcFollower1;
+	uint8_t *VddcFollower2;
+	int16_t  Driver_OD_RequestedVidOffset1;
+	int16_t  Driver_OD_RequestedVidOffset2;
+
+};
+
+typedef struct SMU7_VoltageScoreboard SMU7_VoltageScoreboard;
+
+#define SMU7_MAX_PCIE_LINK_SPEEDS 3 /* 0:Gen1 1:Gen2 2:Gen3 */
+
+struct SMU7_PCIeLinkSpeedScoreboard {
+	uint8_t     DpmEnable;
+	uint8_t     DpmRunning;
+	uint8_t     DpmForce;
+	uint8_t     DpmForceLevel;
+
+	uint8_t     CurrentLinkSpeed;
+	uint8_t     EnabledLevelsChange;
+	uint16_t    AutoDpmInterval;
+
+	uint16_t    AutoDpmRange;
+	uint16_t    AutoDpmCount;
+
+	uint8_t     DpmMode;
+	uint8_t     AcpiReq;
+	uint8_t     AcpiAck;
+	uint8_t     CurrentLinkLevel;
+
+};
+
+typedef struct SMU7_PCIeLinkSpeedScoreboard SMU7_PCIeLinkSpeedScoreboard;
+
+/* -------------------------------------------------------- CAC table ------------------------------------------------------ */
+#define SMU7_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16
+#define SMU7_LKGE_LUT_NUM_OF_VOLT_ENTRIES 16
+#define SMU7_SCALE_I  7
+#define SMU7_SCALE_R 12
+
+struct SMU7_PowerScoreboard {
+	PowerCalculatorData_t VddGfxPowerData[SID_OPTION_COUNT];
+	PowerCalculatorData_t VddcPowerData[SID_OPTION_COUNT];
+
+	uint32_t TotalGpuPower;
+	uint32_t TdcCurrent;
+
+	uint16_t   VddciTotalPower;
+	uint16_t   sparesasfsdfd;
+	uint16_t   Vddr1Power;
+	uint16_t   RocPower;
+
+	uint16_t   CalcMeasPowerBlend;
+	uint8_t    SidOptionPower;
+	uint8_t    SidOptionCurrent;
+
+	uint32_t   WinTime;
+
+	uint16_t Telemetry_1_slope;
+	uint16_t Telemetry_2_slope;
+	int32_t Telemetry_1_offset;
+	int32_t Telemetry_2_offset;
+
+	uint32_t VddcCurrentTelemetry;
+	uint32_t VddGfxCurrentTelemetry;
+	uint32_t VddcPowerTelemetry;
+	uint32_t VddGfxPowerTelemetry;
+	uint32_t VddciPowerTelemetry;
+
+	uint32_t VddcPower;
+	uint32_t VddGfxPower;
+	uint32_t VddciPower;
+
+	uint32_t TelemetryCurrent[2];
+	uint32_t TelemetryVoltage[2];
+	uint32_t TelemetryPower[2];
+};
+
+typedef struct SMU7_PowerScoreboard SMU7_PowerScoreboard;
+
+struct SMU7_ThermalScoreboard {
+	int16_t  GpuLimit;
+	int16_t  GpuHyst;
+	uint16_t CurrGnbTemp;
+	uint16_t FilteredGnbTemp;
+
+	uint8_t  ControllerEnable;
+	uint8_t  ControllerRunning;
+	uint8_t  AutoTmonCalInterval;
+	uint8_t  AutoTmonCalEnable;
+
+	uint8_t  ThermalDpmEnabled;
+	uint8_t  SclkEnabledMask;
+	uint8_t  spare[2];
+	int32_t  temperature_gradient;
+
+	SMU7_HystController_Data HystControllerData;
+	int32_t  WeightedSensorTemperature;
+	uint16_t TemperatureLimit[SMU72_MAX_LEVELS_GRAPHICS];
+	uint32_t Alpha;
+};
+
+typedef struct SMU7_ThermalScoreboard SMU7_ThermalScoreboard;
+
+/* For FeatureEnables: */
+#define SMU7_SCLK_DPM_CONFIG_MASK                        0x01
+#define SMU7_VOLTAGE_CONTROLLER_CONFIG_MASK              0x02
+#define SMU7_THERMAL_CONTROLLER_CONFIG_MASK              0x04
+#define SMU7_MCLK_DPM_CONFIG_MASK                        0x08
+#define SMU7_UVD_DPM_CONFIG_MASK                         0x10
+#define SMU7_VCE_DPM_CONFIG_MASK                         0x20
+#define SMU7_ACP_DPM_CONFIG_MASK                         0x40
+#define SMU7_SAMU_DPM_CONFIG_MASK                        0x80
+#define SMU7_PCIEGEN_DPM_CONFIG_MASK                    0x100
+
+#define SMU7_ACP_MCLK_HANDSHAKE_DISABLE                  0x00000001
+#define SMU7_ACP_SCLK_HANDSHAKE_DISABLE                  0x00000002
+#define SMU7_UVD_MCLK_HANDSHAKE_DISABLE                  0x00000100
+#define SMU7_UVD_SCLK_HANDSHAKE_DISABLE                  0x00000200
+#define SMU7_VCE_MCLK_HANDSHAKE_DISABLE                  0x00010000
+#define SMU7_VCE_SCLK_HANDSHAKE_DISABLE                  0x00020000
+
+/* All 'soft registers' should be uint32_t. */
+struct SMU72_SoftRegisters {
+	uint32_t        RefClockFrequency;
+	uint32_t        PmTimerPeriod;
+	uint32_t        FeatureEnables;
+
+	uint32_t        PreVBlankGap;
+	uint32_t        VBlankTimeout;
+	uint32_t        TrainTimeGap;
+
+	uint32_t        MvddSwitchTime;
+	uint32_t        LongestAcpiTrainTime;
+	uint32_t        AcpiDelay;
+	uint32_t        G5TrainTime;
+	uint32_t        DelayMpllPwron;
+	uint32_t        VoltageChangeTimeout;
+
+	uint32_t        HandshakeDisables;
+
+	uint8_t         DisplayPhy1Config;
+	uint8_t         DisplayPhy2Config;
+	uint8_t         DisplayPhy3Config;
+	uint8_t         DisplayPhy4Config;
+
+	uint8_t         DisplayPhy5Config;
+	uint8_t         DisplayPhy6Config;
+	uint8_t         DisplayPhy7Config;
+	uint8_t         DisplayPhy8Config;
+
+	uint32_t        AverageGraphicsActivity;
+	uint32_t        AverageMemoryActivity;
+	uint32_t        AverageGioActivity;
+
+	uint8_t         SClkDpmEnabledLevels;
+	uint8_t         MClkDpmEnabledLevels;
+	uint8_t         LClkDpmEnabledLevels;
+	uint8_t         PCIeDpmEnabledLevels;
+
+	uint8_t         UVDDpmEnabledLevels;
+	uint8_t         SAMUDpmEnabledLevels;
+	uint8_t         ACPDpmEnabledLevels;
+	uint8_t         VCEDpmEnabledLevels;
+
+	uint32_t        DRAM_LOG_ADDR_H;
+	uint32_t        DRAM_LOG_ADDR_L;
+	uint32_t        DRAM_LOG_PHY_ADDR_H;
+	uint32_t        DRAM_LOG_PHY_ADDR_L;
+	uint32_t        DRAM_LOG_BUFF_SIZE;
+	uint32_t        UlvEnterCount;
+	uint32_t        UlvTime;
+	uint32_t        UcodeLoadStatus;
+	uint32_t        Reserved[2];
+
+};
+
+typedef struct SMU72_SoftRegisters SMU72_SoftRegisters;
+
+struct SMU72_Firmware_Header {
+	uint32_t Digest[5];
+	uint32_t Version;
+	uint32_t HeaderSize;
+	uint32_t Flags;
+	uint32_t EntryPoint;
+	uint32_t CodeSize;
+	uint32_t ImageSize;
+
+	uint32_t Rtos;
+	uint32_t SoftRegisters;
+	uint32_t DpmTable;
+	uint32_t FanTable;
+	uint32_t CacConfigTable;
+	uint32_t CacStatusTable;
+	uint32_t mcRegisterTable;
+	uint32_t mcArbDramTimingTable;
+	uint32_t PmFuseTable;
+	uint32_t Globals;
+	uint32_t ClockStretcherTable;
+	uint32_t Reserved[41];
+	uint32_t Signature;
+};
+
+typedef struct SMU72_Firmware_Header SMU72_Firmware_Header;
+
+#define SMU72_FIRMWARE_HEADER_LOCATION 0x20000
+
+enum  DisplayConfig {
+	PowerDown = 1,
+	DP54x4,
+	DP54x2,
+	DP54x1,
+	DP27x4,
+	DP27x2,
+	DP27x1,
+	HDMI297,
+	HDMI162,
+	LVDS,
+	DP324x4,
+	DP324x2,
+	DP324x1
+};
+
+#define MC_BLOCK_COUNT 1
+#define CPL_BLOCK_COUNT 5
+#define SE_BLOCK_COUNT 15
+#define GC_BLOCK_COUNT 24
+
+struct SMU7_Local_Cac {
+	uint8_t BlockId;
+	uint8_t SignalId;
+	uint8_t Threshold;
+	uint8_t Padding;
+};
+
+typedef struct SMU7_Local_Cac SMU7_Local_Cac;
+
+struct SMU7_Local_Cac_Table {
+	SMU7_Local_Cac CplLocalCac[CPL_BLOCK_COUNT];
+	SMU7_Local_Cac McLocalCac[MC_BLOCK_COUNT];
+	SMU7_Local_Cac SeLocalCac[SE_BLOCK_COUNT];
+	SMU7_Local_Cac GcLocalCac[GC_BLOCK_COUNT];
+};
+
+typedef struct SMU7_Local_Cac_Table SMU7_Local_Cac_Table;
+
+#if !defined(SMC_MICROCODE)
+#pragma pack(pop)
+#endif
+
+/* Description of Clock Gating bitmask for Tonga: */
+/* System Clock Gating */
+#define CG_SYS_BITMASK_FIRST_BIT      0  /* First bit of Sys CG bitmask */
+#define CG_SYS_BITMASK_LAST_BIT       9  /* Last bit of Sys CG bitmask */
+#define CG_SYS_BIF_MGLS_SHIFT         0
+#define CG_SYS_ROM_SHIFT              1
+#define CG_SYS_MC_MGCG_SHIFT          2
+#define CG_SYS_MC_MGLS_SHIFT          3
+#define CG_SYS_SDMA_MGCG_SHIFT        4
+#define CG_SYS_SDMA_MGLS_SHIFT        5
+#define CG_SYS_DRM_MGCG_SHIFT         6
+#define CG_SYS_HDP_MGCG_SHIFT         7
+#define CG_SYS_HDP_MGLS_SHIFT         8
+#define CG_SYS_DRM_MGLS_SHIFT         9
+
+#define CG_SYS_BIF_MGLS_MASK          0x1
+#define CG_SYS_ROM_MASK               0x2
+#define CG_SYS_MC_MGCG_MASK           0x4
+#define CG_SYS_MC_MGLS_MASK           0x8
+#define CG_SYS_SDMA_MGCG_MASK         0x10
+#define CG_SYS_SDMA_MGLS_MASK         0x20
+#define CG_SYS_DRM_MGCG_MASK          0x40
+#define CG_SYS_HDP_MGCG_MASK          0x80
+#define CG_SYS_HDP_MGLS_MASK          0x100
+#define CG_SYS_DRM_MGLS_MASK          0x200
+
+/* Graphics Clock Gating */
+#define CG_GFX_BITMASK_FIRST_BIT      16 /* First bit of Gfx CG bitmask */
+#define CG_GFX_BITMASK_LAST_BIT       20 /* Last bit of Gfx CG bitmask */
+#define CG_GFX_CGCG_SHIFT             16
+#define CG_GFX_CGLS_SHIFT             17
+#define CG_CPF_MGCG_SHIFT             18
+#define CG_RLC_MGCG_SHIFT             19
+#define CG_GFX_OTHERS_MGCG_SHIFT      20
+
+#define CG_GFX_CGCG_MASK              0x00010000
+#define CG_GFX_CGLS_MASK              0x00020000
+#define CG_CPF_MGCG_MASK              0x00040000
+#define CG_RLC_MGCG_MASK              0x00080000
+#define CG_GFX_OTHERS_MGCG_MASK       0x00100000
+
+/* Voltage Regulator Configuration */
+/* VR Config info is contained in dpmTable.VRConfig */
+
+#define VRCONF_VDDC_MASK         0x000000FF
+#define VRCONF_VDDC_SHIFT        0
+#define VRCONF_VDDGFX_MASK       0x0000FF00
+#define VRCONF_VDDGFX_SHIFT      8
+#define VRCONF_VDDCI_MASK        0x00FF0000
+#define VRCONF_VDDCI_SHIFT       16
+#define VRCONF_MVDD_MASK         0xFF000000
+#define VRCONF_MVDD_SHIFT        24
+
+#define VR_MERGED_WITH_VDDC      0
+#define VR_SVI2_PLANE_1          1
+#define VR_SVI2_PLANE_2          2
+#define VR_SMIO_PATTERN_1        3
+#define VR_SMIO_PATTERN_2        4
+#define VR_STATIC_VOLTAGE        5
+
+/* Clock Stretcher Configuration */
+
+#define CLOCK_STRETCHER_MAX_ENTRIES 0x4
+#define CKS_LOOKUPTable_MAX_ENTRIES 0x4
+
+/* The 'settings' field is subdivided in the following way: */
+#define CLOCK_STRETCHER_SETTING_DDT_MASK             0x01
+#define CLOCK_STRETCHER_SETTING_DDT_SHIFT            0x0
+#define CLOCK_STRETCHER_SETTING_STRETCH_AMOUNT_MASK  0x1E
+#define CLOCK_STRETCHER_SETTING_STRETCH_AMOUNT_SHIFT 0x1
+#define CLOCK_STRETCHER_SETTING_ENABLE_MASK          0x80
+#define CLOCK_STRETCHER_SETTING_ENABLE_SHIFT         0x7
+
+struct SMU_ClockStretcherDataTableEntry {
+	uint8_t minVID;
+	uint8_t maxVID;
+
+	uint16_t setting;
+};
+typedef struct SMU_ClockStretcherDataTableEntry SMU_ClockStretcherDataTableEntry;
+
+struct SMU_ClockStretcherDataTable {
+	SMU_ClockStretcherDataTableEntry ClockStretcherDataTableEntry[CLOCK_STRETCHER_MAX_ENTRIES];
+};
+typedef struct SMU_ClockStretcherDataTable SMU_ClockStretcherDataTable;
+
+struct SMU_CKS_LOOKUPTableEntry {
+	uint16_t minFreq;
+	uint16_t maxFreq;
+
+	uint8_t setting;
+	uint8_t padding[3];
+};
+typedef struct SMU_CKS_LOOKUPTableEntry SMU_CKS_LOOKUPTableEntry;
+
+struct SMU_CKS_LOOKUPTable {
+	SMU_CKS_LOOKUPTableEntry CKS_LOOKUPTableEntry[CKS_LOOKUPTable_MAX_ENTRIES];
+};
+typedef struct SMU_CKS_LOOKUPTable SMU_CKS_LOOKUPTable;
+
+#endif
+
+
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu72_discrete.h b/drivers/gpu/drm/amd/powerplay/inc/smu72_discrete.h
new file mode 100644
index 0000000..98f76e9
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/smu72_discrete.h
@@ -0,0 +1,760 @@
+#ifndef SMU72_DISCRETE_H
+#define SMU72_DISCRETE_H
+
+#include "smu72.h"
+
+#if !defined(SMC_MICROCODE)
+#pragma pack(push, 1)
+#endif
+
+struct SMIO_Pattern {
+	uint16_t Voltage;
+	uint8_t  Smio;
+	uint8_t  padding;
+};
+
+typedef struct SMIO_Pattern SMIO_Pattern;
+
+struct SMIO_Table {
+	SMIO_Pattern Pattern[SMU_MAX_SMIO_LEVELS];
+};
+
+typedef struct SMIO_Table SMIO_Table;
+
+struct SMU72_Discrete_GraphicsLevel {
+	SMU_VoltageLevel MinVoltage;
+
+	uint32_t    SclkFrequency;
+
+	uint8_t     pcieDpmLevel;
+	uint8_t     DeepSleepDivId;
+	uint16_t    ActivityLevel;
+
+	uint32_t    CgSpllFuncCntl3;
+	uint32_t    CgSpllFuncCntl4;
+	uint32_t    SpllSpreadSpectrum;
+	uint32_t    SpllSpreadSpectrum2;
+	uint32_t    CcPwrDynRm;
+	uint32_t    CcPwrDynRm1;
+	uint8_t     SclkDid;
+	uint8_t     DisplayWatermark;
+	uint8_t     EnabledForActivity;
+	uint8_t     EnabledForThrottle;
+	uint8_t     UpHyst;
+	uint8_t     DownHyst;
+	uint8_t     VoltageDownHyst;
+	uint8_t     PowerThrottle;
+};
+
+typedef struct SMU72_Discrete_GraphicsLevel SMU72_Discrete_GraphicsLevel;
+
+struct SMU72_Discrete_ACPILevel {
+	uint32_t    Flags;
+	SMU_VoltageLevel MinVoltage;
+	uint32_t    SclkFrequency;
+	uint8_t     SclkDid;
+	uint8_t     DisplayWatermark;
+	uint8_t     DeepSleepDivId;
+	uint8_t     padding;
+	uint32_t    CgSpllFuncCntl;
+	uint32_t    CgSpllFuncCntl2;
+	uint32_t    CgSpllFuncCntl3;
+	uint32_t    CgSpllFuncCntl4;
+	uint32_t    SpllSpreadSpectrum;
+	uint32_t    SpllSpreadSpectrum2;
+	uint32_t    CcPwrDynRm;
+	uint32_t    CcPwrDynRm1;
+};
+
+typedef struct SMU72_Discrete_ACPILevel SMU72_Discrete_ACPILevel;
+
+struct SMU72_Discrete_Ulv {
+	uint32_t    CcPwrDynRm;
+	uint32_t    CcPwrDynRm1;
+	uint16_t    VddcOffset;
+	uint8_t     VddcOffsetVid;
+	uint8_t     VddcPhase;
+	uint32_t    Reserved;
+};
+
+typedef struct SMU72_Discrete_Ulv SMU72_Discrete_Ulv;
+
+struct SMU72_Discrete_MemoryLevel {
+	SMU_VoltageLevel MinVoltage;
+	uint32_t    MinMvdd;
+
+	uint32_t    MclkFrequency;
+
+	uint8_t     EdcReadEnable;
+	uint8_t     EdcWriteEnable;
+	uint8_t     RttEnable;
+	uint8_t     StutterEnable;
+
+	uint8_t     StrobeEnable;
+	uint8_t     StrobeRatio;
+	uint8_t     EnabledForThrottle;
+	uint8_t     EnabledForActivity;
+
+	uint8_t     UpHyst;
+	uint8_t     DownHyst;
+	uint8_t     VoltageDownHyst;
+	uint8_t     padding;
+
+	uint16_t    ActivityLevel;
+	uint8_t     DisplayWatermark;
+	uint8_t     padding1;
+
+	uint32_t    MpllFuncCntl;
+	uint32_t    MpllFuncCntl_1;
+	uint32_t    MpllFuncCntl_2;
+	uint32_t    MpllAdFuncCntl;
+	uint32_t    MpllDqFuncCntl;
+	uint32_t    MclkPwrmgtCntl;
+	uint32_t    DllCntl;
+	uint32_t    MpllSs1;
+	uint32_t    MpllSs2;
+};
+
+typedef struct SMU72_Discrete_MemoryLevel SMU72_Discrete_MemoryLevel;
+
+struct SMU72_Discrete_LinkLevel {
+	uint8_t     PcieGenSpeed;           /*< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 */
+	uint8_t     PcieLaneCount;          /*< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16 */
+	uint8_t     EnabledForActivity;
+	uint8_t     SPC;
+	uint32_t    DownThreshold;
+	uint32_t    UpThreshold;
+	uint32_t    Reserved;
+};
+
+typedef struct SMU72_Discrete_LinkLevel SMU72_Discrete_LinkLevel;
+
+/* MC ARB DRAM Timing registers. */
+struct SMU72_Discrete_MCArbDramTimingTableEntry {
+	uint32_t McArbDramTiming;
+	uint32_t McArbDramTiming2;
+	uint8_t  McArbBurstTime;
+	uint8_t  padding[3];
+};
+
+typedef struct SMU72_Discrete_MCArbDramTimingTableEntry SMU72_Discrete_MCArbDramTimingTableEntry;
+
+struct SMU72_Discrete_MCArbDramTimingTable {
+	SMU72_Discrete_MCArbDramTimingTableEntry entries[SMU__NUM_SCLK_DPM_STATE][SMU__NUM_MCLK_DPM_LEVELS];
+};
+
+typedef struct SMU72_Discrete_MCArbDramTimingTable SMU72_Discrete_MCArbDramTimingTable;
+
+/* UVD VCLK/DCLK state (level) definition. */
+struct SMU72_Discrete_UvdLevel {
+	uint32_t VclkFrequency;
+	uint32_t DclkFrequency;
+	SMU_VoltageLevel MinVoltage;
+	uint8_t  VclkDivider;
+	uint8_t  DclkDivider;
+	uint8_t  padding[2];
+};
+
+typedef struct SMU72_Discrete_UvdLevel SMU72_Discrete_UvdLevel;
+
+/* Clocks for other external blocks (VCE, ACP, SAMU). */
+struct SMU72_Discrete_ExtClkLevel {
+	uint32_t Frequency;
+	SMU_VoltageLevel MinVoltage;
+	uint8_t  Divider;
+	uint8_t  padding[3];
+};
+
+typedef struct SMU72_Discrete_ExtClkLevel SMU72_Discrete_ExtClkLevel;
+
+struct SMU72_Discrete_StateInfo {
+	uint32_t SclkFrequency;
+	uint32_t MclkFrequency;
+	uint32_t VclkFrequency;
+	uint32_t DclkFrequency;
+	uint32_t SamclkFrequency;
+	uint32_t AclkFrequency;
+	uint32_t EclkFrequency;
+	uint16_t MvddVoltage;
+	uint16_t padding16;
+	uint8_t  DisplayWatermark;
+	uint8_t  McArbIndex;
+	uint8_t  McRegIndex;
+	uint8_t  SeqIndex;
+	uint8_t  SclkDid;
+	int8_t   SclkIndex;
+	int8_t   MclkIndex;
+	uint8_t  PCIeGen;
+
+};
+
+typedef struct SMU72_Discrete_StateInfo SMU72_Discrete_StateInfo;
+
+struct SMU72_Discrete_DpmTable {
+	/* Multi-DPM controller settings */
+	SMU72_PIDController                  GraphicsPIDController;
+	SMU72_PIDController                  MemoryPIDController;
+	SMU72_PIDController                  LinkPIDController;
+
+	uint32_t                            SystemFlags;
+
+	/* SMIO masks for voltage and phase controls */
+	uint32_t                            VRConfig;
+	uint32_t                            SmioMask1;
+	uint32_t                            SmioMask2;
+	SMIO_Table                          SmioTable1;
+	SMIO_Table                          SmioTable2;
+
+	uint32_t                            VddcLevelCount;
+	uint32_t                            VddciLevelCount;
+	uint32_t                            VddGfxLevelCount;
+	uint32_t                            MvddLevelCount;
+
+	uint16_t                            VddcTable[SMU72_MAX_LEVELS_VDDC];
+	uint16_t                            VddGfxTable[SMU72_MAX_LEVELS_VDDGFX];
+	uint16_t                            VddciTable[SMU72_MAX_LEVELS_VDDCI];
+
+	uint8_t                             BapmVddGfxVidHiSidd[SMU72_MAX_LEVELS_VDDGFX];
+	uint8_t                             BapmVddGfxVidLoSidd[SMU72_MAX_LEVELS_VDDGFX];
+	uint8_t                             BapmVddGfxVidHiSidd2[SMU72_MAX_LEVELS_VDDGFX];
+
+	uint8_t                             BapmVddcVidHiSidd[SMU72_MAX_LEVELS_VDDC];
+	uint8_t                             BapmVddcVidLoSidd[SMU72_MAX_LEVELS_VDDC];
+	uint8_t                             BapmVddcVidHiSidd2[SMU72_MAX_LEVELS_VDDC];
+
+	uint8_t                             GraphicsDpmLevelCount;
+	uint8_t                             MemoryDpmLevelCount;
+	uint8_t                             LinkLevelCount;
+	uint8_t                             MasterDeepSleepControl;
+
+	uint8_t                             UvdLevelCount;
+	uint8_t                             VceLevelCount;
+	uint8_t                             AcpLevelCount;
+	uint8_t                             SamuLevelCount;
+
+	uint8_t                             ThermOutGpio;
+	uint8_t                             ThermOutPolarity;
+	uint8_t                             ThermOutMode;
+	uint8_t                             DPMFreezeAndForced;
+	uint32_t                            Reserved[4];
+
+	/* State table entries for each DPM state */
+	SMU72_Discrete_GraphicsLevel        GraphicsLevel[SMU72_MAX_LEVELS_GRAPHICS];
+	SMU72_Discrete_MemoryLevel          MemoryACPILevel;
+	SMU72_Discrete_MemoryLevel          MemoryLevel[SMU72_MAX_LEVELS_MEMORY];
+	SMU72_Discrete_LinkLevel            LinkLevel[SMU72_MAX_LEVELS_LINK];
+	SMU72_Discrete_ACPILevel            ACPILevel;
+	SMU72_Discrete_UvdLevel             UvdLevel[SMU72_MAX_LEVELS_UVD];
+	SMU72_Discrete_ExtClkLevel          VceLevel[SMU72_MAX_LEVELS_VCE];
+	SMU72_Discrete_ExtClkLevel          AcpLevel[SMU72_MAX_LEVELS_ACP];
+	SMU72_Discrete_ExtClkLevel          SamuLevel[SMU72_MAX_LEVELS_SAMU];
+	SMU72_Discrete_Ulv                  Ulv;
+
+	uint32_t                            SclkStepSize;
+	uint32_t                            Smio[SMU72_MAX_ENTRIES_SMIO];
+
+	uint8_t                             UvdBootLevel;
+	uint8_t                             VceBootLevel;
+	uint8_t                             AcpBootLevel;
+	uint8_t                             SamuBootLevel;
+
+	uint8_t                             GraphicsBootLevel;
+	uint8_t                             GraphicsVoltageChangeEnable;
+	uint8_t                             GraphicsThermThrottleEnable;
+	uint8_t                             GraphicsInterval;
+
+	uint8_t                             VoltageInterval;
+	uint8_t                             ThermalInterval;
+	uint16_t                            TemperatureLimitHigh;
+
+	uint16_t                            TemperatureLimitLow;
+	uint8_t                             MemoryBootLevel;
+	uint8_t                             MemoryVoltageChangeEnable;
+
+	uint16_t                            BootMVdd;
+	uint8_t                             MemoryInterval;
+	uint8_t                             MemoryThermThrottleEnable;
+
+	uint16_t                            VoltageResponseTime;
+	uint16_t                            PhaseResponseTime;
+
+	uint8_t                             PCIeBootLinkLevel;
+	uint8_t                             PCIeGenInterval;
+	uint8_t                             DTEInterval;
+	uint8_t                             DTEMode;
+
+	uint8_t                             SVI2Enable;
+	uint8_t                             VRHotGpio;
+	uint8_t                             AcDcGpio;
+	uint8_t                             ThermGpio;
+
+	uint16_t                            PPM_PkgPwrLimit;
+	uint16_t                            PPM_TemperatureLimit;
+
+	uint16_t                            DefaultTdp;
+	uint16_t                            TargetTdp;
+
+	uint16_t                            FpsHighThreshold;
+	uint16_t                            FpsLowThreshold;
+
+	uint16_t                            BAPMTI_R[SMU72_DTE_ITERATIONS][SMU72_DTE_SOURCES][SMU72_DTE_SINKS];
+	uint16_t                            BAPMTI_RC[SMU72_DTE_ITERATIONS][SMU72_DTE_SOURCES][SMU72_DTE_SINKS];
+
+	uint8_t                             DTEAmbientTempBase;
+	uint8_t                             DTETjOffset;
+	uint8_t                             GpuTjMax;
+	uint8_t                             GpuTjHyst;
+
+	SMU_VoltageLevel                    BootVoltage;
+
+	uint32_t                            BAPM_TEMP_GRADIENT;
+
+	uint32_t                            LowSclkInterruptThreshold;
+	uint32_t                            VddGfxReChkWait;
+
+	uint8_t                             ClockStretcherAmount;
+
+	uint8_t                             Sclk_CKS_masterEn0_7;
+	uint8_t                             Sclk_CKS_masterEn8_15;
+	uint8_t                             padding[1];
+
+	uint8_t                             Sclk_voltageOffset[8];
+
+	SMU_ClockStretcherDataTable         ClockStretcherDataTable;
+	SMU_CKS_LOOKUPTable                 CKS_LOOKUPTable;
+};
+
+typedef struct SMU72_Discrete_DpmTable SMU72_Discrete_DpmTable;
+
+/* --------------------------------------------------- AC Timing Parameters ------------------------------------------------ */
+#define SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE 16
+#define SMU72_DISCRETE_MC_REGISTER_ARRAY_SET_COUNT SMU72_MAX_LEVELS_MEMORY /* DPM */
+
+struct SMU72_Discrete_MCRegisterAddress {
+	uint16_t s0;
+	uint16_t s1;
+};
+
+typedef struct SMU72_Discrete_MCRegisterAddress SMU72_Discrete_MCRegisterAddress;
+
+struct SMU72_Discrete_MCRegisterSet {
+	uint32_t value[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE];
+};
+
+typedef struct SMU72_Discrete_MCRegisterSet SMU72_Discrete_MCRegisterSet;
+
+struct SMU72_Discrete_MCRegisters {
+	uint8_t                             last;
+	uint8_t                             reserved[3];
+	SMU72_Discrete_MCRegisterAddress     address[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE];
+	SMU72_Discrete_MCRegisterSet         data[SMU72_DISCRETE_MC_REGISTER_ARRAY_SET_COUNT];
+};
+
+typedef struct SMU72_Discrete_MCRegisters SMU72_Discrete_MCRegisters;
+
+
+/* --------------------------------------------------- Fan Table ----------------------------------------------------------- */
+
+struct SMU72_Discrete_FanTable {
+	uint16_t FdoMode;
+	int16_t  TempMin;
+	int16_t  TempMed;
+	int16_t  TempMax;
+	int16_t  Slope1;
+	int16_t  Slope2;
+	int16_t  FdoMin;
+	int16_t  HystUp;
+	int16_t  HystDown;
+	int16_t  HystSlope;
+	int16_t  TempRespLim;
+	int16_t  TempCurr;
+	int16_t  SlopeCurr;
+	int16_t  PwmCurr;
+	uint32_t RefreshPeriod;
+	int16_t  FdoMax;
+	uint8_t  TempSrc;
+	int8_t   FanControl_GL_Flag;
+};
+
+typedef struct SMU72_Discrete_FanTable SMU72_Discrete_FanTable;
+
+#define SMU7_DISCRETE_GPIO_SCLK_DEBUG             4
+#define SMU7_DISCRETE_GPIO_SCLK_DEBUG_BIT         (0x1 << SMU7_DISCRETE_GPIO_SCLK_DEBUG)
+
+struct SMU7_MclkDpmScoreboard {
+
+	uint32_t PercentageBusy;
+
+	int32_t  PIDError;
+	int32_t  PIDIntegral;
+	int32_t  PIDOutput;
+
+	uint32_t SigmaDeltaAccum;
+	uint32_t SigmaDeltaOutput;
+	uint32_t SigmaDeltaLevel;
+
+	uint32_t UtilizationSetpoint;
+
+	uint8_t  TdpClampMode;
+	uint8_t  TdcClampMode;
+	uint8_t  ThermClampMode;
+	uint8_t  VoltageBusy;
+
+	int8_t   CurrLevel;
+	int8_t   TargLevel;
+	uint8_t  LevelChangeInProgress;
+	uint8_t  UpHyst;
+
+	uint8_t  DownHyst;
+	uint8_t  VoltageDownHyst;
+	uint8_t  DpmEnable;
+	uint8_t  DpmRunning;
+
+	uint8_t  DpmForce;
+	uint8_t  DpmForceLevel;
+	uint8_t  DisplayWatermark;
+	uint8_t  McArbIndex;
+
+	uint32_t MinimumPerfMclk;
+
+	uint8_t  AcpiReq;
+	uint8_t  AcpiAck;
+	uint8_t  MclkSwitchInProgress;
+	uint8_t  MclkSwitchCritical;
+
+	uint8_t  IgnoreVBlank;
+	uint8_t  TargetMclkIndex;
+	uint8_t  TargetMvddIndex;
+	uint8_t  MclkSwitchResult;
+
+	uint16_t VbiFailureCount;
+	uint8_t  VbiWaitCounter;
+	uint8_t  EnabledLevelsChange;
+
+	uint16_t LevelResidencyCountersN[SMU72_MAX_LEVELS_MEMORY];
+	uint16_t LevelSwitchCounters[SMU72_MAX_LEVELS_MEMORY];
+
+	void     (*TargetStateCalculator)(uint8_t);
+	void     (*SavedTargetStateCalculator)(uint8_t);
+
+	uint16_t AutoDpmInterval;
+	uint16_t AutoDpmRange;
+
+	uint16_t VbiTimeoutCount;
+	uint16_t MclkSwitchingTime;
+
+	uint8_t  fastSwitch;
+	uint8_t  Save_PIC_VDDGFX_EXIT;
+	uint8_t  Save_PIC_VDDGFX_ENTER;
+	uint8_t  padding;
+
+};
+
+typedef struct SMU7_MclkDpmScoreboard SMU7_MclkDpmScoreboard;
+
+struct SMU7_UlvScoreboard {
+	uint8_t     EnterUlv;
+	uint8_t     ExitUlv;
+	uint8_t     UlvActive;
+	uint8_t     WaitingForUlv;
+	uint8_t     UlvEnable;
+	uint8_t     UlvRunning;
+	uint8_t     UlvMasterEnable;
+	uint8_t     padding;
+	uint32_t    UlvAbortedCount;
+	uint32_t    UlvTimeStamp;
+};
+
+typedef struct SMU7_UlvScoreboard SMU7_UlvScoreboard;
+
+struct VddgfxSavedRegisters {
+	uint32_t GPU_DBG[3];
+	uint32_t MEC_BaseAddress_Hi;
+	uint32_t MEC_BaseAddress_Lo;
+	uint32_t THM_TMON0_CTRL2__RDIR_PRESENT;
+	uint32_t THM_TMON1_CTRL2__RDIR_PRESENT;
+	uint32_t CP_INT_CNTL;
+};
+
+typedef struct VddgfxSavedRegisters VddgfxSavedRegisters;
+
+struct SMU7_VddGfxScoreboard {
+	uint8_t     VddGfxEnable;
+	uint8_t     VddGfxActive;
+	uint8_t     VPUResetOccured;
+	uint8_t     padding;
+
+	uint32_t    VddGfxEnteredCount;
+	uint32_t    VddGfxAbortedCount;
+
+	uint32_t    VddGfxVid;
+
+	VddgfxSavedRegisters SavedRegisters;
+};
+
+typedef struct SMU7_VddGfxScoreboard SMU7_VddGfxScoreboard;
+
+struct SMU7_TdcLimitScoreboard {
+	uint8_t  Enable;
+	uint8_t  Running;
+	uint16_t Alpha;
+	uint32_t FilteredIddc;
+	uint32_t IddcLimit;
+	uint32_t IddcHyst;
+	SMU7_HystController_Data HystControllerData;
+};
+
+typedef struct SMU7_TdcLimitScoreboard SMU7_TdcLimitScoreboard;
+
+struct SMU7_PkgPwrLimitScoreboard {
+	uint8_t  Enable;
+	uint8_t  Running;
+	uint16_t Alpha;
+	uint32_t FilteredPkgPwr;
+	uint32_t Limit;
+	uint32_t Hyst;
+	uint32_t LimitFromDriver;
+	SMU7_HystController_Data HystControllerData;
+};
+
+typedef struct SMU7_PkgPwrLimitScoreboard SMU7_PkgPwrLimitScoreboard;
+
+struct SMU7_BapmScoreboard {
+	uint32_t source_powers[SMU72_DTE_SOURCES];
+	uint32_t source_powers_last[SMU72_DTE_SOURCES];
+	int32_t entity_temperatures[SMU72_NUM_GPU_TES];
+	int32_t initial_entity_temperatures[SMU72_NUM_GPU_TES];
+	int32_t Limit;
+	int32_t Hyst;
+	int32_t therm_influence_coeff_table[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS * 2];
+	int32_t therm_node_table[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS];
+	uint16_t ConfigTDPPowerScalar;
+	uint16_t FanSpeedPowerScalar;
+	uint16_t OverDrivePowerScalar;
+	uint16_t OverDriveLimitScalar;
+	uint16_t FinalPowerScalar;
+	uint8_t VariantID;
+	uint8_t spare997;
+
+	SMU7_HystController_Data HystControllerData;
+
+	int32_t temperature_gradient_slope;
+	int32_t temperature_gradient;
+	uint32_t measured_temperature;
+};
+
+
+typedef struct SMU7_BapmScoreboard SMU7_BapmScoreboard;
+
+struct SMU7_AcpiScoreboard {
+	uint32_t SavedInterruptMask[2];
+	uint8_t LastACPIRequest;
+	uint8_t CgBifResp;
+	uint8_t RequestType;
+	uint8_t Padding;
+	SMU72_Discrete_ACPILevel D0Level;
+};
+
+typedef struct SMU7_AcpiScoreboard SMU7_AcpiScoreboard;
+
+struct SMU72_Discrete_PmFuses {
+	/* dw1  */
+	uint8_t SviLoadLineEn;
+	uint8_t SviLoadLineVddC;
+	uint8_t SviLoadLineTrimVddC;
+	uint8_t SviLoadLineOffsetVddC;
+
+	/* dw2 */
+	uint16_t TDC_VDDC_PkgLimit;
+	uint8_t TDC_VDDC_ThrottleReleaseLimitPerc;
+	uint8_t TDC_MAWt;
+
+	/* dw3 */
+	uint8_t TdcWaterfallCtl;
+	uint8_t LPMLTemperatureMin;
+	uint8_t LPMLTemperatureMax;
+	uint8_t Reserved;
+
+	/* dw4-dw7  */
+	uint8_t LPMLTemperatureScaler[16];
+
+	/* dw8-dw9  */
+	int16_t FuzzyFan_ErrorSetDelta;
+	int16_t FuzzyFan_ErrorRateSetDelta;
+	int16_t FuzzyFan_PwmSetDelta;
+	uint16_t Reserved6;
+
+	/* dw10-dw14  */
+	uint8_t GnbLPML[16];
+
+	/* dw15 */
+	uint8_t GnbLPMLMaxVid;
+	uint8_t GnbLPMLMinVid;
+	uint8_t Reserved1[2];
+
+	/* dw16 */
+	uint16_t BapmVddCBaseLeakageHiSidd;
+	uint16_t BapmVddCBaseLeakageLoSidd;
+};
+
+typedef struct SMU72_Discrete_PmFuses SMU72_Discrete_PmFuses;
+
+struct SMU7_Discrete_Log_Header_Table {
+	uint32_t    version;
+	uint32_t    asic_id;
+	uint16_t    flags;
+	uint16_t    entry_size;
+	uint32_t    total_size;
+	uint32_t    num_of_entries;
+	uint8_t     type;
+	uint8_t     mode;
+	uint8_t     filler_0[2];
+	uint32_t    filler_1[2];
+};
+
+typedef struct SMU7_Discrete_Log_Header_Table SMU7_Discrete_Log_Header_Table;
+
+struct SMU7_Discrete_Log_Cntl {
+	uint8_t             Enabled;
+	uint8_t             Type;
+	uint8_t             padding[2];
+	uint32_t            BufferSize;
+	uint32_t            SamplesLogged;
+	uint32_t            SampleSize;
+	uint32_t            AddrL;
+	uint32_t            AddrH;
+};
+
+typedef struct SMU7_Discrete_Log_Cntl SMU7_Discrete_Log_Cntl;
+
+#define CAC_ACC_NW_NUM_OF_SIGNALS 87
+
+struct SMU7_Discrete_Cac_Collection_Table {
+	uint32_t temperature;
+	uint32_t cac_acc_nw[CAC_ACC_NW_NUM_OF_SIGNALS];
+};
+
+typedef struct SMU7_Discrete_Cac_Collection_Table SMU7_Discrete_Cac_Collection_Table;
+
+struct SMU7_Discrete_Cac_Verification_Table {
+	uint32_t VddcTotalPower;
+	uint32_t VddcLeakagePower;
+	uint32_t VddcConstantPower;
+	uint32_t VddcGfxDynamicPower;
+	uint32_t VddcUvdDynamicPower;
+	uint32_t VddcVceDynamicPower;
+	uint32_t VddcAcpDynamicPower;
+	uint32_t VddcPcieDynamicPower;
+	uint32_t VddcDceDynamicPower;
+	uint32_t VddcCurrent;
+	uint32_t VddcVoltage;
+	uint32_t VddciTotalPower;
+	uint32_t VddciLeakagePower;
+	uint32_t VddciConstantPower;
+	uint32_t VddciDynamicPower;
+	uint32_t Vddr1TotalPower;
+	uint32_t Vddr1LeakagePower;
+	uint32_t Vddr1ConstantPower;
+	uint32_t Vddr1DynamicPower;
+	uint32_t spare[4];
+	uint32_t temperature;
+};
+
+typedef struct SMU7_Discrete_Cac_Verification_Table SMU7_Discrete_Cac_Verification_Table;
+
+struct SMU7_Discrete_Pm_Status_Table {
+	/* Thermal entities */
+	int32_t T_meas_max;
+	int32_t T_meas_acc;
+	int32_t T_calc_max;
+	int32_t T_calc_acc;
+	uint32_t P_scalar_acc;
+	uint32_t P_calc_max;
+	uint32_t P_calc_acc;
+
+	/*Voltage domains */
+	uint32_t I_calc_max;
+	uint32_t I_calc_acc;
+	uint32_t I_calc_acc_vddci;
+	uint32_t V_calc_noload_acc;
+	uint32_t V_calc_load_acc;
+	uint32_t V_calc_noload_acc_vddci;
+	uint32_t P_meas_acc;
+	uint32_t V_meas_noload_acc;
+	uint32_t V_meas_load_acc;
+	uint32_t I_meas_acc;
+	uint32_t P_meas_acc_vddci;
+	uint32_t V_meas_noload_acc_vddci;
+	uint32_t V_meas_load_acc_vddci;
+	uint32_t I_meas_acc_vddci;
+
+	/*Frequency */
+	uint16_t Sclk_dpm_residency[8];
+	uint16_t Uvd_dpm_residency[8];
+	uint16_t Vce_dpm_residency[8];
+	uint16_t Mclk_dpm_residency[4];
+
+	/*Chip */
+	uint32_t P_vddci_acc;
+	uint32_t P_vddr1_acc;
+	uint32_t P_nte1_acc;
+	uint32_t PkgPwr_max;
+	uint32_t PkgPwr_acc;
+	uint32_t MclkSwitchingTime_max;
+	uint32_t MclkSwitchingTime_acc;
+	uint32_t FanPwm_acc;
+	uint32_t FanRpm_acc;
+
+	uint32_t AccCnt;
+};
+
+typedef struct SMU7_Discrete_Pm_Status_Table SMU7_Discrete_Pm_Status_Table;
+
+/*FIXME THESE NEED TO BE UPDATED */
+#define SMU7_SCLK_CAC 0x561
+#define SMU7_MCLK_CAC 0xF9
+#define SMU7_VCLK_CAC 0x2DE
+#define SMU7_DCLK_CAC 0x2DE
+#define SMU7_ECLK_CAC 0x25E
+#define SMU7_ACLK_CAC 0x25E
+#define SMU7_SAMCLK_CAC 0x25E
+#define SMU7_DISPCLK_CAC 0x100
+#define SMU7_CAC_CONSTANT 0x2EE3430
+#define SMU7_CAC_CONSTANT_SHIFT 18
+
+#define SMU7_VDDCI_MCLK_CONST        1765
+#define SMU7_VDDCI_MCLK_CONST_SHIFT  16
+#define SMU7_VDDCI_VDDCI_CONST       50958
+#define SMU7_VDDCI_VDDCI_CONST_SHIFT 14
+#define SMU7_VDDCI_CONST             11781
+
+#define SMU7_12C_VDDCI_MCLK_CONST        1623
+#define SMU7_12C_VDDCI_MCLK_CONST_SHIFT  15
+#define SMU7_12C_VDDCI_VDDCI_CONST       40088
+#define SMU7_12C_VDDCI_VDDCI_CONST_SHIFT 13
+#define SMU7_12C_VDDCI_CONST             20856
+
+#define SMU7_VDDCI_STROBE_PWR        1331
+
+#define SMU7_VDDR1_CONST            693
+#define SMU7_VDDR1_CAC_WEIGHT       20
+#define SMU7_VDDR1_CAC_WEIGHT_SHIFT 19
+#define SMU7_VDDR1_STROBE_PWR       512
+
+#define SMU7_AREA_COEFF_UVD 0xA78
+#define SMU7_AREA_COEFF_VCE 0x190A
+#define SMU7_AREA_COEFF_ACP 0x22D1
+#define SMU7_AREA_COEFF_SAMU 0x534
+
+/*ThermOutMode values */
+#define SMU7_THERM_OUT_MODE_DISABLE       0x0
+#define SMU7_THERM_OUT_MODE_THERM_ONLY    0x1
+#define SMU7_THERM_OUT_MODE_THERM_VRHOT   0x2
+
+#if !defined(SMC_MICROCODE)
+#pragma pack(pop)
+#endif
+
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu73.h b/drivers/gpu/drm/amd/powerplay/inc/smu73.h
new file mode 100644
index 0000000..c6b12a4
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/smu73.h
@@ -0,0 +1,720 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _SMU73_H_
+#define _SMU73_H_
+
+#pragma pack(push, 1)
+enum SID_OPTION {
+  SID_OPTION_HI,
+  SID_OPTION_LO,
+  SID_OPTION_COUNT
+};
+
+enum Poly3rdOrderCoeff {
+    LEAKAGE_TEMPERATURE_SCALAR,
+    LEAKAGE_VOLTAGE_SCALAR,
+    DYNAMIC_VOLTAGE_SCALAR,
+    POLY_3RD_ORDER_COUNT
+};
+
+struct SMU7_Poly3rdOrder_Data
+{
+    int32_t a;
+    int32_t b;
+    int32_t c;
+    int32_t d;
+    uint8_t a_shift;
+    uint8_t b_shift;
+    uint8_t c_shift;
+    uint8_t x_shift;
+};
+
+typedef struct SMU7_Poly3rdOrder_Data SMU7_Poly3rdOrder_Data;
+
+struct Power_Calculator_Data
+{
+  uint16_t NoLoadVoltage;
+  uint16_t LoadVoltage;
+  uint16_t Resistance;
+  uint16_t Temperature;
+  uint16_t BaseLeakage;
+  uint16_t LkgTempScalar;
+  uint16_t LkgVoltScalar;
+  uint16_t LkgAreaScalar;
+  uint16_t LkgPower;
+  uint16_t DynVoltScalar;
+  uint32_t Cac;
+  uint32_t DynPower;
+  uint32_t TotalCurrent;
+  uint32_t TotalPower;
+};
+
+typedef struct Power_Calculator_Data PowerCalculatorData_t;
+
+struct Gc_Cac_Weight_Data
+{
+  uint8_t index;
+  uint32_t value;
+};
+
+typedef struct Gc_Cac_Weight_Data GcCacWeight_Data;
+
+
+typedef struct {
+  uint32_t high;
+  uint32_t low;
+} data_64_t;
+
+typedef struct {
+  data_64_t high;
+  data_64_t low;
+} data_128_t;
+
+#define SMU__NUM_SCLK_DPM_STATE  8
+#define SMU__NUM_MCLK_DPM_LEVELS 4
+#define SMU__NUM_LCLK_DPM_LEVELS 8
+#define SMU__NUM_PCIE_DPM_LEVELS 8
+
+#define SMU7_CONTEXT_ID_SMC        1
+#define SMU7_CONTEXT_ID_VBIOS      2
+
+#define SMU73_MAX_LEVELS_VDDC            16
+#define SMU73_MAX_LEVELS_VDDGFX          16
+#define SMU73_MAX_LEVELS_VDDCI           8
+#define SMU73_MAX_LEVELS_MVDD            4
+
+#define SMU_MAX_SMIO_LEVELS              4
+
+#define SMU73_MAX_LEVELS_GRAPHICS        SMU__NUM_SCLK_DPM_STATE   // SCLK + SQ DPM + ULV
+#define SMU73_MAX_LEVELS_MEMORY          SMU__NUM_MCLK_DPM_LEVELS   // MCLK Levels DPM
+#define SMU73_MAX_LEVELS_GIO             SMU__NUM_LCLK_DPM_LEVELS  // LCLK Levels
+#define SMU73_MAX_LEVELS_LINK            SMU__NUM_PCIE_DPM_LEVELS  // PCIe speed and number of lanes.
+#define SMU73_MAX_LEVELS_UVD             8   // VCLK/DCLK levels for UVD.
+#define SMU73_MAX_LEVELS_VCE             8   // ECLK levels for VCE.
+#define SMU73_MAX_LEVELS_ACP             8   // ACLK levels for ACP.
+#define SMU73_MAX_LEVELS_SAMU            8   // SAMCLK levels for SAMU.
+#define SMU73_MAX_ENTRIES_SMIO           32  // Number of entries in SMIO table.
+
+#define DPM_NO_LIMIT 0
+#define DPM_NO_UP 1
+#define DPM_GO_DOWN 2
+#define DPM_GO_UP 3
+
+#define SMU7_FIRST_DPM_GRAPHICS_LEVEL    0
+#define SMU7_FIRST_DPM_MEMORY_LEVEL      0
+
+#define GPIO_CLAMP_MODE_VRHOT      1
+#define GPIO_CLAMP_MODE_THERM      2
+#define GPIO_CLAMP_MODE_DC         4
+
+#define SCRATCH_B_TARG_PCIE_INDEX_SHIFT 0
+#define SCRATCH_B_TARG_PCIE_INDEX_MASK  (0x7<<SCRATCH_B_TARG_PCIE_INDEX_SHIFT)
+#define SCRATCH_B_CURR_PCIE_INDEX_SHIFT 3
+#define SCRATCH_B_CURR_PCIE_INDEX_MASK  (0x7<<SCRATCH_B_CURR_PCIE_INDEX_SHIFT)
+#define SCRATCH_B_TARG_UVD_INDEX_SHIFT  6
+#define SCRATCH_B_TARG_UVD_INDEX_MASK   (0x7<<SCRATCH_B_TARG_UVD_INDEX_SHIFT)
+#define SCRATCH_B_CURR_UVD_INDEX_SHIFT  9
+#define SCRATCH_B_CURR_UVD_INDEX_MASK   (0x7<<SCRATCH_B_CURR_UVD_INDEX_SHIFT)
+#define SCRATCH_B_TARG_VCE_INDEX_SHIFT  12
+#define SCRATCH_B_TARG_VCE_INDEX_MASK   (0x7<<SCRATCH_B_TARG_VCE_INDEX_SHIFT)
+#define SCRATCH_B_CURR_VCE_INDEX_SHIFT  15
+#define SCRATCH_B_CURR_VCE_INDEX_MASK   (0x7<<SCRATCH_B_CURR_VCE_INDEX_SHIFT)
+#define SCRATCH_B_TARG_ACP_INDEX_SHIFT  18
+#define SCRATCH_B_TARG_ACP_INDEX_MASK   (0x7<<SCRATCH_B_TARG_ACP_INDEX_SHIFT)
+#define SCRATCH_B_CURR_ACP_INDEX_SHIFT  21
+#define SCRATCH_B_CURR_ACP_INDEX_MASK   (0x7<<SCRATCH_B_CURR_ACP_INDEX_SHIFT)
+#define SCRATCH_B_TARG_SAMU_INDEX_SHIFT 24
+#define SCRATCH_B_TARG_SAMU_INDEX_MASK  (0x7<<SCRATCH_B_TARG_SAMU_INDEX_SHIFT)
+#define SCRATCH_B_CURR_SAMU_INDEX_SHIFT 27
+#define SCRATCH_B_CURR_SAMU_INDEX_MASK  (0x7<<SCRATCH_B_CURR_SAMU_INDEX_SHIFT)
+
+// Virtualization Defines
+#define CG_XDMA_MASK  0x1
+#define CG_XDMA_SHIFT 0
+#define CG_UVD_MASK   0x2
+#define CG_UVD_SHIFT  1
+#define CG_VCE_MASK   0x4
+#define CG_VCE_SHIFT  2
+#define CG_SAMU_MASK  0x8
+#define CG_SAMU_SHIFT 3
+#define CG_GFX_MASK   0x10
+#define CG_GFX_SHIFT  4
+#define CG_SDMA_MASK  0x20
+#define CG_SDMA_SHIFT 5
+#define CG_HDP_MASK   0x40
+#define CG_HDP_SHIFT  6
+#define CG_MC_MASK    0x80
+#define CG_MC_SHIFT   7
+#define CG_DRM_MASK   0x100
+#define CG_DRM_SHIFT  8
+#define CG_ROM_MASK   0x200
+#define CG_ROM_SHIFT  9
+#define CG_BIF_MASK   0x400
+#define CG_BIF_SHIFT  10
+
+#define SMU73_DTE_ITERATIONS 5
+#define SMU73_DTE_SOURCES 3
+#define SMU73_DTE_SINKS 1
+#define SMU73_NUM_CPU_TES 0
+#define SMU73_NUM_GPU_TES 1
+#define SMU73_NUM_NON_TES 2
+#define SMU73_DTE_FAN_SCALAR_MIN 0x100
+#define SMU73_DTE_FAN_SCALAR_MAX 0x166
+#define SMU73_DTE_FAN_TEMP_MAX 93
+#define SMU73_DTE_FAN_TEMP_MIN 83
+
+#define SMU73_THERMAL_INPUT_LOOP_COUNT 6
+#define SMU73_THERMAL_CLAMP_MODE_COUNT 8
+
+
+struct SMU7_HystController_Data
+{
+    uint16_t waterfall_up;
+    uint16_t waterfall_down;
+    uint16_t waterfall_limit;
+    uint16_t release_cnt;
+    uint16_t release_limit;
+    uint16_t spare;
+};
+
+typedef struct SMU7_HystController_Data SMU7_HystController_Data;
+
+struct SMU73_PIDController
+{
+    uint32_t Ki;
+    int32_t LFWindupUpperLim;
+    int32_t LFWindupLowerLim;
+    uint32_t StatePrecision;
+
+    uint32_t LfPrecision;
+    uint32_t LfOffset;
+    uint32_t MaxState;
+    uint32_t MaxLfFraction;
+    uint32_t StateShift;
+};
+
+typedef struct SMU73_PIDController SMU73_PIDController;
+
+struct SMU7_LocalDpmScoreboard
+{
+    uint32_t PercentageBusy;
+
+    int32_t  PIDError;
+    int32_t  PIDIntegral;
+    int32_t  PIDOutput;
+
+    uint32_t SigmaDeltaAccum;
+    uint32_t SigmaDeltaOutput;
+    uint32_t SigmaDeltaLevel;
+
+    uint32_t UtilizationSetpoint;
+
+    uint8_t  TdpClampMode;
+    uint8_t  TdcClampMode;
+    uint8_t  ThermClampMode;
+    uint8_t  VoltageBusy;
+
+    int8_t   CurrLevel;
+    int8_t   TargLevel;
+    uint8_t  LevelChangeInProgress;
+    uint8_t  UpHyst;
+
+    uint8_t  DownHyst;
+    uint8_t  VoltageDownHyst;
+    uint8_t  DpmEnable;
+    uint8_t  DpmRunning;
+
+    uint8_t  DpmForce;
+    uint8_t  DpmForceLevel;
+    uint8_t  DisplayWatermark;
+    uint8_t  McArbIndex;
+
+    uint32_t MinimumPerfSclk;
+
+    uint8_t  AcpiReq;
+    uint8_t  AcpiAck;
+    uint8_t  GfxClkSlow;
+    uint8_t  GpioClampMode;
+
+    uint8_t  spare2;
+    uint8_t  EnabledLevelsChange;
+    uint8_t  DteClampMode;
+    uint8_t  FpsClampMode;
+
+    uint16_t LevelResidencyCounters [SMU73_MAX_LEVELS_GRAPHICS];
+    uint16_t LevelSwitchCounters [SMU73_MAX_LEVELS_GRAPHICS];
+
+    void     (*TargetStateCalculator)(uint8_t);
+    void     (*SavedTargetStateCalculator)(uint8_t);
+
+    uint16_t AutoDpmInterval;
+    uint16_t AutoDpmRange;
+
+    uint8_t  FpsEnabled;
+    uint8_t  MaxPerfLevel;
+    uint8_t  AllowLowClkInterruptToHost;
+    uint8_t  FpsRunning;
+
+    uint32_t MaxAllowedFrequency;
+
+    uint32_t FilteredSclkFrequency;
+    uint32_t LastSclkFrequency;
+    uint32_t FilteredSclkFrequencyCnt;
+
+    uint8_t  LedEnable;
+    uint8_t  LedPin0;
+    uint8_t  LedPin1;
+    uint8_t  LedPin2;
+    uint32_t LedAndMask;
+
+    uint16_t FpsAlpha;
+    uint16_t DeltaTime;
+    uint32_t CurrentFps;
+    uint32_t FilteredFps;
+    uint32_t FrameCount;
+    uint32_t FrameCountLast;
+    uint16_t FpsTargetScalar;
+    uint16_t FpsWaterfallLimitScalar;
+    uint16_t FpsAlphaScalar;
+    uint16_t spare8;
+    SMU7_HystController_Data HystControllerData;
+};
+
+typedef struct SMU7_LocalDpmScoreboard SMU7_LocalDpmScoreboard;
+
+#define SMU7_MAX_VOLTAGE_CLIENTS 12
+
+typedef uint8_t (*VoltageChangeHandler_t)(uint16_t, uint8_t);
+
+#define VDDC_MASK    0x00007FFF
+#define VDDC_SHIFT   0
+#define VDDCI_MASK   0x3FFF8000
+#define VDDCI_SHIFT  15
+#define PHASES_MASK  0xC0000000
+#define PHASES_SHIFT 30
+
+typedef uint32_t SMU_VoltageLevel;
+
+struct SMU7_VoltageScoreboard
+{
+    SMU_VoltageLevel TargetVoltage;
+    uint16_t MaxVid;
+    uint8_t  HighestVidOffset;
+    uint8_t  CurrentVidOffset;
+
+    uint16_t CurrentVddc;
+    uint16_t CurrentVddci;
+
+
+    uint8_t  ControllerBusy;
+    uint8_t  CurrentVid;
+    uint8_t  CurrentVddciVid;
+    uint8_t  padding;
+
+    SMU_VoltageLevel RequestedVoltage[SMU7_MAX_VOLTAGE_CLIENTS];
+    SMU_VoltageLevel TargetVoltageState;
+    uint8_t  EnabledRequest[SMU7_MAX_VOLTAGE_CLIENTS];
+
+    uint8_t  padding2;
+    uint8_t  padding3;
+    uint8_t  ControllerEnable;
+    uint8_t  ControllerRunning;
+    uint16_t CurrentStdVoltageHiSidd;
+    uint16_t CurrentStdVoltageLoSidd;
+    uint8_t  OverrideVoltage;
+    uint8_t  padding4;
+    uint8_t  padding5;
+    uint8_t  CurrentPhases;
+
+    VoltageChangeHandler_t ChangeVddc;
+
+    VoltageChangeHandler_t ChangeVddci;
+    VoltageChangeHandler_t ChangePhase;
+    VoltageChangeHandler_t ChangeMvdd;
+
+    VoltageChangeHandler_t functionLinks[6];
+
+    uint16_t * VddcFollower1;
+
+    int16_t  Driver_OD_RequestedVidOffset1;
+    int16_t  Driver_OD_RequestedVidOffset2;
+
+};
+
+typedef struct SMU7_VoltageScoreboard SMU7_VoltageScoreboard;
+
+// -------------------------------------------------------------------------------------------------------------------------
+#define SMU7_MAX_PCIE_LINK_SPEEDS 3 /* 0:Gen1 1:Gen2 2:Gen3 */
+
+struct SMU7_PCIeLinkSpeedScoreboard
+{
+    uint8_t     DpmEnable;
+    uint8_t     DpmRunning;
+    uint8_t     DpmForce;
+    uint8_t     DpmForceLevel;
+
+    uint8_t     CurrentLinkSpeed;
+    uint8_t     EnabledLevelsChange;
+    uint16_t    AutoDpmInterval;
+
+    uint16_t    AutoDpmRange;
+    uint16_t    AutoDpmCount;
+
+    uint8_t     DpmMode;
+    uint8_t     AcpiReq;
+    uint8_t     AcpiAck;
+    uint8_t     CurrentLinkLevel;
+
+};
+
+typedef struct SMU7_PCIeLinkSpeedScoreboard SMU7_PCIeLinkSpeedScoreboard;
+
+// -------------------------------------------------------- CAC table ------------------------------------------------------
+#define SMU7_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16
+#define SMU7_LKGE_LUT_NUM_OF_VOLT_ENTRIES 16
+
+#define SMU7_SCALE_I  7
+#define SMU7_SCALE_R 12
+
+struct SMU7_PowerScoreboard
+{
+    uint32_t GpuPower;
+
+    uint32_t VddcPower;
+    uint32_t VddcVoltage;
+    uint32_t VddcCurrent;
+
+    uint32_t MvddPower;
+    uint32_t MvddVoltage;
+    uint32_t MvddCurrent;
+
+    uint32_t RocPower;
+
+    uint16_t Telemetry_1_slope;
+    uint16_t Telemetry_2_slope;
+    int32_t  Telemetry_1_offset;
+    int32_t  Telemetry_2_offset;
+};
+typedef struct SMU7_PowerScoreboard SMU7_PowerScoreboard;
+
+// For FeatureEnables:
+#define SMU7_SCLK_DPM_CONFIG_MASK                        0x01
+#define SMU7_VOLTAGE_CONTROLLER_CONFIG_MASK              0x02
+#define SMU7_THERMAL_CONTROLLER_CONFIG_MASK              0x04
+#define SMU7_MCLK_DPM_CONFIG_MASK                        0x08
+#define SMU7_UVD_DPM_CONFIG_MASK                         0x10
+#define SMU7_VCE_DPM_CONFIG_MASK                         0x20
+#define SMU7_ACP_DPM_CONFIG_MASK                         0x40
+#define SMU7_SAMU_DPM_CONFIG_MASK                        0x80
+#define SMU7_PCIEGEN_DPM_CONFIG_MASK                    0x100
+
+#define SMU7_ACP_MCLK_HANDSHAKE_DISABLE                  0x00000001
+#define SMU7_ACP_SCLK_HANDSHAKE_DISABLE                  0x00000002
+#define SMU7_UVD_MCLK_HANDSHAKE_DISABLE                  0x00000100
+#define SMU7_UVD_SCLK_HANDSHAKE_DISABLE                  0x00000200
+#define SMU7_VCE_MCLK_HANDSHAKE_DISABLE                  0x00010000
+#define SMU7_VCE_SCLK_HANDSHAKE_DISABLE                  0x00020000
+
+// All 'soft registers' should be uint32_t.
+struct SMU73_SoftRegisters
+{
+    uint32_t        RefClockFrequency;
+    uint32_t        PmTimerPeriod;
+    uint32_t        FeatureEnables;
+
+    uint32_t        PreVBlankGap;
+    uint32_t        VBlankTimeout;
+    uint32_t        TrainTimeGap;
+
+    uint32_t        MvddSwitchTime;
+    uint32_t        LongestAcpiTrainTime;
+    uint32_t        AcpiDelay;
+    uint32_t        G5TrainTime;
+    uint32_t        DelayMpllPwron;
+    uint32_t        VoltageChangeTimeout;
+
+    uint32_t        HandshakeDisables;
+
+    uint8_t         DisplayPhy1Config;
+    uint8_t         DisplayPhy2Config;
+    uint8_t         DisplayPhy3Config;
+    uint8_t         DisplayPhy4Config;
+
+    uint8_t         DisplayPhy5Config;
+    uint8_t         DisplayPhy6Config;
+    uint8_t         DisplayPhy7Config;
+    uint8_t         DisplayPhy8Config;
+
+    uint32_t        AverageGraphicsActivity;
+    uint32_t        AverageMemoryActivity;
+    uint32_t        AverageGioActivity;
+
+    uint8_t         SClkDpmEnabledLevels;
+    uint8_t         MClkDpmEnabledLevels;
+    uint8_t         LClkDpmEnabledLevels;
+    uint8_t         PCIeDpmEnabledLevels;
+
+    uint8_t         UVDDpmEnabledLevels;
+    uint8_t         SAMUDpmEnabledLevels;
+    uint8_t         ACPDpmEnabledLevels;
+    uint8_t         VCEDpmEnabledLevels;
+
+    uint32_t        DRAM_LOG_ADDR_H;
+    uint32_t        DRAM_LOG_ADDR_L;
+    uint32_t        DRAM_LOG_PHY_ADDR_H;
+    uint32_t        DRAM_LOG_PHY_ADDR_L;
+    uint32_t        DRAM_LOG_BUFF_SIZE;
+    uint32_t        UlvEnterCount;
+    uint32_t        UlvTime;
+    uint32_t        UcodeLoadStatus;
+    uint32_t        Reserved[2];
+
+};
+
+typedef struct SMU73_SoftRegisters SMU73_SoftRegisters;
+
+struct SMU73_Firmware_Header
+{
+    uint32_t Digest[5];
+    uint32_t Version;
+    uint32_t HeaderSize;
+    uint32_t Flags;
+    uint32_t EntryPoint;
+    uint32_t CodeSize;
+    uint32_t ImageSize;
+
+    uint32_t Rtos;
+    uint32_t SoftRegisters;
+    uint32_t DpmTable;
+    uint32_t FanTable;
+    uint32_t CacConfigTable;
+    uint32_t CacStatusTable;
+
+
+    uint32_t mcRegisterTable;
+
+
+    uint32_t mcArbDramTimingTable;
+
+
+
+
+    uint32_t PmFuseTable;
+    uint32_t Globals;
+    uint32_t ClockStretcherTable;
+    uint32_t Reserved[41];
+    uint32_t Signature;
+};
+
+typedef struct SMU73_Firmware_Header SMU73_Firmware_Header;
+
+#define SMU7_FIRMWARE_HEADER_LOCATION 0x20000
+
+enum  DisplayConfig {
+    PowerDown = 1,
+    DP54x4,
+    DP54x2,
+    DP54x1,
+    DP27x4,
+    DP27x2,
+    DP27x1,
+    HDMI297,
+    HDMI162,
+    LVDS,
+    DP324x4,
+    DP324x2,
+    DP324x1
+};
+
+
+#define MC_BLOCK_COUNT 1
+#define CPL_BLOCK_COUNT 5
+#define SE_BLOCK_COUNT 15
+#define GC_BLOCK_COUNT 24
+
+struct SMU7_Local_Cac {
+  uint8_t BlockId;
+  uint8_t SignalId;
+  uint8_t Threshold;
+  uint8_t Padding;
+};
+
+typedef struct SMU7_Local_Cac SMU7_Local_Cac;
+
+struct SMU7_Local_Cac_Table {
+
+  SMU7_Local_Cac CplLocalCac[CPL_BLOCK_COUNT];
+  SMU7_Local_Cac McLocalCac[MC_BLOCK_COUNT];
+  SMU7_Local_Cac SeLocalCac[SE_BLOCK_COUNT];
+  SMU7_Local_Cac GcLocalCac[GC_BLOCK_COUNT];
+};
+
+typedef struct SMU7_Local_Cac_Table SMU7_Local_Cac_Table;
+
+#if !defined(SMC_MICROCODE)
+#pragma pack(pop)
+#endif
+
+// Description of Clock Gating bitmask for Tonga:
+// System Clock Gating
+#define CG_SYS_BITMASK_FIRST_BIT      0  // First bit of Sys CG bitmask
+#define CG_SYS_BITMASK_LAST_BIT       9  // Last bit of Sys CG bitmask
+#define CG_SYS_BIF_MGLS_SHIFT         0
+#define CG_SYS_ROM_SHIFT              1
+#define CG_SYS_MC_MGCG_SHIFT          2
+#define CG_SYS_MC_MGLS_SHIFT          3
+#define CG_SYS_SDMA_MGCG_SHIFT        4
+#define CG_SYS_SDMA_MGLS_SHIFT        5
+#define CG_SYS_DRM_MGCG_SHIFT         6
+#define CG_SYS_HDP_MGCG_SHIFT         7
+#define CG_SYS_HDP_MGLS_SHIFT         8
+#define CG_SYS_DRM_MGLS_SHIFT         9
+
+#define CG_SYS_BIF_MGLS_MASK          0x1
+#define CG_SYS_ROM_MASK               0x2
+#define CG_SYS_MC_MGCG_MASK           0x4
+#define CG_SYS_MC_MGLS_MASK           0x8
+#define CG_SYS_SDMA_MGCG_MASK         0x10
+#define CG_SYS_SDMA_MGLS_MASK         0x20
+#define CG_SYS_DRM_MGCG_MASK          0x40
+#define CG_SYS_HDP_MGCG_MASK          0x80
+#define CG_SYS_HDP_MGLS_MASK          0x100
+#define CG_SYS_DRM_MGLS_MASK          0x200
+
+// Graphics Clock Gating
+#define CG_GFX_BITMASK_FIRST_BIT      16 // First bit of Gfx CG bitmask
+#define CG_GFX_BITMASK_LAST_BIT       20 // Last bit of Gfx CG bitmask
+#define CG_GFX_CGCG_SHIFT             16
+#define CG_GFX_CGLS_SHIFT             17
+#define CG_CPF_MGCG_SHIFT             18
+#define CG_RLC_MGCG_SHIFT             19
+#define CG_GFX_OTHERS_MGCG_SHIFT      20
+
+#define CG_GFX_CGCG_MASK              0x00010000
+#define CG_GFX_CGLS_MASK              0x00020000
+#define CG_CPF_MGCG_MASK              0x00040000
+#define CG_RLC_MGCG_MASK              0x00080000
+#define CG_GFX_OTHERS_MGCG_MASK       0x00100000
+
+
+
+// Voltage Regulator Configuration
+// VR Config info is contained in dpmTable.VRConfig
+
+#define VRCONF_VDDC_MASK         0x000000FF
+#define VRCONF_VDDC_SHIFT        0
+#define VRCONF_VDDGFX_MASK       0x0000FF00
+#define VRCONF_VDDGFX_SHIFT      8
+#define VRCONF_VDDCI_MASK        0x00FF0000
+#define VRCONF_VDDCI_SHIFT       16
+#define VRCONF_MVDD_MASK         0xFF000000
+#define VRCONF_MVDD_SHIFT        24
+
+#define VR_MERGED_WITH_VDDC      0
+#define VR_SVI2_PLANE_1          1
+#define VR_SVI2_PLANE_2          2
+#define VR_SMIO_PATTERN_1        3
+#define VR_SMIO_PATTERN_2        4
+#define VR_STATIC_VOLTAGE        5
+
+// Clock Stretcher Configuration
+
+#define CLOCK_STRETCHER_MAX_ENTRIES 0x4
+#define CKS_LOOKUPTable_MAX_ENTRIES 0x4
+
+// The 'settings' field is subdivided in the following way:
+#define CLOCK_STRETCHER_SETTING_DDT_MASK             0x01
+#define CLOCK_STRETCHER_SETTING_DDT_SHIFT            0x0
+#define CLOCK_STRETCHER_SETTING_STRETCH_AMOUNT_MASK  0x1E
+#define CLOCK_STRETCHER_SETTING_STRETCH_AMOUNT_SHIFT 0x1
+#define CLOCK_STRETCHER_SETTING_ENABLE_MASK          0x80
+#define CLOCK_STRETCHER_SETTING_ENABLE_SHIFT         0x7
+
+struct SMU_ClockStretcherDataTableEntry {
+  uint8_t minVID;
+  uint8_t maxVID;
+
+
+  uint16_t setting;
+};
+typedef struct SMU_ClockStretcherDataTableEntry SMU_ClockStretcherDataTableEntry;
+
+struct SMU_ClockStretcherDataTable {
+  SMU_ClockStretcherDataTableEntry ClockStretcherDataTableEntry[CLOCK_STRETCHER_MAX_ENTRIES];
+};
+typedef struct SMU_ClockStretcherDataTable SMU_ClockStretcherDataTable;
+
+struct SMU_CKS_LOOKUPTableEntry {
+  uint16_t minFreq;
+  uint16_t maxFreq;
+
+  uint8_t setting;
+  uint8_t padding[3];
+};
+typedef struct SMU_CKS_LOOKUPTableEntry SMU_CKS_LOOKUPTableEntry;
+
+struct SMU_CKS_LOOKUPTable {
+  SMU_CKS_LOOKUPTableEntry CKS_LOOKUPTableEntry[CKS_LOOKUPTable_MAX_ENTRIES];
+};
+typedef struct SMU_CKS_LOOKUPTable SMU_CKS_LOOKUPTable;
+
+struct AgmAvfsData_t {
+  uint16_t avgPsmCount[28];
+  uint16_t minPsmCount[28];
+};
+typedef struct AgmAvfsData_t AgmAvfsData_t;
+
+// AVFS DEFINES
+
+enum VFT_COLUMNS {
+  SCLK0,
+  SCLK1,
+  SCLK2,
+  SCLK3,
+  SCLK4,
+  SCLK5,
+  SCLK6,
+  SCLK7,
+
+  NUM_VFT_COLUMNS
+};
+
+#define TEMP_RANGE_MAXSTEPS 12
+struct VFT_CELL_t {
+  uint16_t Voltage;
+};
+
+typedef struct VFT_CELL_t VFT_CELL_t;
+
+struct VFT_TABLE_t {
+  VFT_CELL_t    Cell[TEMP_RANGE_MAXSTEPS][NUM_VFT_COLUMNS];
+  uint16_t      AvfsGbv [NUM_VFT_COLUMNS];
+  uint16_t      BtcGbv  [NUM_VFT_COLUMNS];
+  uint16_t      Temperature [TEMP_RANGE_MAXSTEPS];
+
+  uint8_t       NumTemperatureSteps;
+  uint8_t       padding[3];
+};
+typedef struct VFT_TABLE_t VFT_TABLE_t;
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu73_discrete.h b/drivers/gpu/drm/amd/powerplay/inc/smu73_discrete.h
new file mode 100644
index 0000000..5916be0
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/smu73_discrete.h
@@ -0,0 +1,799 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _SMU73_DISCRETE_H_
+#define _SMU73_DISCRETE_H_
+
+#include "smu73.h"
+
+#pragma pack(push, 1)
+
+struct SMIO_Pattern
+{
+  uint16_t Voltage;
+  uint8_t  Smio;
+  uint8_t  padding;
+};
+
+typedef struct SMIO_Pattern SMIO_Pattern;
+
+struct SMIO_Table
+{
+  SMIO_Pattern Pattern[SMU_MAX_SMIO_LEVELS];
+};
+
+typedef struct SMIO_Table SMIO_Table;
+
+struct SMU73_Discrete_GraphicsLevel {
+	uint32_t    MinVoltage;
+
+	uint32_t    SclkFrequency;
+
+	uint8_t     pcieDpmLevel;
+	uint8_t     DeepSleepDivId;
+	uint16_t    ActivityLevel;
+	uint32_t    CgSpllFuncCntl3;
+	uint32_t    CgSpllFuncCntl4;
+	uint32_t    SpllSpreadSpectrum;
+	uint32_t    SpllSpreadSpectrum2;
+	uint32_t    CcPwrDynRm;
+	uint32_t    CcPwrDynRm1;
+	uint8_t     SclkDid;
+	uint8_t     DisplayWatermark;
+	uint8_t     EnabledForActivity;
+	uint8_t     EnabledForThrottle;
+	uint8_t     UpHyst;
+	uint8_t     DownHyst;
+	uint8_t     VoltageDownHyst;
+	uint8_t     PowerThrottle;
+};
+
+typedef struct SMU73_Discrete_GraphicsLevel SMU73_Discrete_GraphicsLevel;
+
+struct SMU73_Discrete_ACPILevel {
+    uint32_t    Flags;
+    uint32_t MinVoltage;
+    uint32_t    SclkFrequency;
+    uint8_t     SclkDid;
+    uint8_t     DisplayWatermark;
+    uint8_t     DeepSleepDivId;
+    uint8_t     padding;
+    uint32_t    CgSpllFuncCntl;
+    uint32_t    CgSpllFuncCntl2;
+    uint32_t    CgSpllFuncCntl3;
+    uint32_t    CgSpllFuncCntl4;
+    uint32_t    SpllSpreadSpectrum;
+    uint32_t    SpllSpreadSpectrum2;
+    uint32_t    CcPwrDynRm;
+    uint32_t    CcPwrDynRm1;
+};
+
+typedef struct SMU73_Discrete_ACPILevel SMU73_Discrete_ACPILevel;
+
+struct SMU73_Discrete_Ulv {
+	uint32_t    CcPwrDynRm;
+	uint32_t    CcPwrDynRm1;
+	uint16_t    VddcOffset;
+	uint8_t     VddcOffsetVid;
+	uint8_t     VddcPhase;
+	uint32_t    Reserved;
+};
+
+typedef struct SMU73_Discrete_Ulv SMU73_Discrete_Ulv;
+
+struct SMU73_Discrete_MemoryLevel
+{
+    uint32_t MinVoltage;
+    uint32_t    MinMvdd;
+
+    uint32_t    MclkFrequency;
+
+    uint8_t     StutterEnable;
+    uint8_t     FreqRange;
+    uint8_t     EnabledForThrottle;
+    uint8_t     EnabledForActivity;
+
+    uint8_t     UpHyst;
+    uint8_t     DownHyst;
+    uint8_t     VoltageDownHyst;
+    uint8_t     padding;
+
+    uint16_t    ActivityLevel;
+    uint8_t     DisplayWatermark;
+    uint8_t     MclkDivider;
+};
+
+typedef struct SMU73_Discrete_MemoryLevel SMU73_Discrete_MemoryLevel;
+
+struct SMU73_Discrete_LinkLevel
+{
+    uint8_t     PcieGenSpeed;           ///< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3
+    uint8_t     PcieLaneCount;          ///< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16 
+    uint8_t     EnabledForActivity;
+    uint8_t     SPC;
+    uint32_t    DownThreshold;
+    uint32_t    UpThreshold;
+    uint32_t    Reserved;
+};
+
+typedef struct SMU73_Discrete_LinkLevel SMU73_Discrete_LinkLevel;
+
+
+// MC ARB DRAM Timing registers.
+struct SMU73_Discrete_MCArbDramTimingTableEntry
+{
+    uint32_t McArbDramTiming;
+    uint32_t McArbDramTiming2;
+    uint8_t  McArbBurstTime;
+    uint8_t  TRRDS;
+    uint8_t  TRRDL;
+    uint8_t  padding;
+};
+
+typedef struct SMU73_Discrete_MCArbDramTimingTableEntry SMU73_Discrete_MCArbDramTimingTableEntry;
+
+struct SMU73_Discrete_MCArbDramTimingTable
+{
+    SMU73_Discrete_MCArbDramTimingTableEntry entries[SMU__NUM_SCLK_DPM_STATE][SMU__NUM_MCLK_DPM_LEVELS];
+};
+
+typedef struct SMU73_Discrete_MCArbDramTimingTable SMU73_Discrete_MCArbDramTimingTable;
+
+// UVD VCLK/DCLK state (level) definition.
+struct SMU73_Discrete_UvdLevel
+{
+    uint32_t VclkFrequency;
+    uint32_t DclkFrequency;
+    uint32_t MinVoltage;
+    uint8_t  VclkDivider;
+    uint8_t  DclkDivider;
+    uint8_t  padding[2];
+};
+
+typedef struct SMU73_Discrete_UvdLevel SMU73_Discrete_UvdLevel;
+
+// Clocks for other external blocks (VCE, ACP, SAMU).
+struct SMU73_Discrete_ExtClkLevel
+{
+    uint32_t Frequency;
+    uint32_t MinVoltage;
+    uint8_t  Divider;
+    uint8_t  padding[3];
+};
+
+typedef struct SMU73_Discrete_ExtClkLevel SMU73_Discrete_ExtClkLevel;
+
+struct SMU73_Discrete_StateInfo
+{
+    uint32_t SclkFrequency;
+    uint32_t MclkFrequency;
+    uint32_t VclkFrequency;
+    uint32_t DclkFrequency;
+    uint32_t SamclkFrequency;
+    uint32_t AclkFrequency;
+    uint32_t EclkFrequency;
+    uint16_t MvddVoltage;
+    uint16_t padding16;
+    uint8_t  DisplayWatermark;
+    uint8_t  McArbIndex;
+    uint8_t  McRegIndex;
+    uint8_t  SeqIndex;
+    uint8_t  SclkDid;
+    int8_t   SclkIndex;
+    int8_t   MclkIndex;
+    uint8_t  PCIeGen;
+
+};
+
+typedef struct SMU73_Discrete_StateInfo SMU73_Discrete_StateInfo;
+
+struct SMU73_Discrete_DpmTable
+{
+    // Multi-DPM controller settings
+    SMU73_PIDController                  GraphicsPIDController;
+    SMU73_PIDController                  MemoryPIDController;
+    SMU73_PIDController                  LinkPIDController;
+
+    uint32_t                            SystemFlags;
+
+    // SMIO masks for voltage and phase controls
+    uint32_t                            VRConfig;
+    uint32_t                            SmioMask1;
+    uint32_t                            SmioMask2;
+    SMIO_Table                          SmioTable1;
+    SMIO_Table                          SmioTable2;
+
+    uint32_t                            MvddLevelCount;
+
+
+    uint8_t                             BapmVddcVidHiSidd        [SMU73_MAX_LEVELS_VDDC];
+    uint8_t                             BapmVddcVidLoSidd        [SMU73_MAX_LEVELS_VDDC];
+    uint8_t                             BapmVddcVidHiSidd2       [SMU73_MAX_LEVELS_VDDC];
+
+    uint8_t                             GraphicsDpmLevelCount;
+    uint8_t                             MemoryDpmLevelCount;
+    uint8_t                             LinkLevelCount;
+    uint8_t                             MasterDeepSleepControl;
+
+    uint8_t                             UvdLevelCount;
+    uint8_t                             VceLevelCount;
+    uint8_t                             AcpLevelCount;
+    uint8_t                             SamuLevelCount;
+
+    uint8_t                             ThermOutGpio;
+    uint8_t                             ThermOutPolarity;
+    uint8_t                             ThermOutMode;
+    uint8_t                             BootPhases;
+    uint32_t                            Reserved[4];
+
+    // State table entries for each DPM state
+    SMU73_Discrete_GraphicsLevel        GraphicsLevel           [SMU73_MAX_LEVELS_GRAPHICS];
+    SMU73_Discrete_MemoryLevel          MemoryACPILevel;
+    SMU73_Discrete_MemoryLevel          MemoryLevel             [SMU73_MAX_LEVELS_MEMORY];
+    SMU73_Discrete_LinkLevel            LinkLevel               [SMU73_MAX_LEVELS_LINK];
+    SMU73_Discrete_ACPILevel            ACPILevel;
+    SMU73_Discrete_UvdLevel             UvdLevel                [SMU73_MAX_LEVELS_UVD];
+    SMU73_Discrete_ExtClkLevel          VceLevel                [SMU73_MAX_LEVELS_VCE];
+    SMU73_Discrete_ExtClkLevel          AcpLevel                [SMU73_MAX_LEVELS_ACP];
+    SMU73_Discrete_ExtClkLevel          SamuLevel               [SMU73_MAX_LEVELS_SAMU];
+    SMU73_Discrete_Ulv                  Ulv;
+
+    uint32_t                            SclkStepSize;
+    uint32_t                            Smio                    [SMU73_MAX_ENTRIES_SMIO];
+
+    uint8_t                             UvdBootLevel;
+    uint8_t                             VceBootLevel;
+    uint8_t                             AcpBootLevel;
+    uint8_t                             SamuBootLevel;
+
+    uint8_t                             GraphicsBootLevel;
+    uint8_t                             GraphicsVoltageChangeEnable;
+    uint8_t                             GraphicsThermThrottleEnable;
+    uint8_t                             GraphicsInterval;
+
+    uint8_t                             VoltageInterval;
+    uint8_t                             ThermalInterval;
+    uint16_t                            TemperatureLimitHigh;
+
+    uint16_t                            TemperatureLimitLow;
+    uint8_t                             MemoryBootLevel;
+    uint8_t                             MemoryVoltageChangeEnable;
+
+    uint16_t                            BootMVdd;
+    uint8_t                             MemoryInterval;
+    uint8_t                             MemoryThermThrottleEnable;
+
+    uint16_t                            VoltageResponseTime;
+    uint16_t                            PhaseResponseTime;
+
+    uint8_t                             PCIeBootLinkLevel;
+    uint8_t                             PCIeGenInterval;
+    uint8_t                             DTEInterval;
+    uint8_t                             DTEMode;
+
+    uint8_t                             SVI2Enable;
+    uint8_t                             VRHotGpio;
+    uint8_t                             AcDcGpio;
+    uint8_t                             ThermGpio;
+
+    uint16_t                            PPM_PkgPwrLimit;
+    uint16_t                            PPM_TemperatureLimit;
+
+    uint16_t                            DefaultTdp;
+    uint16_t                            TargetTdp;
+
+    uint16_t                            FpsHighThreshold;
+    uint16_t                            FpsLowThreshold;
+
+    uint16_t                            TemperatureLimitEdge;
+    uint16_t                            TemperatureLimitHotspot;
+    uint16_t                            TemperatureLimitLiquid1;
+    uint16_t                            TemperatureLimitLiquid2;
+    uint16_t                            TemperatureLimitVrVddc;
+    uint16_t                            TemperatureLimitVrMvdd;
+    uint16_t                            TemperatureLimitPlx;
+
+    uint16_t                            FanGainEdge;
+    uint16_t                            FanGainHotspot;
+    uint16_t                            FanGainLiquid;
+    uint16_t                            FanGainVrVddc;
+    uint16_t                            FanGainVrMvdd;
+    uint16_t                            FanGainPlx;
+    uint16_t                            FanGainHbm;
+
+    uint8_t                             Liquid1_I2C_address;
+    uint8_t                             Liquid2_I2C_address;
+    uint8_t                             Vr_I2C_address;
+    uint8_t                             Plx_I2C_address;
+
+    uint8_t                             GeminiMode;
+    uint8_t                             spare17[3];
+    uint32_t                            GeminiApertureHigh;
+    uint32_t                            GeminiApertureLow;
+
+    uint8_t                             Liquid_I2C_LineSCL;
+    uint8_t                             Liquid_I2C_LineSDA;
+    uint8_t                             Vr_I2C_LineSCL;
+    uint8_t                             Vr_I2C_LineSDA;
+    uint8_t                             Plx_I2C_LineSCL;
+    uint8_t                             Plx_I2C_LineSDA;
+
+    uint8_t                             spare1253[2];
+    uint32_t                            spare123[2];
+
+    uint8_t                             DTEAmbientTempBase;
+    uint8_t                             DTETjOffset;
+    uint8_t                             GpuTjMax;
+    uint8_t                             GpuTjHyst;
+
+    uint16_t                            BootVddc;
+    uint16_t                            BootVddci;
+
+    uint32_t                            BAPM_TEMP_GRADIENT;
+
+    uint32_t                            LowSclkInterruptThreshold;
+    uint32_t                            VddGfxReChkWait;
+
+    uint8_t                             ClockStretcherAmount;
+    uint8_t                             Sclk_CKS_masterEn0_7;
+    uint8_t                             Sclk_CKS_masterEn8_15;
+    uint8_t                             DPMFreezeAndForced;
+
+    uint8_t                             Sclk_voltageOffset[8];
+
+    SMU_ClockStretcherDataTable         ClockStretcherDataTable;
+    SMU_CKS_LOOKUPTable                 CKS_LOOKUPTable;
+};
+
+typedef struct SMU73_Discrete_DpmTable SMU73_Discrete_DpmTable;
+
+
+// --------------------------------------------------- Fan Table -----------------------------------------------------------
+struct SMU73_Discrete_FanTable
+{
+    uint16_t FdoMode;
+    int16_t  TempMin;
+    int16_t  TempMed;
+    int16_t  TempMax;
+    int16_t  Slope1;
+    int16_t  Slope2;
+    int16_t  FdoMin;
+    int16_t  HystUp;
+    int16_t  HystDown;
+    int16_t  HystSlope;
+    int16_t  TempRespLim;
+    int16_t  TempCurr;
+    int16_t  SlopeCurr;
+    int16_t  PwmCurr;
+    uint32_t RefreshPeriod;
+    int16_t  FdoMax;
+    uint8_t  TempSrc;
+    int8_t   Padding;
+};
+
+typedef struct SMU73_Discrete_FanTable SMU73_Discrete_FanTable;
+
+#define SMU7_DISCRETE_GPIO_SCLK_DEBUG             4
+#define SMU7_DISCRETE_GPIO_SCLK_DEBUG_BIT         (0x1 << SMU7_DISCRETE_GPIO_SCLK_DEBUG)
+
+
+
+struct SMU7_MclkDpmScoreboard
+{
+
+    uint32_t PercentageBusy;
+
+    int32_t  PIDError;
+    int32_t  PIDIntegral;
+    int32_t  PIDOutput;
+
+    uint32_t SigmaDeltaAccum;
+    uint32_t SigmaDeltaOutput;
+    uint32_t SigmaDeltaLevel;
+
+    uint32_t UtilizationSetpoint;
+
+    uint8_t  TdpClampMode;
+    uint8_t  TdcClampMode;
+    uint8_t  ThermClampMode;
+    uint8_t  VoltageBusy;
+
+    int8_t   CurrLevel;
+    int8_t   TargLevel;
+    uint8_t  LevelChangeInProgress;
+    uint8_t  UpHyst;
+
+    uint8_t  DownHyst;
+    uint8_t  VoltageDownHyst;
+    uint8_t  DpmEnable;
+    uint8_t  DpmRunning;
+
+    uint8_t  DpmForce;
+    uint8_t  DpmForceLevel;
+    uint8_t  DisplayWatermark;
+    uint8_t  McArbIndex;
+
+    uint32_t MinimumPerfMclk;
+
+    uint8_t  AcpiReq;
+    uint8_t  AcpiAck;
+    uint8_t  MclkSwitchInProgress;
+    uint8_t  MclkSwitchCritical;
+
+    uint8_t  IgnoreVBlank;
+    uint8_t  TargetMclkIndex;
+    uint8_t  TargetMvddIndex;
+    uint8_t  MclkSwitchResult;
+
+    uint16_t VbiFailureCount;
+    uint8_t  VbiWaitCounter;
+    uint8_t  EnabledLevelsChange;
+
+    uint16_t LevelResidencyCounters [SMU73_MAX_LEVELS_MEMORY];
+    uint16_t LevelSwitchCounters [SMU73_MAX_LEVELS_MEMORY];
+
+    void     (*TargetStateCalculator)(uint8_t);
+    void     (*SavedTargetStateCalculator)(uint8_t);
+
+    uint16_t AutoDpmInterval;
+    uint16_t AutoDpmRange;
+
+    uint16_t VbiTimeoutCount;
+    uint16_t MclkSwitchingTime;
+
+    uint8_t  fastSwitch;
+    uint8_t  Save_PIC_VDDGFX_EXIT;
+    uint8_t  Save_PIC_VDDGFX_ENTER;
+    uint8_t  padding;
+
+};
+
+typedef struct SMU7_MclkDpmScoreboard SMU7_MclkDpmScoreboard;
+
+struct SMU7_UlvScoreboard
+{
+    uint8_t     EnterUlv;
+    uint8_t     ExitUlv;
+    uint8_t     UlvActive;
+    uint8_t     WaitingForUlv;
+    uint8_t     UlvEnable;
+    uint8_t     UlvRunning;
+    uint8_t     UlvMasterEnable;
+    uint8_t     padding;
+    uint32_t    UlvAbortedCount;
+    uint32_t    UlvTimeStamp;
+};
+
+typedef struct SMU7_UlvScoreboard SMU7_UlvScoreboard;
+
+struct VddgfxSavedRegisters
+{
+  uint32_t GPU_DBG[3];
+  uint32_t MEC_BaseAddress_Hi;
+  uint32_t MEC_BaseAddress_Lo;
+  uint32_t THM_TMON0_CTRL2__RDIR_PRESENT;
+  uint32_t THM_TMON1_CTRL2__RDIR_PRESENT;
+  uint32_t CP_INT_CNTL;
+};
+
+typedef struct VddgfxSavedRegisters VddgfxSavedRegisters;
+
+struct SMU7_VddGfxScoreboard
+{
+    uint8_t     VddGfxEnable;
+    uint8_t     VddGfxActive;
+    uint8_t     VPUResetOccured;
+    uint8_t     padding;
+
+    uint32_t    VddGfxEnteredCount;
+    uint32_t    VddGfxAbortedCount;
+
+    uint32_t    VddGfxVid;
+
+    VddgfxSavedRegisters SavedRegisters;
+};
+
+typedef struct SMU7_VddGfxScoreboard SMU7_VddGfxScoreboard;
+
+struct SMU7_TdcLimitScoreboard {
+  uint8_t  Enable;
+  uint8_t  Running;
+  uint16_t Alpha;
+  uint32_t FilteredIddc;
+  uint32_t IddcLimit;
+  uint32_t IddcHyst;
+  SMU7_HystController_Data HystControllerData;
+};
+
+typedef struct SMU7_TdcLimitScoreboard SMU7_TdcLimitScoreboard;
+
+struct SMU7_PkgPwrLimitScoreboard {
+  uint8_t  Enable;
+  uint8_t  Running;
+  uint16_t Alpha;
+  uint32_t FilteredPkgPwr;
+  uint32_t Limit;
+  uint32_t Hyst;
+  uint32_t LimitFromDriver;
+  SMU7_HystController_Data HystControllerData;
+};
+
+typedef struct SMU7_PkgPwrLimitScoreboard SMU7_PkgPwrLimitScoreboard;
+
+struct SMU7_BapmScoreboard {
+  uint32_t source_powers[SMU73_DTE_SOURCES];
+  uint32_t source_powers_last[SMU73_DTE_SOURCES];
+  int32_t entity_temperatures[SMU73_NUM_GPU_TES];
+  int32_t initial_entity_temperatures[SMU73_NUM_GPU_TES];
+  int32_t Limit;
+  int32_t Hyst;
+  int32_t therm_influence_coeff_table[SMU73_DTE_ITERATIONS * SMU73_DTE_SOURCES * SMU73_DTE_SINKS * 2];
+  int32_t therm_node_table[SMU73_DTE_ITERATIONS * SMU73_DTE_SOURCES * SMU73_DTE_SINKS];
+  uint16_t ConfigTDPPowerScalar;
+  uint16_t FanSpeedPowerScalar;
+  uint16_t OverDrivePowerScalar;
+  uint16_t OverDriveLimitScalar;
+  uint16_t FinalPowerScalar;
+  uint8_t VariantID;
+  uint8_t spare997;
+
+  SMU7_HystController_Data HystControllerData;
+
+  int32_t temperature_gradient_slope;
+  int32_t temperature_gradient;
+  uint32_t measured_temperature;
+};
+
+
+typedef struct SMU7_BapmScoreboard SMU7_BapmScoreboard;
+
+struct SMU7_AcpiScoreboard {
+  uint32_t SavedInterruptMask[2];
+  uint8_t LastACPIRequest;
+  uint8_t CgBifResp;
+  uint8_t RequestType;
+  uint8_t Padding;
+  SMU73_Discrete_ACPILevel D0Level;
+};
+
+typedef struct SMU7_AcpiScoreboard SMU7_AcpiScoreboard;
+
+struct SMU_QuadraticCoeffs {
+  int32_t m1;
+  uint32_t b;
+
+  int16_t m2;
+  uint8_t m1_shift;
+  uint8_t m2_shift;
+};
+
+typedef struct SMU_QuadraticCoeffs SMU_QuadraticCoeffs;
+
+struct SMU73_Discrete_PmFuses {
+  /* dw0-dw1 */
+  uint8_t BapmVddCVidHiSidd[8];
+
+  /* dw2-dw3 */
+  uint8_t BapmVddCVidLoSidd[8];
+
+  /* dw4-dw5 */
+  uint8_t VddCVid[8];
+
+  /* dw1*/
+  uint8_t SviLoadLineEn;
+  uint8_t SviLoadLineVddC;
+  uint8_t SviLoadLineTrimVddC;
+  uint8_t SviLoadLineOffsetVddC;
+
+  /* dw2 */
+  uint16_t TDC_VDDC_PkgLimit;
+  uint8_t TDC_VDDC_ThrottleReleaseLimitPerc;
+  uint8_t TDC_MAWt;
+
+  /* dw3 */
+  uint8_t TdcWaterfallCtl;
+  uint8_t LPMLTemperatureMin;
+  uint8_t LPMLTemperatureMax;
+  uint8_t Reserved;
+
+  /* dw4-dw7 */
+  uint8_t LPMLTemperatureScaler[16];
+
+  /* dw8-dw9 */
+  int16_t FuzzyFan_ErrorSetDelta;
+  int16_t FuzzyFan_ErrorRateSetDelta;
+  int16_t FuzzyFan_PwmSetDelta;
+  uint16_t Reserved6;
+
+  /* dw10-dw14 */
+  uint8_t GnbLPML[16];
+
+  /* dw15 */
+  uint8_t GnbLPMLMaxVid;
+  uint8_t GnbLPMLMinVid;
+  uint8_t Reserved1[2];
+
+  /* dw16 */
+  uint16_t BapmVddCBaseLeakageHiSidd;
+  uint16_t BapmVddCBaseLeakageLoSidd;
+
+  /* AVFS */
+  uint16_t  VFT_Temp[3];
+  uint16_t  padding;
+
+  SMU_QuadraticCoeffs VFT_ATE[3];
+
+  SMU_QuadraticCoeffs AVFS_GB;
+  SMU_QuadraticCoeffs ATE_ACBTC_GB;
+
+  SMU_QuadraticCoeffs P2V;
+
+  uint32_t PsmCharzFreq;
+
+  uint16_t InversionVoltage;
+  uint16_t PsmCharzTemp;
+
+  uint32_t EnabledAvfsModules;
+};
+
+typedef struct SMU73_Discrete_PmFuses SMU73_Discrete_PmFuses;
+
+struct SMU7_Discrete_Log_Header_Table {
+  uint32_t    version;
+  uint32_t    asic_id;
+  uint16_t    flags;
+  uint16_t    entry_size;
+  uint32_t    total_size;
+  uint32_t    num_of_entries;
+  uint8_t     type;
+  uint8_t     mode;
+  uint8_t     filler_0[2];
+  uint32_t    filler_1[2];
+};
+
+typedef struct SMU7_Discrete_Log_Header_Table SMU7_Discrete_Log_Header_Table;
+
+struct SMU7_Discrete_Log_Cntl {
+    uint8_t             Enabled;
+    uint8_t             Type;
+    uint8_t             padding[2];
+    uint32_t            BufferSize;
+    uint32_t            SamplesLogged;
+    uint32_t            SampleSize;
+    uint32_t            AddrL;
+    uint32_t            AddrH;
+};
+
+typedef struct SMU7_Discrete_Log_Cntl SMU7_Discrete_Log_Cntl;
+
+#define CAC_ACC_NW_NUM_OF_SIGNALS 87
+
+struct SMU7_Discrete_Cac_Collection_Table {
+  uint32_t temperature;
+  uint32_t cac_acc_nw[CAC_ACC_NW_NUM_OF_SIGNALS];
+};
+
+typedef struct SMU7_Discrete_Cac_Collection_Table SMU7_Discrete_Cac_Collection_Table;
+
+struct SMU7_Discrete_Cac_Verification_Table {
+  uint32_t VddcTotalPower;
+  uint32_t VddcLeakagePower;
+  uint32_t VddcConstantPower;
+  uint32_t VddcGfxDynamicPower;
+  uint32_t VddcUvdDynamicPower;
+  uint32_t VddcVceDynamicPower;
+  uint32_t VddcAcpDynamicPower;
+  uint32_t VddcPcieDynamicPower;
+  uint32_t VddcDceDynamicPower;
+  uint32_t VddcCurrent;
+  uint32_t VddcVoltage;
+  uint32_t VddciTotalPower;
+  uint32_t VddciLeakagePower;
+  uint32_t VddciConstantPower;
+  uint32_t VddciDynamicPower;
+  uint32_t Vddr1TotalPower;
+  uint32_t Vddr1LeakagePower;
+  uint32_t Vddr1ConstantPower;
+  uint32_t Vddr1DynamicPower;
+  uint32_t spare[4];
+  uint32_t temperature;
+};
+
+typedef struct SMU7_Discrete_Cac_Verification_Table SMU7_Discrete_Cac_Verification_Table;
+
+struct SMU7_Discrete_Pm_Status_Table {
+  //Thermal entities
+  int32_t  T_meas_max[SMU73_THERMAL_INPUT_LOOP_COUNT];
+  int32_t  T_meas_acc[SMU73_THERMAL_INPUT_LOOP_COUNT];
+  int32_t  T_meas_acc_cnt[SMU73_THERMAL_INPUT_LOOP_COUNT];
+  uint32_t T_hbm_acc;
+
+  //Voltage domains
+  uint32_t I_calc_max;
+  uint32_t I_calc_acc;
+  uint32_t P_meas_acc;
+  uint32_t V_meas_load_acc;
+  uint32_t I_meas_acc;
+  uint32_t P_meas_acc_vddci;
+  uint32_t V_meas_load_acc_vddci;
+  uint32_t I_meas_acc_vddci;
+
+  //Frequency
+  uint16_t Sclk_dpm_residency[8];
+  uint16_t Uvd_dpm_residency[8];
+  uint16_t Vce_dpm_residency[8];
+
+  //Chip
+  uint32_t P_roc_acc;
+  uint32_t PkgPwr_max;
+  uint32_t PkgPwr_acc;
+  uint32_t MclkSwitchingTime_max;
+  uint32_t MclkSwitchingTime_acc;
+  uint32_t FanPwm_acc;
+  uint32_t FanRpm_acc;
+  uint32_t Gfx_busy_acc;
+  uint32_t Mc_busy_acc;
+  uint32_t Fps_acc;
+
+  uint32_t AccCnt;
+};
+
+typedef struct SMU7_Discrete_Pm_Status_Table SMU7_Discrete_Pm_Status_Table;
+
+//FIXME THESE NEED TO BE UPDATED
+#define SMU7_SCLK_CAC 0x561
+#define SMU7_MCLK_CAC 0xF9
+#define SMU7_VCLK_CAC 0x2DE
+#define SMU7_DCLK_CAC 0x2DE
+#define SMU7_ECLK_CAC 0x25E
+#define SMU7_ACLK_CAC 0x25E
+#define SMU7_SAMCLK_CAC 0x25E
+#define SMU7_DISPCLK_CAC 0x100
+#define SMU7_CAC_CONSTANT 0x2EE3430
+#define SMU7_CAC_CONSTANT_SHIFT 18
+
+#define SMU7_VDDCI_MCLK_CONST        1765
+#define SMU7_VDDCI_MCLK_CONST_SHIFT  16
+#define SMU7_VDDCI_VDDCI_CONST       50958
+#define SMU7_VDDCI_VDDCI_CONST_SHIFT 14
+#define SMU7_VDDCI_CONST             11781
+#define SMU7_VDDCI_STROBE_PWR        1331
+
+#define SMU7_VDDR1_CONST            693
+#define SMU7_VDDR1_CAC_WEIGHT       20
+#define SMU7_VDDR1_CAC_WEIGHT_SHIFT 19
+#define SMU7_VDDR1_STROBE_PWR       512
+
+#define SMU7_AREA_COEFF_UVD 0xA78
+#define SMU7_AREA_COEFF_VCE 0x190A
+#define SMU7_AREA_COEFF_ACP 0x22D1
+#define SMU7_AREA_COEFF_SAMU 0x534
+
+//ThermOutMode values
+#define SMU7_THERM_OUT_MODE_DISABLE       0x0
+#define SMU7_THERM_OUT_MODE_THERM_ONLY    0x1
+#define SMU7_THERM_OUT_MODE_THERM_VRHOT   0x2
+
+#pragma pack(pop)
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/amdgpu/smu7_discrete.h b/drivers/gpu/drm/amd/powerplay/inc/smu7_discrete.h
similarity index 100%
rename from drivers/gpu/drm/amd/amdgpu/smu7_discrete.h
rename to drivers/gpu/drm/amd/powerplay/inc/smu7_discrete.h
diff --git a/drivers/gpu/drm/amd/amdgpu/smu7_fusion.h b/drivers/gpu/drm/amd/powerplay/inc/smu7_fusion.h
similarity index 100%
rename from drivers/gpu/drm/amd/amdgpu/smu7_fusion.h
rename to drivers/gpu/drm/amd/powerplay/inc/smu7_fusion.h
diff --git a/drivers/gpu/drm/amd/amdgpu/smu8.h b/drivers/gpu/drm/amd/powerplay/inc/smu8.h
similarity index 100%
rename from drivers/gpu/drm/amd/amdgpu/smu8.h
rename to drivers/gpu/drm/amd/powerplay/inc/smu8.h
diff --git a/drivers/gpu/drm/amd/amdgpu/smu8_fusion.h b/drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h
similarity index 91%
rename from drivers/gpu/drm/amd/amdgpu/smu8_fusion.h
rename to drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h
index 5c9cc3c..0c37c94 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu8_fusion.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h
@@ -48,6 +48,14 @@
 	uint8_t  EnableDramShadow;
 };
 
+/*  Display specific power management parameters */
+#define PWRMGT_SEPARATION_TIME_SHIFT            0
+#define PWRMGT_SEPARATION_TIME_MASK             0xFFFF
+#define PWRMGT_DISABLE_CPU_CSTATES_SHIFT        16
+#define PWRMGT_DISABLE_CPU_CSTATES_MASK         0x1
+#define PWRMGT_DISABLE_CPU_PSTATES_SHIFT        24
+#define PWRMGT_DISABLE_CPU_PSTATES_MASK         0x1
+
 /* Clock Table Definitions */
 #define NUM_SCLK_LEVELS     8
 #define NUM_LCLK_LEVELS     8
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_cz.h b/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h
similarity index 100%
rename from drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_cz.h
rename to drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h b/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h
new file mode 100644
index 0000000..c24a81e
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef SMU_UCODE_XFER_VI_H
+#define SMU_UCODE_XFER_VI_H
+
+#define SMU_DRAMData_TOC_VERSION  1
+#define MAX_IH_REGISTER_COUNT     65535
+#define SMU_DIGEST_SIZE_BYTES     20
+#define SMU_FB_SIZE_BYTES         1048576
+#define SMU_MAX_ENTRIES           12
+
+#define UCODE_ID_SMU              0
+#define UCODE_ID_SDMA0            1
+#define UCODE_ID_SDMA1            2
+#define UCODE_ID_CP_CE            3
+#define UCODE_ID_CP_PFP           4
+#define UCODE_ID_CP_ME            5
+#define UCODE_ID_CP_MEC           6
+#define UCODE_ID_CP_MEC_JT1       7
+#define UCODE_ID_CP_MEC_JT2       8
+#define UCODE_ID_GMCON_RENG       9
+#define UCODE_ID_RLC_G            10
+#define UCODE_ID_IH_REG_RESTORE   11
+#define UCODE_ID_VBIOS            12
+#define UCODE_ID_MISC_METADATA    13
+#define UCODE_ID_RLC_SCRATCH      32
+#define UCODE_ID_RLC_SRM_ARAM     33
+#define UCODE_ID_RLC_SRM_DRAM     34
+#define UCODE_ID_MEC_STORAGE      35
+#define UCODE_ID_VBIOS_PARAMETERS 36
+#define UCODE_META_DATA           0xFF
+
+#define UCODE_ID_SMU_MASK             0x00000001
+#define UCODE_ID_SDMA0_MASK           0x00000002
+#define UCODE_ID_SDMA1_MASK           0x00000004
+#define UCODE_ID_CP_CE_MASK           0x00000008
+#define UCODE_ID_CP_PFP_MASK          0x00000010
+#define UCODE_ID_CP_ME_MASK           0x00000020
+#define UCODE_ID_CP_MEC_MASK          0x00000040
+#define UCODE_ID_CP_MEC_JT1_MASK      0x00000080
+#define UCODE_ID_CP_MEC_JT2_MASK      0x00000100
+#define UCODE_ID_GMCON_RENG_MASK      0x00000200
+#define UCODE_ID_RLC_G_MASK           0x00000400
+#define UCODE_ID_IH_REG_RESTORE_MASK  0x00000800
+#define UCODE_ID_VBIOS_MASK           0x00001000
+
+#define UCODE_FLAG_UNHALT_MASK   0x1
+
+struct SMU_Entry {
+#ifndef __BIG_ENDIAN
+	uint16_t id;
+	uint16_t version;
+	uint32_t image_addr_high;
+	uint32_t image_addr_low;
+	uint32_t meta_data_addr_high;
+	uint32_t meta_data_addr_low;
+	uint32_t data_size_byte;
+	uint16_t flags;
+	uint16_t num_register_entries;
+#else
+	uint16_t version;
+	uint16_t id;
+	uint32_t image_addr_high;
+	uint32_t image_addr_low;
+	uint32_t meta_data_addr_high;
+	uint32_t meta_data_addr_low;
+	uint32_t data_size_byte;
+	uint16_t num_register_entries;
+	uint16_t flags;
+#endif
+};
+
+struct SMU_DRAMData_TOC {
+	uint32_t structure_version;
+	uint32_t num_entries;
+	struct SMU_Entry entry[SMU_MAX_ENTRIES];
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h
new file mode 100644
index 0000000..504f035
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _SMUMGR_H_
+#define _SMUMGR_H_
+#include <linux/types.h>
+#include "pp_instance.h"
+#include "amd_powerplay.h"
+
+struct pp_smumgr;
+struct pp_instance;
+
+#define smu_lower_32_bits(n) ((uint32_t)(n))
+#define smu_upper_32_bits(n) ((uint32_t)(((n)>>16)>>16))
+
+struct pp_smumgr_func {
+	int (*smu_init)(struct pp_smumgr *smumgr);
+	int (*smu_fini)(struct pp_smumgr *smumgr);
+	int (*start_smu)(struct pp_smumgr *smumgr);
+	int (*check_fw_load_finish)(struct pp_smumgr *smumgr,
+				    uint32_t firmware);
+	int (*request_smu_load_fw)(struct pp_smumgr *smumgr);
+	int (*request_smu_load_specific_fw)(struct pp_smumgr *smumgr,
+					    uint32_t firmware);
+	int (*get_argument)(struct pp_smumgr *smumgr);
+	int (*send_msg_to_smc)(struct pp_smumgr *smumgr, uint16_t msg);
+	int (*send_msg_to_smc_with_parameter)(struct pp_smumgr *smumgr,
+					  uint16_t msg, uint32_t parameter);
+	int (*download_pptable_settings)(struct pp_smumgr *smumgr,
+					 void **table);
+	int (*upload_pptable_settings)(struct pp_smumgr *smumgr);
+};
+
+struct pp_smumgr {
+	uint32_t chip_family;
+	uint32_t chip_id;
+	uint32_t hw_revision;
+	void *device;
+	void *backend;
+	uint32_t usec_timeout;
+	bool reload_fw;
+	const struct pp_smumgr_func *smumgr_funcs;
+};
+
+
+extern int smum_init(struct amd_pp_init *pp_init,
+		     struct pp_instance *handle);
+
+extern int smum_fini(struct pp_smumgr *smumgr);
+
+extern int smum_get_argument(struct pp_smumgr *smumgr);
+
+extern int smum_download_powerplay_table(struct pp_smumgr *smumgr, void **table);
+
+extern int smum_upload_powerplay_table(struct pp_smumgr *smumgr);
+
+extern int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg);
+
+extern int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
+					uint16_t msg, uint32_t parameter);
+
+extern int smum_wait_on_register(struct pp_smumgr *smumgr,
+				uint32_t index, uint32_t value, uint32_t mask);
+
+extern int smum_wait_for_register_unequal(struct pp_smumgr *smumgr,
+				uint32_t index, uint32_t value, uint32_t mask);
+
+extern int smum_wait_on_indirect_register(struct pp_smumgr *smumgr,
+				uint32_t indirect_port, uint32_t index,
+				uint32_t value, uint32_t mask);
+
+
+extern void smum_wait_for_indirect_register_unequal(
+				struct pp_smumgr *smumgr,
+				uint32_t indirect_port, uint32_t index,
+				uint32_t value, uint32_t mask);
+
+extern int smu_allocate_memory(void *device, uint32_t size,
+			 enum cgs_gpu_mem_type type,
+			 uint32_t byte_align, uint64_t *mc_addr,
+			 void **kptr, void *handle);
+
+extern int smu_free_memory(void *device, void *handle);
+
+#define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT
+
+#define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK
+
+#define SMUM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(smumgr,			\
+					port, index, value, mask)	\
+	smum_wait_on_indirect_register(smumgr,				\
+				mm##port##_INDEX, index, value, mask)
+
+
+#define SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr,         \
+							index, value, mask) \
+		smum_wait_for_register_unequal(smumgr,            \
+					index, value, mask)
+
+#define SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, value, mask)		\
+	SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr,			\
+				mm##reg, value, mask)
+
+#define SMUM_WAIT_FIELD_UNEQUAL(smumgr, reg, field, fieldval)		\
+	SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg,				\
+		(fieldval) << SMUM_FIELD_SHIFT(reg, field),		\
+		SMUM_FIELD_MASK(reg, field))
+
+#define SMUM_GET_FIELD(value, reg, field)				\
+		(((value) & SMUM_FIELD_MASK(reg, field))		\
+		>> SMUM_FIELD_SHIFT(reg, field))
+
+#define SMUM_READ_FIELD(device, reg, field)                           \
+		SMUM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field)
+
+#define SMUM_SET_FIELD(value, reg, field, field_val)                  \
+		(((value) & ~SMUM_FIELD_MASK(reg, field)) |                    \
+		(SMUM_FIELD_MASK(reg, field) & ((field_val) <<                 \
+			SMUM_FIELD_SHIFT(reg, field))))
+
+#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr,		\
+				port, index, value, mask)		\
+	smum_wait_on_indirect_register(smumgr,				\
+		mm##port##_INDEX_0, index, value, mask)
+
+#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr,	\
+				port, index, value, mask)		\
+	smum_wait_for_indirect_register_unequal(smumgr,			\
+		mm##port##_INDEX_0, index, value, mask)
+
+
+#define SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, value, mask) \
+	SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, port, ix##reg, value, mask)
+
+#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, value, mask)     \
+		SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, ix##reg, value, mask)
+
+
+/*Operations on named fields.*/
+
+#define SMUM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \
+		SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
+			reg, field)
+
+#define SMUM_WRITE_FIELD(device, reg, field, fieldval)            \
+		cgs_write_register(device, mm##reg, \
+		SMUM_SET_FIELD(cgs_read_register(device, mm##reg), reg, field, fieldval))
+
+#define SMUM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval)    \
+		cgs_write_ind_register(device, port, ix##reg, \
+			SMUM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
+			reg, field, fieldval))
+
+#define SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, port, reg, field, fieldval) \
+	SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg,		\
+		(fieldval) << SMUM_FIELD_SHIFT(reg, field),		\
+		SMUM_FIELD_MASK(reg, field))
+
+#define SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, port, reg, field, fieldval) \
+	SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg,	\
+		(fieldval) << SMUM_FIELD_SHIFT(reg, field),		\
+		SMUM_FIELD_MASK(reg, field))
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h
new file mode 100644
index 0000000..6363129
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef TONGA_PP_SMC_H
+#define TONGA_PP_SMC_H
+
+#pragma pack(push, 1)
+
+#define PPSMC_SWSTATE_FLAG_DC				0x01
+#define PPSMC_SWSTATE_FLAG_UVD				0x02
+#define PPSMC_SWSTATE_FLAG_VCE				0x04
+#define PPSMC_SWSTATE_FLAG_PCIE_X1			0x08
+
+#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL             0x00
+#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL             0x01
+#define PPSMC_THERMAL_PROTECT_TYPE_NONE                 0xff
+
+#define PPSMC_SYSTEMFLAG_GPIO_DC                        0x01
+#define PPSMC_SYSTEMFLAG_STEPVDDC                       0x02
+#define PPSMC_SYSTEMFLAG_GDDR5                          0x04
+
+#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP               0x08
+
+#define PPSMC_SYSTEMFLAG_REGULATOR_HOT                  0x10
+#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG           0x20
+#define PPSMC_SYSTEMFLAG_12CHANNEL                      0x40
+
+
+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK              0x07
+#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK     0x08
+
+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE   0x00
+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE  0x01
+
+#define PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH      0x10
+#define PPSMC_EXTRAFLAGS_DRIVER_TO_GPIO17               0x20
+#define PPSMC_EXTRAFLAGS_PCC_TO_GPIO17                  0x40
+
+/* Defines for DPM 2.0 */
+#define PPSMC_DPM2FLAGS_TDPCLMP                         0x01
+#define PPSMC_DPM2FLAGS_PWRSHFT                         0x02
+#define PPSMC_DPM2FLAGS_OCP                             0x04
+
+/* Defines for display watermark level */
+
+#define PPSMC_DISPLAY_WATERMARK_LOW                     0
+#define PPSMC_DISPLAY_WATERMARK_HIGH                    1
+
+/* In the HW performance level's state flags:*/
+#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP    0x01
+#define PPSMC_STATEFLAG_POWERBOOST         0x02
+#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04
+#define PPSMC_STATEFLAG_POWERSHIFT         0x08
+#define PPSMC_STATEFLAG_SLOW_READ_MARGIN   0x10
+#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20
+#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS   0x40
+
+/* Fan control algorithm:*/
+#define FDO_MODE_HARDWARE 0
+#define FDO_MODE_PIECE_WISE_LINEAR 1
+
+enum FAN_CONTROL {
+	FAN_CONTROL_FUZZY,
+	FAN_CONTROL_TABLE
+};
+
+/* Return codes for driver to SMC communication.*/
+
+#define PPSMC_Result_OK             ((uint16_t)0x01)
+#define PPSMC_Result_NoMore         ((uint16_t)0x02)
+#define PPSMC_Result_NotNow         ((uint16_t)0x03)
+
+#define PPSMC_Result_Failed         ((uint16_t)0xFF)
+#define PPSMC_Result_UnknownCmd     ((uint16_t)0xFE)
+#define PPSMC_Result_UnknownVT      ((uint16_t)0xFD)
+
+typedef uint16_t PPSMC_Result;
+
+#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x))
+
+
+#define PPSMC_MSG_Halt                      ((uint16_t)0x10)
+#define PPSMC_MSG_Resume                    ((uint16_t)0x11)
+#define PPSMC_MSG_EnableDPMLevel            ((uint16_t)0x12)
+#define PPSMC_MSG_ZeroLevelsDisabled        ((uint16_t)0x13)
+#define PPSMC_MSG_OneLevelsDisabled         ((uint16_t)0x14)
+#define PPSMC_MSG_TwoLevelsDisabled         ((uint16_t)0x15)
+#define PPSMC_MSG_EnableThermalInterrupt    ((uint16_t)0x16)
+#define PPSMC_MSG_RunningOnAC               ((uint16_t)0x17)
+#define PPSMC_MSG_LevelUp                   ((uint16_t)0x18)
+#define PPSMC_MSG_LevelDown                 ((uint16_t)0x19)
+#define PPSMC_MSG_ResetDPMCounters          ((uint16_t)0x1a)
+#define PPSMC_MSG_SwitchToSwState           ((uint16_t)0x20)
+
+#define PPSMC_MSG_SwitchToSwStateLast       ((uint16_t)0x3f)
+#define PPSMC_MSG_SwitchToInitialState      ((uint16_t)0x40)
+#define PPSMC_MSG_NoForcedLevel             ((uint16_t)0x41)
+#define PPSMC_MSG_ForceHigh                 ((uint16_t)0x42)
+#define PPSMC_MSG_ForceMediumOrHigh         ((uint16_t)0x43)
+
+#define PPSMC_MSG_SwitchToMinimumPower      ((uint16_t)0x51)
+#define PPSMC_MSG_ResumeFromMinimumPower    ((uint16_t)0x52)
+#define PPSMC_MSG_EnableCac                 ((uint16_t)0x53)
+#define PPSMC_MSG_DisableCac                ((uint16_t)0x54)
+#define PPSMC_DPMStateHistoryStart          ((uint16_t)0x55)
+#define PPSMC_DPMStateHistoryStop           ((uint16_t)0x56)
+#define PPSMC_CACHistoryStart               ((uint16_t)0x57)
+#define PPSMC_CACHistoryStop                ((uint16_t)0x58)
+#define PPSMC_TDPClampingActive             ((uint16_t)0x59)
+#define PPSMC_TDPClampingInactive           ((uint16_t)0x5A)
+#define PPSMC_StartFanControl               ((uint16_t)0x5B)
+#define PPSMC_StopFanControl                ((uint16_t)0x5C)
+#define PPSMC_NoDisplay                     ((uint16_t)0x5D)
+#define PPSMC_HasDisplay                    ((uint16_t)0x5E)
+#define PPSMC_MSG_UVDPowerOFF               ((uint16_t)0x60)
+#define PPSMC_MSG_UVDPowerON                ((uint16_t)0x61)
+#define PPSMC_MSG_EnableULV                 ((uint16_t)0x62)
+#define PPSMC_MSG_DisableULV                ((uint16_t)0x63)
+#define PPSMC_MSG_EnterULV                  ((uint16_t)0x64)
+#define PPSMC_MSG_ExitULV                   ((uint16_t)0x65)
+#define PPSMC_PowerShiftActive              ((uint16_t)0x6A)
+#define PPSMC_PowerShiftInactive            ((uint16_t)0x6B)
+#define PPSMC_OCPActive                     ((uint16_t)0x6C)
+#define PPSMC_OCPInactive                   ((uint16_t)0x6D)
+#define PPSMC_CACLongTermAvgEnable          ((uint16_t)0x6E)
+#define PPSMC_CACLongTermAvgDisable         ((uint16_t)0x6F)
+#define PPSMC_MSG_InferredStateSweep_Start  ((uint16_t)0x70)
+#define PPSMC_MSG_InferredStateSweep_Stop   ((uint16_t)0x71)
+#define PPSMC_MSG_SwitchToLowestInfState    ((uint16_t)0x72)
+#define PPSMC_MSG_SwitchToNonInfState       ((uint16_t)0x73)
+#define PPSMC_MSG_AllStateSweep_Start       ((uint16_t)0x74)
+#define PPSMC_MSG_AllStateSweep_Stop        ((uint16_t)0x75)
+#define PPSMC_MSG_SwitchNextLowerInfState   ((uint16_t)0x76)
+#define PPSMC_MSG_SwitchNextHigherInfState  ((uint16_t)0x77)
+#define PPSMC_MSG_MclkRetrainingTest        ((uint16_t)0x78)
+#define PPSMC_MSG_ForceTDPClamping          ((uint16_t)0x79)
+#define PPSMC_MSG_CollectCAC_PowerCorreln   ((uint16_t)0x7A)
+#define PPSMC_MSG_CollectCAC_WeightCalib    ((uint16_t)0x7B)
+#define PPSMC_MSG_CollectCAC_SQonly         ((uint16_t)0x7C)
+#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D)
+
+#define PPSMC_MSG_ExtremitiesTest_Start     ((uint16_t)0x7E)
+#define PPSMC_MSG_ExtremitiesTest_Stop      ((uint16_t)0x7F)
+#define PPSMC_FlushDataCache                ((uint16_t)0x80)
+#define PPSMC_FlushInstrCache               ((uint16_t)0x81)
+
+#define PPSMC_MSG_SetEnabledLevels          ((uint16_t)0x82)
+#define PPSMC_MSG_SetForcedLevels           ((uint16_t)0x83)
+
+#define PPSMC_MSG_ResetToDefaults           ((uint16_t)0x84)
+
+#define PPSMC_MSG_SetForcedLevelsAndJump    ((uint16_t)0x85)
+#define PPSMC_MSG_SetCACHistoryMode         ((uint16_t)0x86)
+#define PPSMC_MSG_EnableDTE                 ((uint16_t)0x87)
+#define PPSMC_MSG_DisableDTE                ((uint16_t)0x88)
+
+#define PPSMC_MSG_SmcSpaceSetAddress        ((uint16_t)0x89)
+#define PPSMC_MSG_ChangeNearTDPLimit        ((uint16_t)0x90)
+#define PPSMC_MSG_ChangeSafePowerLimit      ((uint16_t)0x91)
+
+#define PPSMC_MSG_DPMStateSweepStart        ((uint16_t)0x92)
+#define PPSMC_MSG_DPMStateSweepStop         ((uint16_t)0x93)
+
+#define PPSMC_MSG_OVRDDisableSCLKDS         ((uint16_t)0x94)
+#define PPSMC_MSG_CancelDisableOVRDSCLKDS   ((uint16_t)0x95)
+#define PPSMC_MSG_ThrottleOVRDSCLKDS        ((uint16_t)0x96)
+#define PPSMC_MSG_CancelThrottleOVRDSCLKDS  ((uint16_t)0x97)
+#define PPSMC_MSG_GPIO17					((uint16_t)0x98)
+
+#define PPSMC_MSG_API_SetSvi2Volt_Vddc      ((uint16_t)0x99)
+#define PPSMC_MSG_API_SetSvi2Volt_Vddci     ((uint16_t)0x9A)
+#define PPSMC_MSG_API_SetSvi2Volt_Mvdd      ((uint16_t)0x9B)
+#define PPSMC_MSG_API_GetSvi2Volt_Vddc      ((uint16_t)0x9C)
+#define PPSMC_MSG_API_GetSvi2Volt_Vddci     ((uint16_t)0x9D)
+#define PPSMC_MSG_API_GetSvi2Volt_Mvdd      ((uint16_t)0x9E)
+
+#define PPSMC_MSG_BREAK                     ((uint16_t)0xF8)
+
+/* Trinity Specific Messages*/
+#define PPSMC_MSG_Test                      ((uint16_t) 0x100)
+#define PPSMC_MSG_DPM_Voltage_Pwrmgt        ((uint16_t) 0x101)
+#define PPSMC_MSG_DPM_Config                ((uint16_t) 0x102)
+#define PPSMC_MSG_PM_Controller_Start       ((uint16_t) 0x103)
+#define PPSMC_MSG_DPM_ForceState            ((uint16_t) 0x104)
+#define PPSMC_MSG_PG_PowerDownSIMD          ((uint16_t) 0x105)
+#define PPSMC_MSG_PG_PowerUpSIMD            ((uint16_t) 0x106)
+#define PPSMC_MSG_PM_Controller_Stop        ((uint16_t) 0x107)
+#define PPSMC_MSG_PG_SIMD_Config            ((uint16_t) 0x108)
+#define PPSMC_MSG_Voltage_Cntl_Enable       ((uint16_t) 0x109)
+#define PPSMC_MSG_Thermal_Cntl_Enable       ((uint16_t) 0x10a)
+#define PPSMC_MSG_Reset_Service             ((uint16_t) 0x10b)
+#define PPSMC_MSG_VCEPowerOFF               ((uint16_t) 0x10e)
+#define PPSMC_MSG_VCEPowerON                ((uint16_t) 0x10f)
+#define PPSMC_MSG_DPM_Disable_VCE_HS        ((uint16_t) 0x110)
+#define PPSMC_MSG_DPM_Enable_VCE_HS         ((uint16_t) 0x111)
+#define PPSMC_MSG_DPM_N_LevelsDisabled      ((uint16_t) 0x112)
+#define PPSMC_MSG_DCEPowerOFF               ((uint16_t) 0x113)
+#define PPSMC_MSG_DCEPowerON                ((uint16_t) 0x114)
+#define PPSMC_MSG_PCIE_DDIPowerDown         ((uint16_t) 0x117)
+#define PPSMC_MSG_PCIE_DDIPowerUp           ((uint16_t) 0x118)
+#define PPSMC_MSG_PCIE_CascadePLLPowerDown  ((uint16_t) 0x119)
+#define PPSMC_MSG_PCIE_CascadePLLPowerUp    ((uint16_t) 0x11a)
+#define PPSMC_MSG_SYSPLLPowerOff            ((uint16_t) 0x11b)
+#define PPSMC_MSG_SYSPLLPowerOn             ((uint16_t) 0x11c)
+#define PPSMC_MSG_DCE_RemoveVoltageAdjustment   ((uint16_t) 0x11d)
+#define PPSMC_MSG_DCE_AllowVoltageAdjustment    ((uint16_t) 0x11e)
+#define PPSMC_MSG_DISPLAYPHYStatusNotify    ((uint16_t) 0x11f)
+#define PPSMC_MSG_EnableBAPM                ((uint16_t) 0x120)
+#define PPSMC_MSG_DisableBAPM               ((uint16_t) 0x121)
+#define PPSMC_MSG_PCIE_PHYPowerDown         ((uint16_t) 0x122)
+#define PPSMC_MSG_PCIE_PHYPowerUp           ((uint16_t) 0x123)
+#define PPSMC_MSG_UVD_DPM_Config            ((uint16_t) 0x124)
+#define PPSMC_MSG_Spmi_Enable               ((uint16_t) 0x122)
+#define PPSMC_MSG_Spmi_Timer                ((uint16_t) 0x123)
+#define PPSMC_MSG_LCLK_DPM_Config           ((uint16_t) 0x124)
+#define PPSMC_MSG_NBDPM_Config             ((uint16_t) 0x125)
+#define PPSMC_MSG_PCIE_DDIPhyPowerDown           ((uint16_t) 0x126)
+#define PPSMC_MSG_PCIE_DDIPhyPowerUp             ((uint16_t) 0x127)
+#define PPSMC_MSG_MCLKDPM_Config                ((uint16_t) 0x128)
+
+#define PPSMC_MSG_UVDDPM_Config               ((uint16_t) 0x129)
+#define PPSMC_MSG_VCEDPM_Config               ((uint16_t) 0x12A)
+#define PPSMC_MSG_ACPDPM_Config               ((uint16_t) 0x12B)
+#define PPSMC_MSG_SAMUDPM_Config              ((uint16_t) 0x12C)
+#define PPSMC_MSG_UVDDPM_SetEnabledMask       ((uint16_t) 0x12D)
+#define PPSMC_MSG_VCEDPM_SetEnabledMask       ((uint16_t) 0x12E)
+#define PPSMC_MSG_ACPDPM_SetEnabledMask       ((uint16_t) 0x12F)
+#define PPSMC_MSG_SAMUDPM_SetEnabledMask      ((uint16_t) 0x130)
+#define PPSMC_MSG_MCLKDPM_ForceState          ((uint16_t) 0x131)
+#define PPSMC_MSG_MCLKDPM_NoForcedLevel       ((uint16_t) 0x132)
+#define PPSMC_MSG_Thermal_Cntl_Disable        ((uint16_t) 0x133)
+#define PPSMC_MSG_SetTDPLimit                 ((uint16_t) 0x134)
+#define PPSMC_MSG_Voltage_Cntl_Disable        ((uint16_t) 0x135)
+#define PPSMC_MSG_PCIeDPM_Enable              ((uint16_t) 0x136)
+#define PPSMC_MSG_ACPPowerOFF                 ((uint16_t) 0x137)
+#define PPSMC_MSG_ACPPowerON                  ((uint16_t) 0x138)
+#define PPSMC_MSG_SAMPowerOFF                 ((uint16_t) 0x139)
+#define PPSMC_MSG_SAMPowerON                  ((uint16_t) 0x13a)
+#define PPSMC_MSG_SDMAPowerOFF                ((uint16_t) 0x13b)
+#define PPSMC_MSG_SDMAPowerON                 ((uint16_t) 0x13c)
+#define PPSMC_MSG_PCIeDPM_Disable             ((uint16_t) 0x13d)
+#define PPSMC_MSG_IOMMUPowerOFF               ((uint16_t) 0x13e)
+#define PPSMC_MSG_IOMMUPowerON                ((uint16_t) 0x13f)
+#define PPSMC_MSG_NBDPM_Enable                ((uint16_t) 0x140)
+#define PPSMC_MSG_NBDPM_Disable               ((uint16_t) 0x141)
+#define PPSMC_MSG_NBDPM_ForceNominal          ((uint16_t) 0x142)
+#define PPSMC_MSG_NBDPM_ForcePerformance      ((uint16_t) 0x143)
+#define PPSMC_MSG_NBDPM_UnForce               ((uint16_t) 0x144)
+#define PPSMC_MSG_SCLKDPM_SetEnabledMask      ((uint16_t) 0x145)
+#define PPSMC_MSG_MCLKDPM_SetEnabledMask      ((uint16_t) 0x146)
+#define PPSMC_MSG_PCIeDPM_ForceLevel          ((uint16_t) 0x147)
+#define PPSMC_MSG_PCIeDPM_UnForceLevel        ((uint16_t) 0x148)
+#define PPSMC_MSG_EnableACDCGPIOInterrupt     ((uint16_t) 0x149)
+#define PPSMC_MSG_EnableVRHotGPIOInterrupt    ((uint16_t) 0x14a)
+#define PPSMC_MSG_SwitchToAC                  ((uint16_t) 0x14b)
+
+#define PPSMC_MSG_XDMAPowerOFF                ((uint16_t) 0x14c)
+#define PPSMC_MSG_XDMAPowerON                 ((uint16_t) 0x14d)
+
+#define PPSMC_MSG_DPM_Enable                  ((uint16_t)0x14e)
+#define PPSMC_MSG_DPM_Disable                 ((uint16_t)0x14f)
+#define PPSMC_MSG_MCLKDPM_Enable              ((uint16_t)0x150)
+#define PPSMC_MSG_MCLKDPM_Disable             ((uint16_t)0x151)
+#define PPSMC_MSG_LCLKDPM_Enable              ((uint16_t)0x152)
+#define PPSMC_MSG_LCLKDPM_Disable             ((uint16_t)0x153)
+#define PPSMC_MSG_UVDDPM_Enable               ((uint16_t)0x154)
+#define PPSMC_MSG_UVDDPM_Disable              ((uint16_t)0x155)
+#define PPSMC_MSG_SAMUDPM_Enable              ((uint16_t)0x156)
+#define PPSMC_MSG_SAMUDPM_Disable             ((uint16_t)0x157)
+#define PPSMC_MSG_ACPDPM_Enable               ((uint16_t)0x158)
+#define PPSMC_MSG_ACPDPM_Disable              ((uint16_t)0x159)
+#define PPSMC_MSG_VCEDPM_Enable               ((uint16_t)0x15a)
+#define PPSMC_MSG_VCEDPM_Disable              ((uint16_t)0x15b)
+#define PPSMC_MSG_LCLKDPM_SetEnabledMask      ((uint16_t)0x15c)
+
+#define PPSMC_MSG_DPM_FPS_Mode                ((uint16_t) 0x15d)
+#define PPSMC_MSG_DPM_Activity_Mode           ((uint16_t) 0x15e)
+#define PPSMC_MSG_VddC_Request                ((uint16_t) 0x15f)
+#define PPSMC_MSG_MCLKDPM_GetEnabledMask      ((uint16_t) 0x160)
+#define PPSMC_MSG_LCLKDPM_GetEnabledMask      ((uint16_t) 0x161)
+#define PPSMC_MSG_SCLKDPM_GetEnabledMask      ((uint16_t) 0x162)
+#define PPSMC_MSG_UVDDPM_GetEnabledMask       ((uint16_t) 0x163)
+#define PPSMC_MSG_SAMUDPM_GetEnabledMask      ((uint16_t) 0x164)
+#define PPSMC_MSG_ACPDPM_GetEnabledMask       ((uint16_t) 0x165)
+#define PPSMC_MSG_VCEDPM_GetEnabledMask       ((uint16_t) 0x166)
+#define PPSMC_MSG_PCIeDPM_SetEnabledMask      ((uint16_t) 0x167)
+#define PPSMC_MSG_PCIeDPM_GetEnabledMask      ((uint16_t) 0x168)
+#define PPSMC_MSG_TDCLimitEnable              ((uint16_t) 0x169)
+#define PPSMC_MSG_TDCLimitDisable             ((uint16_t) 0x16a)
+#define PPSMC_MSG_DPM_AutoRotate_Mode         ((uint16_t) 0x16b)
+#define PPSMC_MSG_DISPCLK_FROM_FCH            ((uint16_t)0x16c)
+#define PPSMC_MSG_DISPCLK_FROM_DFS            ((uint16_t)0x16d)
+#define PPSMC_MSG_DPREFCLK_FROM_FCH           ((uint16_t)0x16e)
+#define PPSMC_MSG_DPREFCLK_FROM_DFS           ((uint16_t)0x16f)
+#define PPSMC_MSG_PmStatusLogStart            ((uint16_t)0x170)
+#define PPSMC_MSG_PmStatusLogSample           ((uint16_t)0x171)
+#define PPSMC_MSG_SCLK_AutoDPM_ON             ((uint16_t) 0x172)
+#define PPSMC_MSG_MCLK_AutoDPM_ON             ((uint16_t) 0x173)
+#define PPSMC_MSG_LCLK_AutoDPM_ON             ((uint16_t) 0x174)
+#define PPSMC_MSG_UVD_AutoDPM_ON              ((uint16_t) 0x175)
+#define PPSMC_MSG_SAMU_AutoDPM_ON             ((uint16_t) 0x176)
+#define PPSMC_MSG_ACP_AutoDPM_ON              ((uint16_t) 0x177)
+#define PPSMC_MSG_VCE_AutoDPM_ON              ((uint16_t) 0x178)
+#define PPSMC_MSG_PCIe_AutoDPM_ON             ((uint16_t) 0x179)
+#define PPSMC_MSG_MASTER_AutoDPM_ON           ((uint16_t) 0x17a)
+#define PPSMC_MSG_MASTER_AutoDPM_OFF          ((uint16_t) 0x17b)
+#define PPSMC_MSG_DYNAMICDISPPHYPOWER         ((uint16_t) 0x17c)
+#define PPSMC_MSG_CAC_COLLECTION_ON           ((uint16_t) 0x17d)
+#define PPSMC_MSG_CAC_COLLECTION_OFF          ((uint16_t) 0x17e)
+#define PPSMC_MSG_CAC_CORRELATION_ON          ((uint16_t) 0x17f)
+#define PPSMC_MSG_CAC_CORRELATION_OFF         ((uint16_t) 0x180)
+#define PPSMC_MSG_PM_STATUS_TO_DRAM_ON        ((uint16_t) 0x181)
+#define PPSMC_MSG_PM_STATUS_TO_DRAM_OFF       ((uint16_t) 0x182)
+#define PPSMC_MSG_UVD_HANDSHAKE_OFF           ((uint16_t) 0x183)
+#define PPSMC_MSG_ALLOW_LOWSCLK_INTERRUPT     ((uint16_t) 0x184)
+#define PPSMC_MSG_PkgPwrLimitEnable           ((uint16_t) 0x185)
+#define PPSMC_MSG_PkgPwrLimitDisable          ((uint16_t) 0x186)
+#define PPSMC_MSG_PkgPwrSetLimit              ((uint16_t) 0x187)
+#define PPSMC_MSG_OverDriveSetTargetTdp       ((uint16_t) 0x188)
+#define PPSMC_MSG_SCLKDPM_FreezeLevel         ((uint16_t) 0x189)
+#define PPSMC_MSG_SCLKDPM_UnfreezeLevel       ((uint16_t) 0x18A)
+#define PPSMC_MSG_MCLKDPM_FreezeLevel         ((uint16_t) 0x18B)
+#define PPSMC_MSG_MCLKDPM_UnfreezeLevel       ((uint16_t) 0x18C)
+#define PPSMC_MSG_START_DRAM_LOGGING          ((uint16_t) 0x18D)
+#define PPSMC_MSG_STOP_DRAM_LOGGING           ((uint16_t) 0x18E)
+#define PPSMC_MSG_MASTER_DeepSleep_ON         ((uint16_t) 0x18F)
+#define PPSMC_MSG_MASTER_DeepSleep_OFF        ((uint16_t) 0x190)
+#define PPSMC_MSG_Remove_DC_Clamp             ((uint16_t) 0x191)
+#define PPSMC_MSG_DisableACDCGPIOInterrupt    ((uint16_t) 0x192)
+#define PPSMC_MSG_OverrideVoltageControl_SetVddc       ((uint16_t) 0x193)
+#define PPSMC_MSG_OverrideVoltageControl_SetVddci      ((uint16_t) 0x194)
+#define PPSMC_MSG_SetVidOffset_1              ((uint16_t) 0x195)
+#define PPSMC_MSG_SetVidOffset_2              ((uint16_t) 0x207)
+#define PPSMC_MSG_GetVidOffset_1              ((uint16_t) 0x196)
+#define PPSMC_MSG_GetVidOffset_2              ((uint16_t) 0x208)
+#define PPSMC_MSG_THERMAL_OVERDRIVE_Enable    ((uint16_t) 0x197)
+#define PPSMC_MSG_THERMAL_OVERDRIVE_Disable	  ((uint16_t) 0x198)
+#define PPSMC_MSG_SetTjMax                    ((uint16_t) 0x199)
+#define PPSMC_MSG_SetFanPwmMax                ((uint16_t) 0x19A)
+
+#define PPSMC_MSG_WaitForMclkSwitchFinish	  ((uint16_t) 0x19B)
+#define PPSMC_MSG_ENABLE_THERMAL_DPM          ((uint16_t) 0x19C)
+#define PPSMC_MSG_DISABLE_THERMAL_DPM         ((uint16_t) 0x19D)
+#define PPSMC_MSG_Enable_PCC                  ((uint16_t) 0x19E)
+#define PPSMC_MSG_Disable_PCC                 ((uint16_t) 0x19F)
+
+#define PPSMC_MSG_API_GetSclkFrequency        ((uint16_t) 0x200)
+#define PPSMC_MSG_API_GetMclkFrequency        ((uint16_t) 0x201)
+#define PPSMC_MSG_API_GetSclkBusy             ((uint16_t) 0x202)
+#define PPSMC_MSG_API_GetMclkBusy             ((uint16_t) 0x203)
+#define PPSMC_MSG_API_GetAsicPower            ((uint16_t) 0x204)
+#define PPSMC_MSG_SetFanRpmMax                ((uint16_t) 0x205)
+#define PPSMC_MSG_SetFanSclkTarget            ((uint16_t) 0x206)
+#define PPSMC_MSG_SetFanMinPwm                ((uint16_t) 0x209)
+#define PPSMC_MSG_SetFanTemperatureTarget     ((uint16_t) 0x20A)
+
+#define PPSMC_MSG_BACO_StartMonitor           ((uint16_t) 0x240)
+#define PPSMC_MSG_BACO_Cancel                 ((uint16_t) 0x241)
+#define PPSMC_MSG_EnableVddGfx                ((uint16_t) 0x242)
+#define PPSMC_MSG_DisableVddGfx               ((uint16_t) 0x243)
+#define PPSMC_MSG_UcodeAddressLow             ((uint16_t) 0x244)
+#define PPSMC_MSG_UcodeAddressHigh            ((uint16_t) 0x245)
+#define PPSMC_MSG_UcodeLoadStatus             ((uint16_t) 0x246)
+
+#define PPSMC_MSG_DRV_DRAM_ADDR_HI			  ((uint16_t) 0x250)
+#define PPSMC_MSG_DRV_DRAM_ADDR_LO            ((uint16_t) 0x251)
+#define PPSMC_MSG_SMU_DRAM_ADDR_HI            ((uint16_t) 0x252)
+#define PPSMC_MSG_SMU_DRAM_ADDR_LO            ((uint16_t) 0x253)
+#define PPSMC_MSG_LoadUcodes                  ((uint16_t) 0x254)
+#define PPSMC_MSG_PowerStateNotify            ((uint16_t) 0x255)
+#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_HI      ((uint16_t) 0x256)
+#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_LO      ((uint16_t) 0x257)
+#define PPSMC_MSG_VBIOS_DRAM_ADDR_HI          ((uint16_t) 0x258)
+#define PPSMC_MSG_VBIOS_DRAM_ADDR_LO          ((uint16_t) 0x259)
+#define PPSMC_MSG_LoadVBios                   ((uint16_t) 0x25A)
+#define PPSMC_MSG_GetUcodeVersion             ((uint16_t) 0x25B)
+#define DMCUSMC_MSG_PSREntry                  ((uint16_t) 0x25C)
+#define DMCUSMC_MSG_PSRExit                   ((uint16_t) 0x25D)
+#define PPSMC_MSG_EnableClockGatingFeature    ((uint16_t) 0x260)
+#define PPSMC_MSG_DisableClockGatingFeature   ((uint16_t) 0x261)
+#define PPSMC_MSG_IsDeviceRunning             ((uint16_t) 0x262)
+#define PPSMC_MSG_LoadMetaData                ((uint16_t) 0x263)
+#define PPSMC_MSG_TMON_AutoCaliberate_Enable  ((uint16_t) 0x264)
+#define PPSMC_MSG_TMON_AutoCaliberate_Disable ((uint16_t) 0x265)
+#define PPSMC_MSG_GetTelemetry1Slope          ((uint16_t) 0x266)
+#define PPSMC_MSG_GetTelemetry1Offset         ((uint16_t) 0x267)
+#define PPSMC_MSG_GetTelemetry2Slope          ((uint16_t) 0x268)
+#define PPSMC_MSG_GetTelemetry2Offset         ((uint16_t) 0x269)
+
+typedef uint16_t PPSMC_Msg;
+
+/* If the SMC firmware has an event status soft register this is what the individual bits mean.*/
+#define PPSMC_EVENT_STATUS_THERMAL          0x00000001
+#define PPSMC_EVENT_STATUS_REGULATORHOT     0x00000002
+#define PPSMC_EVENT_STATUS_DC               0x00000004
+#define PPSMC_EVENT_STATUS_GPIO17           0x00000008
+
+
+#pragma pack(pop)
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile
new file mode 100644
index 0000000..6c4ef13
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the 'smu manager' sub-component of powerplay.
+# It provides the smu management services for the driver.
+
+SMU_MGR = smumgr.o cz_smumgr.o tonga_smumgr.o fiji_smumgr.o
+
+AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR))
+
+AMD_POWERPLAY_FILES += $(AMD_PP_SMUMGR)
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c
new file mode 100644
index 0000000..873a8d2
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c
@@ -0,0 +1,858 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/gfp.h>
+#include "linux/delay.h"
+#include "cgs_common.h"
+#include "smu/smu_8_0_d.h"
+#include "smu/smu_8_0_sh_mask.h"
+#include "smu8.h"
+#include "smu8_fusion.h"
+#include "cz_smumgr.h"
+#include "cz_ppsmc.h"
+#include "smu_ucode_xfer_cz.h"
+#include "gca/gfx_8_0_d.h"
+#include "gca/gfx_8_0_sh_mask.h"
+#include "smumgr.h"
+
+#define SIZE_ALIGN_32(x)    (((x) + 31) / 32 * 32)
+
+static enum cz_scratch_entry firmware_list[] = {
+	CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0,
+	CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
+	CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE,
+	CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP,
+	CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME,
+	CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
+	CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
+	CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G,
+};
+
+static int cz_smum_get_argument(struct pp_smumgr *smumgr)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	return cgs_read_register(smumgr->device,
+					mmSMU_MP1_SRBM2P_ARG_0);
+}
+
+static int cz_send_msg_to_smc_async(struct pp_smumgr *smumgr,
+								uint16_t msg)
+{
+	int result = 0;
+
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	result = SMUM_WAIT_FIELD_UNEQUAL(smumgr,
+					SMU_MP1_SRBM2P_RESP_0, CONTENT, 0);
+	if (result != 0) {
+		printk(KERN_ERR "[ powerplay ] cz_send_msg_to_smc_async failed\n");
+		return result;
+	}
+
+	cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0);
+	cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg);
+
+	return 0;
+}
+
+/* Send a message to the SMC, and wait for its response.*/
+static int cz_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
+{
+	int result = 0;
+
+	result = cz_send_msg_to_smc_async(smumgr, msg);
+	if (result != 0)
+		return result;
+
+	result = SMUM_WAIT_FIELD_UNEQUAL(smumgr,
+					SMU_MP1_SRBM2P_RESP_0, CONTENT, 0);
+
+	if (result != 0)
+		return result;
+
+	return 0;
+}
+
+static int cz_set_smc_sram_address(struct pp_smumgr *smumgr,
+				     uint32_t smc_address, uint32_t limit)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	if (0 != (3 & smc_address)) {
+		printk(KERN_ERR "[ powerplay ] SMC address must be 4 byte aligned\n");
+		return -1;
+	}
+
+	if (limit <= (smc_address + 3)) {
+		printk(KERN_ERR "[ powerplay ] SMC address beyond the SMC RAM area\n");
+		return -1;
+	}
+
+	cgs_write_register(smumgr->device, mmMP0PUB_IND_INDEX_0,
+				SMN_MP1_SRAM_START_ADDR + smc_address);
+
+	return 0;
+}
+
+static int cz_write_smc_sram_dword(struct pp_smumgr *smumgr,
+		uint32_t smc_address, uint32_t value, uint32_t limit)
+{
+	int result;
+
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	result = cz_set_smc_sram_address(smumgr, smc_address, limit);
+	cgs_write_register(smumgr->device, mmMP0PUB_IND_DATA_0, value);
+
+	return 0;
+}
+
+static int cz_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
+					  uint16_t msg, uint32_t parameter)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter);
+
+	return cz_send_msg_to_smc(smumgr, msg);
+}
+
+static int cz_request_smu_load_fw(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)(smumgr->backend);
+	int result = 0;
+	uint32_t smc_address;
+
+	if (!smumgr->reload_fw) {
+		printk(KERN_INFO "[ powerplay ] skip reloading...\n");
+		return 0;
+	}
+
+	smc_address = SMU8_FIRMWARE_HEADER_LOCATION +
+		offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
+
+	cz_write_smc_sram_dword(smumgr, smc_address, 0, smc_address+4);
+
+	cz_send_msg_to_smc_with_parameter(smumgr,
+					PPSMC_MSG_DriverDramAddrHi,
+					cz_smu->toc_buffer.mc_addr_high);
+
+	cz_send_msg_to_smc_with_parameter(smumgr,
+					PPSMC_MSG_DriverDramAddrLo,
+					cz_smu->toc_buffer.mc_addr_low);
+
+	cz_send_msg_to_smc(smumgr, PPSMC_MSG_InitJobs);
+
+	cz_send_msg_to_smc_with_parameter(smumgr,
+					PPSMC_MSG_ExecuteJob,
+					cz_smu->toc_entry_aram);
+	cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob,
+				cz_smu->toc_entry_power_profiling_index);
+
+	result = cz_send_msg_to_smc_with_parameter(smumgr,
+					PPSMC_MSG_ExecuteJob,
+					cz_smu->toc_entry_initialize_index);
+
+	return result;
+}
+
+static int cz_check_fw_load_finish(struct pp_smumgr *smumgr,
+				   uint32_t firmware)
+{
+	int i;
+	uint32_t index = SMN_MP1_SRAM_START_ADDR +
+			 SMU8_FIRMWARE_HEADER_LOCATION +
+			 offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
+
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	return cgs_read_register(smumgr->device,
+					mmSMU_MP1_SRBM2P_ARG_0);
+
+	cgs_write_register(smumgr->device, mmMP0PUB_IND_INDEX, index);
+
+	for (i = 0; i < smumgr->usec_timeout; i++) {
+		if (firmware ==
+			(cgs_read_register(smumgr->device, mmMP0PUB_IND_DATA) & firmware))
+			break;
+		udelay(1);
+	}
+
+	if (i >= smumgr->usec_timeout) {
+		printk(KERN_ERR "[ powerplay ] SMU check loaded firmware failed.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int cz_load_mec_firmware(struct pp_smumgr *smumgr)
+{
+	uint32_t reg_data;
+	uint32_t tmp;
+	int ret = 0;
+	struct cgs_firmware_info info = {0};
+	struct cz_smumgr *cz_smu;
+
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	cz_smu = (struct cz_smumgr *)smumgr->backend;
+	ret = cgs_get_firmware_info(smumgr->device,
+						CGS_UCODE_ID_CP_MEC, &info);
+
+	if (ret)
+		return -EINVAL;
+
+	/* Disable MEC parsing/prefetching */
+	tmp = cgs_read_register(smumgr->device,
+					mmCP_MEC_CNTL);
+	tmp = SMUM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1);
+	tmp = SMUM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1);
+	cgs_write_register(smumgr->device, mmCP_MEC_CNTL, tmp);
+
+	tmp = cgs_read_register(smumgr->device,
+					mmCP_CPC_IC_BASE_CNTL);
+
+	tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0);
+	tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0);
+	tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0);
+	tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1);
+	cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_CNTL, tmp);
+
+	reg_data = smu_lower_32_bits(info.mc_addr) &
+			SMUM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO);
+	cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_LO, reg_data);
+
+	reg_data = smu_upper_32_bits(info.mc_addr) &
+			SMUM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI);
+	cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_HI, reg_data);
+
+	return 0;
+}
+
+static int cz_start_smu(struct pp_smumgr *smumgr)
+{
+	int ret = 0;
+	uint32_t fw_to_check = UCODE_ID_RLC_G_MASK |
+				UCODE_ID_SDMA0_MASK |
+				UCODE_ID_SDMA1_MASK |
+				UCODE_ID_CP_CE_MASK |
+				UCODE_ID_CP_ME_MASK |
+				UCODE_ID_CP_PFP_MASK |
+				UCODE_ID_CP_MEC_JT1_MASK |
+				UCODE_ID_CP_MEC_JT2_MASK;
+
+	cz_request_smu_load_fw(smumgr);
+	cz_check_fw_load_finish(smumgr, fw_to_check);
+
+	ret = cz_load_mec_firmware(smumgr);
+	if (ret)
+		printk(KERN_ERR "[ powerplay ] Mec Firmware load failed\n");
+
+	return ret;
+}
+
+static uint8_t cz_translate_firmware_enum_to_arg(
+			enum cz_scratch_entry firmware_enum)
+{
+	uint8_t ret = 0;
+
+	switch (firmware_enum) {
+	case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0:
+		ret = UCODE_ID_SDMA0;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1:
+		ret = UCODE_ID_SDMA1;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE:
+		ret = UCODE_ID_CP_CE;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP:
+		ret = UCODE_ID_CP_PFP;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME:
+		ret = UCODE_ID_CP_ME;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1:
+		ret = UCODE_ID_CP_MEC_JT1;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2:
+		ret = UCODE_ID_CP_MEC_JT2;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG:
+		ret = UCODE_ID_GMCON_RENG;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G:
+		ret = UCODE_ID_RLC_G;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH:
+		ret = UCODE_ID_RLC_SCRATCH;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM:
+		ret = UCODE_ID_RLC_SRM_ARAM;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM:
+		ret = UCODE_ID_RLC_SRM_DRAM;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM:
+		ret = UCODE_ID_DMCU_ERAM;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM:
+		ret = UCODE_ID_DMCU_IRAM;
+		break;
+	case CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING:
+		ret = TASK_ARG_INIT_MM_PWR_LOG;
+		break;
+	case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_HALT:
+	case CZ_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING:
+	case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS:
+	case CZ_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT:
+	case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_START:
+	case CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS:
+		ret = TASK_ARG_REG_MMIO;
+		break;
+	case CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE:
+		ret = TASK_ARG_INIT_CLK_TABLE;
+		break;
+	}
+
+	return ret;
+}
+
+static enum cgs_ucode_id cz_convert_fw_type_to_cgs(uint32_t fw_type)
+{
+	enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
+
+	switch (fw_type) {
+	case UCODE_ID_SDMA0:
+		result = CGS_UCODE_ID_SDMA0;
+		break;
+	case UCODE_ID_SDMA1:
+		result = CGS_UCODE_ID_SDMA1;
+		break;
+	case UCODE_ID_CP_CE:
+		result = CGS_UCODE_ID_CP_CE;
+		break;
+	case UCODE_ID_CP_PFP:
+		result = CGS_UCODE_ID_CP_PFP;
+		break;
+	case UCODE_ID_CP_ME:
+		result = CGS_UCODE_ID_CP_ME;
+		break;
+	case UCODE_ID_CP_MEC_JT1:
+		result = CGS_UCODE_ID_CP_MEC_JT1;
+		break;
+	case UCODE_ID_CP_MEC_JT2:
+		result = CGS_UCODE_ID_CP_MEC_JT2;
+		break;
+	case UCODE_ID_RLC_G:
+		result = CGS_UCODE_ID_RLC_G;
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+static int cz_smu_populate_single_scratch_task(
+			struct pp_smumgr *smumgr,
+			enum cz_scratch_entry fw_enum,
+			uint8_t type, bool is_last)
+{
+	uint8_t i;
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+	struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr;
+	struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++];
+
+	task->type = type;
+	task->arg = cz_translate_firmware_enum_to_arg(fw_enum);
+	task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count;
+
+	for (i = 0; i < cz_smu->scratch_buffer_length; i++)
+		if (cz_smu->scratch_buffer[i].firmware_ID == fw_enum)
+			break;
+
+	if (i >= cz_smu->scratch_buffer_length) {
+		printk(KERN_ERR "[ powerplay ] Invalid Firmware Type\n");
+		return -EINVAL;
+	}
+
+	task->addr.low = cz_smu->scratch_buffer[i].mc_addr_low;
+	task->addr.high = cz_smu->scratch_buffer[i].mc_addr_high;
+	task->size_bytes = cz_smu->scratch_buffer[i].data_size;
+
+	if (CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == fw_enum) {
+		struct cz_ih_meta_data *pIHReg_restore =
+		     (struct cz_ih_meta_data *)cz_smu->scratch_buffer[i].kaddr;
+		pIHReg_restore->command =
+			METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD;
+	}
+
+	return 0;
+}
+
+static int cz_smu_populate_single_ucode_load_task(
+					struct pp_smumgr *smumgr,
+					enum cz_scratch_entry fw_enum,
+					bool is_last)
+{
+	uint8_t i;
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+	struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr;
+	struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++];
+
+	task->type = TASK_TYPE_UCODE_LOAD;
+	task->arg = cz_translate_firmware_enum_to_arg(fw_enum);
+	task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count;
+
+	for (i = 0; i < cz_smu->driver_buffer_length; i++)
+		if (cz_smu->driver_buffer[i].firmware_ID == fw_enum)
+			break;
+
+	if (i >= cz_smu->driver_buffer_length) {
+		printk(KERN_ERR "[ powerplay ] Invalid Firmware Type\n");
+		return -EINVAL;
+	}
+
+	task->addr.low = cz_smu->driver_buffer[i].mc_addr_low;
+	task->addr.high = cz_smu->driver_buffer[i].mc_addr_high;
+	task->size_bytes = cz_smu->driver_buffer[i].data_size;
+
+	return 0;
+}
+
+static int cz_smu_construct_toc_for_rlc_aram_save(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+
+	cz_smu->toc_entry_aram = cz_smu->toc_entry_used_count;
+	cz_smu_populate_single_scratch_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
+				TASK_TYPE_UCODE_SAVE, true);
+
+	return 0;
+}
+
+static int cz_smu_initialize_toc_empty_job_list(struct pp_smumgr *smumgr)
+{
+	int i;
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+	struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr;
+
+	for (i = 0; i < NUM_JOBLIST_ENTRIES; i++)
+		toc->JobList[i] = (uint8_t)IGNORE_JOB;
+
+	return 0;
+}
+
+static int cz_smu_construct_toc_for_vddgfx_enter(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+	struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr;
+
+	toc->JobList[JOB_GFX_SAVE] = (uint8_t)cz_smu->toc_entry_used_count;
+	cz_smu_populate_single_scratch_task(smumgr,
+				    CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
+				    TASK_TYPE_UCODE_SAVE, false);
+
+	cz_smu_populate_single_scratch_task(smumgr,
+				    CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
+				    TASK_TYPE_UCODE_SAVE, true);
+
+	return 0;
+}
+
+
+static int cz_smu_construct_toc_for_vddgfx_exit(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+	struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr;
+
+	toc->JobList[JOB_GFX_RESTORE] = (uint8_t)cz_smu->toc_entry_used_count;
+
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, false);
+
+	/* populate scratch */
+	cz_smu_populate_single_scratch_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
+				TASK_TYPE_UCODE_LOAD, false);
+
+	cz_smu_populate_single_scratch_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
+				TASK_TYPE_UCODE_LOAD, false);
+
+	cz_smu_populate_single_scratch_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
+				TASK_TYPE_UCODE_LOAD, true);
+
+	return 0;
+}
+
+static int cz_smu_construct_toc_for_power_profiling(
+						 struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+
+	cz_smu->toc_entry_power_profiling_index = cz_smu->toc_entry_used_count;
+
+	cz_smu_populate_single_scratch_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
+				TASK_TYPE_INITIALIZE, true);
+	return 0;
+}
+
+static int cz_smu_construct_toc_for_bootup(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+
+	cz_smu->toc_entry_initialize_index = cz_smu->toc_entry_used_count;
+
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
+	cz_smu_populate_single_ucode_load_task(smumgr,
+				CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, true);
+
+	return 0;
+}
+
+static int cz_smu_construct_toc_for_clock_table(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+
+	cz_smu->toc_entry_clock_table = cz_smu->toc_entry_used_count;
+
+	cz_smu_populate_single_scratch_task(smumgr,
+				CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
+				TASK_TYPE_INITIALIZE, true);
+
+	return 0;
+}
+
+static int cz_smu_construct_toc(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+
+	cz_smu->toc_entry_used_count = 0;
+
+	cz_smu_initialize_toc_empty_job_list(smumgr);
+
+	cz_smu_construct_toc_for_rlc_aram_save(smumgr);
+
+	cz_smu_construct_toc_for_vddgfx_enter(smumgr);
+
+	cz_smu_construct_toc_for_vddgfx_exit(smumgr);
+
+	cz_smu_construct_toc_for_power_profiling(smumgr);
+
+	cz_smu_construct_toc_for_bootup(smumgr);
+
+	cz_smu_construct_toc_for_clock_table(smumgr);
+
+	return 0;
+}
+
+static int cz_smu_populate_firmware_entries(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+	uint32_t firmware_type;
+	uint32_t i;
+	int ret;
+	enum cgs_ucode_id ucode_id;
+	struct cgs_firmware_info info = {0};
+
+	cz_smu->driver_buffer_length = 0;
+
+	for (i = 0; i < sizeof(firmware_list)/sizeof(*firmware_list); i++) {
+
+		firmware_type = cz_translate_firmware_enum_to_arg(
+					firmware_list[i]);
+
+		ucode_id = cz_convert_fw_type_to_cgs(firmware_type);
+
+		ret = cgs_get_firmware_info(smumgr->device,
+							ucode_id, &info);
+
+		if (ret == 0) {
+			cz_smu->driver_buffer[i].mc_addr_high =
+					smu_upper_32_bits(info.mc_addr);
+
+			cz_smu->driver_buffer[i].mc_addr_low =
+					smu_lower_32_bits(info.mc_addr);
+
+			cz_smu->driver_buffer[i].data_size = info.image_size;
+
+			cz_smu->driver_buffer[i].firmware_ID = firmware_list[i];
+			cz_smu->driver_buffer_length++;
+		}
+	}
+
+	return 0;
+}
+
+static int cz_smu_populate_single_scratch_entry(
+				struct pp_smumgr *smumgr,
+				enum cz_scratch_entry scratch_type,
+				uint32_t ulsize_byte,
+				struct cz_buffer_entry *entry)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+	long long mc_addr =
+			((long long)(cz_smu->smu_buffer.mc_addr_high) << 32)
+			| cz_smu->smu_buffer.mc_addr_low;
+
+	uint32_t ulsize_aligned = SIZE_ALIGN_32(ulsize_byte);
+
+	mc_addr += cz_smu->smu_buffer_used_bytes;
+
+	entry->data_size = ulsize_byte;
+	entry->kaddr = (char *) cz_smu->smu_buffer.kaddr +
+				cz_smu->smu_buffer_used_bytes;
+	entry->mc_addr_low = smu_lower_32_bits(mc_addr);
+	entry->mc_addr_high = smu_upper_32_bits(mc_addr);
+	entry->firmware_ID = scratch_type;
+
+	cz_smu->smu_buffer_used_bytes += ulsize_aligned;
+
+	return 0;
+}
+
+static int cz_download_pptable_settings(struct pp_smumgr *smumgr, void **table)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+	unsigned long i;
+
+	for (i = 0; i < cz_smu->scratch_buffer_length; i++) {
+		if (cz_smu->scratch_buffer[i].firmware_ID
+			== CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
+			break;
+	}
+
+	*table = (struct SMU8_Fusion_ClkTable *)cz_smu->scratch_buffer[i].kaddr;
+
+	cz_send_msg_to_smc_with_parameter(smumgr,
+				PPSMC_MSG_SetClkTableAddrHi,
+				cz_smu->scratch_buffer[i].mc_addr_high);
+
+	cz_send_msg_to_smc_with_parameter(smumgr,
+				PPSMC_MSG_SetClkTableAddrLo,
+				cz_smu->scratch_buffer[i].mc_addr_low);
+
+	cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob,
+				cz_smu->toc_entry_clock_table);
+
+	cz_send_msg_to_smc(smumgr, PPSMC_MSG_ClkTableXferToDram);
+
+	return 0;
+}
+
+static int cz_upload_pptable_settings(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+	unsigned long i;
+
+	for (i = 0; i < cz_smu->scratch_buffer_length; i++) {
+		if (cz_smu->scratch_buffer[i].firmware_ID
+				== CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
+			break;
+	}
+
+	cz_send_msg_to_smc_with_parameter(smumgr,
+				PPSMC_MSG_SetClkTableAddrHi,
+				cz_smu->scratch_buffer[i].mc_addr_high);
+
+	cz_send_msg_to_smc_with_parameter(smumgr,
+				PPSMC_MSG_SetClkTableAddrLo,
+				cz_smu->scratch_buffer[i].mc_addr_low);
+
+	cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob,
+				cz_smu->toc_entry_clock_table);
+
+	cz_send_msg_to_smc(smumgr, PPSMC_MSG_ClkTableXferToSmu);
+
+	return 0;
+}
+
+static int cz_smu_init(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend;
+	uint64_t mc_addr = 0;
+	int ret = 0;
+
+	cz_smu->toc_buffer.data_size = 4096;
+	cz_smu->smu_buffer.data_size =
+		ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) +
+		ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) +
+		ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) +
+		ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) +
+		ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32);
+
+	ret = smu_allocate_memory(smumgr->device,
+				cz_smu->toc_buffer.data_size,
+				CGS_GPU_MEM_TYPE__GART_CACHEABLE,
+				PAGE_SIZE,
+				&mc_addr,
+				&cz_smu->toc_buffer.kaddr,
+				&cz_smu->toc_buffer.handle);
+	if (ret != 0)
+		return -1;
+
+	cz_smu->toc_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
+	cz_smu->toc_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
+
+	ret = smu_allocate_memory(smumgr->device,
+				cz_smu->smu_buffer.data_size,
+				CGS_GPU_MEM_TYPE__GART_CACHEABLE,
+				PAGE_SIZE,
+				&mc_addr,
+				&cz_smu->smu_buffer.kaddr,
+				&cz_smu->smu_buffer.handle);
+	if (ret != 0)
+		return -1;
+
+	cz_smu->smu_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
+	cz_smu->smu_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
+
+	cz_smu_populate_firmware_entries(smumgr);
+	if (0 != cz_smu_populate_single_scratch_entry(smumgr,
+		CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
+		UCODE_ID_RLC_SCRATCH_SIZE_BYTE,
+		&cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) {
+		printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n");
+		return -1;
+	}
+
+	if (0 != cz_smu_populate_single_scratch_entry(smumgr,
+		CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
+		UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE,
+		&cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) {
+		printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n");
+		return -1;
+	}
+	if (0 != cz_smu_populate_single_scratch_entry(smumgr,
+		CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
+		UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE,
+		&cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) {
+		printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n");
+		return -1;
+	}
+
+	if (0 != cz_smu_populate_single_scratch_entry(smumgr,
+		CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
+		sizeof(struct SMU8_MultimediaPowerLogData),
+		&cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) {
+		printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n");
+		return -1;
+	}
+
+	if (0 != cz_smu_populate_single_scratch_entry(smumgr,
+		CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
+		sizeof(struct SMU8_Fusion_ClkTable),
+		&cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) {
+		printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n");
+		return -1;
+	}
+	cz_smu_construct_toc(smumgr);
+
+	return 0;
+}
+
+static int cz_smu_fini(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu;
+
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	cz_smu = (struct cz_smumgr *)smumgr->backend;
+	if (cz_smu) {
+		cgs_free_gpu_mem(smumgr->device,
+				cz_smu->toc_buffer.handle);
+		cgs_free_gpu_mem(smumgr->device,
+				cz_smu->smu_buffer.handle);
+		kfree(cz_smu);
+		kfree(smumgr);
+	}
+
+	return 0;
+}
+
+static const struct pp_smumgr_func cz_smu_funcs = {
+	.smu_init = cz_smu_init,
+	.smu_fini = cz_smu_fini,
+	.start_smu = cz_start_smu,
+	.check_fw_load_finish = cz_check_fw_load_finish,
+	.request_smu_load_fw = NULL,
+	.request_smu_load_specific_fw = NULL,
+	.get_argument = cz_smum_get_argument,
+	.send_msg_to_smc = cz_send_msg_to_smc,
+	.send_msg_to_smc_with_parameter = cz_send_msg_to_smc_with_parameter,
+	.download_pptable_settings = cz_download_pptable_settings,
+	.upload_pptable_settings = cz_upload_pptable_settings,
+};
+
+int cz_smum_init(struct pp_smumgr *smumgr)
+{
+	struct cz_smumgr *cz_smu;
+
+	cz_smu = kzalloc(sizeof(struct cz_smumgr), GFP_KERNEL);
+	if (cz_smu == NULL)
+		return -ENOMEM;
+
+	smumgr->backend = cz_smu;
+	smumgr->smumgr_funcs = &cz_smu_funcs;
+	return 0;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h
new file mode 100644
index 0000000..8838180
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _CZ_SMUMGR_H_
+#define _CZ_SMUMGR_H_
+
+
+#define MAX_NUM_FIRMWARE                        8
+#define MAX_NUM_SCRATCH                         11
+#define CZ_SCRATCH_SIZE_NONGFX_CLOCKGATING      1024
+#define CZ_SCRATCH_SIZE_NONGFX_GOLDENSETTING    2048
+#define CZ_SCRATCH_SIZE_SDMA_METADATA           1024
+#define CZ_SCRATCH_SIZE_IH                      ((2*256+1)*4)
+
+enum cz_scratch_entry {
+	CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0 = 0,
+	CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
+	CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE,
+	CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP,
+	CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME,
+	CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
+	CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
+	CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG,
+	CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G,
+	CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
+	CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
+	CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
+	CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM,
+	CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM,
+	CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
+	CZ_SCRATCH_ENTRY_DATA_ID_SDMA_HALT,
+	CZ_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING,
+	CZ_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS,
+	CZ_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT,
+	CZ_SCRATCH_ENTRY_DATA_ID_SDMA_START,
+	CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS,
+	CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE
+};
+
+struct cz_buffer_entry {
+	uint32_t data_size;
+	uint32_t mc_addr_low;
+	uint32_t mc_addr_high;
+	void *kaddr;
+	enum cz_scratch_entry firmware_ID;
+	unsigned long handle; /* as bo handle used when release bo */
+};
+
+struct cz_register_index_data_pair {
+	uint32_t offset;
+	uint32_t value;
+};
+
+struct cz_ih_meta_data {
+	uint32_t command;
+	struct cz_register_index_data_pair register_index_value_pair[1];
+};
+
+struct cz_smumgr {
+	uint8_t driver_buffer_length;
+	uint8_t scratch_buffer_length;
+	uint16_t toc_entry_used_count;
+	uint16_t toc_entry_initialize_index;
+	uint16_t toc_entry_power_profiling_index;
+	uint16_t toc_entry_aram;
+	uint16_t toc_entry_ih_register_restore_task_index;
+	uint16_t toc_entry_clock_table;
+	uint16_t ih_register_restore_task_size;
+	uint16_t smu_buffer_used_bytes;
+
+	struct cz_buffer_entry toc_buffer;
+	struct cz_buffer_entry smu_buffer;
+	struct cz_buffer_entry firmware_buffer;
+	struct cz_buffer_entry driver_buffer[MAX_NUM_FIRMWARE];
+	struct cz_buffer_entry meta_data_buffer[MAX_NUM_FIRMWARE];
+	struct cz_buffer_entry scratch_buffer[MAX_NUM_SCRATCH];
+};
+
+struct pp_smumgr;
+
+extern int cz_smum_init(struct pp_smumgr *smumgr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
new file mode 100644
index 0000000..cdbb9f8
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
@@ -0,0 +1,1042 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#include "smumgr.h"
+#include "smu73.h"
+#include "smu_ucode_xfer_vi.h"
+#include "fiji_smumgr.h"
+#include "fiji_ppsmc.h"
+#include "smu73_discrete.h"
+#include "ppatomctrl.h"
+#include "smu/smu_7_1_3_d.h"
+#include "smu/smu_7_1_3_sh_mask.h"
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+#include "oss/oss_3_0_d.h"
+#include "gca/gfx_8_0_d.h"
+#include "bif/bif_5_0_d.h"
+#include "bif/bif_5_0_sh_mask.h"
+#include "pp_debug.h"
+#include "fiji_pwrvirus.h"
+
+#define AVFS_EN_MSB                                        1568
+#define AVFS_EN_LSB                                        1568
+
+#define FIJI_SMC_SIZE 0x20000
+
+struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = {
+		/*  Min        Sclk       pcie     DeepSleep Activity  CgSpll      CgSpll    spllSpread  SpllSpread   CcPwr  CcPwr  Sclk   Display     Enabled     Enabled                       Voltage    Power */
+		/* Voltage,  Frequency,  DpmLevel,  DivId,    Level,  FuncCntl3,  FuncCntl4,  Spectrum,   Spectrum2,  DynRm, DynRm1  Did, Watermark, ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */
+		{ 0x3c0fd047, 0x30750000,   0x00,     0x03,   0x1e00, 0x00200410, 0x87020000, 0x21680000, 0x0c000000,   0,      0,   0x16,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
+		{ 0xa00fd047, 0x409c0000,   0x01,     0x04,   0x1e00, 0x00800510, 0x87020000, 0x21680000, 0x11000000,   0,      0,   0x16,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
+		{ 0x0410d047, 0x50c30000,   0x01,     0x00,   0x1e00, 0x00600410, 0x87020000, 0x21680000, 0x0d000000,   0,      0,   0x0e,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
+		{ 0x6810d047, 0x60ea0000,   0x01,     0x00,   0x1e00, 0x00800410, 0x87020000, 0x21680000, 0x0e000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
+		{ 0xcc10d047, 0xe8fd0000,   0x01,     0x00,   0x1e00, 0x00e00410, 0x87020000, 0x21680000, 0x0f000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
+		{ 0x3011d047, 0x70110100,   0x01,     0x00,   0x1e00, 0x00400510, 0x87020000, 0x21680000, 0x10000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
+		{ 0x9411d047, 0xf8240100,   0x01,     0x00,   0x1e00, 0x00a00510, 0x87020000, 0x21680000, 0x11000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
+		{ 0xf811d047, 0x80380100,   0x01,     0x00,   0x1e00, 0x00000610, 0x87020000, 0x21680000, 0x12000000,   0,      0,   0x0c,   0x01,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 }
+};
+
+static enum cgs_ucode_id fiji_convert_fw_type_to_cgs(uint32_t fw_type)
+{
+	enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
+
+	switch (fw_type) {
+	case UCODE_ID_SMU:
+		result = CGS_UCODE_ID_SMU;
+		break;
+	case UCODE_ID_SDMA0:
+		result = CGS_UCODE_ID_SDMA0;
+		break;
+	case UCODE_ID_SDMA1:
+		result = CGS_UCODE_ID_SDMA1;
+		break;
+	case UCODE_ID_CP_CE:
+		result = CGS_UCODE_ID_CP_CE;
+		break;
+	case UCODE_ID_CP_PFP:
+		result = CGS_UCODE_ID_CP_PFP;
+		break;
+	case UCODE_ID_CP_ME:
+		result = CGS_UCODE_ID_CP_ME;
+		break;
+	case UCODE_ID_CP_MEC:
+		result = CGS_UCODE_ID_CP_MEC;
+		break;
+	case UCODE_ID_CP_MEC_JT1:
+		result = CGS_UCODE_ID_CP_MEC_JT1;
+		break;
+	case UCODE_ID_CP_MEC_JT2:
+		result = CGS_UCODE_ID_CP_MEC_JT2;
+		break;
+	case UCODE_ID_RLC_G:
+		result = CGS_UCODE_ID_RLC_G;
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+/**
+* Set the address for reading/writing the SMC SRAM space.
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    smc_addr the address in the SMC RAM to access.
+*/
+static int fiji_set_smc_sram_address(struct pp_smumgr *smumgr,
+		uint32_t smc_addr, uint32_t limit)
+{
+	PP_ASSERT_WITH_CODE((0 == (3 & smc_addr)),
+			"SMC address must be 4 byte aligned.", return -EINVAL;);
+	PP_ASSERT_WITH_CODE((limit > (smc_addr + 3)),
+			"SMC address is beyond the SMC RAM area.", return -EINVAL;);
+
+	cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, smc_addr);
+	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0);
+
+	return 0;
+}
+
+/**
+* Copy bytes from an array into the SMC RAM space.
+*
+* @param    smumgr  the address of the powerplay SMU manager.
+* @param    smcStartAddress the start address in the SMC RAM to copy bytes to.
+* @param    src the byte array to copy the bytes from.
+* @param    byteCount the number of bytes to copy.
+*/
+int fiji_copy_bytes_to_smc(struct pp_smumgr *smumgr,
+		uint32_t smcStartAddress, const uint8_t *src,
+		uint32_t byteCount, uint32_t limit)
+{
+	int result;
+	uint32_t data, originalData;
+	uint32_t addr, extraShift;
+
+	PP_ASSERT_WITH_CODE((0 == (3 & smcStartAddress)),
+			"SMC address must be 4 byte aligned.", return -EINVAL;);
+	PP_ASSERT_WITH_CODE((limit > (smcStartAddress + byteCount)),
+			"SMC address is beyond the SMC RAM area.", return -EINVAL;);
+
+	addr = smcStartAddress;
+
+	while (byteCount >= 4) {
+		/* Bytes are written into the SMC addres space with the MSB first. */
+		data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3];
+
+		result = fiji_set_smc_sram_address(smumgr, addr, limit);
+		if (result)
+			return result;
+
+		cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data);
+
+		src += 4;
+		byteCount -= 4;
+		addr += 4;
+	}
+
+	if (byteCount) {
+		/* Now write the odd bytes left.
+		 * Do a read modify write cycle.
+		 */
+		data = 0;
+
+		result = fiji_set_smc_sram_address(smumgr, addr, limit);
+		if (result)
+			return result;
+
+		originalData = cgs_read_register(smumgr->device, mmSMC_IND_DATA_0);
+		extraShift = 8 * (4 - byteCount);
+
+		while (byteCount > 0) {
+			/* Bytes are written into the SMC addres
+			 * space with the MSB first.
+			 */
+			data = (0x100 * data) + *src++;
+			byteCount--;
+		}
+		data <<= extraShift;
+		data |= (originalData & ~((~0UL) << extraShift));
+
+		result = fiji_set_smc_sram_address(smumgr, addr, limit);
+		if (!result)
+			return result;
+
+		cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data);
+	}
+	return 0;
+}
+
+int fiji_program_jump_on_start(struct pp_smumgr *smumgr)
+{
+	static unsigned char data[] = { 0xE0, 0x00, 0x80, 0x40 };
+
+	fiji_copy_bytes_to_smc(smumgr, 0x0, data, 4, sizeof(data) + 1);
+
+	return 0;
+}
+
+/**
+* Return if the SMC is currently running.
+*
+* @param    smumgr  the address of the powerplay hardware manager.
+*/
+bool fiji_is_smc_ram_running(struct pp_smumgr *smumgr)
+{
+	return ((0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device,
+			CGS_IND_REG__SMC,
+			SMC_SYSCON_CLOCK_CNTL_0, ck_disable))
+			&& (0x20100 <= cgs_read_ind_register(smumgr->device,
+					CGS_IND_REG__SMC, ixSMC_PC_C)));
+}
+
+/**
+* Send a message to the SMC, and wait for its response.
+*
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    msg the message to send.
+* @return   The response that came from the SMC.
+*/
+int fiji_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
+{
+	if (!fiji_is_smc_ram_running(smumgr))
+		return -1;
+
+	if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) {
+		printk(KERN_ERR "Failed to send Previous Message.");
+		SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+	}
+
+	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+
+	return 0;
+}
+
+/**
+ * Send a message to the SMC with parameter
+ * @param    smumgr:  the address of the powerplay hardware manager.
+ * @param    msg: the message to send.
+ * @param    parameter: the parameter to send
+ * @return   The response that came from the SMC.
+ */
+int fiji_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
+		uint16_t msg, uint32_t parameter)
+{
+	if (!fiji_is_smc_ram_running(smumgr))
+		return -1;
+
+	if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) {
+		printk(KERN_ERR "Failed to send Previous Message.");
+		SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+	}
+
+	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter);
+	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+
+	return 0;
+}
+
+
+/**
+* Send a message to the SMC with parameter, do not wait for response
+*
+* @param    smumgr:  the address of the powerplay hardware manager.
+* @param    msg: the message to send.
+* @param    parameter: the parameter to send
+* @return   The response that came from the SMC.
+*/
+int fiji_send_msg_to_smc_with_parameter_without_waiting(
+		struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter)
+{
+	if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) {
+		printk(KERN_ERR "Failed to send Previous Message.");
+		SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+	}
+	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter);
+	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
+
+	return 0;
+}
+
+/**
+* Uploads the SMU firmware from .hex file
+*
+* @param    smumgr  the address of the powerplay SMU manager.
+* @return   0 or -1.
+*/
+
+static int fiji_upload_smu_firmware_image(struct pp_smumgr *smumgr)
+{
+	const uint8_t *src;
+	uint32_t byte_count;
+	uint32_t *data;
+	struct cgs_firmware_info info = {0};
+
+	cgs_get_firmware_info(smumgr->device,
+			fiji_convert_fw_type_to_cgs(UCODE_ID_SMU), &info);
+
+	if (info.image_size & 3) {
+		printk(KERN_ERR "SMC ucode is not 4 bytes aligned\n");
+		return -EINVAL;
+	}
+
+	if (info.image_size > FIJI_SMC_SIZE) {
+		printk(KERN_ERR "SMC address is beyond the SMC RAM area\n");
+		return -EINVAL;
+	}
+
+	cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, 0x20000);
+	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1);
+
+	byte_count = info.image_size;
+	src = (const uint8_t *)info.kptr;
+
+	data = (uint32_t *)src;
+	for (; byte_count >= 4; data++, byte_count -= 4)
+		cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data[0]);
+
+	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0);
+	return 0;
+}
+
+/**
+* Read a 32bit value from the SMC SRAM space.
+* ALL PARAMETERS ARE IN HOST BYTE ORDER.
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    smc_addr the address in the SMC RAM to access.
+* @param    value and output parameter for the data read from the SMC SRAM.
+*/
+int fiji_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr,
+		uint32_t *value, uint32_t limit)
+{
+	int	result = fiji_set_smc_sram_address(smumgr, smc_addr, limit);
+
+	if (result)
+		return result;
+
+	*value = cgs_read_register(smumgr->device, mmSMC_IND_DATA_0);
+	return 0;
+}
+
+/**
+* Write a 32bit value to the SMC SRAM space.
+* ALL PARAMETERS ARE IN HOST BYTE ORDER.
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    smc_addr the address in the SMC RAM to access.
+* @param    value to write to the SMC SRAM.
+*/
+int fiji_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr,
+		uint32_t value, uint32_t limit)
+{
+	int result;
+
+	result = fiji_set_smc_sram_address(smumgr, smc_addr, limit);
+
+	if (result)
+		return result;
+
+	cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, value);
+	return 0;
+}
+
+static uint32_t fiji_get_mask_for_firmware_type(uint32_t fw_type)
+{
+	uint32_t result = 0;
+
+	switch (fw_type) {
+	case UCODE_ID_SDMA0:
+		result = UCODE_ID_SDMA0_MASK;
+		break;
+	case UCODE_ID_SDMA1:
+		result = UCODE_ID_SDMA1_MASK;
+		break;
+	case UCODE_ID_CP_CE:
+		result = UCODE_ID_CP_CE_MASK;
+		break;
+	case UCODE_ID_CP_PFP:
+		result = UCODE_ID_CP_PFP_MASK;
+		break;
+	case UCODE_ID_CP_ME:
+		result = UCODE_ID_CP_ME_MASK;
+		break;
+	case UCODE_ID_CP_MEC_JT1:
+		result = UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK;
+		break;
+	case UCODE_ID_CP_MEC_JT2:
+		result = UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT2_MASK;
+		break;
+	case UCODE_ID_RLC_G:
+		result = UCODE_ID_RLC_G_MASK;
+		break;
+	default:
+		printk(KERN_ERR "UCode type is out of range!");
+		result = 0;
+	}
+
+	return result;
+}
+
+/* Populate one firmware image to the data structure */
+static int fiji_populate_single_firmware_entry(struct pp_smumgr *smumgr,
+		uint32_t fw_type, struct SMU_Entry *entry)
+{
+	int result;
+	struct cgs_firmware_info info = {0};
+
+	result = cgs_get_firmware_info(
+			smumgr->device,
+			fiji_convert_fw_type_to_cgs(fw_type),
+			&info);
+
+	if (!result) {
+		entry->version = 0;
+		entry->id = (uint16_t)fw_type;
+		entry->image_addr_high = smu_upper_32_bits(info.mc_addr);
+		entry->image_addr_low = smu_lower_32_bits(info.mc_addr);
+		entry->meta_data_addr_high = 0;
+		entry->meta_data_addr_low = 0;
+		entry->data_size_byte = info.image_size;
+		entry->num_register_entries = 0;
+
+		if (fw_type == UCODE_ID_RLC_G)
+			entry->flags = 1;
+		else
+			entry->flags = 0;
+	}
+
+	return result;
+}
+
+static int fiji_request_smu_load_fw(struct pp_smumgr *smumgr)
+{
+	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+	uint32_t fw_to_load;
+	struct SMU_DRAMData_TOC *toc;
+
+	if (priv->soft_regs_start)
+		cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
+				priv->soft_regs_start +
+				offsetof(SMU73_SoftRegisters, UcodeLoadStatus),
+				0x0);
+
+	toc = (struct SMU_DRAMData_TOC *)priv->header;
+	toc->num_entries = 0;
+	toc->structure_version = 1;
+
+	PP_ASSERT_WITH_CODE(
+			0 == fiji_populate_single_firmware_entry(smumgr,
+					UCODE_ID_RLC_G, &toc->entry[toc->num_entries++]),
+			"Failed to Get Firmware Entry.\n" , return -1 );
+	PP_ASSERT_WITH_CODE(
+			0 == fiji_populate_single_firmware_entry(smumgr,
+					UCODE_ID_CP_CE, &toc->entry[toc->num_entries++]),
+			"Failed to Get Firmware Entry.\n" , return -1 );
+	PP_ASSERT_WITH_CODE(
+			0 == fiji_populate_single_firmware_entry(smumgr,
+					UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]),
+			"Failed to Get Firmware Entry.\n" , return -1 );
+	PP_ASSERT_WITH_CODE(
+			0 == fiji_populate_single_firmware_entry(smumgr,
+					UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]),
+			"Failed to Get Firmware Entry.\n" , return -1 );
+	PP_ASSERT_WITH_CODE(
+			0 == fiji_populate_single_firmware_entry(smumgr,
+					UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]),
+			"Failed to Get Firmware Entry.\n" , return -1 );
+	PP_ASSERT_WITH_CODE(
+			0 == fiji_populate_single_firmware_entry(smumgr,
+					UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]),
+					"Failed to Get Firmware Entry.\n" , return -1 );
+	PP_ASSERT_WITH_CODE(
+			0 == fiji_populate_single_firmware_entry(smumgr,
+					UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]),
+					"Failed to Get Firmware Entry.\n" , return -1 );
+	PP_ASSERT_WITH_CODE(
+			0 == fiji_populate_single_firmware_entry(smumgr,
+					UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]),
+					"Failed to Get Firmware Entry.\n" , return -1 );
+	PP_ASSERT_WITH_CODE(
+			0 == fiji_populate_single_firmware_entry(smumgr,
+					UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]),
+					"Failed to Get Firmware Entry.\n" , return -1 );
+
+	fiji_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_HI,
+			priv->header_buffer.mc_addr_high);
+	fiji_send_msg_to_smc_with_parameter(smumgr,PPSMC_MSG_DRV_DRAM_ADDR_LO,
+			priv->header_buffer.mc_addr_low);
+
+	fw_to_load = UCODE_ID_RLC_G_MASK
+			+ UCODE_ID_SDMA0_MASK
+			+ UCODE_ID_SDMA1_MASK
+			+ UCODE_ID_CP_CE_MASK
+			+ UCODE_ID_CP_ME_MASK
+			+ UCODE_ID_CP_PFP_MASK
+			+ UCODE_ID_CP_MEC_MASK
+			+ UCODE_ID_CP_MEC_JT1_MASK
+			+ UCODE_ID_CP_MEC_JT2_MASK;
+
+	if (fiji_send_msg_to_smc_with_parameter(smumgr,
+			PPSMC_MSG_LoadUcodes, fw_to_load))
+		printk(KERN_ERR "Fail to Request SMU Load uCode");
+
+	return 0;
+}
+
+
+/* Check if the FW has been loaded, SMU will not return
+ * if loading has not finished.
+ */
+static int fiji_check_fw_load_finish(struct pp_smumgr *smumgr,
+		uint32_t fw_type)
+{
+	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+	uint32_t mask = fiji_get_mask_for_firmware_type(fw_type);
+
+	/* Check SOFT_REGISTERS_TABLE_28.UcodeLoadStatus */
+	if (smum_wait_on_indirect_register(smumgr, mmSMC_IND_INDEX,
+			priv->soft_regs_start +
+			offsetof(SMU73_SoftRegisters, UcodeLoadStatus),
+			mask, mask)) {
+		printk(KERN_ERR "check firmware loading failed\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+static int fiji_reload_firmware(struct pp_smumgr *smumgr)
+{
+	return smumgr->smumgr_funcs->start_smu(smumgr);
+}
+
+static bool fiji_is_hw_virtualization_enabled(struct pp_smumgr *smumgr)
+{
+	uint32_t value;
+
+	value = cgs_read_register(smumgr->device, mmBIF_IOV_FUNC_IDENTIFIER);
+	if (value & BIF_IOV_FUNC_IDENTIFIER__IOV_ENABLE_MASK) {
+		/* driver reads on SR-IOV enabled PF: 0x80000000
+		 * driver reads on SR-IOV enabled VF: 0x80000001
+		 * driver reads on SR-IOV disabled:   0x00000000
+		 */
+		return true;
+	}
+	return false;
+}
+
+static int fiji_request_smu_specific_fw_load(struct pp_smumgr *smumgr, uint32_t fw_type)
+{
+	if (fiji_is_hw_virtualization_enabled(smumgr)) {
+		uint32_t masks = fiji_get_mask_for_firmware_type(fw_type);
+		if (fiji_send_msg_to_smc_with_parameter_without_waiting(smumgr,
+				PPSMC_MSG_LoadUcodes, masks))
+			printk(KERN_ERR "Fail to Request SMU Load uCode");
+	}
+	/* For non-virtualization cases,
+	 * SMU loads all FWs at once in fiji_request_smu_load_fw.
+	 */
+	return 0;
+}
+
+static int fiji_start_smu_in_protection_mode(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+
+	/* Wait for smc boot up */
+	/* SMUM_WAIT_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND,
+		RCU_UC_EVENTS, boot_seq_done, 0); */
+
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+			SMC_SYSCON_RESET_CNTL, rst_reg, 1);
+
+	result = fiji_upload_smu_firmware_image(smumgr);
+	if (result)
+		return result;
+
+	/* Clear status */
+	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
+			ixSMU_STATUS, 0);
+
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+			SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
+
+	/* De-assert reset */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+			SMC_SYSCON_RESET_CNTL, rst_reg, 0);
+
+	/* Wait for ROM firmware to initialize interrupt hendler */
+	/*SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, SMC_IND,
+			SMC_INTR_CNTL_MASK_0, 0x10040, 0xFFFFFFFF); */
+
+	/* Set SMU Auto Start */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+			SMU_INPUT_DATA, AUTO_START, 1);
+
+	/* Clear firmware interrupt enable flag */
+	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
+			ixFIRMWARE_FLAGS, 0);
+
+	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, RCU_UC_EVENTS,
+			INTERRUPTS_ENABLED, 1);
+
+	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, 0x20000);
+	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test);
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+
+	/* Wait for done bit to be set */
+	SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND,
+			SMU_STATUS, SMU_DONE, 0);
+
+	/* Check pass/failed indicator */
+	if (1 != SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+			SMU_STATUS, SMU_PASS)) {
+		PP_ASSERT_WITH_CODE(false,
+				"SMU Firmware start failed!", return -1);
+	}
+
+	/* Wait for firmware to initialize */
+	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND,
+			FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
+
+	return result;
+}
+
+static int fiji_start_smu_in_non_protection_mode(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+
+	/* wait for smc boot up */
+	SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND,
+			RCU_UC_EVENTS, boot_seq_done, 0);
+
+	/* Clear firmware interrupt enable flag */
+	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
+			ixFIRMWARE_FLAGS, 0);
+
+	/* Assert reset */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+			SMC_SYSCON_RESET_CNTL, rst_reg, 1);
+
+	result = fiji_upload_smu_firmware_image(smumgr);
+	if (result)
+		return result;
+
+	/* Set smc instruct start point at 0x0 */
+	fiji_program_jump_on_start(smumgr);
+
+	/* Enable clock */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+			SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
+
+	/* De-assert reset */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+			SMC_SYSCON_RESET_CNTL, rst_reg, 0);
+
+	/* Wait for firmware to initialize */
+	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND,
+			FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
+
+	return result;
+}
+
+int fiji_setup_pwr_virus(struct pp_smumgr *smumgr)
+{
+	int i, result = -1;
+	uint32_t reg, data;
+	PWR_Command_Table *virus = PwrVirusTable;
+	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+
+	priv->avfs.AvfsBtcStatus = AVFS_LOAD_VIRUS;
+	for (i = 0; (i < PWR_VIRUS_TABLE_SIZE); i++) {
+		switch (virus->command) {
+		case PwrCmdWrite:
+			reg  = virus->reg;
+			data = virus->data;
+			cgs_write_register(smumgr->device, reg, data);
+			break;
+		case PwrCmdEnd:
+			priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_LOADED;
+			result = 0;
+			break;
+		default:
+			printk(KERN_ERR "Table Exit with Invalid Command!");
+			priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_FAIL;
+			result = -1;
+			break;
+		}
+		virus++;
+	}
+	return result;
+}
+
+static int fiji_start_avfs_btc(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+
+	priv->avfs.AvfsBtcStatus = AVFS_BTC_STARTED;
+	if (priv->avfs.AvfsBtcParam) {
+		if (!fiji_send_msg_to_smc_with_parameter(smumgr,
+				PPSMC_MSG_PerformBtc, priv->avfs.AvfsBtcParam)) {
+			if (!fiji_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs)) {
+				priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_UNSAVED;
+				result = 0;
+			} else {
+				printk(KERN_ERR "[AVFS][fiji_start_avfs_btc] Attempt"
+						" to Enable AVFS Failed!");
+				fiji_send_msg_to_smc(smumgr, PPSMC_MSG_DisableAvfs);
+				result = -1;
+			}
+		} else {
+			printk(KERN_ERR "[AVFS][fiji_start_avfs_btc] "
+					"PerformBTC SMU msg failed");
+			result = -1;
+		}
+	}
+	/* Soft-Reset to reset the engine before loading uCode */
+	 /* halt */
+	cgs_write_register(smumgr->device, mmCP_MEC_CNTL, 0x50000000);
+	/* reset everything */
+	cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0xffffffff);
+	/* clear reset */
+	cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0);
+
+	return result;
+}
+
+int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+	uint32_t table_start;
+	uint32_t charz_freq_addr, inversion_voltage_addr, charz_freq;
+	uint16_t inversion_voltage;
+
+	charz_freq = 0x30750000; /* In 10KHz units 0x00007530 Actual value */
+	inversion_voltage = 0x1A04; /* mV Q14.2 0x41A Actual value */
+
+	PP_ASSERT_WITH_CODE(0 == fiji_read_smc_sram_dword(smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header,
+					PmFuseTable), &table_start, 0x40000),
+			"[AVFS][Fiji_SetupGfxLvlStruct] SMU could not communicate "
+			"starting address of PmFuse structure",
+			return -1;);
+
+	charz_freq_addr = table_start +
+			offsetof(struct SMU73_Discrete_PmFuses, PsmCharzFreq);
+	inversion_voltage_addr = table_start +
+			offsetof(struct SMU73_Discrete_PmFuses, InversionVoltage);
+
+	result = fiji_copy_bytes_to_smc(smumgr, charz_freq_addr,
+			(uint8_t *)(&charz_freq), sizeof(charz_freq), 0x40000);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"[AVFS][fiji_setup_pm_fuse_for_avfs] charz_freq could not "
+			"be populated.", return -1;);
+
+	result = fiji_copy_bytes_to_smc(smumgr, inversion_voltage_addr,
+			(uint8_t *)(&inversion_voltage), sizeof(inversion_voltage), 0x40000);
+	PP_ASSERT_WITH_CODE(0 == result, "[AVFS][fiji_setup_pm_fuse_for_avfs] "
+			"charz_freq could not be populated.", return -1;);
+
+	return result;
+}
+
+int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr)
+{
+	int32_t vr_config;
+	uint32_t table_start;
+	uint32_t level_addr, vr_config_addr;
+	uint32_t level_size = sizeof(avfs_graphics_level);
+
+	PP_ASSERT_WITH_CODE(0 == fiji_read_smc_sram_dword(smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU73_Firmware_Header, DpmTable),
+			&table_start, 0x40000),
+			"[AVFS][Fiji_SetupGfxLvlStruct] SMU could not "
+			"communicate starting address of DPM table",
+			return -1;);
+
+	/* Default value for vr_config =
+	 * VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */
+	vr_config = 0x01000500;   /* Real value:0x50001 */
+
+	vr_config_addr = table_start +
+			offsetof(SMU73_Discrete_DpmTable, VRConfig);
+
+	PP_ASSERT_WITH_CODE(0 == fiji_copy_bytes_to_smc(smumgr, vr_config_addr,
+			(uint8_t *)&vr_config, sizeof(int32_t), 0x40000),
+			"[AVFS][Fiji_SetupGfxLvlStruct] Problems copying "
+			"vr_config value over to SMC",
+			return -1;);
+
+	level_addr = table_start + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel);
+
+	PP_ASSERT_WITH_CODE(0 == fiji_copy_bytes_to_smc(smumgr, level_addr,
+			(uint8_t *)(&avfs_graphics_level), level_size, 0x40000),
+			"[AVFS][Fiji_SetupGfxLvlStruct] Copying of DPM table failed!",
+			return -1;);
+
+	return 0;
+}
+
+/* Work in Progress */
+int fiji_restore_vft_table(struct pp_smumgr *smumgr)
+{
+	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+
+	if (AVFS_BTC_COMPLETED_SAVED == priv->avfs.AvfsBtcStatus) {
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED;
+		return 0;
+	} else
+		return -EINVAL;
+}
+
+/* Work in Progress */
+int fiji_save_vft_table(struct pp_smumgr *smumgr)
+{
+	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+
+	if (AVFS_BTC_COMPLETED_SAVED == priv->avfs.AvfsBtcStatus) {
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED;
+		return 0;
+	} else
+		return -EINVAL;
+}
+
+int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started)
+{
+	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+
+	switch (priv->avfs.AvfsBtcStatus) {
+	case AVFS_BTC_COMPLETED_SAVED: /*S3 State - Pre SMU Start */
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_RESTOREVFT_FAILED;
+		PP_ASSERT_WITH_CODE(0 == fiji_restore_vft_table(smumgr),
+				"[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics "
+				"Level table over to SMU",
+				return -1;);
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED;
+		break;
+	case AVFS_BTC_COMPLETED_RESTORED: /*S3 State - Post SMU Start*/
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_SMUMSG_ERROR;
+		PP_ASSERT_WITH_CODE(0 == fiji_send_msg_to_smc(smumgr,
+				PPSMC_MSG_VftTableIsValid),
+				"[AVFS][fiji_avfs_event_mgr] SMU did not respond "
+				"correctly to VftTableIsValid Msg",
+				return -1;);
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_SMUMSG_ERROR;
+		PP_ASSERT_WITH_CODE(0 == fiji_send_msg_to_smc(smumgr,
+				PPSMC_MSG_EnableAvfs),
+				"[AVFS][fiji_avfs_event_mgr] SMU did not respond "
+				"correctly to EnableAvfs Message Msg",
+				return -1;);
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_SAVED;
+		break;
+	case AVFS_BTC_BOOT: /*Cold Boot State - Post SMU Start*/
+		if (!smu_started)
+			break;
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_FAILED;
+		PP_ASSERT_WITH_CODE(0 == fiji_setup_pm_fuse_for_avfs(smumgr),
+				"[AVFS][fiji_avfs_event_mgr] Failure at "
+				"fiji_setup_pm_fuse_for_avfs",
+				return -1;);
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_DPMTABLESETUP_FAILED;
+		PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(smumgr),
+				"[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level"
+				" table over to SMU",
+				return -1;);
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_FAIL;
+		PP_ASSERT_WITH_CODE(0 == fiji_setup_pwr_virus(smumgr),
+				"[AVFS][fiji_avfs_event_mgr] Could not setup "
+				"Pwr Virus for AVFS ",
+				return -1;);
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_FAILED;
+		PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(smumgr),
+				"[AVFS][fiji_avfs_event_mgr] Failure at "
+				"fiji_start_avfs_btc. AVFS Disabled",
+				return -1;);
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_SAVEVFT_FAILED;
+		PP_ASSERT_WITH_CODE(0 == fiji_save_vft_table(smumgr),
+				"[AVFS][fiji_avfs_event_mgr] Could not save VFT Table",
+				return -1;);
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_SAVED;
+		break;
+	case AVFS_BTC_DISABLED: /* Do nothing */
+		break;
+	case AVFS_BTC_NOTSUPPORTED: /* Do nothing */
+		break;
+	default:
+		printk(KERN_ERR "[AVFS] Something is broken. See log!");
+		break;
+	}
+	return 0;
+}
+
+static int fiji_start_smu(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+
+	/* Only start SMC if SMC RAM is not running */
+	if (!fiji_is_smc_ram_running(smumgr)) {
+		fiji_avfs_event_mgr(smumgr, false);
+
+		/* Check if SMU is running in protected mode */
+		if (0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device,
+				CGS_IND_REG__SMC,
+				SMU_FIRMWARE, SMU_MODE)) {
+			result = fiji_start_smu_in_non_protection_mode(smumgr);
+			if (result)
+				return result;
+		} else {
+			result = fiji_start_smu_in_protection_mode(smumgr);
+			if (result)
+				return result;
+		}
+		fiji_avfs_event_mgr(smumgr, true);
+	}
+
+	/* To initialize all clock gating before RLC loaded and running.*/
+	cgs_set_clockgating_state(smumgr->device,
+			AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_GATE);
+	cgs_set_clockgating_state(smumgr->device,
+			AMD_IP_BLOCK_TYPE_GMC, AMD_CG_STATE_GATE);
+	cgs_set_clockgating_state(smumgr->device,
+			AMD_IP_BLOCK_TYPE_SDMA, AMD_CG_STATE_GATE);
+	cgs_set_clockgating_state(smumgr->device,
+			AMD_IP_BLOCK_TYPE_COMMON, AMD_CG_STATE_GATE);
+
+	/* Setup SoftRegsStart here for register lookup in case
+	 * DummyBackEnd is used and ProcessFirmwareHeader is not executed
+	 */
+	fiji_read_smc_sram_dword(smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU73_Firmware_Header, SoftRegisters),
+			&(priv->soft_regs_start), 0x40000);
+
+	result = fiji_request_smu_load_fw(smumgr);
+
+	return result;
+}
+
+static bool fiji_is_hw_avfs_present(struct pp_smumgr *smumgr)
+{
+
+	uint32_t efuse = 0;
+	uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1;
+
+	if (!atomctrl_read_efuse(smumgr->device, AVFS_EN_LSB, AVFS_EN_MSB,
+			mask, &efuse)) {
+		if (efuse)
+			return true;
+	}
+	return false;
+}
+
+/**
+* Write a 32bit value to the SMC SRAM space.
+* ALL PARAMETERS ARE IN HOST BYTE ORDER.
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    smc_addr the address in the SMC RAM to access.
+* @param    value to write to the SMC SRAM.
+*/
+static int fiji_smu_init(struct pp_smumgr *smumgr)
+{
+	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+	uint64_t mc_addr;
+
+	priv->header_buffer.data_size =
+			((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096;
+	smu_allocate_memory(smumgr->device,
+			priv->header_buffer.data_size,
+			CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
+			PAGE_SIZE,
+			&mc_addr,
+			&priv->header_buffer.kaddr,
+			&priv->header_buffer.handle);
+
+	priv->header = priv->header_buffer.kaddr;
+	priv->header_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
+	priv->header_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
+
+	PP_ASSERT_WITH_CODE((NULL != priv->header),
+			"Out of memory.",
+			kfree(smumgr->backend);
+			cgs_free_gpu_mem(smumgr->device,
+			(cgs_handle_t)priv->header_buffer.handle);
+			return -1);
+
+	priv->avfs.AvfsBtcStatus = AVFS_BTC_BOOT;
+	if (fiji_is_hw_avfs_present(smumgr))
+		/* AVFS Parameter
+		 * 0 - BTC DC disabled, BTC AC disabled
+		 * 1 - BTC DC enabled,  BTC AC disabled
+		 * 2 - BTC DC disabled, BTC AC enabled
+		 * 3 - BTC DC enabled,  BTC AC enabled
+		 * Default is 0 - BTC DC disabled, BTC AC disabled
+		 */
+		priv->avfs.AvfsBtcParam = 0;
+	else
+		priv->avfs.AvfsBtcStatus = AVFS_BTC_NOTSUPPORTED;
+
+	priv->acpi_optimization = 1;
+
+	return 0;
+}
+
+static int fiji_smu_fini(struct pp_smumgr *smumgr)
+{
+	if (smumgr->backend) {
+		kfree(smumgr->backend);
+		smumgr->backend = NULL;
+	}
+	return 0;
+}
+
+static const struct pp_smumgr_func fiji_smu_funcs = {
+	.smu_init = &fiji_smu_init,
+	.smu_fini = &fiji_smu_fini,
+	.start_smu = &fiji_start_smu,
+	.check_fw_load_finish = &fiji_check_fw_load_finish,
+	.request_smu_load_fw = &fiji_reload_firmware,
+	.request_smu_load_specific_fw = &fiji_request_smu_specific_fw_load,
+	.send_msg_to_smc = &fiji_send_msg_to_smc,
+	.send_msg_to_smc_with_parameter = &fiji_send_msg_to_smc_with_parameter,
+	.download_pptable_settings = NULL,
+	.upload_pptable_settings = NULL,
+};
+
+int fiji_smum_init(struct pp_smumgr *smumgr)
+{
+	struct fiji_smumgr *fiji_smu = NULL;
+
+	fiji_smu = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL);
+
+	if (fiji_smu == NULL)
+		return -ENOMEM;
+
+	smumgr->backend = fiji_smu;
+	smumgr->smumgr_funcs = &fiji_smu_funcs;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h
new file mode 100644
index 0000000..8cd22d9
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#ifndef _FIJI_SMUMANAGER_H_
+#define _FIJI_SMUMANAGER_H_
+
+enum AVFS_BTC_STATUS {
+	AVFS_BTC_BOOT = 0,
+	AVFS_BTC_BOOT_STARTEDSMU,
+	AVFS_LOAD_VIRUS,
+	AVFS_BTC_VIRUS_LOADED,
+	AVFS_BTC_VIRUS_FAIL,
+	AVFS_BTC_STARTED,
+	AVFS_BTC_FAILED,
+	AVFS_BTC_RESTOREVFT_FAILED,
+	AVFS_BTC_SAVEVFT_FAILED,
+	AVFS_BTC_DPMTABLESETUP_FAILED,
+	AVFS_BTC_COMPLETED_UNSAVED,
+	AVFS_BTC_COMPLETED_SAVED,
+	AVFS_BTC_COMPLETED_RESTORED,
+	AVFS_BTC_DISABLED,
+	AVFS_BTC_NOTSUPPORTED,
+	AVFS_BTC_SMUMSG_ERROR
+};
+
+struct fiji_smu_avfs {
+	enum AVFS_BTC_STATUS AvfsBtcStatus;
+	uint32_t           AvfsBtcParam;
+};
+
+struct fiji_buffer_entry {
+	uint32_t data_size;
+	uint32_t mc_addr_low;
+	uint32_t mc_addr_high;
+	void *kaddr;
+	unsigned long  handle;
+};
+
+struct fiji_smumgr {
+	uint8_t        *header;
+	uint8_t        *mec_image;
+	uint32_t        soft_regs_start;
+	struct fiji_smu_avfs avfs;
+	uint32_t        acpi_optimization;
+
+	struct fiji_buffer_entry header_buffer;
+};
+
+int fiji_smum_init(struct pp_smumgr *smumgr);
+int fiji_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smcAddress,
+		uint32_t *value, uint32_t limit);
+int fiji_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr,
+		uint32_t value, uint32_t limit);
+int fiji_copy_bytes_to_smc(struct pp_smumgr *smumgr, uint32_t smcStartAddress,
+		const uint8_t *src,	uint32_t byteCount, uint32_t limit);
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
new file mode 100644
index 0000000..063ae71
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include "pp_instance.h"
+#include "smumgr.h"
+#include "cgs_common.h"
+#include "linux/delay.h"
+#include "cz_smumgr.h"
+#include "tonga_smumgr.h"
+#include "fiji_smumgr.h"
+
+int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
+{
+	struct pp_smumgr *smumgr;
+
+	if ((handle == NULL) || (pp_init == NULL))
+		return -EINVAL;
+
+	smumgr = kzalloc(sizeof(struct pp_smumgr), GFP_KERNEL);
+	if (smumgr == NULL)
+		return -ENOMEM;
+
+	smumgr->device = pp_init->device;
+	smumgr->chip_family = pp_init->chip_family;
+	smumgr->chip_id = pp_init->chip_id;
+	smumgr->hw_revision = pp_init->rev_id;
+	smumgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
+	smumgr->reload_fw = 1;
+	handle->smu_mgr = smumgr;
+
+	switch (smumgr->chip_family) {
+	case AMD_FAMILY_CZ:
+		cz_smum_init(smumgr);
+		break;
+	case AMD_FAMILY_VI:
+		switch (smumgr->chip_id) {
+		case CHIP_TONGA:
+			tonga_smum_init(smumgr);
+			break;
+		case CHIP_FIJI:
+			fiji_smum_init(smumgr);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		kfree(smumgr);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int smum_fini(struct pp_smumgr *smumgr)
+{
+	kfree(smumgr);
+	return 0;
+}
+
+int smum_get_argument(struct pp_smumgr *smumgr)
+{
+	if (NULL != smumgr->smumgr_funcs->get_argument)
+		return smumgr->smumgr_funcs->get_argument(smumgr);
+
+	return 0;
+}
+
+int smum_download_powerplay_table(struct pp_smumgr *smumgr,
+								void **table)
+{
+	if (NULL != smumgr->smumgr_funcs->download_pptable_settings)
+		return smumgr->smumgr_funcs->download_pptable_settings(smumgr,
+									table);
+
+	return 0;
+}
+
+int smum_upload_powerplay_table(struct pp_smumgr *smumgr)
+{
+	if (NULL != smumgr->smumgr_funcs->upload_pptable_settings)
+		return smumgr->smumgr_funcs->upload_pptable_settings(smumgr);
+
+	return 0;
+}
+
+int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
+{
+	if (smumgr == NULL || smumgr->smumgr_funcs->send_msg_to_smc == NULL)
+		return -EINVAL;
+
+	return smumgr->smumgr_funcs->send_msg_to_smc(smumgr, msg);
+}
+
+int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
+					uint16_t msg, uint32_t parameter)
+{
+	if (smumgr == NULL ||
+		smumgr->smumgr_funcs->send_msg_to_smc_with_parameter == NULL)
+		return -EINVAL;
+	return smumgr->smumgr_funcs->send_msg_to_smc_with_parameter(
+						smumgr, msg, parameter);
+}
+
+/*
+ * Returns once the part of the register indicated by the mask has
+ * reached the given value.
+ */
+int smum_wait_on_register(struct pp_smumgr *smumgr,
+				uint32_t index,
+				uint32_t value, uint32_t mask)
+{
+	uint32_t i;
+	uint32_t cur_value;
+
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	for (i = 0; i < smumgr->usec_timeout; i++) {
+		cur_value = cgs_read_register(smumgr->device, index);
+		if ((cur_value & mask) == (value & mask))
+			break;
+		udelay(1);
+	}
+
+	/* timeout means wrong logic*/
+	if (i == smumgr->usec_timeout)
+		return -1;
+
+	return 0;
+}
+
+int smum_wait_for_register_unequal(struct pp_smumgr *smumgr,
+					uint32_t index,
+					uint32_t value, uint32_t mask)
+{
+	uint32_t i;
+	uint32_t cur_value;
+
+	if (smumgr == NULL)
+		return -EINVAL;
+
+	for (i = 0; i < smumgr->usec_timeout; i++) {
+		cur_value = cgs_read_register(smumgr->device,
+									index);
+		if ((cur_value & mask) != (value & mask))
+			break;
+		udelay(1);
+	}
+
+	/* timeout means wrong logic */
+	if (i == smumgr->usec_timeout)
+		return -1;
+
+	return 0;
+}
+
+
+/*
+ * Returns once the part of the register indicated by the mask
+ * has reached the given value.The indirect space is described by
+ * giving the memory-mapped index of the indirect index register.
+ */
+int smum_wait_on_indirect_register(struct pp_smumgr *smumgr,
+					uint32_t indirect_port,
+					uint32_t index,
+					uint32_t value,
+					uint32_t mask)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	cgs_write_register(smumgr->device, indirect_port, index);
+	return smum_wait_on_register(smumgr, indirect_port + 1,
+						mask, value);
+}
+
+void smum_wait_for_indirect_register_unequal(
+						struct pp_smumgr *smumgr,
+						uint32_t indirect_port,
+						uint32_t index,
+						uint32_t value,
+						uint32_t mask)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return;
+	cgs_write_register(smumgr->device, indirect_port, index);
+	smum_wait_for_register_unequal(smumgr, indirect_port + 1,
+						value, mask);
+}
+
+int smu_allocate_memory(void *device, uint32_t size,
+			 enum cgs_gpu_mem_type type,
+			 uint32_t byte_align, uint64_t *mc_addr,
+			 void **kptr, void *handle)
+{
+	int ret = 0;
+	cgs_handle_t cgs_handle;
+
+	if (device == NULL || handle == NULL ||
+	    mc_addr == NULL || kptr == NULL)
+		return -EINVAL;
+
+	ret = cgs_alloc_gpu_mem(device, type, size, byte_align,
+				0, 0, (cgs_handle_t *)handle);
+	if (ret)
+		return -ENOMEM;
+
+	cgs_handle = *(cgs_handle_t *)handle;
+
+	ret = cgs_gmap_gpu_mem(device, cgs_handle, mc_addr);
+	if (ret)
+		goto error_gmap;
+
+	ret = cgs_kmap_gpu_mem(device, cgs_handle, kptr);
+	if (ret)
+		goto error_kmap;
+
+	return 0;
+
+error_kmap:
+	cgs_gunmap_gpu_mem(device, cgs_handle);
+
+error_gmap:
+	cgs_free_gpu_mem(device, cgs_handle);
+	return ret;
+}
+
+int smu_free_memory(void *device, void *handle)
+{
+	cgs_handle_t cgs_handle = (cgs_handle_t)handle;
+
+	if (device == NULL || handle == NULL)
+		return -EINVAL;
+
+	cgs_kunmap_gpu_mem(device, cgs_handle);
+	cgs_gunmap_gpu_mem(device, cgs_handle);
+	cgs_free_gpu_mem(device, cgs_handle);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
new file mode 100644
index 0000000..ebdb43a
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
@@ -0,0 +1,819 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/gfp.h>
+
+#include "smumgr.h"
+#include "tonga_smumgr.h"
+#include "pp_debug.h"
+#include "smu_ucode_xfer_vi.h"
+#include "tonga_ppsmc.h"
+#include "smu/smu_7_1_2_d.h"
+#include "smu/smu_7_1_2_sh_mask.h"
+#include "cgs_common.h"
+
+#define TONGA_SMC_SIZE			0x20000
+#define BUFFER_SIZE			80000
+#define MAX_STRING_SIZE			15
+#define BUFFER_SIZETWO              131072 /*128 *1024*/
+
+/**
+* Set the address for reading/writing the SMC SRAM space.
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    smcAddress the address in the SMC RAM to access.
+*/
+static int tonga_set_smc_sram_address(struct pp_smumgr *smumgr,
+				uint32_t smcAddress, uint32_t limit)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+	PP_ASSERT_WITH_CODE((0 == (3 & smcAddress)),
+		"SMC address must be 4 byte aligned.",
+		return -1;);
+
+	PP_ASSERT_WITH_CODE((limit > (smcAddress + 3)),
+		"SMC address is beyond the SMC RAM area.",
+		return -1;);
+
+	cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, smcAddress);
+	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0);
+
+	return 0;
+}
+
+/**
+* Copy bytes from an array into the SMC RAM space.
+*
+* @param    smumgr  the address of the powerplay SMU manager.
+* @param    smcStartAddress the start address in the SMC RAM to copy bytes to.
+* @param    src the byte array to copy the bytes from.
+* @param    byteCount the number of bytes to copy.
+*/
+int tonga_copy_bytes_to_smc(struct pp_smumgr *smumgr,
+		uint32_t smcStartAddress, const uint8_t *src,
+		uint32_t byteCount, uint32_t limit)
+{
+	uint32_t addr;
+	uint32_t data, orig_data;
+	int result = 0;
+	uint32_t extra_shift;
+
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+	PP_ASSERT_WITH_CODE((0 == (3 & smcStartAddress)),
+		"SMC address must be 4 byte aligned.",
+		return 0;);
+
+	PP_ASSERT_WITH_CODE((limit > (smcStartAddress + byteCount)),
+		"SMC address is beyond the SMC RAM area.",
+		return 0;);
+
+	addr = smcStartAddress;
+
+	while (byteCount >= 4) {
+		/*
+		 * Bytes are written into the
+		 * SMC address space with the MSB first
+		 */
+		data = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3];
+
+		result = tonga_set_smc_sram_address(smumgr, addr, limit);
+
+		if (result)
+			goto out;
+
+		cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data);
+
+		src += 4;
+		byteCount -= 4;
+		addr += 4;
+	}
+
+	if (0 != byteCount) {
+		/* Now write odd bytes left, do a read modify write cycle */
+		data = 0;
+
+		result = tonga_set_smc_sram_address(smumgr, addr, limit);
+		if (result)
+			goto out;
+
+		orig_data = cgs_read_register(smumgr->device,
+							mmSMC_IND_DATA_0);
+		extra_shift = 8 * (4 - byteCount);
+
+		while (byteCount > 0) {
+			data = (data << 8) + *src++;
+			byteCount--;
+		}
+
+		data <<= extra_shift;
+		data |= (orig_data & ~((~0UL) << extra_shift));
+
+		result = tonga_set_smc_sram_address(smumgr, addr, limit);
+		if (result)
+			goto out;
+
+		cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data);
+	}
+
+out:
+	return result;
+}
+
+
+int tonga_program_jump_on_start(struct pp_smumgr *smumgr)
+{
+	static unsigned char pData[] = { 0xE0, 0x00, 0x80, 0x40 };
+
+	tonga_copy_bytes_to_smc(smumgr, 0x0, pData, 4, sizeof(pData)+1);
+
+	return 0;
+}
+
+/**
+* Return if the SMC is currently running.
+*
+* @param    smumgr  the address of the powerplay hardware manager.
+*/
+static int tonga_is_smc_ram_running(struct pp_smumgr *smumgr)
+{
+	return ((0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+					SMC_SYSCON_CLOCK_CNTL_0, ck_disable))
+			&& (0x20100 <= cgs_read_ind_register(smumgr->device,
+					CGS_IND_REG__SMC, ixSMC_PC_C)));
+}
+
+static int tonga_send_msg_to_smc_offset(struct pp_smumgr *smumgr)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+
+	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, 0x20000);
+	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test);
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+
+	return 0;
+}
+
+/**
+* Send a message to the SMC, and wait for its response.
+*
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    msg the message to send.
+* @return   The response that came from the SMC.
+*/
+static int tonga_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	if (!tonga_is_smc_ram_running(smumgr))
+		return -1;
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+	PP_ASSERT_WITH_CODE(
+		1 == SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP),
+		"Failed to send Previous Message.",
+		);
+
+	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+	PP_ASSERT_WITH_CODE(
+		1 == SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP),
+		"Failed to send Message.",
+		);
+
+	return 0;
+}
+
+/*
+* Send a message to the SMC, and do not wait for its response.
+*
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    msg the message to send.
+* @return   The response that came from the SMC.
+*/
+static int tonga_send_msg_to_smc_without_waiting
+				(struct pp_smumgr *smumgr, uint16_t msg)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+	PP_ASSERT_WITH_CODE(
+		1 == SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP),
+		"Failed to send Previous Message.",
+		);
+	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
+
+	return 0;
+}
+
+/*
+* Send a message to the SMC with parameter
+*
+* @param    smumgr:  the address of the powerplay hardware manager.
+* @param    msg: the message to send.
+* @param    parameter: the parameter to send
+* @return   The response that came from the SMC.
+*/
+static int tonga_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
+				uint16_t msg, uint32_t parameter)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	if (!tonga_is_smc_ram_running(smumgr))
+		return PPSMC_Result_Failed;
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter);
+
+	return tonga_send_msg_to_smc(smumgr, msg);
+}
+
+/*
+* Send a message to the SMC with parameter, do not wait for response
+*
+* @param    smumgr:  the address of the powerplay hardware manager.
+* @param    msg: the message to send.
+* @param    parameter: the parameter to send
+* @return   The response that came from the SMC.
+*/
+static int tonga_send_msg_to_smc_with_parameter_without_waiting(
+			struct pp_smumgr *smumgr,
+			uint16_t msg, uint32_t parameter)
+{
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+
+	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter);
+
+	return tonga_send_msg_to_smc_without_waiting(smumgr, msg);
+}
+
+/*
+ * Read a 32bit value from the SMC SRAM space.
+ * ALL PARAMETERS ARE IN HOST BYTE ORDER.
+ * @param    smumgr  the address of the powerplay hardware manager.
+ * @param    smcAddress the address in the SMC RAM to access.
+ * @param    value and output parameter for the data read from the SMC SRAM.
+ */
+int tonga_read_smc_sram_dword(struct pp_smumgr *smumgr,
+					uint32_t smcAddress, uint32_t *value,
+					uint32_t limit)
+{
+	int result;
+
+	result = tonga_set_smc_sram_address(smumgr, smcAddress, limit);
+
+	if (0 != result)
+		return result;
+
+	*value = cgs_read_register(smumgr->device, mmSMC_IND_DATA_0);
+
+	return 0;
+}
+
+/*
+ * Write a 32bit value to the SMC SRAM space.
+ * ALL PARAMETERS ARE IN HOST BYTE ORDER.
+ * @param    smumgr  the address of the powerplay hardware manager.
+ * @param    smcAddress the address in the SMC RAM to access.
+ * @param    value to write to the SMC SRAM.
+ */
+int tonga_write_smc_sram_dword(struct pp_smumgr *smumgr,
+					uint32_t smcAddress, uint32_t value,
+					uint32_t limit)
+{
+	int result;
+
+	result = tonga_set_smc_sram_address(smumgr, smcAddress, limit);
+
+	if (0 != result)
+		return result;
+
+	cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, value);
+
+	return 0;
+}
+
+static int tonga_smu_fini(struct pp_smumgr *smumgr)
+{
+	if (smumgr->backend != NULL) {
+		kfree(smumgr->backend);
+		smumgr->backend = NULL;
+	}
+	return 0;
+}
+
+static enum cgs_ucode_id tonga_convert_fw_type_to_cgs(uint32_t fw_type)
+{
+	enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
+
+	switch (fw_type) {
+	case UCODE_ID_SMU:
+		result = CGS_UCODE_ID_SMU;
+		break;
+	case UCODE_ID_SDMA0:
+		result = CGS_UCODE_ID_SDMA0;
+		break;
+	case UCODE_ID_SDMA1:
+		result = CGS_UCODE_ID_SDMA1;
+		break;
+	case UCODE_ID_CP_CE:
+		result = CGS_UCODE_ID_CP_CE;
+		break;
+	case UCODE_ID_CP_PFP:
+		result = CGS_UCODE_ID_CP_PFP;
+		break;
+	case UCODE_ID_CP_ME:
+		result = CGS_UCODE_ID_CP_ME;
+		break;
+	case UCODE_ID_CP_MEC:
+		result = CGS_UCODE_ID_CP_MEC;
+		break;
+	case UCODE_ID_CP_MEC_JT1:
+		result = CGS_UCODE_ID_CP_MEC_JT1;
+		break;
+	case UCODE_ID_CP_MEC_JT2:
+		result = CGS_UCODE_ID_CP_MEC_JT2;
+		break;
+	case UCODE_ID_RLC_G:
+		result = CGS_UCODE_ID_RLC_G;
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+/**
+ * Convert the PPIRI firmware type to SMU type mask.
+ * For MEC, we need to check all MEC related type
+*/
+static uint16_t tonga_get_mask_for_firmware_type(uint16_t firmwareType)
+{
+	uint16_t result = 0;
+
+	switch (firmwareType) {
+	case UCODE_ID_SDMA0:
+		result = UCODE_ID_SDMA0_MASK;
+		break;
+	case UCODE_ID_SDMA1:
+		result = UCODE_ID_SDMA1_MASK;
+		break;
+	case UCODE_ID_CP_CE:
+		result = UCODE_ID_CP_CE_MASK;
+		break;
+	case UCODE_ID_CP_PFP:
+		result = UCODE_ID_CP_PFP_MASK;
+		break;
+	case UCODE_ID_CP_ME:
+		result = UCODE_ID_CP_ME_MASK;
+		break;
+	case UCODE_ID_CP_MEC:
+	case UCODE_ID_CP_MEC_JT1:
+	case UCODE_ID_CP_MEC_JT2:
+		result = UCODE_ID_CP_MEC_MASK;
+		break;
+	case UCODE_ID_RLC_G:
+		result = UCODE_ID_RLC_G_MASK;
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+/**
+ * Check if the FW has been loaded,
+ * SMU will not return if loading has not finished.
+*/
+static int tonga_check_fw_load_finish(struct pp_smumgr *smumgr, uint32_t fwType)
+{
+	uint16_t fwMask = tonga_get_mask_for_firmware_type(fwType);
+
+	if (0 != SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, SMC_IND,
+				SOFT_REGISTERS_TABLE_28, fwMask, fwMask)) {
+		printk(KERN_ERR "[ powerplay ] check firmware loading failed\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Populate one firmware image to the data structure */
+static int tonga_populate_single_firmware_entry(struct pp_smumgr *smumgr,
+				uint16_t firmware_type,
+				struct SMU_Entry *pentry)
+{
+	int result;
+	struct cgs_firmware_info info = {0};
+
+	result = cgs_get_firmware_info(
+				smumgr->device,
+				tonga_convert_fw_type_to_cgs(firmware_type),
+				&info);
+
+	if (result == 0) {
+		pentry->version = 0;
+		pentry->id = (uint16_t)firmware_type;
+		pentry->image_addr_high = smu_upper_32_bits(info.mc_addr);
+		pentry->image_addr_low = smu_lower_32_bits(info.mc_addr);
+		pentry->meta_data_addr_high = 0;
+		pentry->meta_data_addr_low = 0;
+		pentry->data_size_byte = info.image_size;
+		pentry->num_register_entries = 0;
+
+		if (firmware_type == UCODE_ID_RLC_G)
+			pentry->flags = 1;
+		else
+			pentry->flags = 0;
+	} else {
+		return result;
+	}
+
+	return result;
+}
+
+static int tonga_request_smu_reload_fw(struct pp_smumgr *smumgr)
+{
+	struct tonga_smumgr *tonga_smu =
+		(struct tonga_smumgr *)(smumgr->backend);
+	uint16_t fw_to_load;
+	int result = 0;
+	struct SMU_DRAMData_TOC *toc;
+	/**
+	 * First time this gets called during SmuMgr init,
+	 * we haven't processed SMU header file yet,
+	 * so Soft Register Start offset is unknown.
+	 * However, for this case, UcodeLoadStatus is already 0,
+	 * so we can skip this if the Soft Registers Start offset is 0.
+	 */
+	cgs_write_ind_register(smumgr->device,
+		CGS_IND_REG__SMC, ixSOFT_REGISTERS_TABLE_28, 0);
+
+	tonga_send_msg_to_smc_with_parameter(smumgr,
+		PPSMC_MSG_SMU_DRAM_ADDR_HI,
+		tonga_smu->smu_buffer.mc_addr_high);
+	tonga_send_msg_to_smc_with_parameter(smumgr,
+		PPSMC_MSG_SMU_DRAM_ADDR_LO,
+		tonga_smu->smu_buffer.mc_addr_low);
+
+	toc = (struct SMU_DRAMData_TOC *)tonga_smu->pHeader;
+	toc->num_entries = 0;
+	toc->structure_version = 1;
+
+	PP_ASSERT_WITH_CODE(
+		0 == tonga_populate_single_firmware_entry(smumgr,
+		UCODE_ID_RLC_G,
+		&toc->entry[toc->num_entries++]),
+		"Failed to Get Firmware Entry.\n",
+		return -1);
+	PP_ASSERT_WITH_CODE(
+		0 == tonga_populate_single_firmware_entry(smumgr,
+		UCODE_ID_CP_CE,
+		&toc->entry[toc->num_entries++]),
+		"Failed to Get Firmware Entry.\n",
+		return -1);
+	PP_ASSERT_WITH_CODE(
+		0 == tonga_populate_single_firmware_entry
+		(smumgr, UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]),
+		"Failed to Get Firmware Entry.\n", return -1);
+	PP_ASSERT_WITH_CODE(
+		0 == tonga_populate_single_firmware_entry
+		(smumgr, UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]),
+		"Failed to Get Firmware Entry.\n", return -1);
+	PP_ASSERT_WITH_CODE(
+		0 == tonga_populate_single_firmware_entry
+		(smumgr, UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]),
+		"Failed to Get Firmware Entry.\n", return -1);
+	PP_ASSERT_WITH_CODE(
+		0 == tonga_populate_single_firmware_entry
+		(smumgr, UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]),
+		"Failed to Get Firmware Entry.\n", return -1);
+	PP_ASSERT_WITH_CODE(
+		0 == tonga_populate_single_firmware_entry
+		(smumgr, UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]),
+		"Failed to Get Firmware Entry.\n", return -1);
+	PP_ASSERT_WITH_CODE(
+		0 == tonga_populate_single_firmware_entry
+		(smumgr, UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]),
+		"Failed to Get Firmware Entry.\n", return -1);
+	PP_ASSERT_WITH_CODE(
+		0 == tonga_populate_single_firmware_entry
+		(smumgr, UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]),
+		"Failed to Get Firmware Entry.\n", return -1);
+
+	tonga_send_msg_to_smc_with_parameter(smumgr,
+		PPSMC_MSG_DRV_DRAM_ADDR_HI,
+		tonga_smu->header_buffer.mc_addr_high);
+	tonga_send_msg_to_smc_with_parameter(smumgr,
+		PPSMC_MSG_DRV_DRAM_ADDR_LO,
+		tonga_smu->header_buffer.mc_addr_low);
+
+	fw_to_load = UCODE_ID_RLC_G_MASK
+			+ UCODE_ID_SDMA0_MASK
+			+ UCODE_ID_SDMA1_MASK
+			+ UCODE_ID_CP_CE_MASK
+			+ UCODE_ID_CP_ME_MASK
+			+ UCODE_ID_CP_PFP_MASK
+			+ UCODE_ID_CP_MEC_MASK;
+
+	PP_ASSERT_WITH_CODE(
+		0 == tonga_send_msg_to_smc_with_parameter_without_waiting(
+		smumgr, PPSMC_MSG_LoadUcodes, fw_to_load),
+		"Fail to Request SMU Load uCode", return 0);
+
+	return result;
+}
+
+static int tonga_request_smu_load_specific_fw(struct pp_smumgr *smumgr,
+				uint32_t firmwareType)
+{
+	return 0;
+}
+
+/**
+ * Upload the SMC firmware to the SMC microcontroller.
+ *
+ * @param    smumgr  the address of the powerplay hardware manager.
+ * @param    pFirmware the data structure containing the various sections of the firmware.
+ */
+static int tonga_smu_upload_firmware_image(struct pp_smumgr *smumgr)
+{
+	const uint8_t *src;
+	uint32_t byte_count;
+	uint32_t *data;
+	struct cgs_firmware_info info = {0};
+
+	if (smumgr == NULL || smumgr->device == NULL)
+		return -EINVAL;
+
+	cgs_get_firmware_info(smumgr->device,
+		tonga_convert_fw_type_to_cgs(UCODE_ID_SMU), &info);
+
+	if (info.image_size & 3) {
+		printk(KERN_ERR "[ powerplay ] SMC ucode is not 4 bytes aligned\n");
+		return -EINVAL;
+	}
+
+	if (info.image_size > TONGA_SMC_SIZE) {
+		printk(KERN_ERR "[ powerplay ] SMC address is beyond the SMC RAM area\n");
+		return -EINVAL;
+	}
+
+	cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, 0x20000);
+	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1);
+
+	byte_count = info.image_size;
+	src = (const uint8_t *)info.kptr;
+
+	data = (uint32_t *)src;
+	for (; byte_count >= 4; data++, byte_count -= 4)
+		cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data[0]);
+
+	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0);
+
+	return 0;
+}
+
+static int tonga_start_in_protection_mode(struct pp_smumgr *smumgr)
+{
+	int result;
+
+	/* Assert reset */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+		SMC_SYSCON_RESET_CNTL, rst_reg, 1);
+
+	result = tonga_smu_upload_firmware_image(smumgr);
+	if (result)
+		return result;
+
+	/* Clear status */
+	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
+		ixSMU_STATUS, 0);
+
+	/* Enable clock */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+		SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
+
+	/* De-assert reset */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+		SMC_SYSCON_RESET_CNTL, rst_reg, 0);
+
+	/* Set SMU Auto Start */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+		SMU_INPUT_DATA, AUTO_START, 1);
+
+	/* Clear firmware interrupt enable flag */
+	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
+		ixFIRMWARE_FLAGS, 0);
+
+	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND,
+		RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1);
+
+	/**
+	 * Call Test SMU message with 0x20000 offset to trigger SMU start
+	 */
+	tonga_send_msg_to_smc_offset(smumgr);
+
+	/* Wait for done bit to be set */
+	SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND,
+		SMU_STATUS, SMU_DONE, 0);
+
+	/* Check pass/failed indicator */
+	if (1 != SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device,
+				CGS_IND_REG__SMC, SMU_STATUS, SMU_PASS)) {
+		printk(KERN_ERR "[ powerplay ] SMU Firmware start failed\n");
+		return -EINVAL;
+	}
+
+	/* Wait for firmware to initialize */
+	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND,
+		FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
+
+	return 0;
+}
+
+
+static int tonga_start_in_non_protection_mode(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+
+	/* wait for smc boot up */
+	SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND,
+		RCU_UC_EVENTS, boot_seq_done, 0);
+
+	/*Clear firmware interrupt enable flag*/
+	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
+		ixFIRMWARE_FLAGS, 0);
+
+
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+		SMC_SYSCON_RESET_CNTL, rst_reg, 1);
+
+	result = tonga_smu_upload_firmware_image(smumgr);
+
+	if (result != 0)
+		return result;
+
+	/* Set smc instruct start point at 0x0 */
+	tonga_program_jump_on_start(smumgr);
+
+
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+		SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
+
+	/*De-assert reset*/
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+		SMC_SYSCON_RESET_CNTL, rst_reg, 0);
+
+	/* Wait for firmware to initialize */
+	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND,
+		FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
+
+	return result;
+}
+
+static int tonga_start_smu(struct pp_smumgr *smumgr)
+{
+	int result;
+
+	/* Only start SMC if SMC RAM is not running */
+	if (!tonga_is_smc_ram_running(smumgr)) {
+		/*Check if SMU is running in protected mode*/
+		if (0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+					SMU_FIRMWARE, SMU_MODE)) {
+			result = tonga_start_in_non_protection_mode(smumgr);
+			if (result)
+				return result;
+		} else {
+			result = tonga_start_in_protection_mode(smumgr);
+			if (result)
+				return result;
+		}
+	}
+
+	result = tonga_request_smu_reload_fw(smumgr);
+
+	return result;
+}
+
+/**
+ * Write a 32bit value to the SMC SRAM space.
+ * ALL PARAMETERS ARE IN HOST BYTE ORDER.
+ * @param    smumgr  the address of the powerplay hardware manager.
+ * @param    smcAddress the address in the SMC RAM to access.
+ * @param    value to write to the SMC SRAM.
+ */
+static int tonga_smu_init(struct pp_smumgr *smumgr)
+{
+	struct tonga_smumgr *tonga_smu;
+	uint8_t *internal_buf;
+	uint64_t mc_addr = 0;
+	/* Allocate memory for backend private data */
+	tonga_smu = (struct tonga_smumgr *)(smumgr->backend);
+	tonga_smu->header_buffer.data_size =
+		((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096;
+	tonga_smu->smu_buffer.data_size = 200*4096;
+
+	smu_allocate_memory(smumgr->device,
+		tonga_smu->header_buffer.data_size,
+		CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
+		PAGE_SIZE,
+		&mc_addr,
+		&tonga_smu->header_buffer.kaddr,
+		&tonga_smu->header_buffer.handle);
+
+	tonga_smu->pHeader = tonga_smu->header_buffer.kaddr;
+	tonga_smu->header_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
+	tonga_smu->header_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
+
+	PP_ASSERT_WITH_CODE((NULL != tonga_smu->pHeader),
+		"Out of memory.",
+		kfree(smumgr->backend);
+		cgs_free_gpu_mem(smumgr->device,
+		(cgs_handle_t)tonga_smu->header_buffer.handle);
+		return -1);
+
+	smu_allocate_memory(smumgr->device,
+		tonga_smu->smu_buffer.data_size,
+		CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
+		PAGE_SIZE,
+		&mc_addr,
+		&tonga_smu->smu_buffer.kaddr,
+		&tonga_smu->smu_buffer.handle);
+
+	internal_buf = tonga_smu->smu_buffer.kaddr;
+	tonga_smu->smu_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
+	tonga_smu->smu_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
+
+	PP_ASSERT_WITH_CODE((NULL != internal_buf),
+		"Out of memory.",
+		kfree(smumgr->backend);
+		cgs_free_gpu_mem(smumgr->device,
+		(cgs_handle_t)tonga_smu->smu_buffer.handle);
+		return -1;);
+
+	return 0;
+}
+
+static const struct pp_smumgr_func tonga_smu_funcs = {
+	.smu_init = &tonga_smu_init,
+	.smu_fini = &tonga_smu_fini,
+	.start_smu = &tonga_start_smu,
+	.check_fw_load_finish = &tonga_check_fw_load_finish,
+	.request_smu_load_fw = &tonga_request_smu_reload_fw,
+	.request_smu_load_specific_fw = &tonga_request_smu_load_specific_fw,
+	.send_msg_to_smc = &tonga_send_msg_to_smc,
+	.send_msg_to_smc_with_parameter = &tonga_send_msg_to_smc_with_parameter,
+	.download_pptable_settings = NULL,
+	.upload_pptable_settings = NULL,
+};
+
+int tonga_smum_init(struct pp_smumgr *smumgr)
+{
+	struct tonga_smumgr *tonga_smu = NULL;
+
+	tonga_smu = kzalloc(sizeof(struct tonga_smumgr), GFP_KERNEL);
+
+	if (tonga_smu == NULL)
+		return -ENOMEM;
+
+	smumgr->backend = tonga_smu;
+	smumgr->smumgr_funcs = &tonga_smu_funcs;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h
new file mode 100644
index 0000000..33c788d
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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.
+ *
+ */
+
+#ifndef _TONGA_SMUMGR_H_
+#define _TONGA_SMUMGR_H_
+
+struct tonga_buffer_entry {
+	uint32_t data_size;
+	uint32_t mc_addr_low;
+	uint32_t mc_addr_high;
+	void *kaddr;
+	unsigned long  handle;
+};
+
+struct tonga_smumgr {
+	uint8_t *pHeader;
+	uint8_t *pMecImage;
+	uint32_t ulSoftRegsStart;
+
+	struct tonga_buffer_entry header_buffer;
+	struct tonga_buffer_entry smu_buffer;
+};
+
+extern int tonga_smum_init(struct pp_smumgr *smumgr);
+extern int tonga_copy_bytes_to_smc(struct pp_smumgr *smumgr,
+		uint32_t smcStartAddress, const uint8_t *src,
+		uint32_t byteCount, uint32_t limit);
+extern int tonga_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smcAddress,
+		uint32_t *value, uint32_t limit);
+extern int tonga_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smcAddress,
+		uint32_t value, uint32_t limit);
+
+#endif
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
index 3a4820e..8b2becd 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -47,6 +47,8 @@
 static void amd_sched_rq_add_entity(struct amd_sched_rq *rq,
 				    struct amd_sched_entity *entity)
 {
+	if (!list_empty(&entity->list))
+		return;
 	spin_lock(&rq->lock);
 	list_add_tail(&entity->list, &rq->entities);
 	spin_unlock(&rq->lock);
@@ -55,6 +57,8 @@
 static void amd_sched_rq_remove_entity(struct amd_sched_rq *rq,
 				       struct amd_sched_entity *entity)
 {
+	if (list_empty(&entity->list))
+		return;
 	spin_lock(&rq->lock);
 	list_del_init(&entity->list);
 	if (rq->current_entity == entity)
@@ -138,9 +142,6 @@
 	atomic_set(&entity->fence_seq, 0);
 	entity->fence_context = fence_context_alloc(1);
 
-	/* Add the entity to the run queue */
-	amd_sched_rq_add_entity(rq, entity);
-
 	return 0;
 }
 
@@ -302,9 +303,11 @@
 	spin_unlock(&entity->queue_lock);
 
 	/* first job wakes up scheduler */
-	if (first)
+	if (first) {
+		/* Add the entity to the run queue */
+		amd_sched_rq_add_entity(entity->rq, entity);
 		amd_sched_wakeup(sched);
-
+	}
 	return added;
 }
 
@@ -349,14 +352,17 @@
 amd_sched_select_entity(struct amd_gpu_scheduler *sched)
 {
 	struct amd_sched_entity *entity;
+	int i;
 
 	if (!amd_sched_ready(sched))
 		return NULL;
 
 	/* Kernel run queue has higher priority than normal run queue*/
-	entity = amd_sched_rq_select_entity(&sched->kernel_rq);
-	if (entity == NULL)
-		entity = amd_sched_rq_select_entity(&sched->sched_rq);
+	for (i = 0; i < AMD_SCHED_MAX_PRIORITY; i++) {
+		entity = amd_sched_rq_select_entity(&sched->sched_rq[i]);
+		if (entity)
+			break;
+	}
 
 	return entity;
 }
@@ -478,12 +484,13 @@
 		   struct amd_sched_backend_ops *ops,
 		   unsigned hw_submission, long timeout, const char *name)
 {
+	int i;
 	sched->ops = ops;
 	sched->hw_submission_limit = hw_submission;
 	sched->name = name;
 	sched->timeout = timeout;
-	amd_sched_rq_init(&sched->sched_rq);
-	amd_sched_rq_init(&sched->kernel_rq);
+	for (i = 0; i < AMD_SCHED_MAX_PRIORITY; i++)
+		amd_sched_rq_init(&sched->sched_rq[i]);
 
 	init_waitqueue_head(&sched->wake_up_worker);
 	init_waitqueue_head(&sched->job_scheduled);
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
index a0f0ae5..9403145 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
@@ -104,6 +104,12 @@
 	struct fence *(*run_job)(struct amd_sched_job *sched_job);
 };
 
+enum amd_sched_priority {
+	AMD_SCHED_PRIORITY_KERNEL = 0,
+	AMD_SCHED_PRIORITY_NORMAL,
+	AMD_SCHED_MAX_PRIORITY
+};
+
 /**
  * One scheduler is implemented for each hardware ring
 */
@@ -112,8 +118,7 @@
 	uint32_t			hw_submission_limit;
 	long				timeout;
 	const char			*name;
-	struct amd_sched_rq		sched_rq;
-	struct amd_sched_rq		kernel_rq;
+	struct amd_sched_rq		sched_rq[AMD_SCHED_MAX_PRIORITY];
 	wait_queue_head_t		wake_up_worker;
 	wait_queue_head_t		job_scheduled;
 	atomic_t			hw_rq_count;
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 4123680..0293eb7 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -928,11 +928,10 @@
 		}
 	}
 
-	mutex_lock(&dev->struct_mutex);
 	if (dcrtc->cursor_obj) {
 		dcrtc->cursor_obj->update = NULL;
 		dcrtc->cursor_obj->update_data = NULL;
-		drm_gem_object_unreference(&dcrtc->cursor_obj->obj);
+		drm_gem_object_unreference_unlocked(&dcrtc->cursor_obj->obj);
 	}
 	dcrtc->cursor_obj = obj;
 	dcrtc->cursor_w = w;
@@ -942,14 +941,12 @@
 		obj->update_data = dcrtc;
 		obj->update = cursor_update;
 	}
-	mutex_unlock(&dev->struct_mutex);
 
 	return ret;
 }
 
 static int armada_drm_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 {
-	struct drm_device *dev = crtc->dev;
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 	int ret;
 
@@ -957,11 +954,9 @@
 	if (!dcrtc->variant->has_spu_adv_reg)
 		return -EFAULT;
 
-	mutex_lock(&dev->struct_mutex);
 	dcrtc->cursor_x = x;
 	dcrtc->cursor_y = y;
 	ret = armada_drm_crtc_cursor_update(dcrtc, false);
-	mutex_unlock(&dev->struct_mutex);
 
 	return ret;
 }
@@ -972,7 +967,7 @@
 	struct armada_private *priv = crtc->dev->dev_private;
 
 	if (dcrtc->cursor_obj)
-		drm_gem_object_unreference(&dcrtc->cursor_obj->obj);
+		drm_gem_object_unreference_unlocked(&dcrtc->cursor_obj->obj);
 
 	priv->dcrtc[dcrtc->num] = NULL;
 	drm_crtc_cleanup(&dcrtc->crtc);
diff --git a/drivers/gpu/drm/armada/armada_debugfs.c b/drivers/gpu/drm/armada/armada_debugfs.c
index 471e456..d4f7ab0 100644
--- a/drivers/gpu/drm/armada/armada_debugfs.c
+++ b/drivers/gpu/drm/armada/armada_debugfs.c
@@ -21,9 +21,9 @@
 	struct armada_private *priv = dev->dev_private;
 	int ret;
 
-	mutex_lock(&dev->struct_mutex);
+	mutex_lock(&priv->linear_lock);
 	ret = drm_mm_dump_table(m, &priv->linear);
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&priv->linear_lock);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index 4df6f2a..3b2bb61 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -57,7 +57,8 @@
 	DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
 	struct drm_fb_helper	*fbdev;
 	struct armada_crtc	*dcrtc[2];
-	struct drm_mm		linear;
+	struct drm_mm		linear; /* protected by linear_lock */
+	struct mutex		linear_lock;
 	struct drm_property	*csc_yuv_prop;
 	struct drm_property	*csc_rgb_prop;
 	struct drm_property	*colorkey_prop;
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 77ab93d..3bd7e1c 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -102,6 +102,7 @@
 	dev->mode_config.preferred_depth = 24;
 	dev->mode_config.funcs = &armada_drm_mode_config_funcs;
 	drm_mm_init(&priv->linear, mem->start, resource_size(mem));
+	mutex_init(&priv->linear_lock);
 
 	ret = component_bind_all(dev->dev, dev);
 	if (ret)
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index 60a688e..6e731db 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -46,22 +46,26 @@
 	return roundup(size, PAGE_SIZE);
 }
 
-/* dev->struct_mutex is held here */
 void armada_gem_free_object(struct drm_gem_object *obj)
 {
 	struct armada_gem_object *dobj = drm_to_armada_gem(obj);
+	struct armada_private *priv = obj->dev->dev_private;
 
 	DRM_DEBUG_DRIVER("release obj %p\n", dobj);
 
 	drm_gem_free_mmap_offset(&dobj->obj);
 
+	might_lock(&priv->linear_lock);
+
 	if (dobj->page) {
 		/* page backed memory */
 		unsigned int order = get_order(dobj->obj.size);
 		__free_pages(dobj->page, order);
 	} else if (dobj->linear) {
 		/* linear backed memory */
+		mutex_lock(&priv->linear_lock);
 		drm_mm_remove_node(dobj->linear);
+		mutex_unlock(&priv->linear_lock);
 		kfree(dobj->linear);
 		if (dobj->addr)
 			iounmap(dobj->addr);
@@ -144,10 +148,10 @@
 		if (!node)
 			return -ENOSPC;
 
-		mutex_lock(&dev->struct_mutex);
+		mutex_lock(&priv->linear_lock);
 		ret = drm_mm_insert_node(&priv->linear, node, size, align,
 					 DRM_MM_SEARCH_DEFAULT);
-		mutex_unlock(&dev->struct_mutex);
+		mutex_unlock(&priv->linear_lock);
 		if (ret) {
 			kfree(node);
 			return ret;
@@ -158,9 +162,9 @@
 		/* Ensure that the memory we're returning is cleared. */
 		ptr = ioremap_wc(obj->linear->start, size);
 		if (!ptr) {
-			mutex_lock(&dev->struct_mutex);
+			mutex_lock(&priv->linear_lock);
 			drm_mm_remove_node(obj->linear);
-			mutex_unlock(&dev->struct_mutex);
+			mutex_unlock(&priv->linear_lock);
 			kfree(obj->linear);
 			obj->linear = NULL;
 			return -ENOMEM;
@@ -274,18 +278,16 @@
 	struct armada_gem_object *obj;
 	int ret = 0;
 
-	mutex_lock(&dev->struct_mutex);
 	obj = armada_gem_object_lookup(dev, file, handle);
 	if (!obj) {
 		DRM_ERROR("failed to lookup gem object\n");
-		ret = -EINVAL;
-		goto err_unlock;
+		return -EINVAL;
 	}
 
 	/* Don't allow imported objects to be mapped */
 	if (obj->obj.import_attach) {
 		ret = -EINVAL;
-		goto err_unlock;
+		goto err_unref;
 	}
 
 	ret = drm_gem_create_mmap_offset(&obj->obj);
@@ -294,9 +296,8 @@
 		DRM_DEBUG_DRIVER("handle %#x offset %llx\n", handle, *offset);
 	}
 
-	drm_gem_object_unreference(&obj->obj);
- err_unlock:
-	mutex_unlock(&dev->struct_mutex);
+ err_unref:
+	drm_gem_object_unreference_unlocked(&obj->obj);
 
 	return ret;
 }
@@ -352,13 +353,13 @@
 		return -ENOENT;
 
 	if (!dobj->obj.filp) {
-		drm_gem_object_unreference(&dobj->obj);
+		drm_gem_object_unreference_unlocked(&dobj->obj);
 		return -EINVAL;
 	}
 
 	addr = vm_mmap(dobj->obj.filp, 0, args->size, PROT_READ | PROT_WRITE,
 		       MAP_SHARED, args->offset);
-	drm_gem_object_unreference(&dobj->obj);
+	drm_gem_object_unreference_unlocked(&dobj->obj);
 	if (IS_ERR_VALUE(addr))
 		return addr;
 
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 6dddd39..27e2022 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -22,7 +22,6 @@
 	  Designware HDMI block.  This is used in conjunction with
 	  the i.MX6 HDMI driver.
 
-
 config DRM_NXP_PTN3460
 	tristate "NXP PTN3460 DP/LVDS bridge"
 	depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index d4e28be..f13c33d 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,6 +1,6 @@
 ccflags-y := -Iinclude/drm
 
-obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o
-obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw_hdmi-ahb-audio.o
+obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
+obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c
similarity index 99%
rename from drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
rename to drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c
index 59f630f..122bb01 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c
@@ -21,7 +21,7 @@
 #include <sound/pcm_drm_eld.h>
 #include <sound/pcm_iec958.h>
 
-#include "dw_hdmi-audio.h"
+#include "dw-hdmi-audio.h"
 
 #define DRIVER_NAME "dw-hdmi-ahb-audio"
 
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-audio.h b/drivers/gpu/drm/bridge/dw-hdmi-audio.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw_hdmi-audio.h
rename to drivers/gpu/drm/bridge/dw-hdmi-audio.h
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
similarity index 98%
rename from drivers/gpu/drm/bridge/dw_hdmi.c
rename to drivers/gpu/drm/bridge/dw-hdmi.c
index f224945..b0aac473 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -22,13 +22,14 @@
 
 #include <drm/drm_of.h>
 #include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder_slave.h>
 #include <drm/bridge/dw_hdmi.h>
 
-#include "dw_hdmi.h"
-#include "dw_hdmi-audio.h"
+#include "dw-hdmi.h"
+#include "dw-hdmi-audio.h"
 
 #define HDMI_EDID_LEN		512
 
@@ -1522,6 +1523,17 @@
 	.force = dw_hdmi_connector_force,
 };
 
+static const struct drm_connector_funcs dw_hdmi_atomic_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = dw_hdmi_connector_detect,
+	.destroy = dw_hdmi_connector_destroy,
+	.force = dw_hdmi_connector_force,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
 static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
 	.get_modes = dw_hdmi_connector_get_modes,
 	.mode_valid = dw_hdmi_connector_mode_valid,
@@ -1645,8 +1657,15 @@
 
 	drm_connector_helper_add(&hdmi->connector,
 				 &dw_hdmi_connector_helper_funcs);
-	drm_connector_init(drm, &hdmi->connector, &dw_hdmi_connector_funcs,
-			   DRM_MODE_CONNECTOR_HDMIA);
+
+	if (drm_core_check_feature(drm, DRIVER_ATOMIC))
+		drm_connector_init(drm, &hdmi->connector,
+				   &dw_hdmi_atomic_connector_funcs,
+				   DRM_MODE_CONNECTOR_HDMIA);
+	else
+		drm_connector_init(drm, &hdmi->connector,
+				   &dw_hdmi_connector_funcs,
+				   DRM_MODE_CONNECTOR_HDMIA);
 
 	drm_mode_connector_attach_encoder(&hdmi->connector, encoder);
 
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw_hdmi.h
rename to drivers/gpu/drm/bridge/dw-hdmi.h
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 3b6627d..6ed90a2 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -666,7 +666,9 @@
 }
 
 static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_num,
-				  u8 vcpi, uint16_t pbn)
+				  u8 vcpi, uint16_t pbn,
+				  u8 number_sdp_streams,
+				  u8 *sdp_stream_sink)
 {
 	struct drm_dp_sideband_msg_req_body req;
 	memset(&req, 0, sizeof(req));
@@ -674,6 +676,9 @@
 	req.u.allocate_payload.port_number = port_num;
 	req.u.allocate_payload.vcpi = vcpi;
 	req.u.allocate_payload.pbn = pbn;
+	req.u.allocate_payload.number_sdp_streams = number_sdp_streams;
+	memcpy(req.u.allocate_payload.sdp_stream_sink, sdp_stream_sink,
+		   number_sdp_streams);
 	drm_dp_encode_sideband_req(&req, msg);
 	msg->path_msg = true;
 	return 0;
@@ -973,17 +978,17 @@
 static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port,
 				 u8 *rad)
 {
-	int lct = port->parent->lct;
+	int parent_lct = port->parent->lct;
 	int shift = 4;
-	int idx = lct / 2;
-	if (lct > 1) {
-		memcpy(rad, port->parent->rad, idx);
-		shift = (lct % 2) ? 4 : 0;
+	int idx = (parent_lct - 1) / 2;
+	if (parent_lct > 1) {
+		memcpy(rad, port->parent->rad, idx + 1);
+		shift = (parent_lct % 2) ? 4 : 0;
 	} else
 		rad[0] = 0;
 
 	rad[idx] |= port->port_num << shift;
-	return lct + 1;
+	return parent_lct + 1;
 }
 
 /*
@@ -1039,7 +1044,7 @@
 	snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id);
 	for (i = 0; i < (mstb->lct - 1); i++) {
 		int shift = (i % 2) ? 0 : 4;
-		int port_num = mstb->rad[i / 2] >> shift;
+		int port_num = (mstb->rad[i / 2] >> shift) & 0xf;
 		snprintf(temp, sizeof(temp), "-%d", port_num);
 		strlcat(proppath, temp, proppath_size);
 	}
@@ -1190,7 +1195,7 @@
 
 	for (i = 0; i < lct - 1; i++) {
 		int shift = (i % 2) ? 0 : 4;
-		int port_num = rad[i / 2] >> shift;
+		int port_num = (rad[i / 2] >> shift) & 0xf;
 
 		list_for_each_entry(port, &mstb->ports, next) {
 			if (port->port_num == port_num) {
@@ -1210,6 +1215,50 @@
 	return mstb;
 }
 
+static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper(
+	struct drm_dp_mst_branch *mstb,
+	uint8_t *guid)
+{
+	struct drm_dp_mst_branch *found_mstb;
+	struct drm_dp_mst_port *port;
+
+	list_for_each_entry(port, &mstb->ports, next) {
+		if (!port->mstb)
+			continue;
+
+		if (port->guid_valid && memcmp(port->guid, guid, 16) == 0)
+			return port->mstb;
+
+		found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid);
+
+		if (found_mstb)
+			return found_mstb;
+	}
+
+	return NULL;
+}
+
+static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid(
+	struct drm_dp_mst_topology_mgr *mgr,
+	uint8_t *guid)
+{
+	struct drm_dp_mst_branch *mstb;
+
+	/* find the port by iterating down */
+	mutex_lock(&mgr->lock);
+
+	if (mgr->guid_valid && memcmp(mgr->guid, guid, 16) == 0)
+		mstb = mgr->mst_primary;
+	else
+		mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
+
+	if (mstb)
+		kref_get(&mstb->kref);
+
+	mutex_unlock(&mgr->lock);
+	return mstb;
+}
+
 static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
 					       struct drm_dp_mst_branch *mstb)
 {
@@ -1320,6 +1369,7 @@
 				  struct drm_dp_sideband_msg_tx *txmsg)
 {
 	struct drm_dp_mst_branch *mstb = txmsg->dst;
+	u8 req_type;
 
 	/* both msg slots are full */
 	if (txmsg->seqno == -1) {
@@ -1336,7 +1386,13 @@
 			txmsg->seqno = 1;
 		mstb->tx_slots[txmsg->seqno] = txmsg;
 	}
-	hdr->broadcast = 0;
+
+	req_type = txmsg->msg[0] & 0x7f;
+	if (req_type == DP_CONNECTION_STATUS_NOTIFY ||
+		req_type == DP_RESOURCE_STATUS_NOTIFY)
+		hdr->broadcast = 1;
+	else
+		hdr->broadcast = 0;
 	hdr->path_msg = txmsg->path_msg;
 	hdr->lct = mstb->lct;
 	hdr->lcr = mstb->lct - 1;
@@ -1438,26 +1494,18 @@
 }
 
 /* called holding qlock */
-static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
+static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
+				       struct drm_dp_sideband_msg_tx *txmsg)
 {
-	struct drm_dp_sideband_msg_tx *txmsg;
 	int ret;
 
 	/* construct a chunk from the first msg in the tx_msg queue */
-	if (list_empty(&mgr->tx_msg_upq)) {
-		mgr->tx_up_in_progress = false;
-		return;
-	}
-
-	txmsg = list_first_entry(&mgr->tx_msg_upq, struct drm_dp_sideband_msg_tx, next);
 	ret = process_single_tx_qlock(mgr, txmsg, true);
-	if (ret == 1) {
-		/* up txmsgs aren't put in slots - so free after we send it */
-		list_del(&txmsg->next);
-		kfree(txmsg);
-	} else if (ret)
+
+	if (ret != 1)
 		DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
-	mgr->tx_up_in_progress = true;
+
+	txmsg->dst->tx_slots[txmsg->seqno] = NULL;
 }
 
 static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
@@ -1562,6 +1610,8 @@
 	struct drm_dp_sideband_msg_tx *txmsg;
 	struct drm_dp_mst_branch *mstb;
 	int len, ret;
+	u8 sinks[DRM_DP_MAX_SDP_STREAMS];
+	int i;
 
 	mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
 	if (!mstb)
@@ -1573,10 +1623,13 @@
 		goto fail_put;
 	}
 
+	for (i = 0; i < port->num_sdp_streams; i++)
+		sinks[i] = i;
+
 	txmsg->dst = mstb;
 	len = build_allocate_payload(txmsg, port->port_num,
 				     id,
-				     pbn);
+				     pbn, port->num_sdp_streams, sinks);
 
 	drm_dp_queue_down_tx(mgr, txmsg);
 
@@ -1846,11 +1899,12 @@
 	drm_dp_encode_up_ack_reply(txmsg, req_type);
 
 	mutex_lock(&mgr->qlock);
-	list_add_tail(&txmsg->next, &mgr->tx_msg_upq);
-	if (!mgr->tx_up_in_progress) {
-		process_single_up_tx_qlock(mgr);
-	}
+
+	process_single_up_tx_qlock(mgr, txmsg);
+
 	mutex_unlock(&mgr->qlock);
+
+	kfree(txmsg);
 	return 0;
 }
 
@@ -2147,28 +2201,50 @@
 
 	if (mgr->up_req_recv.have_eomt) {
 		struct drm_dp_sideband_msg_req_body msg;
-		struct drm_dp_mst_branch *mstb;
+		struct drm_dp_mst_branch *mstb = NULL;
 		bool seqno;
-		mstb = drm_dp_get_mst_branch_device(mgr,
-						    mgr->up_req_recv.initial_hdr.lct,
-						    mgr->up_req_recv.initial_hdr.rad);
-		if (!mstb) {
-			DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
-			memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
-			return 0;
+
+		if (!mgr->up_req_recv.initial_hdr.broadcast) {
+			mstb = drm_dp_get_mst_branch_device(mgr,
+							    mgr->up_req_recv.initial_hdr.lct,
+							    mgr->up_req_recv.initial_hdr.rad);
+			if (!mstb) {
+				DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
+				memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+				return 0;
+			}
 		}
 
 		seqno = mgr->up_req_recv.initial_hdr.seqno;
 		drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
 
 		if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
-			drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
+			drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
+
+			if (!mstb)
+				mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.conn_stat.guid);
+
+			if (!mstb) {
+				DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
+				memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+				return 0;
+			}
+
 			drm_dp_update_port(mstb, &msg.u.conn_stat);
 			DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
 			(*mgr->cbs->hotplug)(mgr);
 
 		} else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
-			drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
+			drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
+			if (!mstb)
+				mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.resource_stat.guid);
+
+			if (!mstb) {
+				DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
+				memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+				return 0;
+			}
+
 			DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
 		}
 
@@ -2261,6 +2337,27 @@
 EXPORT_SYMBOL(drm_dp_mst_detect_port);
 
 /**
+ * drm_dp_mst_port_has_audio() - Check whether port has audio capability or not
+ * @mgr: manager for this port
+ * @port: unverified pointer to a port.
+ *
+ * This returns whether the port supports audio or not.
+ */
+bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr,
+					struct drm_dp_mst_port *port)
+{
+	bool ret = false;
+
+	port = drm_dp_get_validated_port_ref(mgr, port);
+	if (!port)
+		return ret;
+	ret = port->has_audio;
+	drm_dp_put_port(port);
+	return ret;
+}
+EXPORT_SYMBOL(drm_dp_mst_port_has_audio);
+
+/**
  * drm_dp_mst_get_edid() - get EDID for an MST port
  * @connector: toplevel connector to get EDID for
  * @mgr: manager for this port
@@ -2285,6 +2382,7 @@
 		edid = drm_get_edid(connector, &port->aux.ddc);
 		drm_mode_connector_set_tile_property(connector);
 	}
+	port->has_audio = drm_detect_monitor_audio(edid);
 	drm_dp_put_port(port);
 	return edid;
 }
@@ -2568,7 +2666,7 @@
 
 	seq_printf(m, "%smst: %p, %d\n", prefix, mstb, mstb->num_ports);
 	list_for_each_entry(port, &mstb->ports, next) {
-		seq_printf(m, "%sport: %d: ddps: %d ldps: %d, %p, conn: %p\n", prefix, port->port_num, port->ddps, port->ldps, port, port->connector);
+		seq_printf(m, "%sport: %d: ddps: %d ldps: %d, sdp: %d/%d, %p, conn: %p\n", prefix, port->port_num, port->ddps, port->ldps, port->num_sdp_streams, port->num_sdp_stream_sinks, port, port->connector);
 		if (port->mstb)
 			drm_dp_mst_dump_mstb(m, port->mstb);
 	}
@@ -2738,7 +2836,6 @@
 	mutex_init(&mgr->qlock);
 	mutex_init(&mgr->payload_lock);
 	mutex_init(&mgr->destroy_connector_lock);
-	INIT_LIST_HEAD(&mgr->tx_msg_upq);
 	INIT_LIST_HEAD(&mgr->tx_msg_downq);
 	INIT_LIST_HEAD(&mgr->destroy_connector_list);
 	INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 2d5ca8ee..6e6a9c5 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -365,6 +365,44 @@
 }
 EXPORT_SYMBOL(mipi_dsi_create_packet);
 
+/**
+ * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi)
+{
+	struct mipi_dsi_msg msg = {
+		.channel = dsi->channel,
+		.type = MIPI_DSI_SHUTDOWN_PERIPHERAL,
+		.tx_buf = (u8 [2]) { 0, 0 },
+		.tx_len = 2,
+	};
+
+	return mipi_dsi_device_transfer(dsi, &msg);
+}
+EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral);
+
+/**
+ * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
+{
+	struct mipi_dsi_msg msg = {
+		.channel = dsi->channel,
+		.type = MIPI_DSI_TURN_ON_PERIPHERAL,
+		.tx_buf = (u8 [2]) { 0, 0 },
+		.tx_len = 2,
+	};
+
+	return mipi_dsi_device_transfer(dsi, &msg);
+}
+EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
+
 /*
  * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
  *    the payload in a long packet transmitted from the peripheral back to the
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index fcd2a86..a1fff11 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -410,6 +410,26 @@
 }
 EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask);
 
+int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw)
+{
+	struct pci_dev *root;
+	u32 lnkcap;
+
+	*mlw = 0;
+	if (!dev->pdev)
+		return -EINVAL;
+
+	root = dev->pdev->bus->self;
+
+	pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap);
+
+	*mlw = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
+
+	DRM_INFO("probing mlw for device %x:%x = %x\n", root->vendor, root->device, lnkcap);
+	return 0;
+}
+EXPORT_SYMBOL(drm_pcie_get_max_link_width);
+
 #else
 
 int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
diff --git a/drivers/gpu/drm/etnaviv/Kconfig b/drivers/gpu/drm/etnaviv/Kconfig
new file mode 100644
index 0000000..2cde7a5
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/Kconfig
@@ -0,0 +1,20 @@
+
+config DRM_ETNAVIV
+	tristate "ETNAVIV (DRM support for Vivante GPU IP cores)"
+	depends on DRM
+	depends on ARCH_MXC || ARCH_DOVE
+	select SHMEM
+	select TMPFS
+	select IOMMU_API
+	select IOMMU_SUPPORT
+	select WANT_DEV_COREDUMP
+	help
+	  DRM driver for Vivante GPUs.
+
+config DRM_ETNAVIV_REGISTER_LOGGING
+	bool "enable ETNAVIV register logging"
+	depends on DRM_ETNAVIV
+	help
+	  Compile in support for logging register reads/writes in a format
+	  that can be parsed by envytools demsm tool.  If enabled, register
+	  logging can be switched on via etnaviv.reglog=y module param.
diff --git a/drivers/gpu/drm/etnaviv/Makefile b/drivers/gpu/drm/etnaviv/Makefile
new file mode 100644
index 0000000..1086e98
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/Makefile
@@ -0,0 +1,14 @@
+etnaviv-y := \
+	etnaviv_buffer.o \
+	etnaviv_cmd_parser.o \
+	etnaviv_drv.o \
+	etnaviv_dump.o \
+	etnaviv_gem_prime.o \
+	etnaviv_gem_submit.o \
+	etnaviv_gem.o \
+	etnaviv_gpu.o \
+	etnaviv_iommu_v2.o \
+	etnaviv_iommu.o \
+	etnaviv_mmu.o
+
+obj-$(CONFIG_DRM_ETNAVIV)	+= etnaviv.o
diff --git a/drivers/gpu/drm/etnaviv/cmdstream.xml.h b/drivers/gpu/drm/etnaviv/cmdstream.xml.h
new file mode 100644
index 0000000..8c44ba9
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/cmdstream.xml.h
@@ -0,0 +1,218 @@
+#ifndef CMDSTREAM_XML
+#define CMDSTREAM_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- cmdstream.xml (  12589 bytes, from 2014-02-17 14:57:56)
+- common.xml    (  18437 bytes, from 2015-03-25 11:27:41)
+
+Copyright (C) 2014
+*/
+
+
+#define FE_OPCODE_LOAD_STATE					0x00000001
+#define FE_OPCODE_END						0x00000002
+#define FE_OPCODE_NOP						0x00000003
+#define FE_OPCODE_DRAW_2D					0x00000004
+#define FE_OPCODE_DRAW_PRIMITIVES				0x00000005
+#define FE_OPCODE_DRAW_INDEXED_PRIMITIVES			0x00000006
+#define FE_OPCODE_WAIT						0x00000007
+#define FE_OPCODE_LINK						0x00000008
+#define FE_OPCODE_STALL						0x00000009
+#define FE_OPCODE_CALL						0x0000000a
+#define FE_OPCODE_RETURN					0x0000000b
+#define FE_OPCODE_CHIP_SELECT					0x0000000d
+#define PRIMITIVE_TYPE_POINTS					0x00000001
+#define PRIMITIVE_TYPE_LINES					0x00000002
+#define PRIMITIVE_TYPE_LINE_STRIP				0x00000003
+#define PRIMITIVE_TYPE_TRIANGLES				0x00000004
+#define PRIMITIVE_TYPE_TRIANGLE_STRIP				0x00000005
+#define PRIMITIVE_TYPE_TRIANGLE_FAN				0x00000006
+#define PRIMITIVE_TYPE_LINE_LOOP				0x00000007
+#define PRIMITIVE_TYPE_QUADS					0x00000008
+#define VIV_FE_LOAD_STATE					0x00000000
+
+#define VIV_FE_LOAD_STATE_HEADER				0x00000000
+#define VIV_FE_LOAD_STATE_HEADER_OP__MASK			0xf8000000
+#define VIV_FE_LOAD_STATE_HEADER_OP__SHIFT			27
+#define VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE			0x08000000
+#define VIV_FE_LOAD_STATE_HEADER_FIXP				0x04000000
+#define VIV_FE_LOAD_STATE_HEADER_COUNT__MASK			0x03ff0000
+#define VIV_FE_LOAD_STATE_HEADER_COUNT__SHIFT			16
+#define VIV_FE_LOAD_STATE_HEADER_COUNT(x)			(((x) << VIV_FE_LOAD_STATE_HEADER_COUNT__SHIFT) & VIV_FE_LOAD_STATE_HEADER_COUNT__MASK)
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET__MASK			0x0000ffff
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET__SHIFT			0
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET(x)			(((x) << VIV_FE_LOAD_STATE_HEADER_OFFSET__SHIFT) & VIV_FE_LOAD_STATE_HEADER_OFFSET__MASK)
+#define VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR			2
+
+#define VIV_FE_END						0x00000000
+
+#define VIV_FE_END_HEADER					0x00000000
+#define VIV_FE_END_HEADER_EVENT_ID__MASK			0x0000001f
+#define VIV_FE_END_HEADER_EVENT_ID__SHIFT			0
+#define VIV_FE_END_HEADER_EVENT_ID(x)				(((x) << VIV_FE_END_HEADER_EVENT_ID__SHIFT) & VIV_FE_END_HEADER_EVENT_ID__MASK)
+#define VIV_FE_END_HEADER_EVENT_ENABLE				0x00000100
+#define VIV_FE_END_HEADER_OP__MASK				0xf8000000
+#define VIV_FE_END_HEADER_OP__SHIFT				27
+#define VIV_FE_END_HEADER_OP_END				0x10000000
+
+#define VIV_FE_NOP						0x00000000
+
+#define VIV_FE_NOP_HEADER					0x00000000
+#define VIV_FE_NOP_HEADER_OP__MASK				0xf8000000
+#define VIV_FE_NOP_HEADER_OP__SHIFT				27
+#define VIV_FE_NOP_HEADER_OP_NOP				0x18000000
+
+#define VIV_FE_DRAW_2D						0x00000000
+
+#define VIV_FE_DRAW_2D_HEADER					0x00000000
+#define VIV_FE_DRAW_2D_HEADER_COUNT__MASK			0x0000ff00
+#define VIV_FE_DRAW_2D_HEADER_COUNT__SHIFT			8
+#define VIV_FE_DRAW_2D_HEADER_COUNT(x)				(((x) << VIV_FE_DRAW_2D_HEADER_COUNT__SHIFT) & VIV_FE_DRAW_2D_HEADER_COUNT__MASK)
+#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT__MASK			0x07ff0000
+#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT__SHIFT			16
+#define VIV_FE_DRAW_2D_HEADER_DATA_COUNT(x)			(((x) << VIV_FE_DRAW_2D_HEADER_DATA_COUNT__SHIFT) & VIV_FE_DRAW_2D_HEADER_DATA_COUNT__MASK)
+#define VIV_FE_DRAW_2D_HEADER_OP__MASK				0xf8000000
+#define VIV_FE_DRAW_2D_HEADER_OP__SHIFT				27
+#define VIV_FE_DRAW_2D_HEADER_OP_DRAW_2D			0x20000000
+
+#define VIV_FE_DRAW_2D_TOP_LEFT					0x00000008
+#define VIV_FE_DRAW_2D_TOP_LEFT_X__MASK				0x0000ffff
+#define VIV_FE_DRAW_2D_TOP_LEFT_X__SHIFT			0
+#define VIV_FE_DRAW_2D_TOP_LEFT_X(x)				(((x) << VIV_FE_DRAW_2D_TOP_LEFT_X__SHIFT) & VIV_FE_DRAW_2D_TOP_LEFT_X__MASK)
+#define VIV_FE_DRAW_2D_TOP_LEFT_Y__MASK				0xffff0000
+#define VIV_FE_DRAW_2D_TOP_LEFT_Y__SHIFT			16
+#define VIV_FE_DRAW_2D_TOP_LEFT_Y(x)				(((x) << VIV_FE_DRAW_2D_TOP_LEFT_Y__SHIFT) & VIV_FE_DRAW_2D_TOP_LEFT_Y__MASK)
+
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT				0x0000000c
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__MASK			0x0000ffff
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__SHIFT			0
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_X(x)			(((x) << VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__SHIFT) & VIV_FE_DRAW_2D_BOTTOM_RIGHT_X__MASK)
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__MASK			0xffff0000
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__SHIFT			16
+#define VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y(x)			(((x) << VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__SHIFT) & VIV_FE_DRAW_2D_BOTTOM_RIGHT_Y__MASK)
+
+#define VIV_FE_DRAW_PRIMITIVES					0x00000000
+
+#define VIV_FE_DRAW_PRIMITIVES_HEADER				0x00000000
+#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP__MASK			0xf8000000
+#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP__SHIFT			27
+#define VIV_FE_DRAW_PRIMITIVES_HEADER_OP_DRAW_PRIMITIVES	0x28000000
+
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND				0x00000004
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__MASK		0x000000ff
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__SHIFT		0
+#define VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE(x)			(((x) << VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__SHIFT) & VIV_FE_DRAW_PRIMITIVES_COMMAND_TYPE__MASK)
+
+#define VIV_FE_DRAW_PRIMITIVES_START				0x00000008
+
+#define VIV_FE_DRAW_PRIMITIVES_COUNT				0x0000000c
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES				0x00000000
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER			0x00000000
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP__MASK		0xf8000000
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP__SHIFT		27
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP_DRAW_INDEXED_PRIMITIVES	0x30000000
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND			0x00000004
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__MASK	0x000000ff
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__SHIFT	0
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE(x)		(((x) << VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__SHIFT) & VIV_FE_DRAW_INDEXED_PRIMITIVES_COMMAND_TYPE__MASK)
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_START			0x00000008
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_COUNT			0x0000000c
+
+#define VIV_FE_DRAW_INDEXED_PRIMITIVES_OFFSET			0x00000010
+
+#define VIV_FE_WAIT						0x00000000
+
+#define VIV_FE_WAIT_HEADER					0x00000000
+#define VIV_FE_WAIT_HEADER_DELAY__MASK				0x0000ffff
+#define VIV_FE_WAIT_HEADER_DELAY__SHIFT				0
+#define VIV_FE_WAIT_HEADER_DELAY(x)				(((x) << VIV_FE_WAIT_HEADER_DELAY__SHIFT) & VIV_FE_WAIT_HEADER_DELAY__MASK)
+#define VIV_FE_WAIT_HEADER_OP__MASK				0xf8000000
+#define VIV_FE_WAIT_HEADER_OP__SHIFT				27
+#define VIV_FE_WAIT_HEADER_OP_WAIT				0x38000000
+
+#define VIV_FE_LINK						0x00000000
+
+#define VIV_FE_LINK_HEADER					0x00000000
+#define VIV_FE_LINK_HEADER_PREFETCH__MASK			0x0000ffff
+#define VIV_FE_LINK_HEADER_PREFETCH__SHIFT			0
+#define VIV_FE_LINK_HEADER_PREFETCH(x)				(((x) << VIV_FE_LINK_HEADER_PREFETCH__SHIFT) & VIV_FE_LINK_HEADER_PREFETCH__MASK)
+#define VIV_FE_LINK_HEADER_OP__MASK				0xf8000000
+#define VIV_FE_LINK_HEADER_OP__SHIFT				27
+#define VIV_FE_LINK_HEADER_OP_LINK				0x40000000
+
+#define VIV_FE_LINK_ADDRESS					0x00000004
+
+#define VIV_FE_STALL						0x00000000
+
+#define VIV_FE_STALL_HEADER					0x00000000
+#define VIV_FE_STALL_HEADER_OP__MASK				0xf8000000
+#define VIV_FE_STALL_HEADER_OP__SHIFT				27
+#define VIV_FE_STALL_HEADER_OP_STALL				0x48000000
+
+#define VIV_FE_STALL_TOKEN					0x00000004
+#define VIV_FE_STALL_TOKEN_FROM__MASK				0x0000001f
+#define VIV_FE_STALL_TOKEN_FROM__SHIFT				0
+#define VIV_FE_STALL_TOKEN_FROM(x)				(((x) << VIV_FE_STALL_TOKEN_FROM__SHIFT) & VIV_FE_STALL_TOKEN_FROM__MASK)
+#define VIV_FE_STALL_TOKEN_TO__MASK				0x00001f00
+#define VIV_FE_STALL_TOKEN_TO__SHIFT				8
+#define VIV_FE_STALL_TOKEN_TO(x)				(((x) << VIV_FE_STALL_TOKEN_TO__SHIFT) & VIV_FE_STALL_TOKEN_TO__MASK)
+
+#define VIV_FE_CALL						0x00000000
+
+#define VIV_FE_CALL_HEADER					0x00000000
+#define VIV_FE_CALL_HEADER_PREFETCH__MASK			0x0000ffff
+#define VIV_FE_CALL_HEADER_PREFETCH__SHIFT			0
+#define VIV_FE_CALL_HEADER_PREFETCH(x)				(((x) << VIV_FE_CALL_HEADER_PREFETCH__SHIFT) & VIV_FE_CALL_HEADER_PREFETCH__MASK)
+#define VIV_FE_CALL_HEADER_OP__MASK				0xf8000000
+#define VIV_FE_CALL_HEADER_OP__SHIFT				27
+#define VIV_FE_CALL_HEADER_OP_CALL				0x50000000
+
+#define VIV_FE_CALL_ADDRESS					0x00000004
+
+#define VIV_FE_CALL_RETURN_PREFETCH				0x00000008
+
+#define VIV_FE_CALL_RETURN_ADDRESS				0x0000000c
+
+#define VIV_FE_RETURN						0x00000000
+
+#define VIV_FE_RETURN_HEADER					0x00000000
+#define VIV_FE_RETURN_HEADER_OP__MASK				0xf8000000
+#define VIV_FE_RETURN_HEADER_OP__SHIFT				27
+#define VIV_FE_RETURN_HEADER_OP_RETURN				0x58000000
+
+#define VIV_FE_CHIP_SELECT					0x00000000
+
+#define VIV_FE_CHIP_SELECT_HEADER				0x00000000
+#define VIV_FE_CHIP_SELECT_HEADER_OP__MASK			0xf8000000
+#define VIV_FE_CHIP_SELECT_HEADER_OP__SHIFT			27
+#define VIV_FE_CHIP_SELECT_HEADER_OP_CHIP_SELECT		0x68000000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP15			0x00008000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP14			0x00004000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP13			0x00002000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP12			0x00001000
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP11			0x00000800
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP10			0x00000400
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP9			0x00000200
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP8			0x00000100
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP7			0x00000080
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP6			0x00000040
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP5			0x00000020
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP4			0x00000010
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP3			0x00000008
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP2			0x00000004
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP1			0x00000002
+#define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP0			0x00000001
+
+
+#endif /* CMDSTREAM_XML */
diff --git a/drivers/gpu/drm/etnaviv/common.xml.h b/drivers/gpu/drm/etnaviv/common.xml.h
new file mode 100644
index 0000000..9e585d5
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/common.xml.h
@@ -0,0 +1,249 @@
+#ifndef COMMON_XML
+#define COMMON_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- state_vg.xml (   5973 bytes, from 2015-03-25 11:26:01)
+- common.xml   (  18437 bytes, from 2015-03-25 11:27:41)
+
+Copyright (C) 2015
+*/
+
+
+#define PIPE_ID_PIPE_3D						0x00000000
+#define PIPE_ID_PIPE_2D						0x00000001
+#define SYNC_RECIPIENT_FE					0x00000001
+#define SYNC_RECIPIENT_RA					0x00000005
+#define SYNC_RECIPIENT_PE					0x00000007
+#define SYNC_RECIPIENT_DE					0x0000000b
+#define SYNC_RECIPIENT_VG					0x0000000f
+#define SYNC_RECIPIENT_TESSELATOR				0x00000010
+#define SYNC_RECIPIENT_VG2					0x00000011
+#define SYNC_RECIPIENT_TESSELATOR2				0x00000012
+#define SYNC_RECIPIENT_VG3					0x00000013
+#define SYNC_RECIPIENT_TESSELATOR3				0x00000014
+#define ENDIAN_MODE_NO_SWAP					0x00000000
+#define ENDIAN_MODE_SWAP_16					0x00000001
+#define ENDIAN_MODE_SWAP_32					0x00000002
+#define chipModel_GC300						0x00000300
+#define chipModel_GC320						0x00000320
+#define chipModel_GC350						0x00000350
+#define chipModel_GC355						0x00000355
+#define chipModel_GC400						0x00000400
+#define chipModel_GC410						0x00000410
+#define chipModel_GC420						0x00000420
+#define chipModel_GC450						0x00000450
+#define chipModel_GC500						0x00000500
+#define chipModel_GC530						0x00000530
+#define chipModel_GC600						0x00000600
+#define chipModel_GC700						0x00000700
+#define chipModel_GC800						0x00000800
+#define chipModel_GC860						0x00000860
+#define chipModel_GC880						0x00000880
+#define chipModel_GC1000					0x00001000
+#define chipModel_GC2000					0x00002000
+#define chipModel_GC2100					0x00002100
+#define chipModel_GC4000					0x00004000
+#define RGBA_BITS_R						0x00000001
+#define RGBA_BITS_G						0x00000002
+#define RGBA_BITS_B						0x00000004
+#define RGBA_BITS_A						0x00000008
+#define chipFeatures_FAST_CLEAR					0x00000001
+#define chipFeatures_SPECIAL_ANTI_ALIASING			0x00000002
+#define chipFeatures_PIPE_3D					0x00000004
+#define chipFeatures_DXT_TEXTURE_COMPRESSION			0x00000008
+#define chipFeatures_DEBUG_MODE					0x00000010
+#define chipFeatures_Z_COMPRESSION				0x00000020
+#define chipFeatures_YUV420_SCALER				0x00000040
+#define chipFeatures_MSAA					0x00000080
+#define chipFeatures_DC						0x00000100
+#define chipFeatures_PIPE_2D					0x00000200
+#define chipFeatures_ETC1_TEXTURE_COMPRESSION			0x00000400
+#define chipFeatures_FAST_SCALER				0x00000800
+#define chipFeatures_HIGH_DYNAMIC_RANGE				0x00001000
+#define chipFeatures_YUV420_TILER				0x00002000
+#define chipFeatures_MODULE_CG					0x00004000
+#define chipFeatures_MIN_AREA					0x00008000
+#define chipFeatures_NO_EARLY_Z					0x00010000
+#define chipFeatures_NO_422_TEXTURE				0x00020000
+#define chipFeatures_BUFFER_INTERLEAVING			0x00040000
+#define chipFeatures_BYTE_WRITE_2D				0x00080000
+#define chipFeatures_NO_SCALER					0x00100000
+#define chipFeatures_YUY2_AVERAGING				0x00200000
+#define chipFeatures_HALF_PE_CACHE				0x00400000
+#define chipFeatures_HALF_TX_CACHE				0x00800000
+#define chipFeatures_YUY2_RENDER_TARGET				0x01000000
+#define chipFeatures_MEM32					0x02000000
+#define chipFeatures_PIPE_VG					0x04000000
+#define chipFeatures_VGTS					0x08000000
+#define chipFeatures_FE20					0x10000000
+#define chipFeatures_BYTE_WRITE_3D				0x20000000
+#define chipFeatures_RS_YUV_TARGET				0x40000000
+#define chipFeatures_32_BIT_INDICES				0x80000000
+#define chipMinorFeatures0_FLIP_Y				0x00000001
+#define chipMinorFeatures0_DUAL_RETURN_BUS			0x00000002
+#define chipMinorFeatures0_ENDIANNESS_CONFIG			0x00000004
+#define chipMinorFeatures0_TEXTURE_8K				0x00000008
+#define chipMinorFeatures0_CORRECT_TEXTURE_CONVERTER		0x00000010
+#define chipMinorFeatures0_SPECIAL_MSAA_LOD			0x00000020
+#define chipMinorFeatures0_FAST_CLEAR_FLUSH			0x00000040
+#define chipMinorFeatures0_2DPE20				0x00000080
+#define chipMinorFeatures0_CORRECT_AUTO_DISABLE			0x00000100
+#define chipMinorFeatures0_RENDERTARGET_8K			0x00000200
+#define chipMinorFeatures0_2BITPERTILE				0x00000400
+#define chipMinorFeatures0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED	0x00000800
+#define chipMinorFeatures0_SUPER_TILED				0x00001000
+#define chipMinorFeatures0_VG_20				0x00002000
+#define chipMinorFeatures0_TS_EXTENDED_COMMANDS			0x00004000
+#define chipMinorFeatures0_COMPRESSION_FIFO_FIXED		0x00008000
+#define chipMinorFeatures0_HAS_SIGN_FLOOR_CEIL			0x00010000
+#define chipMinorFeatures0_VG_FILTER				0x00020000
+#define chipMinorFeatures0_VG_21				0x00040000
+#define chipMinorFeatures0_SHADER_HAS_W				0x00080000
+#define chipMinorFeatures0_HAS_SQRT_TRIG			0x00100000
+#define chipMinorFeatures0_MORE_MINOR_FEATURES			0x00200000
+#define chipMinorFeatures0_MC20					0x00400000
+#define chipMinorFeatures0_MSAA_SIDEBAND			0x00800000
+#define chipMinorFeatures0_BUG_FIXES0				0x01000000
+#define chipMinorFeatures0_VAA					0x02000000
+#define chipMinorFeatures0_BYPASS_IN_MSAA			0x04000000
+#define chipMinorFeatures0_HZ					0x08000000
+#define chipMinorFeatures0_NEW_TEXTURE				0x10000000
+#define chipMinorFeatures0_2D_A8_TARGET				0x20000000
+#define chipMinorFeatures0_CORRECT_STENCIL			0x40000000
+#define chipMinorFeatures0_ENHANCE_VR				0x80000000
+#define chipMinorFeatures1_RSUV_SWIZZLE				0x00000001
+#define chipMinorFeatures1_V2_COMPRESSION			0x00000002
+#define chipMinorFeatures1_VG_DOUBLE_BUFFER			0x00000004
+#define chipMinorFeatures1_EXTRA_EVENT_STATES			0x00000008
+#define chipMinorFeatures1_NO_STRIPING_NEEDED			0x00000010
+#define chipMinorFeatures1_TEXTURE_STRIDE			0x00000020
+#define chipMinorFeatures1_BUG_FIXES3				0x00000040
+#define chipMinorFeatures1_AUTO_DISABLE				0x00000080
+#define chipMinorFeatures1_AUTO_RESTART_TS			0x00000100
+#define chipMinorFeatures1_DISABLE_PE_GATING			0x00000200
+#define chipMinorFeatures1_L2_WINDOWING				0x00000400
+#define chipMinorFeatures1_HALF_FLOAT				0x00000800
+#define chipMinorFeatures1_PIXEL_DITHER				0x00001000
+#define chipMinorFeatures1_TWO_STENCIL_REFERENCE		0x00002000
+#define chipMinorFeatures1_EXTENDED_PIXEL_FORMAT		0x00004000
+#define chipMinorFeatures1_CORRECT_MIN_MAX_DEPTH		0x00008000
+#define chipMinorFeatures1_2D_DITHER				0x00010000
+#define chipMinorFeatures1_BUG_FIXES5				0x00020000
+#define chipMinorFeatures1_NEW_2D				0x00040000
+#define chipMinorFeatures1_NEW_FP				0x00080000
+#define chipMinorFeatures1_TEXTURE_HALIGN			0x00100000
+#define chipMinorFeatures1_NON_POWER_OF_TWO			0x00200000
+#define chipMinorFeatures1_LINEAR_TEXTURE_SUPPORT		0x00400000
+#define chipMinorFeatures1_HALTI0				0x00800000
+#define chipMinorFeatures1_CORRECT_OVERFLOW_VG			0x01000000
+#define chipMinorFeatures1_NEGATIVE_LOG_FIX			0x02000000
+#define chipMinorFeatures1_RESOLVE_OFFSET			0x04000000
+#define chipMinorFeatures1_OK_TO_GATE_AXI_CLOCK			0x08000000
+#define chipMinorFeatures1_MMU_VERSION				0x10000000
+#define chipMinorFeatures1_WIDE_LINE				0x20000000
+#define chipMinorFeatures1_BUG_FIXES6				0x40000000
+#define chipMinorFeatures1_FC_FLUSH_STALL			0x80000000
+#define chipMinorFeatures2_LINE_LOOP				0x00000001
+#define chipMinorFeatures2_LOGIC_OP				0x00000002
+#define chipMinorFeatures2_UNK2					0x00000004
+#define chipMinorFeatures2_SUPERTILED_TEXTURE			0x00000008
+#define chipMinorFeatures2_UNK4					0x00000010
+#define chipMinorFeatures2_RECT_PRIMITIVE			0x00000020
+#define chipMinorFeatures2_COMPOSITION				0x00000040
+#define chipMinorFeatures2_CORRECT_AUTO_DISABLE_COUNT		0x00000080
+#define chipMinorFeatures2_UNK8					0x00000100
+#define chipMinorFeatures2_UNK9					0x00000200
+#define chipMinorFeatures2_UNK10				0x00000400
+#define chipMinorFeatures2_SAMPLERBASE_16			0x00000800
+#define chipMinorFeatures2_UNK12				0x00001000
+#define chipMinorFeatures2_UNK13				0x00002000
+#define chipMinorFeatures2_UNK14				0x00004000
+#define chipMinorFeatures2_EXTRA_TEXTURE_STATE			0x00008000
+#define chipMinorFeatures2_FULL_DIRECTFB			0x00010000
+#define chipMinorFeatures2_2D_TILING				0x00020000
+#define chipMinorFeatures2_THREAD_WALKER_IN_PS			0x00040000
+#define chipMinorFeatures2_TILE_FILLER				0x00080000
+#define chipMinorFeatures2_UNK20				0x00100000
+#define chipMinorFeatures2_2D_MULTI_SOURCE_BLIT			0x00200000
+#define chipMinorFeatures2_UNK22				0x00400000
+#define chipMinorFeatures2_UNK23				0x00800000
+#define chipMinorFeatures2_UNK24				0x01000000
+#define chipMinorFeatures2_MIXED_STREAMS			0x02000000
+#define chipMinorFeatures2_2D_420_L2CACHE			0x04000000
+#define chipMinorFeatures2_UNK27				0x08000000
+#define chipMinorFeatures2_2D_NO_INDEX8_BRUSH			0x10000000
+#define chipMinorFeatures2_TEXTURE_TILED_READ			0x20000000
+#define chipMinorFeatures2_UNK30				0x40000000
+#define chipMinorFeatures2_UNK31				0x80000000
+#define chipMinorFeatures3_ROTATION_STALL_FIX			0x00000001
+#define chipMinorFeatures3_UNK1					0x00000002
+#define chipMinorFeatures3_2D_MULTI_SOURCE_BLT_EX		0x00000004
+#define chipMinorFeatures3_UNK3					0x00000008
+#define chipMinorFeatures3_UNK4					0x00000010
+#define chipMinorFeatures3_UNK5					0x00000020
+#define chipMinorFeatures3_UNK6					0x00000040
+#define chipMinorFeatures3_UNK7					0x00000080
+#define chipMinorFeatures3_UNK8					0x00000100
+#define chipMinorFeatures3_UNK9					0x00000200
+#define chipMinorFeatures3_BUG_FIXES10				0x00000400
+#define chipMinorFeatures3_UNK11				0x00000800
+#define chipMinorFeatures3_BUG_FIXES11				0x00001000
+#define chipMinorFeatures3_UNK13				0x00002000
+#define chipMinorFeatures3_UNK14				0x00004000
+#define chipMinorFeatures3_UNK15				0x00008000
+#define chipMinorFeatures3_UNK16				0x00010000
+#define chipMinorFeatures3_UNK17				0x00020000
+#define chipMinorFeatures3_UNK18				0x00040000
+#define chipMinorFeatures3_UNK19				0x00080000
+#define chipMinorFeatures3_UNK20				0x00100000
+#define chipMinorFeatures3_UNK21				0x00200000
+#define chipMinorFeatures3_UNK22				0x00400000
+#define chipMinorFeatures3_UNK23				0x00800000
+#define chipMinorFeatures3_UNK24				0x01000000
+#define chipMinorFeatures3_UNK25				0x02000000
+#define chipMinorFeatures3_UNK26				0x04000000
+#define chipMinorFeatures3_UNK27				0x08000000
+#define chipMinorFeatures3_UNK28				0x10000000
+#define chipMinorFeatures3_UNK29				0x20000000
+#define chipMinorFeatures3_UNK30				0x40000000
+#define chipMinorFeatures3_UNK31				0x80000000
+#define chipMinorFeatures4_UNK0					0x00000001
+#define chipMinorFeatures4_UNK1					0x00000002
+#define chipMinorFeatures4_UNK2					0x00000004
+#define chipMinorFeatures4_UNK3					0x00000008
+#define chipMinorFeatures4_UNK4					0x00000010
+#define chipMinorFeatures4_UNK5					0x00000020
+#define chipMinorFeatures4_UNK6					0x00000040
+#define chipMinorFeatures4_UNK7					0x00000080
+#define chipMinorFeatures4_UNK8					0x00000100
+#define chipMinorFeatures4_UNK9					0x00000200
+#define chipMinorFeatures4_UNK10				0x00000400
+#define chipMinorFeatures4_UNK11				0x00000800
+#define chipMinorFeatures4_UNK12				0x00001000
+#define chipMinorFeatures4_UNK13				0x00002000
+#define chipMinorFeatures4_UNK14				0x00004000
+#define chipMinorFeatures4_UNK15				0x00008000
+#define chipMinorFeatures4_UNK16				0x00010000
+#define chipMinorFeatures4_UNK17				0x00020000
+#define chipMinorFeatures4_UNK18				0x00040000
+#define chipMinorFeatures4_UNK19				0x00080000
+#define chipMinorFeatures4_UNK20				0x00100000
+#define chipMinorFeatures4_UNK21				0x00200000
+#define chipMinorFeatures4_UNK22				0x00400000
+#define chipMinorFeatures4_UNK23				0x00800000
+#define chipMinorFeatures4_UNK24				0x01000000
+#define chipMinorFeatures4_UNK25				0x02000000
+#define chipMinorFeatures4_UNK26				0x04000000
+#define chipMinorFeatures4_UNK27				0x08000000
+#define chipMinorFeatures4_UNK28				0x10000000
+#define chipMinorFeatures4_UNK29				0x20000000
+#define chipMinorFeatures4_UNK30				0x40000000
+#define chipMinorFeatures4_UNK31				0x80000000
+
+#endif /* COMMON_XML */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
new file mode 100644
index 0000000..332c55e
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2014 Etnaviv Project
+ * Author: Christian Gmeiner <christian.gmeiner@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 "etnaviv_gpu.h"
+#include "etnaviv_gem.h"
+#include "etnaviv_mmu.h"
+
+#include "common.xml.h"
+#include "state.xml.h"
+#include "cmdstream.xml.h"
+
+/*
+ * Command Buffer helper:
+ */
+
+
+static inline void OUT(struct etnaviv_cmdbuf *buffer, u32 data)
+{
+	u32 *vaddr = (u32 *)buffer->vaddr;
+
+	BUG_ON(buffer->user_size >= buffer->size);
+
+	vaddr[buffer->user_size / 4] = data;
+	buffer->user_size += 4;
+}
+
+static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer,
+	u32 reg, u32 value)
+{
+	u32 index = reg >> VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR;
+
+	buffer->user_size = ALIGN(buffer->user_size, 8);
+
+	/* write a register via cmd stream */
+	OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
+		    VIV_FE_LOAD_STATE_HEADER_COUNT(1) |
+		    VIV_FE_LOAD_STATE_HEADER_OFFSET(index));
+	OUT(buffer, value);
+}
+
+static inline void CMD_END(struct etnaviv_cmdbuf *buffer)
+{
+	buffer->user_size = ALIGN(buffer->user_size, 8);
+
+	OUT(buffer, VIV_FE_END_HEADER_OP_END);
+}
+
+static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer)
+{
+	buffer->user_size = ALIGN(buffer->user_size, 8);
+
+	OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | 200);
+}
+
+static inline void CMD_LINK(struct etnaviv_cmdbuf *buffer,
+	u16 prefetch, u32 address)
+{
+	buffer->user_size = ALIGN(buffer->user_size, 8);
+
+	OUT(buffer, VIV_FE_LINK_HEADER_OP_LINK |
+		    VIV_FE_LINK_HEADER_PREFETCH(prefetch));
+	OUT(buffer, address);
+}
+
+static inline void CMD_STALL(struct etnaviv_cmdbuf *buffer,
+	u32 from, u32 to)
+{
+	buffer->user_size = ALIGN(buffer->user_size, 8);
+
+	OUT(buffer, VIV_FE_STALL_HEADER_OP_STALL);
+	OUT(buffer, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to));
+}
+
+static void etnaviv_cmd_select_pipe(struct etnaviv_cmdbuf *buffer, u8 pipe)
+{
+	u32 flush;
+	u32 stall;
+
+	/*
+	 * This assumes that if we're switching to 2D, we're switching
+	 * away from 3D, and vice versa.  Hence, if we're switching to
+	 * the 2D core, we need to flush the 3D depth and color caches,
+	 * otherwise we need to flush the 2D pixel engine cache.
+	 */
+	if (pipe == ETNA_PIPE_2D)
+		flush = VIVS_GL_FLUSH_CACHE_DEPTH | VIVS_GL_FLUSH_CACHE_COLOR;
+	else
+		flush = VIVS_GL_FLUSH_CACHE_PE2D;
+
+	stall = VIVS_GL_SEMAPHORE_TOKEN_FROM(SYNC_RECIPIENT_FE) |
+		VIVS_GL_SEMAPHORE_TOKEN_TO(SYNC_RECIPIENT_PE);
+
+	CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush);
+	CMD_LOAD_STATE(buffer, VIVS_GL_SEMAPHORE_TOKEN, stall);
+
+	CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
+
+	CMD_LOAD_STATE(buffer, VIVS_GL_PIPE_SELECT,
+		       VIVS_GL_PIPE_SELECT_PIPE(pipe));
+}
+
+static u32 gpu_va(struct etnaviv_gpu *gpu, struct etnaviv_cmdbuf *buf)
+{
+	return buf->paddr - gpu->memory_base;
+}
+
+static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu,
+	struct etnaviv_cmdbuf *buf, u32 off, u32 len)
+{
+	u32 size = buf->size;
+	u32 *ptr = buf->vaddr + off;
+
+	dev_info(gpu->dev, "virt %p phys 0x%08x free 0x%08x\n",
+			ptr, gpu_va(gpu, buf) + off, size - len * 4 - off);
+
+	print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
+			ptr, len * 4, 0);
+}
+
+u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
+{
+	struct etnaviv_cmdbuf *buffer = gpu->buffer;
+
+	/* initialize buffer */
+	buffer->user_size = 0;
+
+	CMD_WAIT(buffer);
+	CMD_LINK(buffer, 2, gpu_va(gpu, buffer) + buffer->user_size - 4);
+
+	return buffer->user_size / 8;
+}
+
+void etnaviv_buffer_end(struct etnaviv_gpu *gpu)
+{
+	struct etnaviv_cmdbuf *buffer = gpu->buffer;
+
+	/* Replace the last WAIT with an END */
+	buffer->user_size -= 16;
+
+	CMD_END(buffer);
+	mb();
+}
+
+void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
+	struct etnaviv_cmdbuf *cmdbuf)
+{
+	struct etnaviv_cmdbuf *buffer = gpu->buffer;
+	u32 *lw = buffer->vaddr + buffer->user_size - 16;
+	u32 back, link_target, link_size, reserve_size, extra_size = 0;
+
+	if (drm_debug & DRM_UT_DRIVER)
+		etnaviv_buffer_dump(gpu, buffer, 0, 0x50);
+
+	/*
+	 * If we need to flush the MMU prior to submitting this buffer, we
+	 * will need to append a mmu flush load state, followed by a new
+	 * link to this buffer - a total of four additional words.
+	 */
+	if (gpu->mmu->need_flush || gpu->switch_context) {
+		/* link command */
+		extra_size += 2;
+		/* flush command */
+		if (gpu->mmu->need_flush)
+			extra_size += 2;
+		/* pipe switch commands */
+		if (gpu->switch_context)
+			extra_size += 8;
+	}
+
+	reserve_size = (6 + extra_size) * 4;
+
+	/*
+	 * if we are going to completely overflow the buffer, we need to wrap.
+	 */
+	if (buffer->user_size + reserve_size > buffer->size)
+		buffer->user_size = 0;
+
+	/* save offset back into main buffer */
+	back = buffer->user_size + reserve_size - 6 * 4;
+	link_target = gpu_va(gpu, buffer) + buffer->user_size;
+	link_size = 6;
+
+	/* Skip over any extra instructions */
+	link_target += extra_size * sizeof(u32);
+
+	if (drm_debug & DRM_UT_DRIVER)
+		pr_info("stream link to 0x%08x @ 0x%08x %p\n",
+			link_target, gpu_va(gpu, cmdbuf), cmdbuf->vaddr);
+
+	/* jump back from cmd to main buffer */
+	CMD_LINK(cmdbuf, link_size, link_target);
+
+	link_target = gpu_va(gpu, cmdbuf);
+	link_size = cmdbuf->size / 8;
+
+
+
+	if (drm_debug & DRM_UT_DRIVER) {
+		print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
+			       cmdbuf->vaddr, cmdbuf->size, 0);
+
+		pr_info("link op: %p\n", lw);
+		pr_info("link addr: %p\n", lw + 1);
+		pr_info("addr: 0x%08x\n", link_target);
+		pr_info("back: 0x%08x\n", gpu_va(gpu, buffer) + back);
+		pr_info("event: %d\n", event);
+	}
+
+	if (gpu->mmu->need_flush || gpu->switch_context) {
+		u32 new_target = gpu_va(gpu, buffer) + buffer->user_size;
+
+		if (gpu->mmu->need_flush) {
+			/* Add the MMU flush */
+			CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_MMU,
+				       VIVS_GL_FLUSH_MMU_FLUSH_FEMMU |
+				       VIVS_GL_FLUSH_MMU_FLUSH_UNK1 |
+				       VIVS_GL_FLUSH_MMU_FLUSH_UNK2 |
+				       VIVS_GL_FLUSH_MMU_FLUSH_PEMMU |
+				       VIVS_GL_FLUSH_MMU_FLUSH_UNK4);
+
+			gpu->mmu->need_flush = false;
+		}
+
+		if (gpu->switch_context) {
+			etnaviv_cmd_select_pipe(buffer, cmdbuf->exec_state);
+			gpu->switch_context = false;
+		}
+
+		/* And the link to the first buffer */
+		CMD_LINK(buffer, link_size, link_target);
+
+		/* Update the link target to point to above instructions */
+		link_target = new_target;
+		link_size = extra_size;
+	}
+
+	/* trigger event */
+	CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
+		       VIVS_GL_EVENT_FROM_PE);
+
+	/* append WAIT/LINK to main buffer */
+	CMD_WAIT(buffer);
+	CMD_LINK(buffer, 2, gpu_va(gpu, buffer) + (buffer->user_size - 4));
+
+	/* Change WAIT into a LINK command; write the address first. */
+	*(lw + 1) = link_target;
+	mb();
+	*(lw) = VIV_FE_LINK_HEADER_OP_LINK |
+		VIV_FE_LINK_HEADER_PREFETCH(link_size);
+	mb();
+
+	if (drm_debug & DRM_UT_DRIVER)
+		etnaviv_buffer_dump(gpu, buffer, 0, 0x50);
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c b/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c
new file mode 100644
index 0000000..dcfd565
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 <linux/kernel.h>
+
+#include "etnaviv_gem.h"
+#include "etnaviv_gpu.h"
+
+#include "cmdstream.xml.h"
+
+#define EXTRACT(val, field) (((val) & field##__MASK) >> field##__SHIFT)
+
+struct etna_validation_state {
+	struct etnaviv_gpu *gpu;
+	const struct drm_etnaviv_gem_submit_reloc *relocs;
+	unsigned int num_relocs;
+	u32 *start;
+};
+
+static const struct {
+	u16 offset;
+	u16 size;
+} etnaviv_sensitive_states[] __initconst = {
+#define ST(start, num) { (start) >> 2, (num) }
+	/* 2D */
+	ST(0x1200, 1),
+	ST(0x1228, 1),
+	ST(0x1238, 1),
+	ST(0x1284, 1),
+	ST(0x128c, 1),
+	ST(0x1304, 1),
+	ST(0x1310, 1),
+	ST(0x1318, 1),
+	ST(0x12800, 4),
+	ST(0x128a0, 4),
+	ST(0x128c0, 4),
+	ST(0x12970, 4),
+	ST(0x12a00, 8),
+	ST(0x12b40, 8),
+	ST(0x12b80, 8),
+	ST(0x12ce0, 8),
+	/* 3D */
+	ST(0x0644, 1),
+	ST(0x064c, 1),
+	ST(0x0680, 8),
+	ST(0x1410, 1),
+	ST(0x1430, 1),
+	ST(0x1458, 1),
+	ST(0x1460, 8),
+	ST(0x1480, 8),
+	ST(0x1500, 8),
+	ST(0x1520, 8),
+	ST(0x1608, 1),
+	ST(0x1610, 1),
+	ST(0x1658, 1),
+	ST(0x165c, 1),
+	ST(0x1664, 1),
+	ST(0x1668, 1),
+	ST(0x16a4, 1),
+	ST(0x16c0, 8),
+	ST(0x16e0, 8),
+	ST(0x1740, 8),
+	ST(0x2400, 14 * 16),
+	ST(0x10800, 32 * 16),
+#undef ST
+};
+
+#define ETNAVIV_STATES_SIZE (VIV_FE_LOAD_STATE_HEADER_OFFSET__MASK + 1u)
+static DECLARE_BITMAP(etnaviv_states, ETNAVIV_STATES_SIZE);
+
+void __init etnaviv_validate_init(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(etnaviv_sensitive_states); i++)
+		bitmap_set(etnaviv_states, etnaviv_sensitive_states[i].offset,
+			   etnaviv_sensitive_states[i].size);
+}
+
+static void etnaviv_warn_if_non_sensitive(struct etna_validation_state *state,
+	unsigned int buf_offset, unsigned int state_addr)
+{
+	if (state->num_relocs && state->relocs->submit_offset < buf_offset) {
+		dev_warn_once(state->gpu->dev,
+			      "%s: relocation for non-sensitive state 0x%x at offset %u\n",
+			      __func__, state_addr,
+			      state->relocs->submit_offset);
+		while (state->num_relocs &&
+		       state->relocs->submit_offset < buf_offset) {
+			state->relocs++;
+			state->num_relocs--;
+		}
+	}
+}
+
+static bool etnaviv_validate_load_state(struct etna_validation_state *state,
+	u32 *ptr, unsigned int state_offset, unsigned int num)
+{
+	unsigned int size = min(ETNAVIV_STATES_SIZE, state_offset + num);
+	unsigned int st_offset = state_offset, buf_offset;
+
+	for_each_set_bit_from(st_offset, etnaviv_states, size) {
+		buf_offset = (ptr - state->start +
+			      st_offset - state_offset) * 4;
+
+		etnaviv_warn_if_non_sensitive(state, buf_offset, st_offset * 4);
+		if (state->num_relocs &&
+		    state->relocs->submit_offset == buf_offset) {
+			state->relocs++;
+			state->num_relocs--;
+			continue;
+		}
+
+		dev_warn_ratelimited(state->gpu->dev,
+				     "%s: load state touches restricted state 0x%x at offset %u\n",
+				     __func__, st_offset * 4, buf_offset);
+		return false;
+	}
+
+	if (state->num_relocs) {
+		buf_offset = (ptr - state->start + num) * 4;
+		etnaviv_warn_if_non_sensitive(state, buf_offset, st_offset * 4 +
+					      state->relocs->submit_offset -
+					      buf_offset);
+	}
+
+	return true;
+}
+
+static uint8_t cmd_length[32] = {
+	[FE_OPCODE_DRAW_PRIMITIVES] = 4,
+	[FE_OPCODE_DRAW_INDEXED_PRIMITIVES] = 6,
+	[FE_OPCODE_NOP] = 2,
+	[FE_OPCODE_STALL] = 2,
+};
+
+bool etnaviv_cmd_validate_one(struct etnaviv_gpu *gpu, u32 *stream,
+			      unsigned int size,
+			      struct drm_etnaviv_gem_submit_reloc *relocs,
+			      unsigned int reloc_size)
+{
+	struct etna_validation_state state;
+	u32 *buf = stream;
+	u32 *end = buf + size;
+
+	state.gpu = gpu;
+	state.relocs = relocs;
+	state.num_relocs = reloc_size;
+	state.start = stream;
+
+	while (buf < end) {
+		u32 cmd = *buf;
+		unsigned int len, n, off;
+		unsigned int op = cmd >> 27;
+
+		switch (op) {
+		case FE_OPCODE_LOAD_STATE:
+			n = EXTRACT(cmd, VIV_FE_LOAD_STATE_HEADER_COUNT);
+			len = ALIGN(1 + n, 2);
+			if (buf + len > end)
+				break;
+
+			off = EXTRACT(cmd, VIV_FE_LOAD_STATE_HEADER_OFFSET);
+			if (!etnaviv_validate_load_state(&state, buf + 1,
+							 off, n))
+				return false;
+			break;
+
+		case FE_OPCODE_DRAW_2D:
+			n = EXTRACT(cmd, VIV_FE_DRAW_2D_HEADER_COUNT);
+			if (n == 0)
+				n = 256;
+			len = 2 + n * 2;
+			break;
+
+		default:
+			len = cmd_length[op];
+			if (len == 0) {
+				dev_err(gpu->dev, "%s: op %u not permitted at offset %tu\n",
+					__func__, op, buf - state.start);
+				return false;
+			}
+			break;
+		}
+
+		buf += len;
+	}
+
+	if (buf > end) {
+		dev_err(gpu->dev, "%s: commands overflow end of buffer: %tu > %u\n",
+			__func__, buf - state.start, size);
+		return false;
+	}
+
+	return true;
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
new file mode 100644
index 0000000..5c89ebb
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -0,0 +1,707 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 <linux/component.h>
+#include <linux/of_platform.h>
+
+#include "etnaviv_drv.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_gem.h"
+#include "etnaviv_mmu.h"
+#include "etnaviv_gem.h"
+
+#ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING
+static bool reglog;
+MODULE_PARM_DESC(reglog, "Enable register read/write logging");
+module_param(reglog, bool, 0600);
+#else
+#define reglog 0
+#endif
+
+void __iomem *etnaviv_ioremap(struct platform_device *pdev, const char *name,
+		const char *dbgname)
+{
+	struct resource *res;
+	void __iomem *ptr;
+
+	if (name)
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+	else
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	ptr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ptr)) {
+		dev_err(&pdev->dev, "failed to ioremap %s: %ld\n", name,
+			PTR_ERR(ptr));
+		return ptr;
+	}
+
+	if (reglog)
+		dev_printk(KERN_DEBUG, &pdev->dev, "IO:region %s 0x%p %08zx\n",
+			   dbgname, ptr, (size_t)resource_size(res));
+
+	return ptr;
+}
+
+void etnaviv_writel(u32 data, void __iomem *addr)
+{
+	if (reglog)
+		printk(KERN_DEBUG "IO:W %p %08x\n", addr, data);
+
+	writel(data, addr);
+}
+
+u32 etnaviv_readl(const void __iomem *addr)
+{
+	u32 val = readl(addr);
+
+	if (reglog)
+		printk(KERN_DEBUG "IO:R %p %08x\n", addr, val);
+
+	return val;
+}
+
+/*
+ * DRM operations:
+ */
+
+
+static void load_gpu(struct drm_device *dev)
+{
+	struct etnaviv_drm_private *priv = dev->dev_private;
+	unsigned int i;
+
+	for (i = 0; i < ETNA_MAX_PIPES; i++) {
+		struct etnaviv_gpu *g = priv->gpu[i];
+
+		if (g) {
+			int ret;
+
+			ret = etnaviv_gpu_init(g);
+			if (ret) {
+				dev_err(g->dev, "hw init failed: %d\n", ret);
+				priv->gpu[i] = NULL;
+			}
+		}
+	}
+}
+
+static int etnaviv_open(struct drm_device *dev, struct drm_file *file)
+{
+	struct etnaviv_file_private *ctx;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	file->driver_priv = ctx;
+
+	return 0;
+}
+
+static void etnaviv_preclose(struct drm_device *dev, struct drm_file *file)
+{
+	struct etnaviv_drm_private *priv = dev->dev_private;
+	struct etnaviv_file_private *ctx = file->driver_priv;
+	unsigned int i;
+
+	for (i = 0; i < ETNA_MAX_PIPES; i++) {
+		struct etnaviv_gpu *gpu = priv->gpu[i];
+
+		if (gpu) {
+			mutex_lock(&gpu->lock);
+			if (gpu->lastctx == ctx)
+				gpu->lastctx = NULL;
+			mutex_unlock(&gpu->lock);
+		}
+	}
+
+	kfree(ctx);
+}
+
+/*
+ * DRM debugfs:
+ */
+
+#ifdef CONFIG_DEBUG_FS
+static int etnaviv_gem_show(struct drm_device *dev, struct seq_file *m)
+{
+	struct etnaviv_drm_private *priv = dev->dev_private;
+
+	etnaviv_gem_describe_objects(priv, m);
+
+	return 0;
+}
+
+static int etnaviv_mm_show(struct drm_device *dev, struct seq_file *m)
+{
+	int ret;
+
+	read_lock(&dev->vma_offset_manager->vm_lock);
+	ret = drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
+	read_unlock(&dev->vma_offset_manager->vm_lock);
+
+	return ret;
+}
+
+static int etnaviv_mmu_show(struct etnaviv_gpu *gpu, struct seq_file *m)
+{
+	seq_printf(m, "Active Objects (%s):\n", dev_name(gpu->dev));
+
+	mutex_lock(&gpu->mmu->lock);
+	drm_mm_dump_table(m, &gpu->mmu->mm);
+	mutex_unlock(&gpu->mmu->lock);
+
+	return 0;
+}
+
+static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, struct seq_file *m)
+{
+	struct etnaviv_cmdbuf *buf = gpu->buffer;
+	u32 size = buf->size;
+	u32 *ptr = buf->vaddr;
+	u32 i;
+
+	seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n",
+			buf->vaddr, (u64)buf->paddr, size - buf->user_size);
+
+	for (i = 0; i < size / 4; i++) {
+		if (i && !(i % 4))
+			seq_puts(m, "\n");
+		if (i % 4 == 0)
+			seq_printf(m, "\t0x%p: ", ptr + i);
+		seq_printf(m, "%08x ", *(ptr + i));
+	}
+	seq_puts(m, "\n");
+}
+
+static int etnaviv_ring_show(struct etnaviv_gpu *gpu, struct seq_file *m)
+{
+	seq_printf(m, "Ring Buffer (%s): ", dev_name(gpu->dev));
+
+	mutex_lock(&gpu->lock);
+	etnaviv_buffer_dump(gpu, m);
+	mutex_unlock(&gpu->lock);
+
+	return 0;
+}
+
+static int show_unlocked(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	int (*show)(struct drm_device *dev, struct seq_file *m) =
+			node->info_ent->data;
+
+	return show(dev, m);
+}
+
+static int show_each_gpu(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct etnaviv_drm_private *priv = dev->dev_private;
+	struct etnaviv_gpu *gpu;
+	int (*show)(struct etnaviv_gpu *gpu, struct seq_file *m) =
+			node->info_ent->data;
+	unsigned int i;
+	int ret = 0;
+
+	for (i = 0; i < ETNA_MAX_PIPES; i++) {
+		gpu = priv->gpu[i];
+		if (!gpu)
+			continue;
+
+		ret = show(gpu, m);
+		if (ret < 0)
+			break;
+	}
+
+	return ret;
+}
+
+static struct drm_info_list etnaviv_debugfs_list[] = {
+		{"gpu", show_each_gpu, 0, etnaviv_gpu_debugfs},
+		{"gem", show_unlocked, 0, etnaviv_gem_show},
+		{ "mm", show_unlocked, 0, etnaviv_mm_show },
+		{"mmu", show_each_gpu, 0, etnaviv_mmu_show},
+		{"ring", show_each_gpu, 0, etnaviv_ring_show},
+};
+
+static int etnaviv_debugfs_init(struct drm_minor *minor)
+{
+	struct drm_device *dev = minor->dev;
+	int ret;
+
+	ret = drm_debugfs_create_files(etnaviv_debugfs_list,
+			ARRAY_SIZE(etnaviv_debugfs_list),
+			minor->debugfs_root, minor);
+
+	if (ret) {
+		dev_err(dev->dev, "could not install etnaviv_debugfs_list\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static void etnaviv_debugfs_cleanup(struct drm_minor *minor)
+{
+	drm_debugfs_remove_files(etnaviv_debugfs_list,
+			ARRAY_SIZE(etnaviv_debugfs_list), minor);
+}
+#endif
+
+/*
+ * DRM ioctls:
+ */
+
+static int etnaviv_ioctl_get_param(struct drm_device *dev, void *data,
+		struct drm_file *file)
+{
+	struct etnaviv_drm_private *priv = dev->dev_private;
+	struct drm_etnaviv_param *args = data;
+	struct etnaviv_gpu *gpu;
+
+	if (args->pipe >= ETNA_MAX_PIPES)
+		return -EINVAL;
+
+	gpu = priv->gpu[args->pipe];
+	if (!gpu)
+		return -ENXIO;
+
+	return etnaviv_gpu_get_param(gpu, args->param, &args->value);
+}
+
+static int etnaviv_ioctl_gem_new(struct drm_device *dev, void *data,
+		struct drm_file *file)
+{
+	struct drm_etnaviv_gem_new *args = data;
+
+	if (args->flags & ~(ETNA_BO_CACHED | ETNA_BO_WC | ETNA_BO_UNCACHED |
+			    ETNA_BO_FORCE_MMU))
+		return -EINVAL;
+
+	return etnaviv_gem_new_handle(dev, file, args->size,
+			args->flags, &args->handle);
+}
+
+#define TS(t) ((struct timespec){ \
+	.tv_sec = (t).tv_sec, \
+	.tv_nsec = (t).tv_nsec \
+})
+
+static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
+		struct drm_file *file)
+{
+	struct drm_etnaviv_gem_cpu_prep *args = data;
+	struct drm_gem_object *obj;
+	int ret;
+
+	if (args->op & ~(ETNA_PREP_READ | ETNA_PREP_WRITE | ETNA_PREP_NOSYNC))
+		return -EINVAL;
+
+	obj = drm_gem_object_lookup(dev, file, args->handle);
+	if (!obj)
+		return -ENOENT;
+
+	ret = etnaviv_gem_cpu_prep(obj, args->op, &TS(args->timeout));
+
+	drm_gem_object_unreference_unlocked(obj);
+
+	return ret;
+}
+
+static int etnaviv_ioctl_gem_cpu_fini(struct drm_device *dev, void *data,
+		struct drm_file *file)
+{
+	struct drm_etnaviv_gem_cpu_fini *args = data;
+	struct drm_gem_object *obj;
+	int ret;
+
+	if (args->flags)
+		return -EINVAL;
+
+	obj = drm_gem_object_lookup(dev, file, args->handle);
+	if (!obj)
+		return -ENOENT;
+
+	ret = etnaviv_gem_cpu_fini(obj);
+
+	drm_gem_object_unreference_unlocked(obj);
+
+	return ret;
+}
+
+static int etnaviv_ioctl_gem_info(struct drm_device *dev, void *data,
+		struct drm_file *file)
+{
+	struct drm_etnaviv_gem_info *args = data;
+	struct drm_gem_object *obj;
+	int ret;
+
+	if (args->pad)
+		return -EINVAL;
+
+	obj = drm_gem_object_lookup(dev, file, args->handle);
+	if (!obj)
+		return -ENOENT;
+
+	ret = etnaviv_gem_mmap_offset(obj, &args->offset);
+	drm_gem_object_unreference_unlocked(obj);
+
+	return ret;
+}
+
+static int etnaviv_ioctl_wait_fence(struct drm_device *dev, void *data,
+		struct drm_file *file)
+{
+	struct drm_etnaviv_wait_fence *args = data;
+	struct etnaviv_drm_private *priv = dev->dev_private;
+	struct timespec *timeout = &TS(args->timeout);
+	struct etnaviv_gpu *gpu;
+
+	if (args->flags & ~(ETNA_WAIT_NONBLOCK))
+		return -EINVAL;
+
+	if (args->pipe >= ETNA_MAX_PIPES)
+		return -EINVAL;
+
+	gpu = priv->gpu[args->pipe];
+	if (!gpu)
+		return -ENXIO;
+
+	if (args->flags & ETNA_WAIT_NONBLOCK)
+		timeout = NULL;
+
+	return etnaviv_gpu_wait_fence_interruptible(gpu, args->fence,
+						    timeout);
+}
+
+static int etnaviv_ioctl_gem_userptr(struct drm_device *dev, void *data,
+	struct drm_file *file)
+{
+	struct drm_etnaviv_gem_userptr *args = data;
+	int access;
+
+	if (args->flags & ~(ETNA_USERPTR_READ|ETNA_USERPTR_WRITE) ||
+	    args->flags == 0)
+		return -EINVAL;
+
+	if (offset_in_page(args->user_ptr | args->user_size) ||
+	    (uintptr_t)args->user_ptr != args->user_ptr ||
+	    (u32)args->user_size != args->user_size ||
+	    args->user_ptr & ~PAGE_MASK)
+		return -EINVAL;
+
+	if (args->flags & ETNA_USERPTR_WRITE)
+		access = VERIFY_WRITE;
+	else
+		access = VERIFY_READ;
+
+	if (!access_ok(access, (void __user *)(unsigned long)args->user_ptr,
+		       args->user_size))
+		return -EFAULT;
+
+	return etnaviv_gem_new_userptr(dev, file, args->user_ptr,
+				       args->user_size, args->flags,
+				       &args->handle);
+}
+
+static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data,
+	struct drm_file *file)
+{
+	struct etnaviv_drm_private *priv = dev->dev_private;
+	struct drm_etnaviv_gem_wait *args = data;
+	struct timespec *timeout = &TS(args->timeout);
+	struct drm_gem_object *obj;
+	struct etnaviv_gpu *gpu;
+	int ret;
+
+	if (args->flags & ~(ETNA_WAIT_NONBLOCK))
+		return -EINVAL;
+
+	if (args->pipe >= ETNA_MAX_PIPES)
+		return -EINVAL;
+
+	gpu = priv->gpu[args->pipe];
+	if (!gpu)
+		return -ENXIO;
+
+	obj = drm_gem_object_lookup(dev, file, args->handle);
+	if (!obj)
+		return -ENOENT;
+
+	if (args->flags & ETNA_WAIT_NONBLOCK)
+		timeout = NULL;
+
+	ret = etnaviv_gem_wait_bo(gpu, obj, timeout);
+
+	drm_gem_object_unreference_unlocked(obj);
+
+	return ret;
+}
+
+static const struct drm_ioctl_desc etnaviv_ioctls[] = {
+#define ETNA_IOCTL(n, func, flags) \
+	DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags)
+	ETNA_IOCTL(GET_PARAM,    get_param,    DRM_AUTH|DRM_RENDER_ALLOW),
+	ETNA_IOCTL(GEM_NEW,      gem_new,      DRM_AUTH|DRM_RENDER_ALLOW),
+	ETNA_IOCTL(GEM_INFO,     gem_info,     DRM_AUTH|DRM_RENDER_ALLOW),
+	ETNA_IOCTL(GEM_CPU_PREP, gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
+	ETNA_IOCTL(GEM_CPU_FINI, gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW),
+	ETNA_IOCTL(GEM_SUBMIT,   gem_submit,   DRM_AUTH|DRM_RENDER_ALLOW),
+	ETNA_IOCTL(WAIT_FENCE,   wait_fence,   DRM_AUTH|DRM_RENDER_ALLOW),
+	ETNA_IOCTL(GEM_USERPTR,  gem_userptr,  DRM_AUTH|DRM_RENDER_ALLOW),
+	ETNA_IOCTL(GEM_WAIT,     gem_wait,     DRM_AUTH|DRM_RENDER_ALLOW),
+};
+
+static const struct vm_operations_struct vm_ops = {
+	.fault = etnaviv_gem_fault,
+	.open = drm_gem_vm_open,
+	.close = drm_gem_vm_close,
+};
+
+static const struct file_operations 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               = etnaviv_gem_mmap,
+};
+
+static struct drm_driver etnaviv_drm_driver = {
+	.driver_features    = DRIVER_HAVE_IRQ |
+				DRIVER_GEM |
+				DRIVER_PRIME |
+				DRIVER_RENDER,
+	.open               = etnaviv_open,
+	.preclose           = etnaviv_preclose,
+	.set_busid          = drm_platform_set_busid,
+	.gem_free_object    = etnaviv_gem_free_object,
+	.gem_vm_ops         = &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   = drm_gem_prime_export,
+	.gem_prime_import   = drm_gem_prime_import,
+	.gem_prime_pin      = etnaviv_gem_prime_pin,
+	.gem_prime_unpin    = etnaviv_gem_prime_unpin,
+	.gem_prime_get_sg_table = etnaviv_gem_prime_get_sg_table,
+	.gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table,
+	.gem_prime_vmap     = etnaviv_gem_prime_vmap,
+	.gem_prime_vunmap   = etnaviv_gem_prime_vunmap,
+#ifdef CONFIG_DEBUG_FS
+	.debugfs_init       = etnaviv_debugfs_init,
+	.debugfs_cleanup    = etnaviv_debugfs_cleanup,
+#endif
+	.ioctls             = etnaviv_ioctls,
+	.num_ioctls         = DRM_ETNAVIV_NUM_IOCTLS,
+	.fops               = &fops,
+	.name               = "etnaviv",
+	.desc               = "etnaviv DRM",
+	.date               = "20151214",
+	.major              = 1,
+	.minor              = 0,
+};
+
+/*
+ * Platform driver:
+ */
+static int etnaviv_bind(struct device *dev)
+{
+	struct etnaviv_drm_private *priv;
+	struct drm_device *drm;
+	int ret;
+
+	drm = drm_dev_alloc(&etnaviv_drm_driver, dev);
+	if (!drm)
+		return -ENOMEM;
+
+	drm->platformdev = to_platform_device(dev);
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(dev, "failed to allocate private data\n");
+		ret = -ENOMEM;
+		goto out_unref;
+	}
+	drm->dev_private = priv;
+
+	priv->wq = alloc_ordered_workqueue("etnaviv", 0);
+	if (!priv->wq) {
+		ret = -ENOMEM;
+		goto out_wq;
+	}
+
+	mutex_init(&priv->gem_lock);
+	INIT_LIST_HEAD(&priv->gem_list);
+	priv->num_gpus = 0;
+
+	dev_set_drvdata(dev, drm);
+
+	ret = component_bind_all(dev, drm);
+	if (ret < 0)
+		goto out_bind;
+
+	load_gpu(drm);
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto out_register;
+
+	return 0;
+
+out_register:
+	component_unbind_all(dev, drm);
+out_bind:
+	flush_workqueue(priv->wq);
+	destroy_workqueue(priv->wq);
+out_wq:
+	kfree(priv);
+out_unref:
+	drm_dev_unref(drm);
+
+	return ret;
+}
+
+static void etnaviv_unbind(struct device *dev)
+{
+	struct drm_device *drm = dev_get_drvdata(dev);
+	struct etnaviv_drm_private *priv = drm->dev_private;
+
+	drm_dev_unregister(drm);
+
+	flush_workqueue(priv->wq);
+	destroy_workqueue(priv->wq);
+
+	component_unbind_all(dev, drm);
+
+	drm->dev_private = NULL;
+	kfree(priv);
+
+	drm_put_dev(drm);
+}
+
+static const struct component_master_ops etnaviv_master_ops = {
+	.bind = etnaviv_bind,
+	.unbind = etnaviv_unbind,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+	struct device_node *np = data;
+
+	return dev->of_node == np;
+}
+
+static int compare_str(struct device *dev, void *data)
+{
+	return !strcmp(dev_name(dev), data);
+}
+
+static int etnaviv_pdev_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct component_match *match = NULL;
+
+	dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+	if (node) {
+		struct device_node *core_node;
+		int i;
+
+		for (i = 0; ; i++) {
+			core_node = of_parse_phandle(node, "cores", i);
+			if (!core_node)
+				break;
+
+			component_match_add(&pdev->dev, &match, compare_of,
+					    core_node);
+			of_node_put(core_node);
+		}
+	} else if (dev->platform_data) {
+		char **names = dev->platform_data;
+		unsigned i;
+
+		for (i = 0; names[i]; i++)
+			component_match_add(dev, &match, compare_str, names[i]);
+	}
+
+	return component_master_add_with_match(dev, &etnaviv_master_ops, match);
+}
+
+static int etnaviv_pdev_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &etnaviv_master_ops);
+
+	return 0;
+}
+
+static const struct of_device_id dt_match[] = {
+	{ .compatible = "fsl,imx-gpu-subsystem" },
+	{ .compatible = "marvell,dove-gpu-subsystem" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, dt_match);
+
+static struct platform_driver etnaviv_platform_driver = {
+	.probe      = etnaviv_pdev_probe,
+	.remove     = etnaviv_pdev_remove,
+	.driver     = {
+		.owner  = THIS_MODULE,
+		.name   = "etnaviv",
+		.of_match_table = dt_match,
+	},
+};
+
+static int __init etnaviv_init(void)
+{
+	int ret;
+
+	etnaviv_validate_init();
+
+	ret = platform_driver_register(&etnaviv_gpu_driver);
+	if (ret != 0)
+		return ret;
+
+	ret = platform_driver_register(&etnaviv_platform_driver);
+	if (ret != 0)
+		platform_driver_unregister(&etnaviv_gpu_driver);
+
+	return ret;
+}
+module_init(etnaviv_init);
+
+static void __exit etnaviv_exit(void)
+{
+	platform_driver_unregister(&etnaviv_gpu_driver);
+	platform_driver_unregister(&etnaviv_platform_driver);
+}
+module_exit(etnaviv_exit);
+
+MODULE_AUTHOR("Christian Gmeiner <christian.gmeiner@gmail.com>");
+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
+MODULE_AUTHOR("Lucas Stach <l.stach@pengutronix.de>");
+MODULE_DESCRIPTION("etnaviv DRM Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:etnaviv");
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
new file mode 100644
index 0000000..d6bd438
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 __ETNAVIV_DRV_H__
+#define __ETNAVIV_DRV_H__
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/iommu.h>
+#include <linux/types.h>
+#include <linux/sizes.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/etnaviv_drm.h>
+
+struct etnaviv_cmdbuf;
+struct etnaviv_gpu;
+struct etnaviv_mmu;
+struct etnaviv_gem_object;
+struct etnaviv_gem_submit;
+
+struct etnaviv_file_private {
+	/* currently we don't do anything useful with this.. but when
+	 * per-context address spaces are supported we'd keep track of
+	 * the context's page-tables here.
+	 */
+	int dummy;
+};
+
+struct etnaviv_drm_private {
+	int num_gpus;
+	struct etnaviv_gpu *gpu[ETNA_MAX_PIPES];
+
+	/* list of GEM objects: */
+	struct mutex gem_lock;
+	struct list_head gem_list;
+
+	struct workqueue_struct *wq;
+};
+
+static inline void etnaviv_queue_work(struct drm_device *dev,
+	struct work_struct *w)
+{
+	struct etnaviv_drm_private *priv = dev->dev_private;
+
+	queue_work(priv->wq, w);
+}
+
+int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
+		struct drm_file *file);
+
+int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset);
+int etnaviv_gem_get_iova(struct etnaviv_gpu *gpu,
+	struct drm_gem_object *obj, u32 *iova);
+void etnaviv_gem_put_iova(struct etnaviv_gpu *gpu, struct drm_gem_object *obj);
+struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj);
+void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj);
+void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
+	struct dma_buf_attachment *attach, struct sg_table *sg);
+int etnaviv_gem_prime_pin(struct drm_gem_object *obj);
+void etnaviv_gem_prime_unpin(struct drm_gem_object *obj);
+void *etnaviv_gem_vaddr(struct drm_gem_object *obj);
+int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op,
+		struct timespec *timeout);
+int etnaviv_gem_cpu_fini(struct drm_gem_object *obj);
+void etnaviv_gem_free_object(struct drm_gem_object *obj);
+int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
+		u32 size, u32 flags, u32 *handle);
+struct drm_gem_object *etnaviv_gem_new_locked(struct drm_device *dev,
+		u32 size, u32 flags);
+struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
+		u32 size, u32 flags);
+int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
+	uintptr_t ptr, u32 size, u32 flags, u32 *handle);
+u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu);
+void etnaviv_buffer_end(struct etnaviv_gpu *gpu);
+void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
+	struct etnaviv_cmdbuf *cmdbuf);
+void etnaviv_validate_init(void);
+bool etnaviv_cmd_validate_one(struct etnaviv_gpu *gpu,
+	u32 *stream, unsigned int size,
+	struct drm_etnaviv_gem_submit_reloc *relocs, unsigned int reloc_size);
+
+#ifdef CONFIG_DEBUG_FS
+void etnaviv_gem_describe_objects(struct etnaviv_drm_private *priv,
+	struct seq_file *m);
+#endif
+
+void __iomem *etnaviv_ioremap(struct platform_device *pdev, const char *name,
+		const char *dbgname);
+void etnaviv_writel(u32 data, void __iomem *addr);
+u32 etnaviv_readl(const void __iomem *addr);
+
+#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+
+/*
+ * Return the storage size of a structure with a variable length array.
+ * The array is nelem elements of elem_size, where the base structure
+ * is defined by base.  If the size overflows size_t, return zero.
+ */
+static inline size_t size_vstruct(size_t nelem, size_t elem_size, size_t base)
+{
+	if (elem_size && nelem > (SIZE_MAX - base) / elem_size)
+		return 0;
+	return base + nelem * elem_size;
+}
+
+/* returns true if fence a comes after fence b */
+static inline bool fence_after(u32 a, u32 b)
+{
+	return (s32)(a - b) > 0;
+}
+
+static inline bool fence_after_eq(u32 a, u32 b)
+{
+	return (s32)(a - b) >= 0;
+}
+
+static inline unsigned long etnaviv_timeout_to_jiffies(
+	const struct timespec *timeout)
+{
+	unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
+	unsigned long start_jiffies = jiffies;
+	unsigned long remaining_jiffies;
+
+	if (time_after(start_jiffies, timeout_jiffies))
+		remaining_jiffies = 0;
+	else
+		remaining_jiffies = timeout_jiffies - start_jiffies;
+
+	return remaining_jiffies;
+}
+
+#endif /* __ETNAVIV_DRV_H__ */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
new file mode 100644
index 0000000..bf8fa85
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 <linux/devcoredump.h>
+#include "etnaviv_dump.h"
+#include "etnaviv_gem.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_mmu.h"
+#include "state.xml.h"
+#include "state_hi.xml.h"
+
+struct core_dump_iterator {
+	void *start;
+	struct etnaviv_dump_object_header *hdr;
+	void *data;
+};
+
+static const unsigned short etnaviv_dump_registers[] = {
+	VIVS_HI_AXI_STATUS,
+	VIVS_HI_CLOCK_CONTROL,
+	VIVS_HI_IDLE_STATE,
+	VIVS_HI_AXI_CONFIG,
+	VIVS_HI_INTR_ENBL,
+	VIVS_HI_CHIP_IDENTITY,
+	VIVS_HI_CHIP_FEATURE,
+	VIVS_HI_CHIP_MODEL,
+	VIVS_HI_CHIP_REV,
+	VIVS_HI_CHIP_DATE,
+	VIVS_HI_CHIP_TIME,
+	VIVS_HI_CHIP_MINOR_FEATURE_0,
+	VIVS_HI_CACHE_CONTROL,
+	VIVS_HI_AXI_CONTROL,
+	VIVS_PM_POWER_CONTROLS,
+	VIVS_PM_MODULE_CONTROLS,
+	VIVS_PM_MODULE_STATUS,
+	VIVS_PM_PULSE_EATER,
+	VIVS_MC_MMU_FE_PAGE_TABLE,
+	VIVS_MC_MMU_TX_PAGE_TABLE,
+	VIVS_MC_MMU_PE_PAGE_TABLE,
+	VIVS_MC_MMU_PEZ_PAGE_TABLE,
+	VIVS_MC_MMU_RA_PAGE_TABLE,
+	VIVS_MC_DEBUG_MEMORY,
+	VIVS_MC_MEMORY_BASE_ADDR_RA,
+	VIVS_MC_MEMORY_BASE_ADDR_FE,
+	VIVS_MC_MEMORY_BASE_ADDR_TX,
+	VIVS_MC_MEMORY_BASE_ADDR_PEZ,
+	VIVS_MC_MEMORY_BASE_ADDR_PE,
+	VIVS_MC_MEMORY_TIMING_CONTROL,
+	VIVS_MC_BUS_CONFIG,
+	VIVS_FE_DMA_STATUS,
+	VIVS_FE_DMA_DEBUG_STATE,
+	VIVS_FE_DMA_ADDRESS,
+	VIVS_FE_DMA_LOW,
+	VIVS_FE_DMA_HIGH,
+	VIVS_FE_AUTO_FLUSH,
+};
+
+static void etnaviv_core_dump_header(struct core_dump_iterator *iter,
+	u32 type, void *data_end)
+{
+	struct etnaviv_dump_object_header *hdr = iter->hdr;
+
+	hdr->magic = cpu_to_le32(ETDUMP_MAGIC);
+	hdr->type = cpu_to_le32(type);
+	hdr->file_offset = cpu_to_le32(iter->data - iter->start);
+	hdr->file_size = cpu_to_le32(data_end - iter->data);
+
+	iter->hdr++;
+	iter->data += hdr->file_size;
+}
+
+static void etnaviv_core_dump_registers(struct core_dump_iterator *iter,
+	struct etnaviv_gpu *gpu)
+{
+	struct etnaviv_dump_registers *reg = iter->data;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(etnaviv_dump_registers); i++, reg++) {
+		reg->reg = etnaviv_dump_registers[i];
+		reg->value = gpu_read(gpu, etnaviv_dump_registers[i]);
+	}
+
+	etnaviv_core_dump_header(iter, ETDUMP_BUF_REG, reg);
+}
+
+static void etnaviv_core_dump_mmu(struct core_dump_iterator *iter,
+	struct etnaviv_gpu *gpu, size_t mmu_size)
+{
+	etnaviv_iommu_dump(gpu->mmu, iter->data);
+
+	etnaviv_core_dump_header(iter, ETDUMP_BUF_MMU, iter->data + mmu_size);
+}
+
+static void etnaviv_core_dump_mem(struct core_dump_iterator *iter, u32 type,
+	void *ptr, size_t size, u64 iova)
+{
+	memcpy(iter->data, ptr, size);
+
+	iter->hdr->iova = cpu_to_le64(iova);
+
+	etnaviv_core_dump_header(iter, type, iter->data + size);
+}
+
+void etnaviv_core_dump(struct etnaviv_gpu *gpu)
+{
+	struct core_dump_iterator iter;
+	struct etnaviv_vram_mapping *vram;
+	struct etnaviv_gem_object *obj;
+	struct etnaviv_cmdbuf *cmd;
+	unsigned int n_obj, n_bomap_pages;
+	size_t file_size, mmu_size;
+	__le64 *bomap, *bomap_start;
+
+	mmu_size = etnaviv_iommu_dump_size(gpu->mmu);
+
+	/* We always dump registers, mmu, ring and end marker */
+	n_obj = 4;
+	n_bomap_pages = 0;
+	file_size = ARRAY_SIZE(etnaviv_dump_registers) *
+			sizeof(struct etnaviv_dump_registers) +
+		    mmu_size + gpu->buffer->size;
+
+	/* Add in the active command buffers */
+	list_for_each_entry(cmd, &gpu->active_cmd_list, node) {
+		file_size += cmd->size;
+		n_obj++;
+	}
+
+	/* Add in the active buffer objects */
+	list_for_each_entry(vram, &gpu->mmu->mappings, mmu_node) {
+		if (!vram->use)
+			continue;
+
+		obj = vram->object;
+		file_size += obj->base.size;
+		n_bomap_pages += obj->base.size >> PAGE_SHIFT;
+		n_obj++;
+	}
+
+	/* If we have any buffer objects, add a bomap object */
+	if (n_bomap_pages) {
+		file_size += n_bomap_pages * sizeof(__le64);
+		n_obj++;
+	}
+
+	/* Add the size of the headers */
+	file_size += sizeof(*iter.hdr) * n_obj;
+
+	/* Allocate the file in vmalloc memory, it's likely to be big */
+	iter.start = vmalloc(file_size);
+	if (!iter.start) {
+		dev_warn(gpu->dev, "failed to allocate devcoredump file\n");
+		return;
+	}
+
+	/* Point the data member after the headers */
+	iter.hdr = iter.start;
+	iter.data = &iter.hdr[n_obj];
+
+	memset(iter.hdr, 0, iter.data - iter.start);
+
+	etnaviv_core_dump_registers(&iter, gpu);
+	etnaviv_core_dump_mmu(&iter, gpu, mmu_size);
+	etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer->vaddr,
+			      gpu->buffer->size, gpu->buffer->paddr);
+
+	list_for_each_entry(cmd, &gpu->active_cmd_list, node)
+		etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, cmd->vaddr,
+				      cmd->size, cmd->paddr);
+
+	/* Reserve space for the bomap */
+	if (n_bomap_pages) {
+		bomap_start = bomap = iter.data;
+		memset(bomap, 0, sizeof(*bomap) * n_bomap_pages);
+		etnaviv_core_dump_header(&iter, ETDUMP_BUF_BOMAP,
+					 bomap + n_bomap_pages);
+	} else {
+		/* Silence warning */
+		bomap_start = bomap = NULL;
+	}
+
+	list_for_each_entry(vram, &gpu->mmu->mappings, mmu_node) {
+		struct page **pages;
+		void *vaddr;
+
+		if (vram->use == 0)
+			continue;
+
+		obj = vram->object;
+
+		pages = etnaviv_gem_get_pages(obj);
+		if (pages) {
+			int j;
+
+			iter.hdr->data[0] = bomap - bomap_start;
+
+			for (j = 0; j < obj->base.size >> PAGE_SHIFT; j++)
+				*bomap++ = cpu_to_le64(page_to_phys(*pages++));
+		}
+
+		iter.hdr->iova = cpu_to_le64(vram->iova);
+
+		vaddr = etnaviv_gem_vaddr(&obj->base);
+		if (vaddr && !IS_ERR(vaddr))
+			memcpy(iter.data, vaddr, obj->base.size);
+
+		etnaviv_core_dump_header(&iter, ETDUMP_BUF_BO, iter.data +
+					 obj->base.size);
+	}
+
+	etnaviv_core_dump_header(&iter, ETDUMP_BUF_END, iter.data);
+
+	dev_coredumpv(gpu->dev, iter.start, iter.data - iter.start, GFP_KERNEL);
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.h b/drivers/gpu/drm/etnaviv/etnaviv_dump.h
new file mode 100644
index 0000000..97f2f8d
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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/>.
+ *
+ * Etnaviv devcoredump file definitions
+ */
+#ifndef ETNAVIV_DUMP_H
+#define ETNAVIV_DUMP_H
+
+#include <linux/types.h>
+
+enum {
+	ETDUMP_MAGIC = 0x414e5445,
+	ETDUMP_BUF_REG = 0,
+	ETDUMP_BUF_MMU,
+	ETDUMP_BUF_RING,
+	ETDUMP_BUF_CMD,
+	ETDUMP_BUF_BOMAP,
+	ETDUMP_BUF_BO,
+	ETDUMP_BUF_END,
+};
+
+struct etnaviv_dump_object_header {
+	__le32 magic;
+	__le32 type;
+	__le32 file_offset;
+	__le32 file_size;
+	__le64 iova;
+	__le32 data[2];
+};
+
+/* Registers object, an array of these */
+struct etnaviv_dump_registers {
+	__le32 reg;
+	__le32 value;
+};
+
+#ifdef __KERNEL__
+struct etnaviv_gpu;
+void etnaviv_core_dump(struct etnaviv_gpu *gpu);
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
new file mode 100644
index 0000000..9f77c3b
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -0,0 +1,899 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 <linux/spinlock.h>
+#include <linux/shmem_fs.h>
+
+#include "etnaviv_drv.h"
+#include "etnaviv_gem.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_mmu.h"
+
+static void etnaviv_gem_scatter_map(struct etnaviv_gem_object *etnaviv_obj)
+{
+	struct drm_device *dev = etnaviv_obj->base.dev;
+	struct sg_table *sgt = etnaviv_obj->sgt;
+
+	/*
+	 * For non-cached buffers, ensure the new pages are clean
+	 * because display controller, GPU, etc. are not coherent.
+	 */
+	if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK)
+		dma_map_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+}
+
+static void etnaviv_gem_scatterlist_unmap(struct etnaviv_gem_object *etnaviv_obj)
+{
+	struct drm_device *dev = etnaviv_obj->base.dev;
+	struct sg_table *sgt = etnaviv_obj->sgt;
+
+	/*
+	 * For non-cached buffers, ensure the new pages are clean
+	 * because display controller, GPU, etc. are not coherent:
+	 *
+	 * WARNING: The DMA API does not support concurrent CPU
+	 * and device access to the memory area.  With BIDIRECTIONAL,
+	 * we will clean the cache lines which overlap the region,
+	 * and invalidate all cache lines (partially) contained in
+	 * the region.
+	 *
+	 * If you have dirty data in the overlapping cache lines,
+	 * that will corrupt the GPU-written data.  If you have
+	 * written into the remainder of the region, this can
+	 * discard those writes.
+	 */
+	if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK)
+		dma_unmap_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+}
+
+/* called with etnaviv_obj->lock held */
+static int etnaviv_gem_shmem_get_pages(struct etnaviv_gem_object *etnaviv_obj)
+{
+	struct drm_device *dev = etnaviv_obj->base.dev;
+	struct page **p = drm_gem_get_pages(&etnaviv_obj->base);
+
+	if (IS_ERR(p)) {
+		dev_err(dev->dev, "could not get pages: %ld\n", PTR_ERR(p));
+		return PTR_ERR(p);
+	}
+
+	etnaviv_obj->pages = p;
+
+	return 0;
+}
+
+static void put_pages(struct etnaviv_gem_object *etnaviv_obj)
+{
+	if (etnaviv_obj->sgt) {
+		etnaviv_gem_scatterlist_unmap(etnaviv_obj);
+		sg_free_table(etnaviv_obj->sgt);
+		kfree(etnaviv_obj->sgt);
+		etnaviv_obj->sgt = NULL;
+	}
+	if (etnaviv_obj->pages) {
+		drm_gem_put_pages(&etnaviv_obj->base, etnaviv_obj->pages,
+				  true, false);
+
+		etnaviv_obj->pages = NULL;
+	}
+}
+
+struct page **etnaviv_gem_get_pages(struct etnaviv_gem_object *etnaviv_obj)
+{
+	int ret;
+
+	lockdep_assert_held(&etnaviv_obj->lock);
+
+	if (!etnaviv_obj->pages) {
+		ret = etnaviv_obj->ops->get_pages(etnaviv_obj);
+		if (ret < 0)
+			return ERR_PTR(ret);
+	}
+
+	if (!etnaviv_obj->sgt) {
+		struct drm_device *dev = etnaviv_obj->base.dev;
+		int npages = etnaviv_obj->base.size >> PAGE_SHIFT;
+		struct sg_table *sgt;
+
+		sgt = drm_prime_pages_to_sg(etnaviv_obj->pages, npages);
+		if (IS_ERR(sgt)) {
+			dev_err(dev->dev, "failed to allocate sgt: %ld\n",
+				PTR_ERR(sgt));
+			return ERR_CAST(sgt);
+		}
+
+		etnaviv_obj->sgt = sgt;
+
+		etnaviv_gem_scatter_map(etnaviv_obj);
+	}
+
+	return etnaviv_obj->pages;
+}
+
+void etnaviv_gem_put_pages(struct etnaviv_gem_object *etnaviv_obj)
+{
+	lockdep_assert_held(&etnaviv_obj->lock);
+	/* when we start tracking the pin count, then do something here */
+}
+
+static int etnaviv_gem_mmap_obj(struct drm_gem_object *obj,
+		struct vm_area_struct *vma)
+{
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+	pgprot_t vm_page_prot;
+
+	vma->vm_flags &= ~VM_PFNMAP;
+	vma->vm_flags |= VM_MIXEDMAP;
+
+	vm_page_prot = vm_get_page_prot(vma->vm_flags);
+
+	if (etnaviv_obj->flags & ETNA_BO_WC) {
+		vma->vm_page_prot = pgprot_writecombine(vm_page_prot);
+	} else if (etnaviv_obj->flags & ETNA_BO_UNCACHED) {
+		vma->vm_page_prot = pgprot_noncached(vm_page_prot);
+	} else {
+		/*
+		 * Shunt off cached objs to shmem file so they have their own
+		 * address_space (so unmap_mapping_range does what we want,
+		 * in particular in the case of mmap'd dmabufs)
+		 */
+		fput(vma->vm_file);
+		get_file(obj->filp);
+		vma->vm_pgoff = 0;
+		vma->vm_file  = obj->filp;
+
+		vma->vm_page_prot = vm_page_prot;
+	}
+
+	return 0;
+}
+
+int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct etnaviv_gem_object *obj;
+	int ret;
+
+	ret = drm_gem_mmap(filp, vma);
+	if (ret) {
+		DBG("mmap failed: %d", ret);
+		return ret;
+	}
+
+	obj = to_etnaviv_bo(vma->vm_private_data);
+	return etnaviv_gem_mmap_obj(vma->vm_private_data, vma);
+}
+
+int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct drm_gem_object *obj = vma->vm_private_data;
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+	struct page **pages, *page;
+	pgoff_t pgoff;
+	int ret;
+
+	/*
+	 * Make sure we don't parallel update on a fault, nor move or remove
+	 * something from beneath our feet.  Note that vm_insert_page() is
+	 * specifically coded to take care of this, so we don't have to.
+	 */
+	ret = mutex_lock_interruptible(&etnaviv_obj->lock);
+	if (ret)
+		goto out;
+
+	/* make sure we have pages attached now */
+	pages = etnaviv_gem_get_pages(etnaviv_obj);
+	mutex_unlock(&etnaviv_obj->lock);
+
+	if (IS_ERR(pages)) {
+		ret = PTR_ERR(pages);
+		goto out;
+	}
+
+	/* We don't use vmf->pgoff since that has the fake offset: */
+	pgoff = ((unsigned long)vmf->virtual_address -
+			vma->vm_start) >> PAGE_SHIFT;
+
+	page = pages[pgoff];
+
+	VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
+	     page_to_pfn(page), page_to_pfn(page) << PAGE_SHIFT);
+
+	ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page);
+
+out:
+	switch (ret) {
+	case -EAGAIN:
+	case 0:
+	case -ERESTARTSYS:
+	case -EINTR:
+	case -EBUSY:
+		/*
+		 * EBUSY is ok: this just means that another thread
+		 * already did the job.
+		 */
+		return VM_FAULT_NOPAGE;
+	case -ENOMEM:
+		return VM_FAULT_OOM;
+	default:
+		return VM_FAULT_SIGBUS;
+	}
+}
+
+int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset)
+{
+	int ret;
+
+	/* Make it mmapable */
+	ret = drm_gem_create_mmap_offset(obj);
+	if (ret)
+		dev_err(obj->dev->dev, "could not allocate mmap offset\n");
+	else
+		*offset = drm_vma_node_offset_addr(&obj->vma_node);
+
+	return ret;
+}
+
+static struct etnaviv_vram_mapping *
+etnaviv_gem_get_vram_mapping(struct etnaviv_gem_object *obj,
+			     struct etnaviv_iommu *mmu)
+{
+	struct etnaviv_vram_mapping *mapping;
+
+	list_for_each_entry(mapping, &obj->vram_list, obj_node) {
+		if (mapping->mmu == mmu)
+			return mapping;
+	}
+
+	return NULL;
+}
+
+int etnaviv_gem_get_iova(struct etnaviv_gpu *gpu,
+	struct drm_gem_object *obj, u32 *iova)
+{
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+	struct etnaviv_vram_mapping *mapping;
+	struct page **pages;
+	int ret = 0;
+
+	mutex_lock(&etnaviv_obj->lock);
+	mapping = etnaviv_gem_get_vram_mapping(etnaviv_obj, gpu->mmu);
+	if (mapping) {
+		/*
+		 * Holding the object lock prevents the use count changing
+		 * beneath us.  If the use count is zero, the MMU might be
+		 * reaping this object, so take the lock and re-check that
+		 * the MMU owns this mapping to close this race.
+		 */
+		if (mapping->use == 0) {
+			mutex_lock(&gpu->mmu->lock);
+			if (mapping->mmu == gpu->mmu)
+				mapping->use += 1;
+			else
+				mapping = NULL;
+			mutex_unlock(&gpu->mmu->lock);
+			if (mapping)
+				goto out;
+		} else {
+			mapping->use += 1;
+			goto out;
+		}
+	}
+
+	pages = etnaviv_gem_get_pages(etnaviv_obj);
+	if (IS_ERR(pages)) {
+		ret = PTR_ERR(pages);
+		goto out;
+	}
+
+	/*
+	 * See if we have a reaped vram mapping we can re-use before
+	 * allocating a fresh mapping.
+	 */
+	mapping = etnaviv_gem_get_vram_mapping(etnaviv_obj, NULL);
+	if (!mapping) {
+		mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+		if (!mapping) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		INIT_LIST_HEAD(&mapping->scan_node);
+		mapping->object = etnaviv_obj;
+	} else {
+		list_del(&mapping->obj_node);
+	}
+
+	mapping->mmu = gpu->mmu;
+	mapping->use = 1;
+
+	ret = etnaviv_iommu_map_gem(gpu->mmu, etnaviv_obj, gpu->memory_base,
+				    mapping);
+	if (ret < 0)
+		kfree(mapping);
+	else
+		list_add_tail(&mapping->obj_node, &etnaviv_obj->vram_list);
+
+out:
+	mutex_unlock(&etnaviv_obj->lock);
+
+	if (!ret) {
+		/* Take a reference on the object */
+		drm_gem_object_reference(obj);
+		*iova = mapping->iova;
+	}
+
+	return ret;
+}
+
+void etnaviv_gem_put_iova(struct etnaviv_gpu *gpu, struct drm_gem_object *obj)
+{
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+	struct etnaviv_vram_mapping *mapping;
+
+	mutex_lock(&etnaviv_obj->lock);
+	mapping = etnaviv_gem_get_vram_mapping(etnaviv_obj, gpu->mmu);
+
+	WARN_ON(mapping->use == 0);
+	mapping->use -= 1;
+	mutex_unlock(&etnaviv_obj->lock);
+
+	drm_gem_object_unreference_unlocked(obj);
+}
+
+void *etnaviv_gem_vaddr(struct drm_gem_object *obj)
+{
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+	mutex_lock(&etnaviv_obj->lock);
+	if (!etnaviv_obj->vaddr) {
+		struct page **pages = etnaviv_gem_get_pages(etnaviv_obj);
+
+		if (IS_ERR(pages))
+			return ERR_CAST(pages);
+
+		etnaviv_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
+				VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+	}
+	mutex_unlock(&etnaviv_obj->lock);
+
+	return etnaviv_obj->vaddr;
+}
+
+static inline enum dma_data_direction etnaviv_op_to_dma_dir(u32 op)
+{
+	if (op & ETNA_PREP_READ)
+		return DMA_FROM_DEVICE;
+	else if (op & ETNA_PREP_WRITE)
+		return DMA_TO_DEVICE;
+	else
+		return DMA_BIDIRECTIONAL;
+}
+
+int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op,
+		struct timespec *timeout)
+{
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+	struct drm_device *dev = obj->dev;
+	bool write = !!(op & ETNA_PREP_WRITE);
+	int ret;
+
+	if (op & ETNA_PREP_NOSYNC) {
+		if (!reservation_object_test_signaled_rcu(etnaviv_obj->resv,
+							  write))
+			return -EBUSY;
+	} else {
+		unsigned long remain = etnaviv_timeout_to_jiffies(timeout);
+
+		ret = reservation_object_wait_timeout_rcu(etnaviv_obj->resv,
+							  write, true, remain);
+		if (ret <= 0)
+			return ret == 0 ? -ETIMEDOUT : ret;
+	}
+
+	if (etnaviv_obj->flags & ETNA_BO_CACHED) {
+		if (!etnaviv_obj->sgt) {
+			void *ret;
+
+			mutex_lock(&etnaviv_obj->lock);
+			ret = etnaviv_gem_get_pages(etnaviv_obj);
+			mutex_unlock(&etnaviv_obj->lock);
+			if (IS_ERR(ret))
+				return PTR_ERR(ret);
+		}
+
+		dma_sync_sg_for_cpu(dev->dev, etnaviv_obj->sgt->sgl,
+				    etnaviv_obj->sgt->nents,
+				    etnaviv_op_to_dma_dir(op));
+		etnaviv_obj->last_cpu_prep_op = op;
+	}
+
+	return 0;
+}
+
+int etnaviv_gem_cpu_fini(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+	if (etnaviv_obj->flags & ETNA_BO_CACHED) {
+		/* fini without a prep is almost certainly a userspace error */
+		WARN_ON(etnaviv_obj->last_cpu_prep_op == 0);
+		dma_sync_sg_for_device(dev->dev, etnaviv_obj->sgt->sgl,
+			etnaviv_obj->sgt->nents,
+			etnaviv_op_to_dma_dir(etnaviv_obj->last_cpu_prep_op));
+		etnaviv_obj->last_cpu_prep_op = 0;
+	}
+
+	return 0;
+}
+
+int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
+	struct timespec *timeout)
+{
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+	return etnaviv_gpu_wait_obj_inactive(gpu, etnaviv_obj, timeout);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void etnaviv_gem_describe_fence(struct fence *fence,
+	const char *type, struct seq_file *m)
+{
+	if (!test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+		seq_printf(m, "\t%9s: %s %s seq %u\n",
+			   type,
+			   fence->ops->get_driver_name(fence),
+			   fence->ops->get_timeline_name(fence),
+			   fence->seqno);
+}
+
+static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
+{
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+	struct reservation_object *robj = etnaviv_obj->resv;
+	struct reservation_object_list *fobj;
+	struct fence *fence;
+	unsigned long off = drm_vma_node_start(&obj->vma_node);
+
+	seq_printf(m, "%08x: %c %2d (%2d) %08lx %p %zd\n",
+			etnaviv_obj->flags, is_active(etnaviv_obj) ? 'A' : 'I',
+			obj->name, obj->refcount.refcount.counter,
+			off, etnaviv_obj->vaddr, obj->size);
+
+	rcu_read_lock();
+	fobj = rcu_dereference(robj->fence);
+	if (fobj) {
+		unsigned int i, shared_count = fobj->shared_count;
+
+		for (i = 0; i < shared_count; i++) {
+			fence = rcu_dereference(fobj->shared[i]);
+			etnaviv_gem_describe_fence(fence, "Shared", m);
+		}
+	}
+
+	fence = rcu_dereference(robj->fence_excl);
+	if (fence)
+		etnaviv_gem_describe_fence(fence, "Exclusive", m);
+	rcu_read_unlock();
+}
+
+void etnaviv_gem_describe_objects(struct etnaviv_drm_private *priv,
+	struct seq_file *m)
+{
+	struct etnaviv_gem_object *etnaviv_obj;
+	int count = 0;
+	size_t size = 0;
+
+	mutex_lock(&priv->gem_lock);
+	list_for_each_entry(etnaviv_obj, &priv->gem_list, gem_node) {
+		struct drm_gem_object *obj = &etnaviv_obj->base;
+
+		seq_puts(m, "   ");
+		etnaviv_gem_describe(obj, m);
+		count++;
+		size += obj->size;
+	}
+	mutex_unlock(&priv->gem_lock);
+
+	seq_printf(m, "Total %d objects, %zu bytes\n", count, size);
+}
+#endif
+
+static void etnaviv_gem_shmem_release(struct etnaviv_gem_object *etnaviv_obj)
+{
+	if (etnaviv_obj->vaddr)
+		vunmap(etnaviv_obj->vaddr);
+	put_pages(etnaviv_obj);
+}
+
+static const struct etnaviv_gem_ops etnaviv_gem_shmem_ops = {
+	.get_pages = etnaviv_gem_shmem_get_pages,
+	.release = etnaviv_gem_shmem_release,
+};
+
+void etnaviv_gem_free_object(struct drm_gem_object *obj)
+{
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+	struct etnaviv_vram_mapping *mapping, *tmp;
+
+	/* object should not be active */
+	WARN_ON(is_active(etnaviv_obj));
+
+	list_del(&etnaviv_obj->gem_node);
+
+	list_for_each_entry_safe(mapping, tmp, &etnaviv_obj->vram_list,
+				 obj_node) {
+		struct etnaviv_iommu *mmu = mapping->mmu;
+
+		WARN_ON(mapping->use);
+
+		if (mmu)
+			etnaviv_iommu_unmap_gem(mmu, mapping);
+
+		list_del(&mapping->obj_node);
+		kfree(mapping);
+	}
+
+	drm_gem_free_mmap_offset(obj);
+	etnaviv_obj->ops->release(etnaviv_obj);
+	if (etnaviv_obj->resv == &etnaviv_obj->_resv)
+		reservation_object_fini(&etnaviv_obj->_resv);
+	drm_gem_object_release(obj);
+
+	kfree(etnaviv_obj);
+}
+
+int etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj)
+{
+	struct etnaviv_drm_private *priv = dev->dev_private;
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+	mutex_lock(&priv->gem_lock);
+	list_add_tail(&etnaviv_obj->gem_node, &priv->gem_list);
+	mutex_unlock(&priv->gem_lock);
+
+	return 0;
+}
+
+static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
+	struct reservation_object *robj, const struct etnaviv_gem_ops *ops,
+	struct drm_gem_object **obj)
+{
+	struct etnaviv_gem_object *etnaviv_obj;
+	unsigned sz = sizeof(*etnaviv_obj);
+	bool valid = true;
+
+	/* validate flags */
+	switch (flags & ETNA_BO_CACHE_MASK) {
+	case ETNA_BO_UNCACHED:
+	case ETNA_BO_CACHED:
+	case ETNA_BO_WC:
+		break;
+	default:
+		valid = false;
+	}
+
+	if (!valid) {
+		dev_err(dev->dev, "invalid cache flag: %x\n",
+			(flags & ETNA_BO_CACHE_MASK));
+		return -EINVAL;
+	}
+
+	etnaviv_obj = kzalloc(sz, GFP_KERNEL);
+	if (!etnaviv_obj)
+		return -ENOMEM;
+
+	etnaviv_obj->flags = flags;
+	etnaviv_obj->ops = ops;
+	if (robj) {
+		etnaviv_obj->resv = robj;
+	} else {
+		etnaviv_obj->resv = &etnaviv_obj->_resv;
+		reservation_object_init(&etnaviv_obj->_resv);
+	}
+
+	mutex_init(&etnaviv_obj->lock);
+	INIT_LIST_HEAD(&etnaviv_obj->vram_list);
+
+	*obj = &etnaviv_obj->base;
+
+	return 0;
+}
+
+static struct drm_gem_object *__etnaviv_gem_new(struct drm_device *dev,
+		u32 size, u32 flags)
+{
+	struct drm_gem_object *obj = NULL;
+	int ret;
+
+	size = PAGE_ALIGN(size);
+
+	ret = etnaviv_gem_new_impl(dev, size, flags, NULL,
+				   &etnaviv_gem_shmem_ops, &obj);
+	if (ret)
+		goto fail;
+
+	ret = drm_gem_object_init(dev, obj, size);
+	if (ret == 0) {
+		struct address_space *mapping;
+
+		/*
+		 * Our buffers are kept pinned, so allocating them
+		 * from the MOVABLE zone is a really bad idea, and
+		 * conflicts with CMA.  See coments above new_inode()
+		 * why this is required _and_ expected if you're
+		 * going to pin these pages.
+		 */
+		mapping = file_inode(obj->filp)->i_mapping;
+		mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
+	}
+
+	if (ret)
+		goto fail;
+
+	return obj;
+
+fail:
+	if (obj)
+		drm_gem_object_unreference_unlocked(obj);
+
+	return ERR_PTR(ret);
+}
+
+/* convenience method to construct a GEM buffer object, and userspace handle */
+int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
+		u32 size, u32 flags, u32 *handle)
+{
+	struct drm_gem_object *obj;
+	int ret;
+
+	obj = __etnaviv_gem_new(dev, size, flags);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	ret = etnaviv_gem_obj_add(dev, obj);
+	if (ret < 0) {
+		drm_gem_object_unreference_unlocked(obj);
+		return ret;
+	}
+
+	ret = drm_gem_handle_create(file, obj, handle);
+
+	/* drop reference from allocate - handle holds it now */
+	drm_gem_object_unreference_unlocked(obj);
+
+	return ret;
+}
+
+struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
+		u32 size, u32 flags)
+{
+	struct drm_gem_object *obj;
+	int ret;
+
+	obj = __etnaviv_gem_new(dev, size, flags);
+	if (IS_ERR(obj))
+		return obj;
+
+	ret = etnaviv_gem_obj_add(dev, obj);
+	if (ret < 0) {
+		drm_gem_object_unreference_unlocked(obj);
+		return ERR_PTR(ret);
+	}
+
+	return obj;
+}
+
+int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
+	struct reservation_object *robj, const struct etnaviv_gem_ops *ops,
+	struct etnaviv_gem_object **res)
+{
+	struct drm_gem_object *obj;
+	int ret;
+
+	ret = etnaviv_gem_new_impl(dev, size, flags, robj, ops, &obj);
+	if (ret)
+		return ret;
+
+	drm_gem_private_object_init(dev, obj, size);
+
+	*res = to_etnaviv_bo(obj);
+
+	return 0;
+}
+
+struct get_pages_work {
+	struct work_struct work;
+	struct mm_struct *mm;
+	struct task_struct *task;
+	struct etnaviv_gem_object *etnaviv_obj;
+};
+
+static struct page **etnaviv_gem_userptr_do_get_pages(
+	struct etnaviv_gem_object *etnaviv_obj, struct mm_struct *mm, struct task_struct *task)
+{
+	int ret = 0, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT;
+	struct page **pvec;
+	uintptr_t ptr;
+
+	pvec = drm_malloc_ab(npages, sizeof(struct page *));
+	if (!pvec)
+		return ERR_PTR(-ENOMEM);
+
+	pinned = 0;
+	ptr = etnaviv_obj->userptr.ptr;
+
+	down_read(&mm->mmap_sem);
+	while (pinned < npages) {
+		ret = get_user_pages(task, mm, ptr, npages - pinned,
+				     !etnaviv_obj->userptr.ro, 0,
+				     pvec + pinned, NULL);
+		if (ret < 0)
+			break;
+
+		ptr += ret * PAGE_SIZE;
+		pinned += ret;
+	}
+	up_read(&mm->mmap_sem);
+
+	if (ret < 0) {
+		release_pages(pvec, pinned, 0);
+		drm_free_large(pvec);
+		return ERR_PTR(ret);
+	}
+
+	return pvec;
+}
+
+static void __etnaviv_gem_userptr_get_pages(struct work_struct *_work)
+{
+	struct get_pages_work *work = container_of(_work, typeof(*work), work);
+	struct etnaviv_gem_object *etnaviv_obj = work->etnaviv_obj;
+	struct page **pvec;
+
+	pvec = etnaviv_gem_userptr_do_get_pages(etnaviv_obj, work->mm, work->task);
+
+	mutex_lock(&etnaviv_obj->lock);
+	if (IS_ERR(pvec)) {
+		etnaviv_obj->userptr.work = ERR_CAST(pvec);
+	} else {
+		etnaviv_obj->userptr.work = NULL;
+		etnaviv_obj->pages = pvec;
+	}
+
+	mutex_unlock(&etnaviv_obj->lock);
+	drm_gem_object_unreference_unlocked(&etnaviv_obj->base);
+
+	mmput(work->mm);
+	put_task_struct(work->task);
+	kfree(work);
+}
+
+static int etnaviv_gem_userptr_get_pages(struct etnaviv_gem_object *etnaviv_obj)
+{
+	struct page **pvec = NULL;
+	struct get_pages_work *work;
+	struct mm_struct *mm;
+	int ret, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT;
+
+	if (etnaviv_obj->userptr.work) {
+		if (IS_ERR(etnaviv_obj->userptr.work)) {
+			ret = PTR_ERR(etnaviv_obj->userptr.work);
+			etnaviv_obj->userptr.work = NULL;
+		} else {
+			ret = -EAGAIN;
+		}
+		return ret;
+	}
+
+	mm = get_task_mm(etnaviv_obj->userptr.task);
+	pinned = 0;
+	if (mm == current->mm) {
+		pvec = drm_malloc_ab(npages, sizeof(struct page *));
+		if (!pvec) {
+			mmput(mm);
+			return -ENOMEM;
+		}
+
+		pinned = __get_user_pages_fast(etnaviv_obj->userptr.ptr, npages,
+					       !etnaviv_obj->userptr.ro, pvec);
+		if (pinned < 0) {
+			drm_free_large(pvec);
+			mmput(mm);
+			return pinned;
+		}
+
+		if (pinned == npages) {
+			etnaviv_obj->pages = pvec;
+			mmput(mm);
+			return 0;
+		}
+	}
+
+	release_pages(pvec, pinned, 0);
+	drm_free_large(pvec);
+
+	work = kmalloc(sizeof(*work), GFP_KERNEL);
+	if (!work) {
+		mmput(mm);
+		return -ENOMEM;
+	}
+
+	get_task_struct(current);
+	drm_gem_object_reference(&etnaviv_obj->base);
+
+	work->mm = mm;
+	work->task = current;
+	work->etnaviv_obj = etnaviv_obj;
+
+	etnaviv_obj->userptr.work = &work->work;
+	INIT_WORK(&work->work, __etnaviv_gem_userptr_get_pages);
+
+	etnaviv_queue_work(etnaviv_obj->base.dev, &work->work);
+
+	return -EAGAIN;
+}
+
+static void etnaviv_gem_userptr_release(struct etnaviv_gem_object *etnaviv_obj)
+{
+	if (etnaviv_obj->sgt) {
+		etnaviv_gem_scatterlist_unmap(etnaviv_obj);
+		sg_free_table(etnaviv_obj->sgt);
+		kfree(etnaviv_obj->sgt);
+	}
+	if (etnaviv_obj->pages) {
+		int npages = etnaviv_obj->base.size >> PAGE_SHIFT;
+
+		release_pages(etnaviv_obj->pages, npages, 0);
+		drm_free_large(etnaviv_obj->pages);
+	}
+	put_task_struct(etnaviv_obj->userptr.task);
+}
+
+static const struct etnaviv_gem_ops etnaviv_gem_userptr_ops = {
+	.get_pages = etnaviv_gem_userptr_get_pages,
+	.release = etnaviv_gem_userptr_release,
+};
+
+int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
+	uintptr_t ptr, u32 size, u32 flags, u32 *handle)
+{
+	struct etnaviv_gem_object *etnaviv_obj;
+	int ret;
+
+	ret = etnaviv_gem_new_private(dev, size, ETNA_BO_CACHED, NULL,
+				      &etnaviv_gem_userptr_ops, &etnaviv_obj);
+	if (ret)
+		return ret;
+
+	etnaviv_obj->userptr.ptr = ptr;
+	etnaviv_obj->userptr.task = current;
+	etnaviv_obj->userptr.ro = !(flags & ETNA_USERPTR_WRITE);
+	get_task_struct(current);
+
+	ret = etnaviv_gem_obj_add(dev, &etnaviv_obj->base);
+	if (ret) {
+		drm_gem_object_unreference_unlocked(&etnaviv_obj->base);
+		return ret;
+	}
+
+	ret = drm_gem_handle_create(file, &etnaviv_obj->base, handle);
+
+	/* drop reference from allocate - handle holds it now */
+	drm_gem_object_unreference_unlocked(&etnaviv_obj->base);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
new file mode 100644
index 0000000..a300b4b
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 __ETNAVIV_GEM_H__
+#define __ETNAVIV_GEM_H__
+
+#include <linux/reservation.h>
+#include "etnaviv_drv.h"
+
+struct etnaviv_gem_ops;
+struct etnaviv_gem_object;
+
+struct etnaviv_gem_userptr {
+	uintptr_t ptr;
+	struct task_struct *task;
+	struct work_struct *work;
+	bool ro;
+};
+
+struct etnaviv_vram_mapping {
+	struct list_head obj_node;
+	struct list_head scan_node;
+	struct list_head mmu_node;
+	struct etnaviv_gem_object *object;
+	struct etnaviv_iommu *mmu;
+	struct drm_mm_node vram_node;
+	unsigned int use;
+	u32 iova;
+};
+
+struct etnaviv_gem_object {
+	struct drm_gem_object base;
+	const struct etnaviv_gem_ops *ops;
+	struct mutex lock;
+
+	u32 flags;
+
+	struct list_head gem_node;
+	struct etnaviv_gpu *gpu;     /* non-null if active */
+	atomic_t gpu_active;
+	u32 access;
+
+	struct page **pages;
+	struct sg_table *sgt;
+	void *vaddr;
+
+	/* normally (resv == &_resv) except for imported bo's */
+	struct reservation_object *resv;
+	struct reservation_object _resv;
+
+	struct list_head vram_list;
+
+	/* cache maintenance */
+	u32 last_cpu_prep_op;
+
+	struct etnaviv_gem_userptr userptr;
+};
+
+static inline
+struct etnaviv_gem_object *to_etnaviv_bo(struct drm_gem_object *obj)
+{
+	return container_of(obj, struct etnaviv_gem_object, base);
+}
+
+struct etnaviv_gem_ops {
+	int (*get_pages)(struct etnaviv_gem_object *);
+	void (*release)(struct etnaviv_gem_object *);
+};
+
+static inline bool is_active(struct etnaviv_gem_object *etnaviv_obj)
+{
+	return atomic_read(&etnaviv_obj->gpu_active) != 0;
+}
+
+#define MAX_CMDS 4
+
+/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
+ * associated with the cmdstream submission for synchronization (and
+ * make it easier to unwind when things go wrong, etc).  This only
+ * lasts for the duration of the submit-ioctl.
+ */
+struct etnaviv_gem_submit {
+	struct drm_device *dev;
+	struct etnaviv_gpu *gpu;
+	struct ww_acquire_ctx ticket;
+	u32 fence;
+	unsigned int nr_bos;
+	struct {
+		u32 flags;
+		struct etnaviv_gem_object *obj;
+		u32 iova;
+	} bos[0];
+};
+
+int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
+	struct timespec *timeout);
+int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
+	struct reservation_object *robj, const struct etnaviv_gem_ops *ops,
+	struct etnaviv_gem_object **res);
+int etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj);
+struct page **etnaviv_gem_get_pages(struct etnaviv_gem_object *obj);
+void etnaviv_gem_put_pages(struct etnaviv_gem_object *obj);
+
+#endif /* __ETNAVIV_GEM_H__ */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
new file mode 100644
index 0000000..e94db4f
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
@@ -0,0 +1,122 @@
+/*
+ * 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 <linux/dma-buf.h>
+#include "etnaviv_drv.h"
+#include "etnaviv_gem.h"
+
+
+struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj)
+{
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+	BUG_ON(!etnaviv_obj->sgt);  /* should have already pinned! */
+
+	return etnaviv_obj->sgt;
+}
+
+void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj)
+{
+	return etnaviv_gem_vaddr(obj);
+}
+
+void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+{
+	/* TODO msm_gem_vunmap() */
+}
+
+int etnaviv_gem_prime_pin(struct drm_gem_object *obj)
+{
+	if (!obj->import_attach) {
+		struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+		mutex_lock(&etnaviv_obj->lock);
+		etnaviv_gem_get_pages(etnaviv_obj);
+		mutex_unlock(&etnaviv_obj->lock);
+	}
+	return 0;
+}
+
+void etnaviv_gem_prime_unpin(struct drm_gem_object *obj)
+{
+	if (!obj->import_attach) {
+		struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+		mutex_lock(&etnaviv_obj->lock);
+		etnaviv_gem_put_pages(to_etnaviv_bo(obj));
+		mutex_unlock(&etnaviv_obj->lock);
+	}
+}
+
+static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj)
+{
+	if (etnaviv_obj->vaddr)
+		dma_buf_vunmap(etnaviv_obj->base.import_attach->dmabuf,
+			       etnaviv_obj->vaddr);
+
+	/* Don't drop the pages for imported dmabuf, as they are not
+	 * ours, just free the array we allocated:
+	 */
+	if (etnaviv_obj->pages)
+		drm_free_large(etnaviv_obj->pages);
+
+	drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt);
+}
+
+static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
+	/* .get_pages should never be called */
+	.release = etnaviv_gem_prime_release,
+};
+
+struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
+	struct dma_buf_attachment *attach, struct sg_table *sgt)
+{
+	struct etnaviv_gem_object *etnaviv_obj;
+	size_t size = PAGE_ALIGN(attach->dmabuf->size);
+	int ret, npages;
+
+	ret = etnaviv_gem_new_private(dev, size, ETNA_BO_WC,
+				      attach->dmabuf->resv,
+				      &etnaviv_gem_prime_ops, &etnaviv_obj);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	npages = size / PAGE_SIZE;
+
+	etnaviv_obj->sgt = sgt;
+	etnaviv_obj->pages = drm_malloc_ab(npages, sizeof(struct page *));
+	if (!etnaviv_obj->pages) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	ret = drm_prime_sg_to_page_addr_arrays(sgt, etnaviv_obj->pages,
+					       NULL, npages);
+	if (ret)
+		goto fail;
+
+	ret = etnaviv_gem_obj_add(dev, &etnaviv_obj->base);
+	if (ret)
+		goto fail;
+
+	return &etnaviv_obj->base;
+
+fail:
+	drm_gem_object_unreference_unlocked(&etnaviv_obj->base);
+
+	return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
new file mode 100644
index 0000000..1aba01a
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 <linux/reservation.h>
+#include "etnaviv_drv.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_gem.h"
+
+/*
+ * Cmdstream submission:
+ */
+
+#define BO_INVALID_FLAGS ~(ETNA_SUBMIT_BO_READ | ETNA_SUBMIT_BO_WRITE)
+/* make sure these don't conflict w/ ETNAVIV_SUBMIT_BO_x */
+#define BO_LOCKED   0x4000
+#define BO_PINNED   0x2000
+
+static inline void __user *to_user_ptr(u64 address)
+{
+	return (void __user *)(uintptr_t)address;
+}
+
+static struct etnaviv_gem_submit *submit_create(struct drm_device *dev,
+		struct etnaviv_gpu *gpu, size_t nr)
+{
+	struct etnaviv_gem_submit *submit;
+	size_t sz = size_vstruct(nr, sizeof(submit->bos[0]), sizeof(*submit));
+
+	submit = kmalloc(sz, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
+	if (submit) {
+		submit->dev = dev;
+		submit->gpu = gpu;
+
+		/* initially, until copy_from_user() and bo lookup succeeds: */
+		submit->nr_bos = 0;
+
+		ww_acquire_init(&submit->ticket, &reservation_ww_class);
+	}
+
+	return submit;
+}
+
+static int submit_lookup_objects(struct etnaviv_gem_submit *submit,
+	struct drm_file *file, struct drm_etnaviv_gem_submit_bo *submit_bos,
+	unsigned nr_bos)
+{
+	struct drm_etnaviv_gem_submit_bo *bo;
+	unsigned i;
+	int ret = 0;
+
+	spin_lock(&file->table_lock);
+
+	for (i = 0, bo = submit_bos; i < nr_bos; i++, bo++) {
+		struct drm_gem_object *obj;
+
+		if (bo->flags & BO_INVALID_FLAGS) {
+			DRM_ERROR("invalid flags: %x\n", bo->flags);
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+
+		submit->bos[i].flags = bo->flags;
+
+		/* normally use drm_gem_object_lookup(), but for bulk lookup
+		 * all under single table_lock just hit object_idr directly:
+		 */
+		obj = idr_find(&file->object_idr, bo->handle);
+		if (!obj) {
+			DRM_ERROR("invalid handle %u at index %u\n",
+				  bo->handle, i);
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+
+		/*
+		 * Take a refcount on the object. The file table lock
+		 * prevents the object_idr's refcount on this being dropped.
+		 */
+		drm_gem_object_reference(obj);
+
+		submit->bos[i].obj = to_etnaviv_bo(obj);
+	}
+
+out_unlock:
+	submit->nr_bos = i;
+	spin_unlock(&file->table_lock);
+
+	return ret;
+}
+
+static void submit_unlock_object(struct etnaviv_gem_submit *submit, int i)
+{
+	if (submit->bos[i].flags & BO_LOCKED) {
+		struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+
+		ww_mutex_unlock(&etnaviv_obj->resv->lock);
+		submit->bos[i].flags &= ~BO_LOCKED;
+	}
+}
+
+static int submit_lock_objects(struct etnaviv_gem_submit *submit)
+{
+	int contended, slow_locked = -1, i, ret = 0;
+
+retry:
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+
+		if (slow_locked == i)
+			slow_locked = -1;
+
+		contended = i;
+
+		if (!(submit->bos[i].flags & BO_LOCKED)) {
+			ret = ww_mutex_lock_interruptible(&etnaviv_obj->resv->lock,
+					&submit->ticket);
+			if (ret == -EALREADY)
+				DRM_ERROR("BO at index %u already on submit list\n",
+					  i);
+			if (ret)
+				goto fail;
+			submit->bos[i].flags |= BO_LOCKED;
+		}
+	}
+
+	ww_acquire_done(&submit->ticket);
+
+	return 0;
+
+fail:
+	for (; i >= 0; i--)
+		submit_unlock_object(submit, i);
+
+	if (slow_locked > 0)
+		submit_unlock_object(submit, slow_locked);
+
+	if (ret == -EDEADLK) {
+		struct etnaviv_gem_object *etnaviv_obj;
+
+		etnaviv_obj = submit->bos[contended].obj;
+
+		/* we lost out in a seqno race, lock and retry.. */
+		ret = ww_mutex_lock_slow_interruptible(&etnaviv_obj->resv->lock,
+				&submit->ticket);
+		if (!ret) {
+			submit->bos[contended].flags |= BO_LOCKED;
+			slow_locked = contended;
+			goto retry;
+		}
+	}
+
+	return ret;
+}
+
+static int submit_fence_sync(const struct etnaviv_gem_submit *submit)
+{
+	unsigned int context = submit->gpu->fence_context;
+	int i, ret = 0;
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+		bool write = submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE;
+
+		ret = etnaviv_gpu_fence_sync_obj(etnaviv_obj, context, write);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static void submit_unpin_objects(struct etnaviv_gem_submit *submit)
+{
+	int i;
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+
+		if (submit->bos[i].flags & BO_PINNED)
+			etnaviv_gem_put_iova(submit->gpu, &etnaviv_obj->base);
+
+		submit->bos[i].iova = 0;
+		submit->bos[i].flags &= ~BO_PINNED;
+	}
+}
+
+static int submit_pin_objects(struct etnaviv_gem_submit *submit)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+		u32 iova;
+
+		ret = etnaviv_gem_get_iova(submit->gpu, &etnaviv_obj->base,
+					   &iova);
+		if (ret)
+			break;
+
+		submit->bos[i].flags |= BO_PINNED;
+		submit->bos[i].iova = iova;
+	}
+
+	return ret;
+}
+
+static int submit_bo(struct etnaviv_gem_submit *submit, u32 idx,
+		struct etnaviv_gem_object **obj, u32 *iova)
+{
+	if (idx >= submit->nr_bos) {
+		DRM_ERROR("invalid buffer index: %u (out of %u)\n",
+				idx, submit->nr_bos);
+		return -EINVAL;
+	}
+
+	if (obj)
+		*obj = submit->bos[idx].obj;
+	if (iova)
+		*iova = submit->bos[idx].iova;
+
+	return 0;
+}
+
+/* process the reloc's and patch up the cmdstream as needed: */
+static int submit_reloc(struct etnaviv_gem_submit *submit, void *stream,
+		u32 size, const struct drm_etnaviv_gem_submit_reloc *relocs,
+		u32 nr_relocs)
+{
+	u32 i, last_offset = 0;
+	u32 *ptr = stream;
+	int ret;
+
+	for (i = 0; i < nr_relocs; i++) {
+		const struct drm_etnaviv_gem_submit_reloc *r = relocs + i;
+		struct etnaviv_gem_object *bobj;
+		u32 iova, off;
+
+		if (unlikely(r->flags)) {
+			DRM_ERROR("invalid reloc flags\n");
+			return -EINVAL;
+		}
+
+		if (r->submit_offset % 4) {
+			DRM_ERROR("non-aligned reloc offset: %u\n",
+				  r->submit_offset);
+			return -EINVAL;
+		}
+
+		/* offset in dwords: */
+		off = r->submit_offset / 4;
+
+		if ((off >= size ) ||
+				(off < last_offset)) {
+			DRM_ERROR("invalid offset %u at reloc %u\n", off, i);
+			return -EINVAL;
+		}
+
+		ret = submit_bo(submit, r->reloc_idx, &bobj, &iova);
+		if (ret)
+			return ret;
+
+		if (r->reloc_offset >=
+		    bobj->base.size - sizeof(*ptr)) {
+			DRM_ERROR("relocation %u outside object", i);
+			return -EINVAL;
+		}
+
+		ptr[off] = iova + r->reloc_offset;
+
+		last_offset = off;
+	}
+
+	return 0;
+}
+
+static void submit_cleanup(struct etnaviv_gem_submit *submit)
+{
+	unsigned i;
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+
+		submit_unlock_object(submit, i);
+		drm_gem_object_unreference_unlocked(&etnaviv_obj->base);
+	}
+
+	ww_acquire_fini(&submit->ticket);
+	kfree(submit);
+}
+
+int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
+		struct drm_file *file)
+{
+	struct etnaviv_drm_private *priv = dev->dev_private;
+	struct drm_etnaviv_gem_submit *args = data;
+	struct drm_etnaviv_gem_submit_reloc *relocs;
+	struct drm_etnaviv_gem_submit_bo *bos;
+	struct etnaviv_gem_submit *submit;
+	struct etnaviv_cmdbuf *cmdbuf;
+	struct etnaviv_gpu *gpu;
+	void *stream;
+	int ret;
+
+	if (args->pipe >= ETNA_MAX_PIPES)
+		return -EINVAL;
+
+	gpu = priv->gpu[args->pipe];
+	if (!gpu)
+		return -ENXIO;
+
+	if (args->stream_size % 4) {
+		DRM_ERROR("non-aligned cmdstream buffer size: %u\n",
+			  args->stream_size);
+		return -EINVAL;
+	}
+
+	if (args->exec_state != ETNA_PIPE_3D &&
+	    args->exec_state != ETNA_PIPE_2D &&
+	    args->exec_state != ETNA_PIPE_VG) {
+		DRM_ERROR("invalid exec_state: 0x%x\n", args->exec_state);
+		return -EINVAL;
+	}
+
+	/*
+	 * Copy the command submission and bo array to kernel space in
+	 * one go, and do this outside of any locks.
+	 */
+	bos = drm_malloc_ab(args->nr_bos, sizeof(*bos));
+	relocs = drm_malloc_ab(args->nr_relocs, sizeof(*relocs));
+	stream = drm_malloc_ab(1, args->stream_size);
+	cmdbuf = etnaviv_gpu_cmdbuf_new(gpu, ALIGN(args->stream_size, 8) + 8,
+					args->nr_bos);
+	if (!bos || !relocs || !stream || !cmdbuf) {
+		ret = -ENOMEM;
+		goto err_submit_cmds;
+	}
+
+	cmdbuf->exec_state = args->exec_state;
+	cmdbuf->ctx = file->driver_priv;
+
+	ret = copy_from_user(bos, to_user_ptr(args->bos),
+			     args->nr_bos * sizeof(*bos));
+	if (ret) {
+		ret = -EFAULT;
+		goto err_submit_cmds;
+	}
+
+	ret = copy_from_user(relocs, to_user_ptr(args->relocs),
+			     args->nr_relocs * sizeof(*relocs));
+	if (ret) {
+		ret = -EFAULT;
+		goto err_submit_cmds;
+	}
+
+	ret = copy_from_user(stream, to_user_ptr(args->stream),
+			     args->stream_size);
+	if (ret) {
+		ret = -EFAULT;
+		goto err_submit_cmds;
+	}
+
+	submit = submit_create(dev, gpu, args->nr_bos);
+	if (!submit) {
+		ret = -ENOMEM;
+		goto err_submit_cmds;
+	}
+
+	ret = submit_lookup_objects(submit, file, bos, args->nr_bos);
+	if (ret)
+		goto err_submit_objects;
+
+	ret = submit_lock_objects(submit);
+	if (ret)
+		goto err_submit_objects;
+
+	if (!etnaviv_cmd_validate_one(gpu, stream, args->stream_size / 4,
+				      relocs, args->nr_relocs)) {
+		ret = -EINVAL;
+		goto err_submit_objects;
+	}
+
+	ret = submit_fence_sync(submit);
+	if (ret)
+		goto err_submit_objects;
+
+	ret = submit_pin_objects(submit);
+	if (ret)
+		goto out;
+
+	ret = submit_reloc(submit, stream, args->stream_size / 4,
+			   relocs, args->nr_relocs);
+	if (ret)
+		goto out;
+
+	memcpy(cmdbuf->vaddr, stream, args->stream_size);
+	cmdbuf->user_size = ALIGN(args->stream_size, 8);
+
+	ret = etnaviv_gpu_submit(gpu, submit, cmdbuf);
+	if (ret == 0)
+		cmdbuf = NULL;
+
+	args->fence = submit->fence;
+
+out:
+	submit_unpin_objects(submit);
+
+	/*
+	 * If we're returning -EAGAIN, it may be due to the userptr code
+	 * wanting to run its workqueue outside of any locks. Flush our
+	 * workqueue to ensure that it is run in a timely manner.
+	 */
+	if (ret == -EAGAIN)
+		flush_workqueue(priv->wq);
+
+err_submit_objects:
+	submit_cleanup(submit);
+
+err_submit_cmds:
+	/* if we still own the cmdbuf */
+	if (cmdbuf)
+		etnaviv_gpu_cmdbuf_free(cmdbuf);
+	if (stream)
+		drm_free_large(stream);
+	if (bos)
+		drm_free_large(bos);
+	if (relocs)
+		drm_free_large(relocs);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
new file mode 100644
index 0000000..056a72e
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -0,0 +1,1647 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 <linux/component.h>
+#include <linux/fence.h>
+#include <linux/moduleparam.h>
+#include <linux/of_device.h>
+#include "etnaviv_dump.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_gem.h"
+#include "etnaviv_mmu.h"
+#include "etnaviv_iommu.h"
+#include "etnaviv_iommu_v2.h"
+#include "common.xml.h"
+#include "state.xml.h"
+#include "state_hi.xml.h"
+#include "cmdstream.xml.h"
+
+static const struct platform_device_id gpu_ids[] = {
+	{ .name = "etnaviv-gpu,2d" },
+	{ },
+};
+
+static bool etnaviv_dump_core = true;
+module_param_named(dump_core, etnaviv_dump_core, bool, 0600);
+
+/*
+ * Driver functions:
+ */
+
+int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value)
+{
+	switch (param) {
+	case ETNAVIV_PARAM_GPU_MODEL:
+		*value = gpu->identity.model;
+		break;
+
+	case ETNAVIV_PARAM_GPU_REVISION:
+		*value = gpu->identity.revision;
+		break;
+
+	case ETNAVIV_PARAM_GPU_FEATURES_0:
+		*value = gpu->identity.features;
+		break;
+
+	case ETNAVIV_PARAM_GPU_FEATURES_1:
+		*value = gpu->identity.minor_features0;
+		break;
+
+	case ETNAVIV_PARAM_GPU_FEATURES_2:
+		*value = gpu->identity.minor_features1;
+		break;
+
+	case ETNAVIV_PARAM_GPU_FEATURES_3:
+		*value = gpu->identity.minor_features2;
+		break;
+
+	case ETNAVIV_PARAM_GPU_FEATURES_4:
+		*value = gpu->identity.minor_features3;
+		break;
+
+	case ETNAVIV_PARAM_GPU_STREAM_COUNT:
+		*value = gpu->identity.stream_count;
+		break;
+
+	case ETNAVIV_PARAM_GPU_REGISTER_MAX:
+		*value = gpu->identity.register_max;
+		break;
+
+	case ETNAVIV_PARAM_GPU_THREAD_COUNT:
+		*value = gpu->identity.thread_count;
+		break;
+
+	case ETNAVIV_PARAM_GPU_VERTEX_CACHE_SIZE:
+		*value = gpu->identity.vertex_cache_size;
+		break;
+
+	case ETNAVIV_PARAM_GPU_SHADER_CORE_COUNT:
+		*value = gpu->identity.shader_core_count;
+		break;
+
+	case ETNAVIV_PARAM_GPU_PIXEL_PIPES:
+		*value = gpu->identity.pixel_pipes;
+		break;
+
+	case ETNAVIV_PARAM_GPU_VERTEX_OUTPUT_BUFFER_SIZE:
+		*value = gpu->identity.vertex_output_buffer_size;
+		break;
+
+	case ETNAVIV_PARAM_GPU_BUFFER_SIZE:
+		*value = gpu->identity.buffer_size;
+		break;
+
+	case ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT:
+		*value = gpu->identity.instruction_count;
+		break;
+
+	case ETNAVIV_PARAM_GPU_NUM_CONSTANTS:
+		*value = gpu->identity.num_constants;
+		break;
+
+	default:
+		DBG("%s: invalid param: %u", dev_name(gpu->dev), param);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void etnaviv_hw_specs(struct etnaviv_gpu *gpu)
+{
+	if (gpu->identity.minor_features0 &
+	    chipMinorFeatures0_MORE_MINOR_FEATURES) {
+		u32 specs[2];
+
+		specs[0] = gpu_read(gpu, VIVS_HI_CHIP_SPECS);
+		specs[1] = gpu_read(gpu, VIVS_HI_CHIP_SPECS_2);
+
+		gpu->identity.stream_count =
+			(specs[0] & VIVS_HI_CHIP_SPECS_STREAM_COUNT__MASK)
+				>> VIVS_HI_CHIP_SPECS_STREAM_COUNT__SHIFT;
+		gpu->identity.register_max =
+			(specs[0] & VIVS_HI_CHIP_SPECS_REGISTER_MAX__MASK)
+				>> VIVS_HI_CHIP_SPECS_REGISTER_MAX__SHIFT;
+		gpu->identity.thread_count =
+			(specs[0] & VIVS_HI_CHIP_SPECS_THREAD_COUNT__MASK)
+				>> VIVS_HI_CHIP_SPECS_THREAD_COUNT__SHIFT;
+		gpu->identity.vertex_cache_size =
+			(specs[0] & VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__MASK)
+				>> VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__SHIFT;
+		gpu->identity.shader_core_count =
+			(specs[0] & VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__MASK)
+				>> VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__SHIFT;
+		gpu->identity.pixel_pipes =
+			(specs[0] & VIVS_HI_CHIP_SPECS_PIXEL_PIPES__MASK)
+				>> VIVS_HI_CHIP_SPECS_PIXEL_PIPES__SHIFT;
+		gpu->identity.vertex_output_buffer_size =
+			(specs[0] & VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__MASK)
+				>> VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__SHIFT;
+
+		gpu->identity.buffer_size =
+			(specs[1] & VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__MASK)
+				>> VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__SHIFT;
+		gpu->identity.instruction_count =
+			(specs[1] & VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__MASK)
+				>> VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__SHIFT;
+		gpu->identity.num_constants =
+			(specs[1] & VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__MASK)
+				>> VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__SHIFT;
+	}
+
+	/* Fill in the stream count if not specified */
+	if (gpu->identity.stream_count == 0) {
+		if (gpu->identity.model >= 0x1000)
+			gpu->identity.stream_count = 4;
+		else
+			gpu->identity.stream_count = 1;
+	}
+
+	/* Convert the register max value */
+	if (gpu->identity.register_max)
+		gpu->identity.register_max = 1 << gpu->identity.register_max;
+	else if (gpu->identity.model == 0x0400)
+		gpu->identity.register_max = 32;
+	else
+		gpu->identity.register_max = 64;
+
+	/* Convert thread count */
+	if (gpu->identity.thread_count)
+		gpu->identity.thread_count = 1 << gpu->identity.thread_count;
+	else if (gpu->identity.model == 0x0400)
+		gpu->identity.thread_count = 64;
+	else if (gpu->identity.model == 0x0500 ||
+		 gpu->identity.model == 0x0530)
+		gpu->identity.thread_count = 128;
+	else
+		gpu->identity.thread_count = 256;
+
+	if (gpu->identity.vertex_cache_size == 0)
+		gpu->identity.vertex_cache_size = 8;
+
+	if (gpu->identity.shader_core_count == 0) {
+		if (gpu->identity.model >= 0x1000)
+			gpu->identity.shader_core_count = 2;
+		else
+			gpu->identity.shader_core_count = 1;
+	}
+
+	if (gpu->identity.pixel_pipes == 0)
+		gpu->identity.pixel_pipes = 1;
+
+	/* Convert virtex buffer size */
+	if (gpu->identity.vertex_output_buffer_size) {
+		gpu->identity.vertex_output_buffer_size =
+			1 << gpu->identity.vertex_output_buffer_size;
+	} else if (gpu->identity.model == 0x0400) {
+		if (gpu->identity.revision < 0x4000)
+			gpu->identity.vertex_output_buffer_size = 512;
+		else if (gpu->identity.revision < 0x4200)
+			gpu->identity.vertex_output_buffer_size = 256;
+		else
+			gpu->identity.vertex_output_buffer_size = 128;
+	} else {
+		gpu->identity.vertex_output_buffer_size = 512;
+	}
+
+	switch (gpu->identity.instruction_count) {
+	case 0:
+		if ((gpu->identity.model == 0x2000 &&
+		     gpu->identity.revision == 0x5108) ||
+		    gpu->identity.model == 0x880)
+			gpu->identity.instruction_count = 512;
+		else
+			gpu->identity.instruction_count = 256;
+		break;
+
+	case 1:
+		gpu->identity.instruction_count = 1024;
+		break;
+
+	case 2:
+		gpu->identity.instruction_count = 2048;
+		break;
+
+	default:
+		gpu->identity.instruction_count = 256;
+		break;
+	}
+
+	if (gpu->identity.num_constants == 0)
+		gpu->identity.num_constants = 168;
+}
+
+static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
+{
+	u32 chipIdentity;
+
+	chipIdentity = gpu_read(gpu, VIVS_HI_CHIP_IDENTITY);
+
+	/* Special case for older graphic cores. */
+	if (((chipIdentity & VIVS_HI_CHIP_IDENTITY_FAMILY__MASK)
+	     >> VIVS_HI_CHIP_IDENTITY_FAMILY__SHIFT) ==  0x01) {
+		gpu->identity.model    = 0x500; /* gc500 */
+		gpu->identity.revision =
+			(chipIdentity & VIVS_HI_CHIP_IDENTITY_REVISION__MASK)
+			>> VIVS_HI_CHIP_IDENTITY_REVISION__SHIFT;
+	} else {
+
+		gpu->identity.model = gpu_read(gpu, VIVS_HI_CHIP_MODEL);
+		gpu->identity.revision = gpu_read(gpu, VIVS_HI_CHIP_REV);
+
+		/*
+		 * !!!! HACK ALERT !!!!
+		 * Because people change device IDs without letting software
+		 * know about it - here is the hack to make it all look the
+		 * same.  Only for GC400 family.
+		 */
+		if ((gpu->identity.model & 0xff00) == 0x0400 &&
+		    gpu->identity.model != 0x0420) {
+			gpu->identity.model = gpu->identity.model & 0x0400;
+		}
+
+		/* Another special case */
+		if (gpu->identity.model == 0x300 &&
+		    gpu->identity.revision == 0x2201) {
+			u32 chipDate = gpu_read(gpu, VIVS_HI_CHIP_DATE);
+			u32 chipTime = gpu_read(gpu, VIVS_HI_CHIP_TIME);
+
+			if (chipDate == 0x20080814 && chipTime == 0x12051100) {
+				/*
+				 * This IP has an ECO; put the correct
+				 * revision in it.
+				 */
+				gpu->identity.revision = 0x1051;
+			}
+		}
+	}
+
+	dev_info(gpu->dev, "model: GC%x, revision: %x\n",
+		 gpu->identity.model, gpu->identity.revision);
+
+	gpu->identity.features = gpu_read(gpu, VIVS_HI_CHIP_FEATURE);
+
+	/* Disable fast clear on GC700. */
+	if (gpu->identity.model == 0x700)
+		gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
+
+	if ((gpu->identity.model == 0x500 && gpu->identity.revision < 2) ||
+	    (gpu->identity.model == 0x300 && gpu->identity.revision < 0x2000)) {
+
+		/*
+		 * GC500 rev 1.x and GC300 rev < 2.0 doesn't have these
+		 * registers.
+		 */
+		gpu->identity.minor_features0 = 0;
+		gpu->identity.minor_features1 = 0;
+		gpu->identity.minor_features2 = 0;
+		gpu->identity.minor_features3 = 0;
+	} else
+		gpu->identity.minor_features0 =
+				gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_0);
+
+	if (gpu->identity.minor_features0 &
+	    chipMinorFeatures0_MORE_MINOR_FEATURES) {
+		gpu->identity.minor_features1 =
+				gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_1);
+		gpu->identity.minor_features2 =
+				gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_2);
+		gpu->identity.minor_features3 =
+				gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_3);
+	}
+
+	/* GC600 idle register reports zero bits where modules aren't present */
+	if (gpu->identity.model == chipModel_GC600) {
+		gpu->idle_mask = VIVS_HI_IDLE_STATE_TX |
+				 VIVS_HI_IDLE_STATE_RA |
+				 VIVS_HI_IDLE_STATE_SE |
+				 VIVS_HI_IDLE_STATE_PA |
+				 VIVS_HI_IDLE_STATE_SH |
+				 VIVS_HI_IDLE_STATE_PE |
+				 VIVS_HI_IDLE_STATE_DE |
+				 VIVS_HI_IDLE_STATE_FE;
+	} else {
+		gpu->idle_mask = ~VIVS_HI_IDLE_STATE_AXI_LP;
+	}
+
+	etnaviv_hw_specs(gpu);
+}
+
+static void etnaviv_gpu_load_clock(struct etnaviv_gpu *gpu, u32 clock)
+{
+	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock |
+		  VIVS_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD);
+	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
+}
+
+static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
+{
+	u32 control, idle;
+	unsigned long timeout;
+	bool failed = true;
+
+	/* TODO
+	 *
+	 * - clock gating
+	 * - puls eater
+	 * - what about VG?
+	 */
+
+	/* We hope that the GPU resets in under one second */
+	timeout = jiffies + msecs_to_jiffies(1000);
+
+	while (time_is_after_jiffies(timeout)) {
+		control = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
+			  VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
+
+		/* enable clock */
+		etnaviv_gpu_load_clock(gpu, control);
+
+		/* Wait for stable clock.  Vivante's code waited for 1ms */
+		usleep_range(1000, 10000);
+
+		/* isolate the GPU. */
+		control |= VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU;
+		gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+		/* set soft reset. */
+		control |= VIVS_HI_CLOCK_CONTROL_SOFT_RESET;
+		gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+		/* wait for reset. */
+		msleep(1);
+
+		/* reset soft reset bit. */
+		control &= ~VIVS_HI_CLOCK_CONTROL_SOFT_RESET;
+		gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+		/* reset GPU isolation. */
+		control &= ~VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU;
+		gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+		/* read idle register. */
+		idle = gpu_read(gpu, VIVS_HI_IDLE_STATE);
+
+		/* try reseting again if FE it not idle */
+		if ((idle & VIVS_HI_IDLE_STATE_FE) == 0) {
+			dev_dbg(gpu->dev, "FE is not idle\n");
+			continue;
+		}
+
+		/* read reset register. */
+		control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
+
+		/* is the GPU idle? */
+		if (((control & VIVS_HI_CLOCK_CONTROL_IDLE_3D) == 0) ||
+		    ((control & VIVS_HI_CLOCK_CONTROL_IDLE_2D) == 0)) {
+			dev_dbg(gpu->dev, "GPU is not idle\n");
+			continue;
+		}
+
+		failed = false;
+		break;
+	}
+
+	if (failed) {
+		idle = gpu_read(gpu, VIVS_HI_IDLE_STATE);
+		control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
+
+		dev_err(gpu->dev, "GPU failed to reset: FE %sidle, 3D %sidle, 2D %sidle\n",
+			idle & VIVS_HI_IDLE_STATE_FE ? "" : "not ",
+			control & VIVS_HI_CLOCK_CONTROL_IDLE_3D ? "" : "not ",
+			control & VIVS_HI_CLOCK_CONTROL_IDLE_2D ? "" : "not ");
+
+		return -EBUSY;
+	}
+
+	/* We rely on the GPU running, so program the clock */
+	control = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
+		  VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
+
+	/* enable clock */
+	etnaviv_gpu_load_clock(gpu, control);
+
+	return 0;
+}
+
+static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
+{
+	u16 prefetch;
+
+	if (gpu->identity.model == chipModel_GC320 &&
+	    gpu_read(gpu, VIVS_HI_CHIP_TIME) != 0x2062400 &&
+	    (gpu->identity.revision == 0x5007 ||
+	     gpu->identity.revision == 0x5220)) {
+		u32 mc_memory_debug;
+
+		mc_memory_debug = gpu_read(gpu, VIVS_MC_DEBUG_MEMORY) & ~0xff;
+
+		if (gpu->identity.revision == 0x5007)
+			mc_memory_debug |= 0x0c;
+		else
+			mc_memory_debug |= 0x08;
+
+		gpu_write(gpu, VIVS_MC_DEBUG_MEMORY, mc_memory_debug);
+	}
+
+	/*
+	 * Update GPU AXI cache atttribute to "cacheable, no allocate".
+	 * This is necessary to prevent the iMX6 SoC locking up.
+	 */
+	gpu_write(gpu, VIVS_HI_AXI_CONFIG,
+		  VIVS_HI_AXI_CONFIG_AWCACHE(2) |
+		  VIVS_HI_AXI_CONFIG_ARCACHE(2));
+
+	/* GC2000 rev 5108 needs a special bus config */
+	if (gpu->identity.model == 0x2000 && gpu->identity.revision == 0x5108) {
+		u32 bus_config = gpu_read(gpu, VIVS_MC_BUS_CONFIG);
+		bus_config &= ~(VIVS_MC_BUS_CONFIG_FE_BUS_CONFIG__MASK |
+				VIVS_MC_BUS_CONFIG_TX_BUS_CONFIG__MASK);
+		bus_config |= VIVS_MC_BUS_CONFIG_FE_BUS_CONFIG(1) |
+			      VIVS_MC_BUS_CONFIG_TX_BUS_CONFIG(0);
+		gpu_write(gpu, VIVS_MC_BUS_CONFIG, bus_config);
+	}
+
+	/* set base addresses */
+	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_RA, gpu->memory_base);
+	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_FE, gpu->memory_base);
+	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_TX, gpu->memory_base);
+	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_PEZ, gpu->memory_base);
+	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_PE, gpu->memory_base);
+
+	/* setup the MMU page table pointers */
+	etnaviv_iommu_domain_restore(gpu, gpu->mmu->domain);
+
+	/* Start command processor */
+	prefetch = etnaviv_buffer_init(gpu);
+
+	gpu_write(gpu, VIVS_HI_INTR_ENBL, ~0U);
+	gpu_write(gpu, VIVS_FE_COMMAND_ADDRESS,
+		  gpu->buffer->paddr - gpu->memory_base);
+	gpu_write(gpu, VIVS_FE_COMMAND_CONTROL,
+		  VIVS_FE_COMMAND_CONTROL_ENABLE |
+		  VIVS_FE_COMMAND_CONTROL_PREFETCH(prefetch));
+}
+
+int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
+{
+	int ret, i;
+	struct iommu_domain *iommu;
+	enum etnaviv_iommu_version version;
+	bool mmuv2;
+
+	ret = pm_runtime_get_sync(gpu->dev);
+	if (ret < 0)
+		return ret;
+
+	etnaviv_hw_identify(gpu);
+
+	if (gpu->identity.model == 0) {
+		dev_err(gpu->dev, "Unknown GPU model\n");
+		pm_runtime_put_autosuspend(gpu->dev);
+		return -ENXIO;
+	}
+
+	ret = etnaviv_hw_reset(gpu);
+	if (ret)
+		goto fail;
+
+	/* Setup IOMMU.. eventually we will (I think) do this once per context
+	 * and have separate page tables per context.  For now, to keep things
+	 * simple and to get something working, just use a single address space:
+	 */
+	mmuv2 = gpu->identity.minor_features1 & chipMinorFeatures1_MMU_VERSION;
+	dev_dbg(gpu->dev, "mmuv2: %d\n", mmuv2);
+
+	if (!mmuv2) {
+		iommu = etnaviv_iommu_domain_alloc(gpu);
+		version = ETNAVIV_IOMMU_V1;
+	} else {
+		iommu = etnaviv_iommu_v2_domain_alloc(gpu);
+		version = ETNAVIV_IOMMU_V2;
+	}
+
+	if (!iommu) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	/* TODO: we will leak here memory - fix it! */
+
+	gpu->mmu = etnaviv_iommu_new(gpu, iommu, version);
+	if (!gpu->mmu) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	/* Create buffer: */
+	gpu->buffer = etnaviv_gpu_cmdbuf_new(gpu, PAGE_SIZE, 0);
+	if (!gpu->buffer) {
+		ret = -ENOMEM;
+		dev_err(gpu->dev, "could not create command buffer\n");
+		goto fail;
+	}
+	if (gpu->buffer->paddr - gpu->memory_base > 0x80000000) {
+		ret = -EINVAL;
+		dev_err(gpu->dev,
+			"command buffer outside valid memory window\n");
+		goto free_buffer;
+	}
+
+	/* Setup event management */
+	spin_lock_init(&gpu->event_spinlock);
+	init_completion(&gpu->event_free);
+	for (i = 0; i < ARRAY_SIZE(gpu->event); i++) {
+		gpu->event[i].used = false;
+		complete(&gpu->event_free);
+	}
+
+	/* Now program the hardware */
+	mutex_lock(&gpu->lock);
+	etnaviv_gpu_hw_init(gpu);
+	mutex_unlock(&gpu->lock);
+
+	pm_runtime_mark_last_busy(gpu->dev);
+	pm_runtime_put_autosuspend(gpu->dev);
+
+	return 0;
+
+free_buffer:
+	etnaviv_gpu_cmdbuf_free(gpu->buffer);
+	gpu->buffer = NULL;
+fail:
+	pm_runtime_mark_last_busy(gpu->dev);
+	pm_runtime_put_autosuspend(gpu->dev);
+
+	return ret;
+}
+
+#ifdef CONFIG_DEBUG_FS
+struct dma_debug {
+	u32 address[2];
+	u32 state[2];
+};
+
+static void verify_dma(struct etnaviv_gpu *gpu, struct dma_debug *debug)
+{
+	u32 i;
+
+	debug->address[0] = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
+	debug->state[0]   = gpu_read(gpu, VIVS_FE_DMA_DEBUG_STATE);
+
+	for (i = 0; i < 500; i++) {
+		debug->address[1] = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
+		debug->state[1]   = gpu_read(gpu, VIVS_FE_DMA_DEBUG_STATE);
+
+		if (debug->address[0] != debug->address[1])
+			break;
+
+		if (debug->state[0] != debug->state[1])
+			break;
+	}
+}
+
+int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m)
+{
+	struct dma_debug debug;
+	u32 dma_lo, dma_hi, axi, idle;
+	int ret;
+
+	seq_printf(m, "%s Status:\n", dev_name(gpu->dev));
+
+	ret = pm_runtime_get_sync(gpu->dev);
+	if (ret < 0)
+		return ret;
+
+	dma_lo = gpu_read(gpu, VIVS_FE_DMA_LOW);
+	dma_hi = gpu_read(gpu, VIVS_FE_DMA_HIGH);
+	axi = gpu_read(gpu, VIVS_HI_AXI_STATUS);
+	idle = gpu_read(gpu, VIVS_HI_IDLE_STATE);
+
+	verify_dma(gpu, &debug);
+
+	seq_puts(m, "\tfeatures\n");
+	seq_printf(m, "\t minor_features0: 0x%08x\n",
+		   gpu->identity.minor_features0);
+	seq_printf(m, "\t minor_features1: 0x%08x\n",
+		   gpu->identity.minor_features1);
+	seq_printf(m, "\t minor_features2: 0x%08x\n",
+		   gpu->identity.minor_features2);
+	seq_printf(m, "\t minor_features3: 0x%08x\n",
+		   gpu->identity.minor_features3);
+
+	seq_puts(m, "\tspecs\n");
+	seq_printf(m, "\t stream_count:  %d\n",
+			gpu->identity.stream_count);
+	seq_printf(m, "\t register_max: %d\n",
+			gpu->identity.register_max);
+	seq_printf(m, "\t thread_count: %d\n",
+			gpu->identity.thread_count);
+	seq_printf(m, "\t vertex_cache_size: %d\n",
+			gpu->identity.vertex_cache_size);
+	seq_printf(m, "\t shader_core_count: %d\n",
+			gpu->identity.shader_core_count);
+	seq_printf(m, "\t pixel_pipes: %d\n",
+			gpu->identity.pixel_pipes);
+	seq_printf(m, "\t vertex_output_buffer_size: %d\n",
+			gpu->identity.vertex_output_buffer_size);
+	seq_printf(m, "\t buffer_size: %d\n",
+			gpu->identity.buffer_size);
+	seq_printf(m, "\t instruction_count: %d\n",
+			gpu->identity.instruction_count);
+	seq_printf(m, "\t num_constants: %d\n",
+			gpu->identity.num_constants);
+
+	seq_printf(m, "\taxi: 0x%08x\n", axi);
+	seq_printf(m, "\tidle: 0x%08x\n", idle);
+	idle |= ~gpu->idle_mask & ~VIVS_HI_IDLE_STATE_AXI_LP;
+	if ((idle & VIVS_HI_IDLE_STATE_FE) == 0)
+		seq_puts(m, "\t FE is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_DE) == 0)
+		seq_puts(m, "\t DE is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_PE) == 0)
+		seq_puts(m, "\t PE is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_SH) == 0)
+		seq_puts(m, "\t SH is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_PA) == 0)
+		seq_puts(m, "\t PA is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_SE) == 0)
+		seq_puts(m, "\t SE is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_RA) == 0)
+		seq_puts(m, "\t RA is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_TX) == 0)
+		seq_puts(m, "\t TX is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_VG) == 0)
+		seq_puts(m, "\t VG is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_IM) == 0)
+		seq_puts(m, "\t IM is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_FP) == 0)
+		seq_puts(m, "\t FP is not idle\n");
+	if ((idle & VIVS_HI_IDLE_STATE_TS) == 0)
+		seq_puts(m, "\t TS is not idle\n");
+	if (idle & VIVS_HI_IDLE_STATE_AXI_LP)
+		seq_puts(m, "\t AXI low power mode\n");
+
+	if (gpu->identity.features & chipFeatures_DEBUG_MODE) {
+		u32 read0 = gpu_read(gpu, VIVS_MC_DEBUG_READ0);
+		u32 read1 = gpu_read(gpu, VIVS_MC_DEBUG_READ1);
+		u32 write = gpu_read(gpu, VIVS_MC_DEBUG_WRITE);
+
+		seq_puts(m, "\tMC\n");
+		seq_printf(m, "\t read0: 0x%08x\n", read0);
+		seq_printf(m, "\t read1: 0x%08x\n", read1);
+		seq_printf(m, "\t write: 0x%08x\n", write);
+	}
+
+	seq_puts(m, "\tDMA ");
+
+	if (debug.address[0] == debug.address[1] &&
+	    debug.state[0] == debug.state[1]) {
+		seq_puts(m, "seems to be stuck\n");
+	} else if (debug.address[0] == debug.address[1]) {
+		seq_puts(m, "adress is constant\n");
+	} else {
+		seq_puts(m, "is runing\n");
+	}
+
+	seq_printf(m, "\t address 0: 0x%08x\n", debug.address[0]);
+	seq_printf(m, "\t address 1: 0x%08x\n", debug.address[1]);
+	seq_printf(m, "\t state 0: 0x%08x\n", debug.state[0]);
+	seq_printf(m, "\t state 1: 0x%08x\n", debug.state[1]);
+	seq_printf(m, "\t last fetch 64 bit word: 0x%08x 0x%08x\n",
+		   dma_lo, dma_hi);
+
+	ret = 0;
+
+	pm_runtime_mark_last_busy(gpu->dev);
+	pm_runtime_put_autosuspend(gpu->dev);
+
+	return ret;
+}
+#endif
+
+/*
+ * Power Management:
+ */
+static int enable_clk(struct etnaviv_gpu *gpu)
+{
+	if (gpu->clk_core)
+		clk_prepare_enable(gpu->clk_core);
+	if (gpu->clk_shader)
+		clk_prepare_enable(gpu->clk_shader);
+
+	return 0;
+}
+
+static int disable_clk(struct etnaviv_gpu *gpu)
+{
+	if (gpu->clk_core)
+		clk_disable_unprepare(gpu->clk_core);
+	if (gpu->clk_shader)
+		clk_disable_unprepare(gpu->clk_shader);
+
+	return 0;
+}
+
+static int enable_axi(struct etnaviv_gpu *gpu)
+{
+	if (gpu->clk_bus)
+		clk_prepare_enable(gpu->clk_bus);
+
+	return 0;
+}
+
+static int disable_axi(struct etnaviv_gpu *gpu)
+{
+	if (gpu->clk_bus)
+		clk_disable_unprepare(gpu->clk_bus);
+
+	return 0;
+}
+
+/*
+ * Hangcheck detection for locked gpu:
+ */
+static void recover_worker(struct work_struct *work)
+{
+	struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu,
+					       recover_work);
+	unsigned long flags;
+	unsigned int i;
+
+	dev_err(gpu->dev, "hangcheck recover!\n");
+
+	if (pm_runtime_get_sync(gpu->dev) < 0)
+		return;
+
+	mutex_lock(&gpu->lock);
+
+	/* Only catch the first event, or when manually re-armed */
+	if (etnaviv_dump_core) {
+		etnaviv_core_dump(gpu);
+		etnaviv_dump_core = false;
+	}
+
+	etnaviv_hw_reset(gpu);
+
+	/* complete all events, the GPU won't do it after the reset */
+	spin_lock_irqsave(&gpu->event_spinlock, flags);
+	for (i = 0; i < ARRAY_SIZE(gpu->event); i++) {
+		if (!gpu->event[i].used)
+			continue;
+		fence_signal(gpu->event[i].fence);
+		gpu->event[i].fence = NULL;
+		gpu->event[i].used = false;
+		complete(&gpu->event_free);
+		/*
+		 * Decrement the PM count for each stuck event. This is safe
+		 * even in atomic context as we use ASYNC RPM here.
+		 */
+		pm_runtime_put_autosuspend(gpu->dev);
+	}
+	spin_unlock_irqrestore(&gpu->event_spinlock, flags);
+	gpu->completed_fence = gpu->active_fence;
+
+	etnaviv_gpu_hw_init(gpu);
+	gpu->switch_context = true;
+
+	mutex_unlock(&gpu->lock);
+	pm_runtime_mark_last_busy(gpu->dev);
+	pm_runtime_put_autosuspend(gpu->dev);
+
+	/* Retire the buffer objects in a work */
+	etnaviv_queue_work(gpu->drm, &gpu->retire_work);
+}
+
+static void hangcheck_timer_reset(struct etnaviv_gpu *gpu)
+{
+	DBG("%s", dev_name(gpu->dev));
+	mod_timer(&gpu->hangcheck_timer,
+		  round_jiffies_up(jiffies + DRM_ETNAVIV_HANGCHECK_JIFFIES));
+}
+
+static void hangcheck_handler(unsigned long data)
+{
+	struct etnaviv_gpu *gpu = (struct etnaviv_gpu *)data;
+	u32 fence = gpu->completed_fence;
+	bool progress = false;
+
+	if (fence != gpu->hangcheck_fence) {
+		gpu->hangcheck_fence = fence;
+		progress = true;
+	}
+
+	if (!progress) {
+		u32 dma_addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
+		int change = dma_addr - gpu->hangcheck_dma_addr;
+
+		if (change < 0 || change > 16) {
+			gpu->hangcheck_dma_addr = dma_addr;
+			progress = true;
+		}
+	}
+
+	if (!progress && fence_after(gpu->active_fence, fence)) {
+		dev_err(gpu->dev, "hangcheck detected gpu lockup!\n");
+		dev_err(gpu->dev, "     completed fence: %u\n", fence);
+		dev_err(gpu->dev, "     active fence: %u\n",
+			gpu->active_fence);
+		etnaviv_queue_work(gpu->drm, &gpu->recover_work);
+	}
+
+	/* if still more pending work, reset the hangcheck timer: */
+	if (fence_after(gpu->active_fence, gpu->hangcheck_fence))
+		hangcheck_timer_reset(gpu);
+}
+
+static void hangcheck_disable(struct etnaviv_gpu *gpu)
+{
+	del_timer_sync(&gpu->hangcheck_timer);
+	cancel_work_sync(&gpu->recover_work);
+}
+
+/* fence object management */
+struct etnaviv_fence {
+	struct etnaviv_gpu *gpu;
+	struct fence base;
+};
+
+static inline struct etnaviv_fence *to_etnaviv_fence(struct fence *fence)
+{
+	return container_of(fence, struct etnaviv_fence, base);
+}
+
+static const char *etnaviv_fence_get_driver_name(struct fence *fence)
+{
+	return "etnaviv";
+}
+
+static const char *etnaviv_fence_get_timeline_name(struct fence *fence)
+{
+	struct etnaviv_fence *f = to_etnaviv_fence(fence);
+
+	return dev_name(f->gpu->dev);
+}
+
+static bool etnaviv_fence_enable_signaling(struct fence *fence)
+{
+	return true;
+}
+
+static bool etnaviv_fence_signaled(struct fence *fence)
+{
+	struct etnaviv_fence *f = to_etnaviv_fence(fence);
+
+	return fence_completed(f->gpu, f->base.seqno);
+}
+
+static void etnaviv_fence_release(struct fence *fence)
+{
+	struct etnaviv_fence *f = to_etnaviv_fence(fence);
+
+	kfree_rcu(f, base.rcu);
+}
+
+static const struct fence_ops etnaviv_fence_ops = {
+	.get_driver_name = etnaviv_fence_get_driver_name,
+	.get_timeline_name = etnaviv_fence_get_timeline_name,
+	.enable_signaling = etnaviv_fence_enable_signaling,
+	.signaled = etnaviv_fence_signaled,
+	.wait = fence_default_wait,
+	.release = etnaviv_fence_release,
+};
+
+static struct fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu)
+{
+	struct etnaviv_fence *f;
+
+	f = kzalloc(sizeof(*f), GFP_KERNEL);
+	if (!f)
+		return NULL;
+
+	f->gpu = gpu;
+
+	fence_init(&f->base, &etnaviv_fence_ops, &gpu->fence_spinlock,
+		   gpu->fence_context, ++gpu->next_fence);
+
+	return &f->base;
+}
+
+int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
+	unsigned int context, bool exclusive)
+{
+	struct reservation_object *robj = etnaviv_obj->resv;
+	struct reservation_object_list *fobj;
+	struct fence *fence;
+	int i, ret;
+
+	if (!exclusive) {
+		ret = reservation_object_reserve_shared(robj);
+		if (ret)
+			return ret;
+	}
+
+	/*
+	 * If we have any shared fences, then the exclusive fence
+	 * should be ignored as it will already have been signalled.
+	 */
+	fobj = reservation_object_get_list(robj);
+	if (!fobj || fobj->shared_count == 0) {
+		/* Wait on any existing exclusive fence which isn't our own */
+		fence = reservation_object_get_excl(robj);
+		if (fence && fence->context != context) {
+			ret = fence_wait(fence, true);
+			if (ret)
+				return ret;
+		}
+	}
+
+	if (!exclusive || !fobj)
+		return 0;
+
+	for (i = 0; i < fobj->shared_count; i++) {
+		fence = rcu_dereference_protected(fobj->shared[i],
+						reservation_object_held(robj));
+		if (fence->context != context) {
+			ret = fence_wait(fence, true);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * event management:
+ */
+
+static unsigned int event_alloc(struct etnaviv_gpu *gpu)
+{
+	unsigned long ret, flags;
+	unsigned int i, event = ~0U;
+
+	ret = wait_for_completion_timeout(&gpu->event_free,
+					  msecs_to_jiffies(10 * 10000));
+	if (!ret)
+		dev_err(gpu->dev, "wait_for_completion_timeout failed");
+
+	spin_lock_irqsave(&gpu->event_spinlock, flags);
+
+	/* find first free event */
+	for (i = 0; i < ARRAY_SIZE(gpu->event); i++) {
+		if (gpu->event[i].used == false) {
+			gpu->event[i].used = true;
+			event = i;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&gpu->event_spinlock, flags);
+
+	return event;
+}
+
+static void event_free(struct etnaviv_gpu *gpu, unsigned int event)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpu->event_spinlock, flags);
+
+	if (gpu->event[event].used == false) {
+		dev_warn(gpu->dev, "event %u is already marked as free",
+			 event);
+		spin_unlock_irqrestore(&gpu->event_spinlock, flags);
+	} else {
+		gpu->event[event].used = false;
+		spin_unlock_irqrestore(&gpu->event_spinlock, flags);
+
+		complete(&gpu->event_free);
+	}
+}
+
+/*
+ * Cmdstream submission/retirement:
+ */
+
+struct etnaviv_cmdbuf *etnaviv_gpu_cmdbuf_new(struct etnaviv_gpu *gpu, u32 size,
+	size_t nr_bos)
+{
+	struct etnaviv_cmdbuf *cmdbuf;
+	size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo[0]),
+				 sizeof(*cmdbuf));
+
+	cmdbuf = kzalloc(sz, GFP_KERNEL);
+	if (!cmdbuf)
+		return NULL;
+
+	cmdbuf->vaddr = dma_alloc_writecombine(gpu->dev, size, &cmdbuf->paddr,
+					       GFP_KERNEL);
+	if (!cmdbuf->vaddr) {
+		kfree(cmdbuf);
+		return NULL;
+	}
+
+	cmdbuf->gpu = gpu;
+	cmdbuf->size = size;
+
+	return cmdbuf;
+}
+
+void etnaviv_gpu_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
+{
+	dma_free_writecombine(cmdbuf->gpu->dev, cmdbuf->size,
+			      cmdbuf->vaddr, cmdbuf->paddr);
+	kfree(cmdbuf);
+}
+
+static void retire_worker(struct work_struct *work)
+{
+	struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu,
+					       retire_work);
+	u32 fence = gpu->completed_fence;
+	struct etnaviv_cmdbuf *cmdbuf, *tmp;
+	unsigned int i;
+
+	mutex_lock(&gpu->lock);
+	list_for_each_entry_safe(cmdbuf, tmp, &gpu->active_cmd_list, node) {
+		if (!fence_is_signaled(cmdbuf->fence))
+			break;
+
+		list_del(&cmdbuf->node);
+		fence_put(cmdbuf->fence);
+
+		for (i = 0; i < cmdbuf->nr_bos; i++) {
+			struct etnaviv_gem_object *etnaviv_obj = cmdbuf->bo[i];
+
+			atomic_dec(&etnaviv_obj->gpu_active);
+			/* drop the refcount taken in etnaviv_gpu_submit */
+			etnaviv_gem_put_iova(gpu, &etnaviv_obj->base);
+		}
+
+		etnaviv_gpu_cmdbuf_free(cmdbuf);
+	}
+
+	gpu->retired_fence = fence;
+
+	mutex_unlock(&gpu->lock);
+
+	wake_up_all(&gpu->fence_event);
+}
+
+int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu,
+	u32 fence, struct timespec *timeout)
+{
+	int ret;
+
+	if (fence_after(fence, gpu->next_fence)) {
+		DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
+				fence, gpu->next_fence);
+		return -EINVAL;
+	}
+
+	if (!timeout) {
+		/* No timeout was requested: just test for completion */
+		ret = fence_completed(gpu, fence) ? 0 : -EBUSY;
+	} else {
+		unsigned long remaining = etnaviv_timeout_to_jiffies(timeout);
+
+		ret = wait_event_interruptible_timeout(gpu->fence_event,
+						fence_completed(gpu, fence),
+						remaining);
+		if (ret == 0) {
+			DBG("timeout waiting for fence: %u (retired: %u completed: %u)",
+				fence, gpu->retired_fence,
+				gpu->completed_fence);
+			ret = -ETIMEDOUT;
+		} else if (ret != -ERESTARTSYS) {
+			ret = 0;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Wait for an object to become inactive.  This, on it's own, is not race
+ * free: the object is moved by the retire worker off the active list, and
+ * then the iova is put.  Moreover, the object could be re-submitted just
+ * after we notice that it's become inactive.
+ *
+ * Although the retirement happens under the gpu lock, we don't want to hold
+ * that lock in this function while waiting.
+ */
+int etnaviv_gpu_wait_obj_inactive(struct etnaviv_gpu *gpu,
+	struct etnaviv_gem_object *etnaviv_obj, struct timespec *timeout)
+{
+	unsigned long remaining;
+	long ret;
+
+	if (!timeout)
+		return !is_active(etnaviv_obj) ? 0 : -EBUSY;
+
+	remaining = etnaviv_timeout_to_jiffies(timeout);
+
+	ret = wait_event_interruptible_timeout(gpu->fence_event,
+					       !is_active(etnaviv_obj),
+					       remaining);
+	if (ret > 0) {
+		struct etnaviv_drm_private *priv = gpu->drm->dev_private;
+
+		/* Synchronise with the retire worker */
+		flush_workqueue(priv->wq);
+		return 0;
+	} else if (ret == -ERESTARTSYS) {
+		return -ERESTARTSYS;
+	} else {
+		return -ETIMEDOUT;
+	}
+}
+
+int etnaviv_gpu_pm_get_sync(struct etnaviv_gpu *gpu)
+{
+	return pm_runtime_get_sync(gpu->dev);
+}
+
+void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu)
+{
+	pm_runtime_mark_last_busy(gpu->dev);
+	pm_runtime_put_autosuspend(gpu->dev);
+}
+
+/* add bo's to gpu's ring, and kick gpu: */
+int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
+	struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf)
+{
+	struct fence *fence;
+	unsigned int event, i;
+	int ret;
+
+	ret = etnaviv_gpu_pm_get_sync(gpu);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&gpu->lock);
+
+	/*
+	 * TODO
+	 *
+	 * - flush
+	 * - data endian
+	 * - prefetch
+	 *
+	 */
+
+	event = event_alloc(gpu);
+	if (unlikely(event == ~0U)) {
+		DRM_ERROR("no free event\n");
+		ret = -EBUSY;
+		goto out_unlock;
+	}
+
+	fence = etnaviv_gpu_fence_alloc(gpu);
+	if (!fence) {
+		event_free(gpu, event);
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
+
+	gpu->event[event].fence = fence;
+	submit->fence = fence->seqno;
+	gpu->active_fence = submit->fence;
+
+	if (gpu->lastctx != cmdbuf->ctx) {
+		gpu->mmu->need_flush = true;
+		gpu->switch_context = true;
+		gpu->lastctx = cmdbuf->ctx;
+	}
+
+	etnaviv_buffer_queue(gpu, event, cmdbuf);
+
+	cmdbuf->fence = fence;
+	list_add_tail(&cmdbuf->node, &gpu->active_cmd_list);
+
+	/* We're committed to adding this command buffer, hold a PM reference */
+	pm_runtime_get_noresume(gpu->dev);
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
+		u32 iova;
+
+		/* Each cmdbuf takes a refcount on the iova */
+		etnaviv_gem_get_iova(gpu, &etnaviv_obj->base, &iova);
+		cmdbuf->bo[i] = etnaviv_obj;
+		atomic_inc(&etnaviv_obj->gpu_active);
+
+		if (submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE)
+			reservation_object_add_excl_fence(etnaviv_obj->resv,
+							  fence);
+		else
+			reservation_object_add_shared_fence(etnaviv_obj->resv,
+							    fence);
+	}
+	cmdbuf->nr_bos = submit->nr_bos;
+	hangcheck_timer_reset(gpu);
+	ret = 0;
+
+out_unlock:
+	mutex_unlock(&gpu->lock);
+
+	etnaviv_gpu_pm_put(gpu);
+
+	return ret;
+}
+
+/*
+ * Init/Cleanup:
+ */
+static irqreturn_t irq_handler(int irq, void *data)
+{
+	struct etnaviv_gpu *gpu = data;
+	irqreturn_t ret = IRQ_NONE;
+
+	u32 intr = gpu_read(gpu, VIVS_HI_INTR_ACKNOWLEDGE);
+
+	if (intr != 0) {
+		int event;
+
+		pm_runtime_mark_last_busy(gpu->dev);
+
+		dev_dbg(gpu->dev, "intr 0x%08x\n", intr);
+
+		if (intr & VIVS_HI_INTR_ACKNOWLEDGE_AXI_BUS_ERROR) {
+			dev_err(gpu->dev, "AXI bus error\n");
+			intr &= ~VIVS_HI_INTR_ACKNOWLEDGE_AXI_BUS_ERROR;
+		}
+
+		while ((event = ffs(intr)) != 0) {
+			struct fence *fence;
+
+			event -= 1;
+
+			intr &= ~(1 << event);
+
+			dev_dbg(gpu->dev, "event %u\n", event);
+
+			fence = gpu->event[event].fence;
+			gpu->event[event].fence = NULL;
+			fence_signal(fence);
+
+			/*
+			 * Events can be processed out of order.  Eg,
+			 * - allocate and queue event 0
+			 * - allocate event 1
+			 * - event 0 completes, we process it
+			 * - allocate and queue event 0
+			 * - event 1 and event 0 complete
+			 * we can end up processing event 0 first, then 1.
+			 */
+			if (fence_after(fence->seqno, gpu->completed_fence))
+				gpu->completed_fence = fence->seqno;
+
+			event_free(gpu, event);
+
+			/*
+			 * We need to balance the runtime PM count caused by
+			 * each submission.  Upon submission, we increment
+			 * the runtime PM counter, and allocate one event.
+			 * So here, we put the runtime PM count for each
+			 * completed event.
+			 */
+			pm_runtime_put_autosuspend(gpu->dev);
+		}
+
+		/* Retire the buffer objects in a work */
+		etnaviv_queue_work(gpu->drm, &gpu->retire_work);
+
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+static int etnaviv_gpu_clk_enable(struct etnaviv_gpu *gpu)
+{
+	int ret;
+
+	ret = enable_clk(gpu);
+	if (ret)
+		return ret;
+
+	ret = enable_axi(gpu);
+	if (ret) {
+		disable_clk(gpu);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int etnaviv_gpu_clk_disable(struct etnaviv_gpu *gpu)
+{
+	int ret;
+
+	ret = disable_axi(gpu);
+	if (ret)
+		return ret;
+
+	ret = disable_clk(gpu);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
+{
+	if (gpu->buffer) {
+		unsigned long timeout;
+
+		/* Replace the last WAIT with END */
+		etnaviv_buffer_end(gpu);
+
+		/*
+		 * We know that only the FE is busy here, this should
+		 * happen quickly (as the WAIT is only 200 cycles).  If
+		 * we fail, just warn and continue.
+		 */
+		timeout = jiffies + msecs_to_jiffies(100);
+		do {
+			u32 idle = gpu_read(gpu, VIVS_HI_IDLE_STATE);
+
+			if ((idle & gpu->idle_mask) == gpu->idle_mask)
+				break;
+
+			if (time_is_before_jiffies(timeout)) {
+				dev_warn(gpu->dev,
+					 "timed out waiting for idle: idle=0x%x\n",
+					 idle);
+				break;
+			}
+
+			udelay(5);
+		} while (1);
+	}
+
+	return etnaviv_gpu_clk_disable(gpu);
+}
+
+#ifdef CONFIG_PM
+static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu)
+{
+	u32 clock;
+	int ret;
+
+	ret = mutex_lock_killable(&gpu->lock);
+	if (ret)
+		return ret;
+
+	clock = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
+		VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
+
+	etnaviv_gpu_load_clock(gpu, clock);
+	etnaviv_gpu_hw_init(gpu);
+
+	gpu->switch_context = true;
+
+	mutex_unlock(&gpu->lock);
+
+	return 0;
+}
+#endif
+
+static int etnaviv_gpu_bind(struct device *dev, struct device *master,
+	void *data)
+{
+	struct drm_device *drm = data;
+	struct etnaviv_drm_private *priv = drm->dev_private;
+	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+	int ret;
+
+#ifdef CONFIG_PM
+	ret = pm_runtime_get_sync(gpu->dev);
+#else
+	ret = etnaviv_gpu_clk_enable(gpu);
+#endif
+	if (ret < 0)
+		return ret;
+
+	gpu->drm = drm;
+	gpu->fence_context = fence_context_alloc(1);
+	spin_lock_init(&gpu->fence_spinlock);
+
+	INIT_LIST_HEAD(&gpu->active_cmd_list);
+	INIT_WORK(&gpu->retire_work, retire_worker);
+	INIT_WORK(&gpu->recover_work, recover_worker);
+	init_waitqueue_head(&gpu->fence_event);
+
+	setup_timer(&gpu->hangcheck_timer, hangcheck_handler,
+			(unsigned long)gpu);
+
+	priv->gpu[priv->num_gpus++] = gpu;
+
+	pm_runtime_mark_last_busy(gpu->dev);
+	pm_runtime_put_autosuspend(gpu->dev);
+
+	return 0;
+}
+
+static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
+	void *data)
+{
+	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+
+	DBG("%s", dev_name(gpu->dev));
+
+	hangcheck_disable(gpu);
+
+#ifdef CONFIG_PM
+	pm_runtime_get_sync(gpu->dev);
+	pm_runtime_put_sync_suspend(gpu->dev);
+#else
+	etnaviv_gpu_hw_suspend(gpu);
+#endif
+
+	if (gpu->buffer) {
+		etnaviv_gpu_cmdbuf_free(gpu->buffer);
+		gpu->buffer = NULL;
+	}
+
+	if (gpu->mmu) {
+		etnaviv_iommu_destroy(gpu->mmu);
+		gpu->mmu = NULL;
+	}
+
+	gpu->drm = NULL;
+}
+
+static const struct component_ops gpu_ops = {
+	.bind = etnaviv_gpu_bind,
+	.unbind = etnaviv_gpu_unbind,
+};
+
+static const struct of_device_id etnaviv_gpu_match[] = {
+	{
+		.compatible = "vivante,gc"
+	},
+	{ /* sentinel */ }
+};
+
+static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct etnaviv_gpu *gpu;
+	int err = 0;
+
+	gpu = devm_kzalloc(dev, sizeof(*gpu), GFP_KERNEL);
+	if (!gpu)
+		return -ENOMEM;
+
+	gpu->dev = &pdev->dev;
+	mutex_init(&gpu->lock);
+
+	/*
+	 * Set the GPU base address to the start of physical memory.  This
+	 * ensures that if we have up to 2GB, the v1 MMU can address the
+	 * highest memory.  This is important as command buffers may be
+	 * allocated outside of this limit.
+	 */
+	gpu->memory_base = PHYS_OFFSET;
+
+	/* Map registers: */
+	gpu->mmio = etnaviv_ioremap(pdev, NULL, dev_name(gpu->dev));
+	if (IS_ERR(gpu->mmio))
+		return PTR_ERR(gpu->mmio);
+
+	/* Get Interrupt: */
+	gpu->irq = platform_get_irq(pdev, 0);
+	if (gpu->irq < 0) {
+		err = gpu->irq;
+		dev_err(dev, "failed to get irq: %d\n", err);
+		goto fail;
+	}
+
+	err = devm_request_irq(&pdev->dev, gpu->irq, irq_handler, 0,
+			       dev_name(gpu->dev), gpu);
+	if (err) {
+		dev_err(dev, "failed to request IRQ%u: %d\n", gpu->irq, err);
+		goto fail;
+	}
+
+	/* Get Clocks: */
+	gpu->clk_bus = devm_clk_get(&pdev->dev, "bus");
+	DBG("clk_bus: %p", gpu->clk_bus);
+	if (IS_ERR(gpu->clk_bus))
+		gpu->clk_bus = NULL;
+
+	gpu->clk_core = devm_clk_get(&pdev->dev, "core");
+	DBG("clk_core: %p", gpu->clk_core);
+	if (IS_ERR(gpu->clk_core))
+		gpu->clk_core = NULL;
+
+	gpu->clk_shader = devm_clk_get(&pdev->dev, "shader");
+	DBG("clk_shader: %p", gpu->clk_shader);
+	if (IS_ERR(gpu->clk_shader))
+		gpu->clk_shader = NULL;
+
+	/* TODO: figure out max mapped size */
+	dev_set_drvdata(dev, gpu);
+
+	/*
+	 * We treat the device as initially suspended.  The runtime PM
+	 * autosuspend delay is rather arbitary: no measurements have
+	 * yet been performed to determine an appropriate value.
+	 */
+	pm_runtime_use_autosuspend(gpu->dev);
+	pm_runtime_set_autosuspend_delay(gpu->dev, 200);
+	pm_runtime_enable(gpu->dev);
+
+	err = component_add(&pdev->dev, &gpu_ops);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register component: %d\n", err);
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+	return err;
+}
+
+static int etnaviv_gpu_platform_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &gpu_ops);
+	pm_runtime_disable(&pdev->dev);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int etnaviv_gpu_rpm_suspend(struct device *dev)
+{
+	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+	u32 idle, mask;
+
+	/* If we have outstanding fences, we're not idle */
+	if (gpu->completed_fence != gpu->active_fence)
+		return -EBUSY;
+
+	/* Check whether the hardware (except FE) is idle */
+	mask = gpu->idle_mask & ~VIVS_HI_IDLE_STATE_FE;
+	idle = gpu_read(gpu, VIVS_HI_IDLE_STATE) & mask;
+	if (idle != mask)
+		return -EBUSY;
+
+	return etnaviv_gpu_hw_suspend(gpu);
+}
+
+static int etnaviv_gpu_rpm_resume(struct device *dev)
+{
+	struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+	int ret;
+
+	ret = etnaviv_gpu_clk_enable(gpu);
+	if (ret)
+		return ret;
+
+	/* Re-initialise the basic hardware state */
+	if (gpu->drm && gpu->buffer) {
+		ret = etnaviv_gpu_hw_resume(gpu);
+		if (ret) {
+			etnaviv_gpu_clk_disable(gpu);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops etnaviv_gpu_pm_ops = {
+	SET_RUNTIME_PM_OPS(etnaviv_gpu_rpm_suspend, etnaviv_gpu_rpm_resume,
+			   NULL)
+};
+
+struct platform_driver etnaviv_gpu_driver = {
+	.driver = {
+		.name = "etnaviv-gpu",
+		.owner = THIS_MODULE,
+		.pm = &etnaviv_gpu_pm_ops,
+		.of_match_table = etnaviv_gpu_match,
+	},
+	.probe = etnaviv_gpu_platform_probe,
+	.remove = etnaviv_gpu_platform_remove,
+	.id_table = gpu_ids,
+};
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
new file mode 100644
index 0000000..c75d503
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 __ETNAVIV_GPU_H__
+#define __ETNAVIV_GPU_H__
+
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+
+#include "etnaviv_drv.h"
+
+struct etnaviv_gem_submit;
+
+struct etnaviv_chip_identity {
+	/* Chip model. */
+	u32 model;
+
+	/* Revision value.*/
+	u32 revision;
+
+	/* Supported feature fields. */
+	u32 features;
+
+	/* Supported minor feature fields. */
+	u32 minor_features0;
+
+	/* Supported minor feature 1 fields. */
+	u32 minor_features1;
+
+	/* Supported minor feature 2 fields. */
+	u32 minor_features2;
+
+	/* Supported minor feature 3 fields. */
+	u32 minor_features3;
+
+	/* Number of streams supported. */
+	u32 stream_count;
+
+	/* Total number of temporary registers per thread. */
+	u32 register_max;
+
+	/* Maximum number of threads. */
+	u32 thread_count;
+
+	/* Number of shader cores. */
+	u32 shader_core_count;
+
+	/* Size of the vertex cache. */
+	u32 vertex_cache_size;
+
+	/* Number of entries in the vertex output buffer. */
+	u32 vertex_output_buffer_size;
+
+	/* Number of pixel pipes. */
+	u32 pixel_pipes;
+
+	/* Number of instructions. */
+	u32 instruction_count;
+
+	/* Number of constants. */
+	u32 num_constants;
+
+	/* Buffer size */
+	u32 buffer_size;
+};
+
+struct etnaviv_event {
+	bool used;
+	struct fence *fence;
+};
+
+struct etnaviv_cmdbuf;
+
+struct etnaviv_gpu {
+	struct drm_device *drm;
+	struct device *dev;
+	struct mutex lock;
+	struct etnaviv_chip_identity identity;
+	struct etnaviv_file_private *lastctx;
+	bool switch_context;
+
+	/* 'ring'-buffer: */
+	struct etnaviv_cmdbuf *buffer;
+
+	/* bus base address of memory  */
+	u32 memory_base;
+
+	/* event management: */
+	struct etnaviv_event event[30];
+	struct completion event_free;
+	spinlock_t event_spinlock;
+
+	/* list of currently in-flight command buffers */
+	struct list_head active_cmd_list;
+
+	u32 idle_mask;
+
+	/* Fencing support */
+	u32 next_fence;
+	u32 active_fence;
+	u32 completed_fence;
+	u32 retired_fence;
+	wait_queue_head_t fence_event;
+	unsigned int fence_context;
+	spinlock_t fence_spinlock;
+
+	/* worker for handling active-list retiring: */
+	struct work_struct retire_work;
+
+	void __iomem *mmio;
+	int irq;
+
+	struct etnaviv_iommu *mmu;
+
+	/* Power Control: */
+	struct clk *clk_bus;
+	struct clk *clk_core;
+	struct clk *clk_shader;
+
+	/* Hang Detction: */
+#define DRM_ETNAVIV_HANGCHECK_PERIOD 500 /* in ms */
+#define DRM_ETNAVIV_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_ETNAVIV_HANGCHECK_PERIOD)
+	struct timer_list hangcheck_timer;
+	u32 hangcheck_fence;
+	u32 hangcheck_dma_addr;
+	struct work_struct recover_work;
+};
+
+struct etnaviv_cmdbuf {
+	/* device this cmdbuf is allocated for */
+	struct etnaviv_gpu *gpu;
+	/* user context key, must be unique between all active users */
+	struct etnaviv_file_private *ctx;
+	/* cmdbuf properties */
+	void *vaddr;
+	dma_addr_t paddr;
+	u32 size;
+	u32 user_size;
+	/* fence after which this buffer is to be disposed */
+	struct fence *fence;
+	/* target exec state */
+	u32 exec_state;
+	/* per GPU in-flight list */
+	struct list_head node;
+	/* BOs attached to this command buffer */
+	unsigned int nr_bos;
+	struct etnaviv_gem_object *bo[0];
+};
+
+static inline void gpu_write(struct etnaviv_gpu *gpu, u32 reg, u32 data)
+{
+	etnaviv_writel(data, gpu->mmio + reg);
+}
+
+static inline u32 gpu_read(struct etnaviv_gpu *gpu, u32 reg)
+{
+	return etnaviv_readl(gpu->mmio + reg);
+}
+
+static inline bool fence_completed(struct etnaviv_gpu *gpu, u32 fence)
+{
+	return fence_after_eq(gpu->completed_fence, fence);
+}
+
+static inline bool fence_retired(struct etnaviv_gpu *gpu, u32 fence)
+{
+	return fence_after_eq(gpu->retired_fence, fence);
+}
+
+int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value);
+
+int etnaviv_gpu_init(struct etnaviv_gpu *gpu);
+
+#ifdef CONFIG_DEBUG_FS
+int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m);
+#endif
+
+int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
+	unsigned int context, bool exclusive);
+
+void etnaviv_gpu_retire(struct etnaviv_gpu *gpu);
+int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu,
+	u32 fence, struct timespec *timeout);
+int etnaviv_gpu_wait_obj_inactive(struct etnaviv_gpu *gpu,
+	struct etnaviv_gem_object *etnaviv_obj, struct timespec *timeout);
+int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
+	struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf);
+struct etnaviv_cmdbuf *etnaviv_gpu_cmdbuf_new(struct etnaviv_gpu *gpu,
+					      u32 size, size_t nr_bos);
+void etnaviv_gpu_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf);
+int etnaviv_gpu_pm_get_sync(struct etnaviv_gpu *gpu);
+void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu);
+
+extern struct platform_driver etnaviv_gpu_driver;
+
+#endif /* __ETNAVIV_GPU_H__ */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu.c
new file mode 100644
index 0000000..522cfd4
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2014 Christian Gmeiner <christian.gmeiner@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 <linux/iommu.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/bitops.h>
+
+#include "etnaviv_gpu.h"
+#include "etnaviv_mmu.h"
+#include "etnaviv_iommu.h"
+#include "state_hi.xml.h"
+
+#define PT_SIZE		SZ_2M
+#define PT_ENTRIES	(PT_SIZE / sizeof(u32))
+
+#define GPU_MEM_START	0x80000000
+
+struct etnaviv_iommu_domain_pgtable {
+	u32 *pgtable;
+	dma_addr_t paddr;
+};
+
+struct etnaviv_iommu_domain {
+	struct iommu_domain domain;
+	struct device *dev;
+	void *bad_page_cpu;
+	dma_addr_t bad_page_dma;
+	struct etnaviv_iommu_domain_pgtable pgtable;
+	spinlock_t map_lock;
+};
+
+static struct etnaviv_iommu_domain *to_etnaviv_domain(struct iommu_domain *domain)
+{
+	return container_of(domain, struct etnaviv_iommu_domain, domain);
+}
+
+static int pgtable_alloc(struct etnaviv_iommu_domain_pgtable *pgtable,
+			 size_t size)
+{
+	pgtable->pgtable = dma_alloc_coherent(NULL, size, &pgtable->paddr, GFP_KERNEL);
+	if (!pgtable->pgtable)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void pgtable_free(struct etnaviv_iommu_domain_pgtable *pgtable,
+			 size_t size)
+{
+	dma_free_coherent(NULL, size, pgtable->pgtable, pgtable->paddr);
+}
+
+static u32 pgtable_read(struct etnaviv_iommu_domain_pgtable *pgtable,
+			   unsigned long iova)
+{
+	/* calcuate index into page table */
+	unsigned int index = (iova - GPU_MEM_START) / SZ_4K;
+	phys_addr_t paddr;
+
+	paddr = pgtable->pgtable[index];
+
+	return paddr;
+}
+
+static void pgtable_write(struct etnaviv_iommu_domain_pgtable *pgtable,
+			  unsigned long iova, phys_addr_t paddr)
+{
+	/* calcuate index into page table */
+	unsigned int index = (iova - GPU_MEM_START) / SZ_4K;
+
+	pgtable->pgtable[index] = paddr;
+}
+
+static int __etnaviv_iommu_init(struct etnaviv_iommu_domain *etnaviv_domain)
+{
+	u32 *p;
+	int ret, i;
+
+	etnaviv_domain->bad_page_cpu = dma_alloc_coherent(etnaviv_domain->dev,
+						  SZ_4K,
+						  &etnaviv_domain->bad_page_dma,
+						  GFP_KERNEL);
+	if (!etnaviv_domain->bad_page_cpu)
+		return -ENOMEM;
+
+	p = etnaviv_domain->bad_page_cpu;
+	for (i = 0; i < SZ_4K / 4; i++)
+		*p++ = 0xdead55aa;
+
+	ret = pgtable_alloc(&etnaviv_domain->pgtable, PT_SIZE);
+	if (ret < 0) {
+		dma_free_coherent(etnaviv_domain->dev, SZ_4K,
+				  etnaviv_domain->bad_page_cpu,
+				  etnaviv_domain->bad_page_dma);
+		return ret;
+	}
+
+	for (i = 0; i < PT_ENTRIES; i++)
+		etnaviv_domain->pgtable.pgtable[i] =
+			etnaviv_domain->bad_page_dma;
+
+	spin_lock_init(&etnaviv_domain->map_lock);
+
+	return 0;
+}
+
+static void etnaviv_domain_free(struct iommu_domain *domain)
+{
+	struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);
+
+	pgtable_free(&etnaviv_domain->pgtable, PT_SIZE);
+
+	dma_free_coherent(etnaviv_domain->dev, SZ_4K,
+			  etnaviv_domain->bad_page_cpu,
+			  etnaviv_domain->bad_page_dma);
+
+	kfree(etnaviv_domain);
+}
+
+static int etnaviv_iommuv1_map(struct iommu_domain *domain, unsigned long iova,
+	   phys_addr_t paddr, size_t size, int prot)
+{
+	struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);
+
+	if (size != SZ_4K)
+		return -EINVAL;
+
+	spin_lock(&etnaviv_domain->map_lock);
+	pgtable_write(&etnaviv_domain->pgtable, iova, paddr);
+	spin_unlock(&etnaviv_domain->map_lock);
+
+	return 0;
+}
+
+static size_t etnaviv_iommuv1_unmap(struct iommu_domain *domain,
+	unsigned long iova, size_t size)
+{
+	struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);
+
+	if (size != SZ_4K)
+		return -EINVAL;
+
+	spin_lock(&etnaviv_domain->map_lock);
+	pgtable_write(&etnaviv_domain->pgtable, iova,
+		      etnaviv_domain->bad_page_dma);
+	spin_unlock(&etnaviv_domain->map_lock);
+
+	return SZ_4K;
+}
+
+static phys_addr_t etnaviv_iommu_iova_to_phys(struct iommu_domain *domain,
+	dma_addr_t iova)
+{
+	struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);
+
+	return pgtable_read(&etnaviv_domain->pgtable, iova);
+}
+
+static size_t etnaviv_iommuv1_dump_size(struct iommu_domain *domain)
+{
+	return PT_SIZE;
+}
+
+static void etnaviv_iommuv1_dump(struct iommu_domain *domain, void *buf)
+{
+	struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);
+
+	memcpy(buf, etnaviv_domain->pgtable.pgtable, PT_SIZE);
+}
+
+static struct etnaviv_iommu_ops etnaviv_iommu_ops = {
+	.ops = {
+		.domain_free = etnaviv_domain_free,
+		.map = etnaviv_iommuv1_map,
+		.unmap = etnaviv_iommuv1_unmap,
+		.iova_to_phys = etnaviv_iommu_iova_to_phys,
+		.pgsize_bitmap = SZ_4K,
+	},
+	.dump_size = etnaviv_iommuv1_dump_size,
+	.dump = etnaviv_iommuv1_dump,
+};
+
+void etnaviv_iommu_domain_restore(struct etnaviv_gpu *gpu,
+	struct iommu_domain *domain)
+{
+	struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain);
+	u32 pgtable;
+
+	/* set page table address in MC */
+	pgtable = (u32)etnaviv_domain->pgtable.paddr;
+
+	gpu_write(gpu, VIVS_MC_MMU_FE_PAGE_TABLE, pgtable);
+	gpu_write(gpu, VIVS_MC_MMU_TX_PAGE_TABLE, pgtable);
+	gpu_write(gpu, VIVS_MC_MMU_PE_PAGE_TABLE, pgtable);
+	gpu_write(gpu, VIVS_MC_MMU_PEZ_PAGE_TABLE, pgtable);
+	gpu_write(gpu, VIVS_MC_MMU_RA_PAGE_TABLE, pgtable);
+}
+
+struct iommu_domain *etnaviv_iommu_domain_alloc(struct etnaviv_gpu *gpu)
+{
+	struct etnaviv_iommu_domain *etnaviv_domain;
+	int ret;
+
+	etnaviv_domain = kzalloc(sizeof(*etnaviv_domain), GFP_KERNEL);
+	if (!etnaviv_domain)
+		return NULL;
+
+	etnaviv_domain->dev = gpu->dev;
+
+	etnaviv_domain->domain.type = __IOMMU_DOMAIN_PAGING;
+	etnaviv_domain->domain.ops = &etnaviv_iommu_ops.ops;
+	etnaviv_domain->domain.geometry.aperture_start = GPU_MEM_START;
+	etnaviv_domain->domain.geometry.aperture_end = GPU_MEM_START + PT_ENTRIES * SZ_4K - 1;
+
+	ret = __etnaviv_iommu_init(etnaviv_domain);
+	if (ret)
+		goto out_free;
+
+	return &etnaviv_domain->domain;
+
+out_free:
+	kfree(etnaviv_domain);
+	return NULL;
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu.h b/drivers/gpu/drm/etnaviv/etnaviv_iommu.h
new file mode 100644
index 0000000..cf45503
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2014 Christian Gmeiner <christian.gmeiner@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 __ETNAVIV_IOMMU_H__
+#define __ETNAVIV_IOMMU_H__
+
+#include <linux/iommu.h>
+struct etnaviv_gpu;
+
+struct iommu_domain *etnaviv_iommu_domain_alloc(struct etnaviv_gpu *gpu);
+void etnaviv_iommu_domain_restore(struct etnaviv_gpu *gpu,
+	struct iommu_domain *domain);
+struct iommu_domain *etnaviv_iommu_v2_domain_alloc(struct etnaviv_gpu *gpu);
+
+#endif /* __ETNAVIV_IOMMU_H__ */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
new file mode 100644
index 0000000..fbb4aed
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014 Christian Gmeiner <christian.gmeiner@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 <linux/iommu.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/bitops.h>
+
+#include "etnaviv_gpu.h"
+#include "etnaviv_iommu.h"
+#include "state_hi.xml.h"
+
+
+struct iommu_domain *etnaviv_iommu_v2_domain_alloc(struct etnaviv_gpu *gpu)
+{
+	/* TODO */
+	return NULL;
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.h b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.h
new file mode 100644
index 0000000..603ea41
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 Christian Gmeiner <christian.gmeiner@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 __ETNAVIV_IOMMU_V2_H__
+#define __ETNAVIV_IOMMU_V2_H__
+
+#include <linux/iommu.h>
+struct etnaviv_gpu;
+
+struct iommu_domain *etnaviv_iommu_v2_domain_alloc(struct etnaviv_gpu *gpu);
+
+#endif /* __ETNAVIV_IOMMU_V2_H__ */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
new file mode 100644
index 0000000..6743bc6
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 "etnaviv_drv.h"
+#include "etnaviv_gem.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_mmu.h"
+
+static int etnaviv_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 etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova,
+		struct sg_table *sgt, unsigned len, int prot)
+{
+	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_dma_address(sg) - sg->offset;
+		size_t bytes = sg_dma_len(sg) + sg->offset;
+
+		VERB("map[%d]: %08x %08x(%zx)", 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_dma_len(sg) + sg->offset;
+
+		iommu_unmap(domain, da, bytes);
+		da += bytes;
+	}
+	return ret;
+}
+
+int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova,
+		struct sg_table *sgt, unsigned len)
+{
+	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_dma_len(sg) + sg->offset;
+		size_t unmapped;
+
+		unmapped = iommu_unmap(domain, da, bytes);
+		if (unmapped < bytes)
+			return unmapped;
+
+		VERB("unmap[%d]: %08x(%zx)", i, iova, bytes);
+
+		BUG_ON(!PAGE_ALIGNED(bytes));
+
+		da += bytes;
+	}
+
+	return 0;
+}
+
+static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu *mmu,
+	struct etnaviv_vram_mapping *mapping)
+{
+	struct etnaviv_gem_object *etnaviv_obj = mapping->object;
+
+	etnaviv_iommu_unmap(mmu, mapping->vram_node.start,
+			    etnaviv_obj->sgt, etnaviv_obj->base.size);
+	drm_mm_remove_node(&mapping->vram_node);
+}
+
+int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
+	struct etnaviv_gem_object *etnaviv_obj, u32 memory_base,
+	struct etnaviv_vram_mapping *mapping)
+{
+	struct etnaviv_vram_mapping *free = NULL;
+	struct sg_table *sgt = etnaviv_obj->sgt;
+	struct drm_mm_node *node;
+	int ret;
+
+	lockdep_assert_held(&etnaviv_obj->lock);
+
+	mutex_lock(&mmu->lock);
+
+	/* v1 MMU can optimize single entry (contiguous) scatterlists */
+	if (sgt->nents == 1 && !(etnaviv_obj->flags & ETNA_BO_FORCE_MMU)) {
+		u32 iova;
+
+		iova = sg_dma_address(sgt->sgl) - memory_base;
+		if (iova < 0x80000000 - sg_dma_len(sgt->sgl)) {
+			mapping->iova = iova;
+			list_add_tail(&mapping->mmu_node, &mmu->mappings);
+			mutex_unlock(&mmu->lock);
+			return 0;
+		}
+	}
+
+	node = &mapping->vram_node;
+	while (1) {
+		struct etnaviv_vram_mapping *m, *n;
+		struct list_head list;
+		bool found;
+
+		ret = drm_mm_insert_node_in_range(&mmu->mm, node,
+			etnaviv_obj->base.size, 0, mmu->last_iova, ~0UL,
+			DRM_MM_SEARCH_DEFAULT);
+
+		if (ret != -ENOSPC)
+			break;
+
+		/*
+		 * If we did not search from the start of the MMU region,
+		 * try again in case there are free slots.
+		 */
+		if (mmu->last_iova) {
+			mmu->last_iova = 0;
+			mmu->need_flush = true;
+			continue;
+		}
+
+		/* Try to retire some entries */
+		drm_mm_init_scan(&mmu->mm, etnaviv_obj->base.size, 0, 0);
+
+		found = 0;
+		INIT_LIST_HEAD(&list);
+		list_for_each_entry(free, &mmu->mappings, mmu_node) {
+			/* If this vram node has not been used, skip this. */
+			if (!free->vram_node.mm)
+				continue;
+
+			/*
+			 * If the iova is pinned, then it's in-use,
+			 * so we must keep its mapping.
+			 */
+			if (free->use)
+				continue;
+
+			list_add(&free->scan_node, &list);
+			if (drm_mm_scan_add_block(&free->vram_node)) {
+				found = true;
+				break;
+			}
+		}
+
+		if (!found) {
+			/* Nothing found, clean up and fail */
+			list_for_each_entry_safe(m, n, &list, scan_node)
+				BUG_ON(drm_mm_scan_remove_block(&m->vram_node));
+			break;
+		}
+
+		/*
+		 * drm_mm does not allow any other operations while
+		 * scanning, so we have to remove all blocks first.
+		 * If drm_mm_scan_remove_block() returns false, we
+		 * can leave the block pinned.
+		 */
+		list_for_each_entry_safe(m, n, &list, scan_node)
+			if (!drm_mm_scan_remove_block(&m->vram_node))
+				list_del_init(&m->scan_node);
+
+		/*
+		 * Unmap the blocks which need to be reaped from the MMU.
+		 * Clear the mmu pointer to prevent the get_iova finding
+		 * this mapping.
+		 */
+		list_for_each_entry_safe(m, n, &list, scan_node) {
+			etnaviv_iommu_remove_mapping(mmu, m);
+			m->mmu = NULL;
+			list_del_init(&m->mmu_node);
+			list_del_init(&m->scan_node);
+		}
+
+		/*
+		 * We removed enough mappings so that the new allocation will
+		 * succeed.  Ensure that the MMU will be flushed before the
+		 * associated commit requesting this mapping, and retry the
+		 * allocation one more time.
+		 */
+		mmu->need_flush = true;
+	}
+
+	if (ret < 0) {
+		mutex_unlock(&mmu->lock);
+		return ret;
+	}
+
+	mmu->last_iova = node->start + etnaviv_obj->base.size;
+	mapping->iova = node->start;
+	ret = etnaviv_iommu_map(mmu, node->start, sgt, etnaviv_obj->base.size,
+				IOMMU_READ | IOMMU_WRITE);
+
+	if (ret < 0) {
+		drm_mm_remove_node(node);
+		mutex_unlock(&mmu->lock);
+		return ret;
+	}
+
+	list_add_tail(&mapping->mmu_node, &mmu->mappings);
+	mutex_unlock(&mmu->lock);
+
+	return ret;
+}
+
+void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu,
+	struct etnaviv_vram_mapping *mapping)
+{
+	WARN_ON(mapping->use);
+
+	mutex_lock(&mmu->lock);
+
+	/* If the vram node is on the mm, unmap and remove the node */
+	if (mapping->vram_node.mm == &mmu->mm)
+		etnaviv_iommu_remove_mapping(mmu, mapping);
+
+	list_del(&mapping->mmu_node);
+	mutex_unlock(&mmu->lock);
+}
+
+void etnaviv_iommu_destroy(struct etnaviv_iommu *mmu)
+{
+	drm_mm_takedown(&mmu->mm);
+	iommu_domain_free(mmu->domain);
+	kfree(mmu);
+}
+
+struct etnaviv_iommu *etnaviv_iommu_new(struct etnaviv_gpu *gpu,
+	struct iommu_domain *domain, enum etnaviv_iommu_version version)
+{
+	struct etnaviv_iommu *mmu;
+
+	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
+	if (!mmu)
+		return ERR_PTR(-ENOMEM);
+
+	mmu->domain = domain;
+	mmu->gpu = gpu;
+	mmu->version = version;
+	mutex_init(&mmu->lock);
+	INIT_LIST_HEAD(&mmu->mappings);
+
+	drm_mm_init(&mmu->mm, domain->geometry.aperture_start,
+		    domain->geometry.aperture_end -
+		      domain->geometry.aperture_start + 1);
+
+	iommu_set_fault_handler(domain, etnaviv_fault_handler, gpu->dev);
+
+	return mmu;
+}
+
+size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu)
+{
+	struct etnaviv_iommu_ops *ops;
+
+	ops = container_of(iommu->domain->ops, struct etnaviv_iommu_ops, ops);
+
+	return ops->dump_size(iommu->domain);
+}
+
+void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf)
+{
+	struct etnaviv_iommu_ops *ops;
+
+	ops = container_of(iommu->domain->ops, struct etnaviv_iommu_ops, ops);
+
+	ops->dump(iommu->domain, buf);
+}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
new file mode 100644
index 0000000..fff215a4
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 __ETNAVIV_MMU_H__
+#define __ETNAVIV_MMU_H__
+
+#include <linux/iommu.h>
+
+enum etnaviv_iommu_version {
+	ETNAVIV_IOMMU_V1 = 0,
+	ETNAVIV_IOMMU_V2,
+};
+
+struct etnaviv_gpu;
+struct etnaviv_vram_mapping;
+
+struct etnaviv_iommu_ops {
+	struct iommu_ops ops;
+	size_t (*dump_size)(struct iommu_domain *);
+	void (*dump)(struct iommu_domain *, void *);
+};
+
+struct etnaviv_iommu {
+	struct etnaviv_gpu *gpu;
+	struct iommu_domain *domain;
+
+	enum etnaviv_iommu_version version;
+
+	/* memory manager for GPU address area */
+	struct mutex lock;
+	struct list_head mappings;
+	struct drm_mm mm;
+	u32 last_iova;
+	bool need_flush;
+};
+
+struct etnaviv_gem_object;
+
+int etnaviv_iommu_attach(struct etnaviv_iommu *iommu, const char **names,
+	int cnt);
+int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova,
+	struct sg_table *sgt, unsigned len, int prot);
+int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova,
+	struct sg_table *sgt, unsigned len);
+int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
+	struct etnaviv_gem_object *etnaviv_obj, u32 memory_base,
+	struct etnaviv_vram_mapping *mapping);
+void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu,
+	struct etnaviv_vram_mapping *mapping);
+void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu);
+
+size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu);
+void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf);
+
+struct etnaviv_iommu *etnaviv_iommu_new(struct etnaviv_gpu *gpu,
+	struct iommu_domain *domain, enum etnaviv_iommu_version version);
+
+#endif /* __ETNAVIV_MMU_H__ */
diff --git a/drivers/gpu/drm/etnaviv/state.xml.h b/drivers/gpu/drm/etnaviv/state.xml.h
new file mode 100644
index 0000000..3682183
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/state.xml.h
@@ -0,0 +1,351 @@
+#ifndef STATE_XML
+#define STATE_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- state.xml    (  18882 bytes, from 2015-03-25 11:42:32)
+- common.xml   (  18437 bytes, from 2015-03-25 11:27:41)
+- state_hi.xml (  23420 bytes, from 2015-03-25 11:47:21)
+- state_2d.xml (  51549 bytes, from 2015-03-25 11:25:06)
+- state_3d.xml (  54600 bytes, from 2015-03-25 11:25:19)
+- state_vg.xml (   5973 bytes, from 2015-03-25 11:26:01)
+
+Copyright (C) 2015
+*/
+
+
+#define VARYING_COMPONENT_USE_UNUSED				0x00000000
+#define VARYING_COMPONENT_USE_USED				0x00000001
+#define VARYING_COMPONENT_USE_POINTCOORD_X			0x00000002
+#define VARYING_COMPONENT_USE_POINTCOORD_Y			0x00000003
+#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__MASK		0x000000ff
+#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__SHIFT		0
+#define FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE(x)		(((x) << FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__SHIFT) & FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE__MASK)
+#define VIVS_FE							0x00000000
+
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG(i0)		       (0x00000600 + 0x4*(i0))
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG__ESIZE			0x00000004
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG__LEN			0x00000010
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE__MASK		0x0000000f
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE__SHIFT		0
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_BYTE			0x00000000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_BYTE	0x00000001
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_SHORT		0x00000002
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_SHORT	0x00000003
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_INT			0x00000004
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_INT		0x00000005
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FLOAT		0x00000008
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_HALF_FLOAT		0x00000009
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_FIXED		0x0000000b
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_INT_10_10_10_2	0x0000000c
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_TYPE_UNSIGNED_INT_10_10_10_2	0x0000000d
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__MASK		0x00000030
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT		4
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(x)			(((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE		0x00000080
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__MASK		0x00000700
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT		8
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(x)			(((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__MASK			0x00003000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT		12
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(x)			(((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE__MASK		0x0000c000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE__SHIFT		14
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF		0x00000000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_ON		0x00008000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START__MASK		0x00ff0000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT		16
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_START(x)			(((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_START__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_START__MASK)
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END__MASK			0xff000000
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT		24
+#define VIVS_FE_VERTEX_ELEMENT_CONFIG_END(x)			(((x) << VIVS_FE_VERTEX_ELEMENT_CONFIG_END__SHIFT) & VIVS_FE_VERTEX_ELEMENT_CONFIG_END__MASK)
+
+#define VIVS_FE_CMD_STREAM_BASE_ADDR				0x00000640
+
+#define VIVS_FE_INDEX_STREAM_BASE_ADDR				0x00000644
+
+#define VIVS_FE_INDEX_STREAM_CONTROL				0x00000648
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE__MASK			0x00000003
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE__SHIFT		0
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_CHAR		0x00000000
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_SHORT	0x00000001
+#define VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_INT		0x00000002
+
+#define VIVS_FE_VERTEX_STREAM_BASE_ADDR				0x0000064c
+
+#define VIVS_FE_VERTEX_STREAM_CONTROL				0x00000650
+
+#define VIVS_FE_COMMAND_ADDRESS					0x00000654
+
+#define VIVS_FE_COMMAND_CONTROL					0x00000658
+#define VIVS_FE_COMMAND_CONTROL_PREFETCH__MASK			0x0000ffff
+#define VIVS_FE_COMMAND_CONTROL_PREFETCH__SHIFT			0
+#define VIVS_FE_COMMAND_CONTROL_PREFETCH(x)			(((x) << VIVS_FE_COMMAND_CONTROL_PREFETCH__SHIFT) & VIVS_FE_COMMAND_CONTROL_PREFETCH__MASK)
+#define VIVS_FE_COMMAND_CONTROL_ENABLE				0x00010000
+
+#define VIVS_FE_DMA_STATUS					0x0000065c
+
+#define VIVS_FE_DMA_DEBUG_STATE					0x00000660
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE__MASK			0x0000001f
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE__SHIFT		0
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_IDLE			0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DEC			0x00000001
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_ADR0			0x00000002
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LOAD0			0x00000003
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_ADR1			0x00000004
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LOAD1			0x00000005
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DADR			0x00000006
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DCMD			0x00000007
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DCNTL		0x00000008
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_3DIDXCNTL		0x00000009
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_INITREQDMA		0x0000000a
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DRAWIDX		0x0000000b
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_DRAW			0x0000000c
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DRECT0		0x0000000d
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DRECT1		0x0000000e
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DDATA0		0x0000000f
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_2DDATA1		0x00000010
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_WAITFIFO		0x00000011
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_WAIT			0x00000012
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_LINK			0x00000013
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_END			0x00000014
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_STATE_STALL			0x00000015
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE__MASK		0x00000300
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE__SHIFT		8
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_IDLE		0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_START		0x00000100
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_REQ		0x00000200
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_DMA_STATE_END		0x00000300
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE__MASK		0x00000c00
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE__SHIFT		10
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_IDLE		0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_RAMVALID	0x00000400
+#define VIVS_FE_DMA_DEBUG_STATE_CMD_FETCH_STATE_VALID		0x00000800
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE__MASK		0x00003000
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE__SHIFT		12
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_IDLE		0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_WAITIDX		0x00001000
+#define VIVS_FE_DMA_DEBUG_STATE_REQ_DMA_STATE_CAL		0x00002000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE__MASK			0x0000c000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE__SHIFT		14
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_IDLE			0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_LDADR			0x00004000
+#define VIVS_FE_DMA_DEBUG_STATE_CAL_STATE_IDXCALC		0x00008000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE__MASK		0x00030000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE__SHIFT		16
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_IDLE		0x00000000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_CKCACHE		0x00010000
+#define VIVS_FE_DMA_DEBUG_STATE_VE_REQ_STATE_MISS		0x00020000
+
+#define VIVS_FE_DMA_ADDRESS					0x00000664
+
+#define VIVS_FE_DMA_LOW						0x00000668
+
+#define VIVS_FE_DMA_HIGH					0x0000066c
+
+#define VIVS_FE_AUTO_FLUSH					0x00000670
+
+#define VIVS_FE_UNK00678					0x00000678
+
+#define VIVS_FE_UNK0067C					0x0000067c
+
+#define VIVS_FE_VERTEX_STREAMS(i0)			       (0x00000000 + 0x4*(i0))
+#define VIVS_FE_VERTEX_STREAMS__ESIZE				0x00000004
+#define VIVS_FE_VERTEX_STREAMS__LEN				0x00000008
+
+#define VIVS_FE_VERTEX_STREAMS_BASE_ADDR(i0)		       (0x00000680 + 0x4*(i0))
+
+#define VIVS_FE_VERTEX_STREAMS_CONTROL(i0)		       (0x000006a0 + 0x4*(i0))
+
+#define VIVS_FE_UNK00700(i0)				       (0x00000700 + 0x4*(i0))
+#define VIVS_FE_UNK00700__ESIZE					0x00000004
+#define VIVS_FE_UNK00700__LEN					0x00000010
+
+#define VIVS_FE_UNK00740(i0)				       (0x00000740 + 0x4*(i0))
+#define VIVS_FE_UNK00740__ESIZE					0x00000004
+#define VIVS_FE_UNK00740__LEN					0x00000010
+
+#define VIVS_FE_UNK00780(i0)				       (0x00000780 + 0x4*(i0))
+#define VIVS_FE_UNK00780__ESIZE					0x00000004
+#define VIVS_FE_UNK00780__LEN					0x00000010
+
+#define VIVS_GL							0x00000000
+
+#define VIVS_GL_PIPE_SELECT					0x00003800
+#define VIVS_GL_PIPE_SELECT_PIPE__MASK				0x00000001
+#define VIVS_GL_PIPE_SELECT_PIPE__SHIFT				0
+#define VIVS_GL_PIPE_SELECT_PIPE(x)				(((x) << VIVS_GL_PIPE_SELECT_PIPE__SHIFT) & VIVS_GL_PIPE_SELECT_PIPE__MASK)
+
+#define VIVS_GL_EVENT						0x00003804
+#define VIVS_GL_EVENT_EVENT_ID__MASK				0x0000001f
+#define VIVS_GL_EVENT_EVENT_ID__SHIFT				0
+#define VIVS_GL_EVENT_EVENT_ID(x)				(((x) << VIVS_GL_EVENT_EVENT_ID__SHIFT) & VIVS_GL_EVENT_EVENT_ID__MASK)
+#define VIVS_GL_EVENT_FROM_FE					0x00000020
+#define VIVS_GL_EVENT_FROM_PE					0x00000040
+#define VIVS_GL_EVENT_SOURCE__MASK				0x00001f00
+#define VIVS_GL_EVENT_SOURCE__SHIFT				8
+#define VIVS_GL_EVENT_SOURCE(x)					(((x) << VIVS_GL_EVENT_SOURCE__SHIFT) & VIVS_GL_EVENT_SOURCE__MASK)
+
+#define VIVS_GL_SEMAPHORE_TOKEN					0x00003808
+#define VIVS_GL_SEMAPHORE_TOKEN_FROM__MASK			0x0000001f
+#define VIVS_GL_SEMAPHORE_TOKEN_FROM__SHIFT			0
+#define VIVS_GL_SEMAPHORE_TOKEN_FROM(x)				(((x) << VIVS_GL_SEMAPHORE_TOKEN_FROM__SHIFT) & VIVS_GL_SEMAPHORE_TOKEN_FROM__MASK)
+#define VIVS_GL_SEMAPHORE_TOKEN_TO__MASK			0x00001f00
+#define VIVS_GL_SEMAPHORE_TOKEN_TO__SHIFT			8
+#define VIVS_GL_SEMAPHORE_TOKEN_TO(x)				(((x) << VIVS_GL_SEMAPHORE_TOKEN_TO__SHIFT) & VIVS_GL_SEMAPHORE_TOKEN_TO__MASK)
+
+#define VIVS_GL_FLUSH_CACHE					0x0000380c
+#define VIVS_GL_FLUSH_CACHE_DEPTH				0x00000001
+#define VIVS_GL_FLUSH_CACHE_COLOR				0x00000002
+#define VIVS_GL_FLUSH_CACHE_TEXTURE				0x00000004
+#define VIVS_GL_FLUSH_CACHE_PE2D				0x00000008
+#define VIVS_GL_FLUSH_CACHE_TEXTUREVS				0x00000010
+#define VIVS_GL_FLUSH_CACHE_SHADER_L1				0x00000020
+#define VIVS_GL_FLUSH_CACHE_SHADER_L2				0x00000040
+
+#define VIVS_GL_FLUSH_MMU					0x00003810
+#define VIVS_GL_FLUSH_MMU_FLUSH_FEMMU				0x00000001
+#define VIVS_GL_FLUSH_MMU_FLUSH_UNK1				0x00000002
+#define VIVS_GL_FLUSH_MMU_FLUSH_UNK2				0x00000004
+#define VIVS_GL_FLUSH_MMU_FLUSH_PEMMU				0x00000008
+#define VIVS_GL_FLUSH_MMU_FLUSH_UNK4				0x00000010
+
+#define VIVS_GL_VERTEX_ELEMENT_CONFIG				0x00003814
+
+#define VIVS_GL_MULTI_SAMPLE_CONFIG				0x00003818
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__MASK		0x00000003
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__SHIFT		0
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE		0x00000000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X		0x00000001
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X		0x00000002
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_MASK		0x00000008
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__MASK		0x000000f0
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__SHIFT		4
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES(x)		(((x) << VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__SHIFT) & VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES__MASK)
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES_MASK		0x00000100
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__MASK			0x00007000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__SHIFT		12
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12(x)			(((x) << VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__SHIFT) & VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12__MASK)
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK12_MASK			0x00008000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__MASK			0x00030000
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__SHIFT		16
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16(x)			(((x) << VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__SHIFT) & VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16__MASK)
+#define VIVS_GL_MULTI_SAMPLE_CONFIG_UNK16_MASK			0x00080000
+
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS			0x0000381c
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__MASK		0x000000ff
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__SHIFT		0
+#define VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM(x)			(((x) << VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__SHIFT) & VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM__MASK)
+
+#define VIVS_GL_VARYING_NUM_COMPONENTS				0x00003820
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__MASK		0x00000007
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__SHIFT		0
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR0(x)			(((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR0__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__MASK		0x00000070
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__SHIFT		4
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR1(x)			(((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR1__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__MASK		0x00000700
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__SHIFT		8
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR2(x)			(((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR2__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__MASK		0x00007000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__SHIFT		12
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR3(x)			(((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR3__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__MASK		0x00070000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__SHIFT		16
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR4(x)			(((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR4__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__MASK		0x00700000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__SHIFT		20
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR5(x)			(((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR5__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__MASK		0x07000000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__SHIFT		24
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR6(x)			(((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR6__MASK)
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__MASK		0x70000000
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__SHIFT		28
+#define VIVS_GL_VARYING_NUM_COMPONENTS_VAR7(x)			(((x) << VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__SHIFT) & VIVS_GL_VARYING_NUM_COMPONENTS_VAR7__MASK)
+
+#define VIVS_GL_VARYING_COMPONENT_USE(i0)		       (0x00003828 + 0x4*(i0))
+#define VIVS_GL_VARYING_COMPONENT_USE__ESIZE			0x00000004
+#define VIVS_GL_VARYING_COMPONENT_USE__LEN			0x00000002
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP0__MASK		0x00000003
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP0__SHIFT		0
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP0(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP0__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP0__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP1__MASK		0x0000000c
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP1__SHIFT		2
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP1(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP1__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP1__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP2__MASK		0x00000030
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP2__SHIFT		4
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP2(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP2__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP2__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP3__MASK		0x000000c0
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP3__SHIFT		6
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP3(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP3__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP3__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP4__MASK		0x00000300
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP4__SHIFT		8
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP4(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP4__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP4__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP5__MASK		0x00000c00
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP5__SHIFT		10
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP5(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP5__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP5__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP6__MASK		0x00003000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP6__SHIFT		12
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP6(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP6__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP6__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP7__MASK		0x0000c000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP7__SHIFT		14
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP7(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP7__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP7__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP8__MASK		0x00030000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP8__SHIFT		16
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP8(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP8__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP8__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP9__MASK		0x000c0000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP9__SHIFT		18
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP9(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP9__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP9__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP10__MASK		0x00300000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP10__SHIFT		20
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP10(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP10__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP10__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP11__MASK		0x00c00000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP11__SHIFT		22
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP11(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP11__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP11__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP12__MASK		0x03000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP12__SHIFT		24
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP12(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP12__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP12__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP13__MASK		0x0c000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP13__SHIFT		26
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP13(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP13__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP13__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP14__MASK		0x30000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP14__SHIFT		28
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP14(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP14__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP14__MASK)
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP15__MASK		0xc0000000
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP15__SHIFT		30
+#define VIVS_GL_VARYING_COMPONENT_USE_COMP15(x)			(((x) << VIVS_GL_VARYING_COMPONENT_USE_COMP15__SHIFT) & VIVS_GL_VARYING_COMPONENT_USE_COMP15__MASK)
+
+#define VIVS_GL_UNK03834					0x00003834
+
+#define VIVS_GL_UNK03838					0x00003838
+
+#define VIVS_GL_API_MODE					0x0000384c
+#define VIVS_GL_API_MODE_OPENGL					0x00000000
+#define VIVS_GL_API_MODE_OPENVG					0x00000001
+#define VIVS_GL_API_MODE_OPENCL					0x00000002
+
+#define VIVS_GL_CONTEXT_POINTER					0x00003850
+
+#define VIVS_GL_UNK03A00					0x00003a00
+
+#define VIVS_GL_STALL_TOKEN					0x00003c00
+#define VIVS_GL_STALL_TOKEN_FROM__MASK				0x0000001f
+#define VIVS_GL_STALL_TOKEN_FROM__SHIFT				0
+#define VIVS_GL_STALL_TOKEN_FROM(x)				(((x) << VIVS_GL_STALL_TOKEN_FROM__SHIFT) & VIVS_GL_STALL_TOKEN_FROM__MASK)
+#define VIVS_GL_STALL_TOKEN_TO__MASK				0x00001f00
+#define VIVS_GL_STALL_TOKEN_TO__SHIFT				8
+#define VIVS_GL_STALL_TOKEN_TO(x)				(((x) << VIVS_GL_STALL_TOKEN_TO__SHIFT) & VIVS_GL_STALL_TOKEN_TO__MASK)
+#define VIVS_GL_STALL_TOKEN_FLIP0				0x40000000
+#define VIVS_GL_STALL_TOKEN_FLIP1				0x80000000
+
+#define VIVS_DUMMY						0x00000000
+
+#define VIVS_DUMMY_DUMMY					0x0003fffc
+
+
+#endif /* STATE_XML */
diff --git a/drivers/gpu/drm/etnaviv/state_hi.xml.h b/drivers/gpu/drm/etnaviv/state_hi.xml.h
new file mode 100644
index 0000000..0064f26
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/state_hi.xml.h
@@ -0,0 +1,407 @@
+#ifndef STATE_HI_XML
+#define STATE_HI_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- state_hi.xml (  23420 bytes, from 2015-03-25 11:47:21)
+- common.xml   (  18437 bytes, from 2015-03-25 11:27:41)
+
+Copyright (C) 2015
+*/
+
+
+#define MMU_EXCEPTION_SLAVE_NOT_PRESENT				0x00000001
+#define MMU_EXCEPTION_PAGE_NOT_PRESENT				0x00000002
+#define MMU_EXCEPTION_WRITE_VIOLATION				0x00000003
+#define VIVS_HI							0x00000000
+
+#define VIVS_HI_CLOCK_CONTROL					0x00000000
+#define VIVS_HI_CLOCK_CONTROL_CLK3D_DIS				0x00000001
+#define VIVS_HI_CLOCK_CONTROL_CLK2D_DIS				0x00000002
+#define VIVS_HI_CLOCK_CONTROL_FSCALE_VAL__MASK			0x000001fc
+#define VIVS_HI_CLOCK_CONTROL_FSCALE_VAL__SHIFT			2
+#define VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(x)			(((x) << VIVS_HI_CLOCK_CONTROL_FSCALE_VAL__SHIFT) & VIVS_HI_CLOCK_CONTROL_FSCALE_VAL__MASK)
+#define VIVS_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD			0x00000200
+#define VIVS_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING		0x00000400
+#define VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS		0x00000800
+#define VIVS_HI_CLOCK_CONTROL_SOFT_RESET			0x00001000
+#define VIVS_HI_CLOCK_CONTROL_IDLE_3D				0x00010000
+#define VIVS_HI_CLOCK_CONTROL_IDLE_2D				0x00020000
+#define VIVS_HI_CLOCK_CONTROL_IDLE_VG				0x00040000
+#define VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU			0x00080000
+#define VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK		0x00f00000
+#define VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__SHIFT		20
+#define VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(x)		(((x) << VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__SHIFT) & VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK)
+
+#define VIVS_HI_IDLE_STATE					0x00000004
+#define VIVS_HI_IDLE_STATE_FE					0x00000001
+#define VIVS_HI_IDLE_STATE_DE					0x00000002
+#define VIVS_HI_IDLE_STATE_PE					0x00000004
+#define VIVS_HI_IDLE_STATE_SH					0x00000008
+#define VIVS_HI_IDLE_STATE_PA					0x00000010
+#define VIVS_HI_IDLE_STATE_SE					0x00000020
+#define VIVS_HI_IDLE_STATE_RA					0x00000040
+#define VIVS_HI_IDLE_STATE_TX					0x00000080
+#define VIVS_HI_IDLE_STATE_VG					0x00000100
+#define VIVS_HI_IDLE_STATE_IM					0x00000200
+#define VIVS_HI_IDLE_STATE_FP					0x00000400
+#define VIVS_HI_IDLE_STATE_TS					0x00000800
+#define VIVS_HI_IDLE_STATE_AXI_LP				0x80000000
+
+#define VIVS_HI_AXI_CONFIG					0x00000008
+#define VIVS_HI_AXI_CONFIG_AWID__MASK				0x0000000f
+#define VIVS_HI_AXI_CONFIG_AWID__SHIFT				0
+#define VIVS_HI_AXI_CONFIG_AWID(x)				(((x) << VIVS_HI_AXI_CONFIG_AWID__SHIFT) & VIVS_HI_AXI_CONFIG_AWID__MASK)
+#define VIVS_HI_AXI_CONFIG_ARID__MASK				0x000000f0
+#define VIVS_HI_AXI_CONFIG_ARID__SHIFT				4
+#define VIVS_HI_AXI_CONFIG_ARID(x)				(((x) << VIVS_HI_AXI_CONFIG_ARID__SHIFT) & VIVS_HI_AXI_CONFIG_ARID__MASK)
+#define VIVS_HI_AXI_CONFIG_AWCACHE__MASK			0x00000f00
+#define VIVS_HI_AXI_CONFIG_AWCACHE__SHIFT			8
+#define VIVS_HI_AXI_CONFIG_AWCACHE(x)				(((x) << VIVS_HI_AXI_CONFIG_AWCACHE__SHIFT) & VIVS_HI_AXI_CONFIG_AWCACHE__MASK)
+#define VIVS_HI_AXI_CONFIG_ARCACHE__MASK			0x0000f000
+#define VIVS_HI_AXI_CONFIG_ARCACHE__SHIFT			12
+#define VIVS_HI_AXI_CONFIG_ARCACHE(x)				(((x) << VIVS_HI_AXI_CONFIG_ARCACHE__SHIFT) & VIVS_HI_AXI_CONFIG_ARCACHE__MASK)
+
+#define VIVS_HI_AXI_STATUS					0x0000000c
+#define VIVS_HI_AXI_STATUS_WR_ERR_ID__MASK			0x0000000f
+#define VIVS_HI_AXI_STATUS_WR_ERR_ID__SHIFT			0
+#define VIVS_HI_AXI_STATUS_WR_ERR_ID(x)				(((x) << VIVS_HI_AXI_STATUS_WR_ERR_ID__SHIFT) & VIVS_HI_AXI_STATUS_WR_ERR_ID__MASK)
+#define VIVS_HI_AXI_STATUS_RD_ERR_ID__MASK			0x000000f0
+#define VIVS_HI_AXI_STATUS_RD_ERR_ID__SHIFT			4
+#define VIVS_HI_AXI_STATUS_RD_ERR_ID(x)				(((x) << VIVS_HI_AXI_STATUS_RD_ERR_ID__SHIFT) & VIVS_HI_AXI_STATUS_RD_ERR_ID__MASK)
+#define VIVS_HI_AXI_STATUS_DET_WR_ERR				0x00000100
+#define VIVS_HI_AXI_STATUS_DET_RD_ERR				0x00000200
+
+#define VIVS_HI_INTR_ACKNOWLEDGE				0x00000010
+#define VIVS_HI_INTR_ACKNOWLEDGE_INTR_VEC__MASK			0x7fffffff
+#define VIVS_HI_INTR_ACKNOWLEDGE_INTR_VEC__SHIFT		0
+#define VIVS_HI_INTR_ACKNOWLEDGE_INTR_VEC(x)			(((x) << VIVS_HI_INTR_ACKNOWLEDGE_INTR_VEC__SHIFT) & VIVS_HI_INTR_ACKNOWLEDGE_INTR_VEC__MASK)
+#define VIVS_HI_INTR_ACKNOWLEDGE_AXI_BUS_ERROR			0x80000000
+
+#define VIVS_HI_INTR_ENBL					0x00000014
+#define VIVS_HI_INTR_ENBL_INTR_ENBL_VEC__MASK			0xffffffff
+#define VIVS_HI_INTR_ENBL_INTR_ENBL_VEC__SHIFT			0
+#define VIVS_HI_INTR_ENBL_INTR_ENBL_VEC(x)			(((x) << VIVS_HI_INTR_ENBL_INTR_ENBL_VEC__SHIFT) & VIVS_HI_INTR_ENBL_INTR_ENBL_VEC__MASK)
+
+#define VIVS_HI_CHIP_IDENTITY					0x00000018
+#define VIVS_HI_CHIP_IDENTITY_FAMILY__MASK			0xff000000
+#define VIVS_HI_CHIP_IDENTITY_FAMILY__SHIFT			24
+#define VIVS_HI_CHIP_IDENTITY_FAMILY(x)				(((x) << VIVS_HI_CHIP_IDENTITY_FAMILY__SHIFT) & VIVS_HI_CHIP_IDENTITY_FAMILY__MASK)
+#define VIVS_HI_CHIP_IDENTITY_PRODUCT__MASK			0x00ff0000
+#define VIVS_HI_CHIP_IDENTITY_PRODUCT__SHIFT			16
+#define VIVS_HI_CHIP_IDENTITY_PRODUCT(x)			(((x) << VIVS_HI_CHIP_IDENTITY_PRODUCT__SHIFT) & VIVS_HI_CHIP_IDENTITY_PRODUCT__MASK)
+#define VIVS_HI_CHIP_IDENTITY_REVISION__MASK			0x0000f000
+#define VIVS_HI_CHIP_IDENTITY_REVISION__SHIFT			12
+#define VIVS_HI_CHIP_IDENTITY_REVISION(x)			(((x) << VIVS_HI_CHIP_IDENTITY_REVISION__SHIFT) & VIVS_HI_CHIP_IDENTITY_REVISION__MASK)
+
+#define VIVS_HI_CHIP_FEATURE					0x0000001c
+
+#define VIVS_HI_CHIP_MODEL					0x00000020
+
+#define VIVS_HI_CHIP_REV					0x00000024
+
+#define VIVS_HI_CHIP_DATE					0x00000028
+
+#define VIVS_HI_CHIP_TIME					0x0000002c
+
+#define VIVS_HI_CHIP_MINOR_FEATURE_0				0x00000034
+
+#define VIVS_HI_CACHE_CONTROL					0x00000038
+
+#define VIVS_HI_MEMORY_COUNTER_RESET				0x0000003c
+
+#define VIVS_HI_PROFILE_READ_BYTES8				0x00000040
+
+#define VIVS_HI_PROFILE_WRITE_BYTES8				0x00000044
+
+#define VIVS_HI_CHIP_SPECS					0x00000048
+#define VIVS_HI_CHIP_SPECS_STREAM_COUNT__MASK			0x0000000f
+#define VIVS_HI_CHIP_SPECS_STREAM_COUNT__SHIFT			0
+#define VIVS_HI_CHIP_SPECS_STREAM_COUNT(x)			(((x) << VIVS_HI_CHIP_SPECS_STREAM_COUNT__SHIFT) & VIVS_HI_CHIP_SPECS_STREAM_COUNT__MASK)
+#define VIVS_HI_CHIP_SPECS_REGISTER_MAX__MASK			0x000000f0
+#define VIVS_HI_CHIP_SPECS_REGISTER_MAX__SHIFT			4
+#define VIVS_HI_CHIP_SPECS_REGISTER_MAX(x)			(((x) << VIVS_HI_CHIP_SPECS_REGISTER_MAX__SHIFT) & VIVS_HI_CHIP_SPECS_REGISTER_MAX__MASK)
+#define VIVS_HI_CHIP_SPECS_THREAD_COUNT__MASK			0x00000f00
+#define VIVS_HI_CHIP_SPECS_THREAD_COUNT__SHIFT			8
+#define VIVS_HI_CHIP_SPECS_THREAD_COUNT(x)			(((x) << VIVS_HI_CHIP_SPECS_THREAD_COUNT__SHIFT) & VIVS_HI_CHIP_SPECS_THREAD_COUNT__MASK)
+#define VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__MASK		0x0001f000
+#define VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__SHIFT		12
+#define VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE(x)			(((x) << VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__SHIFT) & VIVS_HI_CHIP_SPECS_VERTEX_CACHE_SIZE__MASK)
+#define VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__MASK		0x01f00000
+#define VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__SHIFT		20
+#define VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT(x)			(((x) << VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__SHIFT) & VIVS_HI_CHIP_SPECS_SHADER_CORE_COUNT__MASK)
+#define VIVS_HI_CHIP_SPECS_PIXEL_PIPES__MASK			0x0e000000
+#define VIVS_HI_CHIP_SPECS_PIXEL_PIPES__SHIFT			25
+#define VIVS_HI_CHIP_SPECS_PIXEL_PIPES(x)			(((x) << VIVS_HI_CHIP_SPECS_PIXEL_PIPES__SHIFT) & VIVS_HI_CHIP_SPECS_PIXEL_PIPES__MASK)
+#define VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__MASK	0xf0000000
+#define VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__SHIFT	28
+#define VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE(x)		(((x) << VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__SHIFT) & VIVS_HI_CHIP_SPECS_VERTEX_OUTPUT_BUFFER_SIZE__MASK)
+
+#define VIVS_HI_PROFILE_WRITE_BURSTS				0x0000004c
+
+#define VIVS_HI_PROFILE_WRITE_REQUESTS				0x00000050
+
+#define VIVS_HI_PROFILE_READ_BURSTS				0x00000058
+
+#define VIVS_HI_PROFILE_READ_REQUESTS				0x0000005c
+
+#define VIVS_HI_PROFILE_READ_LASTS				0x00000060
+
+#define VIVS_HI_GP_OUT0						0x00000064
+
+#define VIVS_HI_GP_OUT1						0x00000068
+
+#define VIVS_HI_GP_OUT2						0x0000006c
+
+#define VIVS_HI_AXI_CONTROL					0x00000070
+#define VIVS_HI_AXI_CONTROL_WR_FULL_BURST_MODE			0x00000001
+
+#define VIVS_HI_CHIP_MINOR_FEATURE_1				0x00000074
+
+#define VIVS_HI_PROFILE_TOTAL_CYCLES				0x00000078
+
+#define VIVS_HI_PROFILE_IDLE_CYCLES				0x0000007c
+
+#define VIVS_HI_CHIP_SPECS_2					0x00000080
+#define VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__MASK			0x000000ff
+#define VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__SHIFT			0
+#define VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE(x)			(((x) << VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__SHIFT) & VIVS_HI_CHIP_SPECS_2_BUFFER_SIZE__MASK)
+#define VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__MASK		0x0000ff00
+#define VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__SHIFT		8
+#define VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT(x)		(((x) << VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__SHIFT) & VIVS_HI_CHIP_SPECS_2_INSTRUCTION_COUNT__MASK)
+#define VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__MASK		0xffff0000
+#define VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__SHIFT		16
+#define VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS(x)			(((x) << VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__SHIFT) & VIVS_HI_CHIP_SPECS_2_NUM_CONSTANTS__MASK)
+
+#define VIVS_HI_CHIP_MINOR_FEATURE_2				0x00000084
+
+#define VIVS_HI_CHIP_MINOR_FEATURE_3				0x00000088
+
+#define VIVS_HI_CHIP_MINOR_FEATURE_4				0x00000094
+
+#define VIVS_PM							0x00000000
+
+#define VIVS_PM_POWER_CONTROLS					0x00000100
+#define VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING	0x00000001
+#define VIVS_PM_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING	0x00000002
+#define VIVS_PM_POWER_CONTROLS_DISABLE_STARVE_MODULE_CLOCK_GATING	0x00000004
+#define VIVS_PM_POWER_CONTROLS_TURN_ON_COUNTER__MASK		0x000000f0
+#define VIVS_PM_POWER_CONTROLS_TURN_ON_COUNTER__SHIFT		4
+#define VIVS_PM_POWER_CONTROLS_TURN_ON_COUNTER(x)		(((x) << VIVS_PM_POWER_CONTROLS_TURN_ON_COUNTER__SHIFT) & VIVS_PM_POWER_CONTROLS_TURN_ON_COUNTER__MASK)
+#define VIVS_PM_POWER_CONTROLS_TURN_OFF_COUNTER__MASK		0xffff0000
+#define VIVS_PM_POWER_CONTROLS_TURN_OFF_COUNTER__SHIFT		16
+#define VIVS_PM_POWER_CONTROLS_TURN_OFF_COUNTER(x)		(((x) << VIVS_PM_POWER_CONTROLS_TURN_OFF_COUNTER__SHIFT) & VIVS_PM_POWER_CONTROLS_TURN_OFF_COUNTER__MASK)
+
+#define VIVS_PM_MODULE_CONTROLS					0x00000104
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_FE	0x00000001
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_DE	0x00000002
+#define VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_PE	0x00000004
+
+#define VIVS_PM_MODULE_STATUS					0x00000108
+#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_FE		0x00000001
+#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_DE		0x00000002
+#define VIVS_PM_MODULE_STATUS_MODULE_CLOCK_GATED_PE		0x00000004
+
+#define VIVS_PM_PULSE_EATER					0x0000010c
+
+#define VIVS_MMUv2						0x00000000
+
+#define VIVS_MMUv2_SAFE_ADDRESS					0x00000180
+
+#define VIVS_MMUv2_CONFIGURATION				0x00000184
+#define VIVS_MMUv2_CONFIGURATION_MODE__MASK			0x00000001
+#define VIVS_MMUv2_CONFIGURATION_MODE__SHIFT			0
+#define VIVS_MMUv2_CONFIGURATION_MODE_MODE4_K			0x00000000
+#define VIVS_MMUv2_CONFIGURATION_MODE_MODE1_K			0x00000001
+#define VIVS_MMUv2_CONFIGURATION_MODE_MASK			0x00000008
+#define VIVS_MMUv2_CONFIGURATION_FLUSH__MASK			0x00000010
+#define VIVS_MMUv2_CONFIGURATION_FLUSH__SHIFT			4
+#define VIVS_MMUv2_CONFIGURATION_FLUSH_FLUSH			0x00000010
+#define VIVS_MMUv2_CONFIGURATION_FLUSH_MASK			0x00000080
+#define VIVS_MMUv2_CONFIGURATION_ADDRESS_MASK			0x00000100
+#define VIVS_MMUv2_CONFIGURATION_ADDRESS__MASK			0xfffffc00
+#define VIVS_MMUv2_CONFIGURATION_ADDRESS__SHIFT			10
+#define VIVS_MMUv2_CONFIGURATION_ADDRESS(x)			(((x) << VIVS_MMUv2_CONFIGURATION_ADDRESS__SHIFT) & VIVS_MMUv2_CONFIGURATION_ADDRESS__MASK)
+
+#define VIVS_MMUv2_STATUS					0x00000188
+#define VIVS_MMUv2_STATUS_EXCEPTION0__MASK			0x00000003
+#define VIVS_MMUv2_STATUS_EXCEPTION0__SHIFT			0
+#define VIVS_MMUv2_STATUS_EXCEPTION0(x)				(((x) << VIVS_MMUv2_STATUS_EXCEPTION0__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION0__MASK)
+#define VIVS_MMUv2_STATUS_EXCEPTION1__MASK			0x00000030
+#define VIVS_MMUv2_STATUS_EXCEPTION1__SHIFT			4
+#define VIVS_MMUv2_STATUS_EXCEPTION1(x)				(((x) << VIVS_MMUv2_STATUS_EXCEPTION1__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION1__MASK)
+#define VIVS_MMUv2_STATUS_EXCEPTION2__MASK			0x00000300
+#define VIVS_MMUv2_STATUS_EXCEPTION2__SHIFT			8
+#define VIVS_MMUv2_STATUS_EXCEPTION2(x)				(((x) << VIVS_MMUv2_STATUS_EXCEPTION2__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION2__MASK)
+#define VIVS_MMUv2_STATUS_EXCEPTION3__MASK			0x00003000
+#define VIVS_MMUv2_STATUS_EXCEPTION3__SHIFT			12
+#define VIVS_MMUv2_STATUS_EXCEPTION3(x)				(((x) << VIVS_MMUv2_STATUS_EXCEPTION3__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION3__MASK)
+
+#define VIVS_MMUv2_CONTROL					0x0000018c
+#define VIVS_MMUv2_CONTROL_ENABLE				0x00000001
+
+#define VIVS_MMUv2_EXCEPTION_ADDR(i0)			       (0x00000190 + 0x4*(i0))
+#define VIVS_MMUv2_EXCEPTION_ADDR__ESIZE			0x00000004
+#define VIVS_MMUv2_EXCEPTION_ADDR__LEN				0x00000004
+
+#define VIVS_MC							0x00000000
+
+#define VIVS_MC_MMU_FE_PAGE_TABLE				0x00000400
+
+#define VIVS_MC_MMU_TX_PAGE_TABLE				0x00000404
+
+#define VIVS_MC_MMU_PE_PAGE_TABLE				0x00000408
+
+#define VIVS_MC_MMU_PEZ_PAGE_TABLE				0x0000040c
+
+#define VIVS_MC_MMU_RA_PAGE_TABLE				0x00000410
+
+#define VIVS_MC_DEBUG_MEMORY					0x00000414
+#define VIVS_MC_DEBUG_MEMORY_SPECIAL_PATCH_GC320		0x00000008
+#define VIVS_MC_DEBUG_MEMORY_FAST_CLEAR_BYPASS			0x00100000
+#define VIVS_MC_DEBUG_MEMORY_COMPRESSION_BYPASS			0x00200000
+
+#define VIVS_MC_MEMORY_BASE_ADDR_RA				0x00000418
+
+#define VIVS_MC_MEMORY_BASE_ADDR_FE				0x0000041c
+
+#define VIVS_MC_MEMORY_BASE_ADDR_TX				0x00000420
+
+#define VIVS_MC_MEMORY_BASE_ADDR_PEZ				0x00000424
+
+#define VIVS_MC_MEMORY_BASE_ADDR_PE				0x00000428
+
+#define VIVS_MC_MEMORY_TIMING_CONTROL				0x0000042c
+
+#define VIVS_MC_MEMORY_FLUSH					0x00000430
+
+#define VIVS_MC_PROFILE_CYCLE_COUNTER				0x00000438
+
+#define VIVS_MC_DEBUG_READ0					0x0000043c
+
+#define VIVS_MC_DEBUG_READ1					0x00000440
+
+#define VIVS_MC_DEBUG_WRITE					0x00000444
+
+#define VIVS_MC_PROFILE_RA_READ					0x00000448
+
+#define VIVS_MC_PROFILE_TX_READ					0x0000044c
+
+#define VIVS_MC_PROFILE_FE_READ					0x00000450
+
+#define VIVS_MC_PROFILE_PE_READ					0x00000454
+
+#define VIVS_MC_PROFILE_DE_READ					0x00000458
+
+#define VIVS_MC_PROFILE_SH_READ					0x0000045c
+
+#define VIVS_MC_PROFILE_PA_READ					0x00000460
+
+#define VIVS_MC_PROFILE_SE_READ					0x00000464
+
+#define VIVS_MC_PROFILE_MC_READ					0x00000468
+
+#define VIVS_MC_PROFILE_HI_READ					0x0000046c
+
+#define VIVS_MC_PROFILE_CONFIG0					0x00000470
+#define VIVS_MC_PROFILE_CONFIG0_FE__MASK			0x0000000f
+#define VIVS_MC_PROFILE_CONFIG0_FE__SHIFT			0
+#define VIVS_MC_PROFILE_CONFIG0_FE_RESET			0x0000000f
+#define VIVS_MC_PROFILE_CONFIG0_DE__MASK			0x00000f00
+#define VIVS_MC_PROFILE_CONFIG0_DE__SHIFT			8
+#define VIVS_MC_PROFILE_CONFIG0_DE_RESET			0x00000f00
+#define VIVS_MC_PROFILE_CONFIG0_PE__MASK			0x000f0000
+#define VIVS_MC_PROFILE_CONFIG0_PE__SHIFT			16
+#define VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE	0x00000000
+#define VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE	0x00010000
+#define VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE	0x00020000
+#define VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE	0x00030000
+#define VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D		0x000b0000
+#define VIVS_MC_PROFILE_CONFIG0_PE_RESET			0x000f0000
+#define VIVS_MC_PROFILE_CONFIG0_SH__MASK			0x0f000000
+#define VIVS_MC_PROFILE_CONFIG0_SH__SHIFT			24
+#define VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES		0x04000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER		0x07000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER	0x08000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER		0x09000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER	0x0a000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER	0x0b000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER	0x0c000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER	0x0d000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER	0x0e000000
+#define VIVS_MC_PROFILE_CONFIG0_SH_RESET			0x0f000000
+
+#define VIVS_MC_PROFILE_CONFIG1					0x00000474
+#define VIVS_MC_PROFILE_CONFIG1_PA__MASK			0x0000000f
+#define VIVS_MC_PROFILE_CONFIG1_PA__SHIFT			0
+#define VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER		0x00000003
+#define VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER		0x00000004
+#define VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER		0x00000005
+#define VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER	0x00000006
+#define VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER	0x00000007
+#define VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER		0x00000008
+#define VIVS_MC_PROFILE_CONFIG1_PA_RESET			0x0000000f
+#define VIVS_MC_PROFILE_CONFIG1_SE__MASK			0x00000f00
+#define VIVS_MC_PROFILE_CONFIG1_SE__SHIFT			8
+#define VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT	0x00000000
+#define VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT		0x00000100
+#define VIVS_MC_PROFILE_CONFIG1_SE_RESET			0x00000f00
+#define VIVS_MC_PROFILE_CONFIG1_RA__MASK			0x000f0000
+#define VIVS_MC_PROFILE_CONFIG1_RA__SHIFT			16
+#define VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT		0x00000000
+#define VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT		0x00010000
+#define VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z	0x00020000
+#define VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT	0x00030000
+#define VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER	0x00090000
+#define VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER	0x000a0000
+#define VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT		0x000b0000
+#define VIVS_MC_PROFILE_CONFIG1_RA_RESET			0x000f0000
+#define VIVS_MC_PROFILE_CONFIG1_TX__MASK			0x0f000000
+#define VIVS_MC_PROFILE_CONFIG1_TX__SHIFT			24
+#define VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS	0x00000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS	0x01000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS	0x02000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS	0x03000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_UNKNOWN			0x04000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT		0x05000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT		0x06000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT		0x07000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT	0x08000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT	0x09000000
+#define VIVS_MC_PROFILE_CONFIG1_TX_RESET			0x0f000000
+
+#define VIVS_MC_PROFILE_CONFIG2					0x00000478
+#define VIVS_MC_PROFILE_CONFIG2_MC__MASK			0x0000000f
+#define VIVS_MC_PROFILE_CONFIG2_MC__SHIFT			0
+#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE	0x00000001
+#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP	0x00000002
+#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE	0x00000003
+#define VIVS_MC_PROFILE_CONFIG2_MC_RESET			0x0000000f
+#define VIVS_MC_PROFILE_CONFIG2_HI__MASK			0x00000f00
+#define VIVS_MC_PROFILE_CONFIG2_HI__SHIFT			8
+#define VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED	0x00000000
+#define VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED	0x00000100
+#define VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED	0x00000200
+#define VIVS_MC_PROFILE_CONFIG2_HI_RESET			0x00000f00
+
+#define VIVS_MC_PROFILE_CONFIG3					0x0000047c
+
+#define VIVS_MC_BUS_CONFIG					0x00000480
+#define VIVS_MC_BUS_CONFIG_FE_BUS_CONFIG__MASK			0x0000000f
+#define VIVS_MC_BUS_CONFIG_FE_BUS_CONFIG__SHIFT			0
+#define VIVS_MC_BUS_CONFIG_FE_BUS_CONFIG(x)			(((x) << VIVS_MC_BUS_CONFIG_FE_BUS_CONFIG__SHIFT) & VIVS_MC_BUS_CONFIG_FE_BUS_CONFIG__MASK)
+#define VIVS_MC_BUS_CONFIG_TX_BUS_CONFIG__MASK			0x000000f0
+#define VIVS_MC_BUS_CONFIG_TX_BUS_CONFIG__SHIFT			4
+#define VIVS_MC_BUS_CONFIG_TX_BUS_CONFIG(x)			(((x) << VIVS_MC_BUS_CONFIG_TX_BUS_CONFIG__SHIFT) & VIVS_MC_BUS_CONFIG_TX_BUS_CONFIG__MASK)
+
+#define VIVS_MC_START_COMPOSITION				0x00000554
+
+#define VIVS_MC_128B_MERGE					0x00000558
+
+
+#endif /* STATE_HI_XML */
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index c7362b9..1bf6a21 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -248,15 +248,16 @@
 		       protect ? ~0 : 0);
 }
 
-static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
-					struct exynos_drm_plane *plane)
+static void decon_atomic_begin(struct exynos_drm_crtc *crtc)
 {
 	struct decon_context *ctx = crtc->ctx;
+	int i;
 
 	if (test_bit(BIT_SUSPENDED, &ctx->flags))
 		return;
 
-	decon_shadow_protect_win(ctx, plane->zpos, true);
+	for (i = ctx->first_win; i < WINDOWS_NR; i++)
+		decon_shadow_protect_win(ctx, i, true);
 }
 
 #define BIT_VAL(x, e, s) (((x) & ((1 << ((e) - (s) + 1)) - 1)) << (s))
@@ -270,7 +271,7 @@
 				to_exynos_plane_state(plane->base.state);
 	struct decon_context *ctx = crtc->ctx;
 	struct drm_framebuffer *fb = state->base.fb;
-	unsigned int win = plane->zpos;
+	unsigned int win = plane->index;
 	unsigned int bpp = fb->bits_per_pixel >> 3;
 	unsigned int pitch = fb->pitches[0];
 	dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0);
@@ -320,7 +321,7 @@
 				struct exynos_drm_plane *plane)
 {
 	struct decon_context *ctx = crtc->ctx;
-	unsigned int win = plane->zpos;
+	unsigned int win = plane->index;
 
 	if (test_bit(BIT_SUSPENDED, &ctx->flags))
 		return;
@@ -336,15 +337,16 @@
 	decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
 }
 
-static void decon_atomic_flush(struct exynos_drm_crtc *crtc,
-				struct exynos_drm_plane *plane)
+static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
 {
 	struct decon_context *ctx = crtc->ctx;
+	int i;
 
 	if (test_bit(BIT_SUSPENDED, &ctx->flags))
 		return;
 
-	decon_shadow_protect_win(ctx, plane->zpos, false);
+	for (i = ctx->first_win; i < WINDOWS_NR; i++)
+		decon_shadow_protect_win(ctx, i, false);
 
 	if (ctx->out_type == IFTYPE_I80)
 		set_bit(BIT_WIN_UPDATED, &ctx->flags);
@@ -502,7 +504,7 @@
 		ctx->configs[win].zpos = win;
 		ctx->configs[win].type = decon_win_types[tmp];
 
-		ret = exynos_plane_init(drm_dev, &ctx->planes[win],
+		ret = exynos_plane_init(drm_dev, &ctx->planes[win], win,
 					1 << ctx->pipe, &ctx->configs[win]);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index c47f9af..52bda3b 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -385,15 +385,16 @@
 	writel(val, ctx->regs + SHADOWCON);
 }
 
-static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
-					struct exynos_drm_plane *plane)
+static void decon_atomic_begin(struct exynos_drm_crtc *crtc)
 {
 	struct decon_context *ctx = crtc->ctx;
+	int i;
 
 	if (ctx->suspended)
 		return;
 
-	decon_shadow_protect_win(ctx, plane->zpos, true);
+	for (i = 0; i < WINDOWS_NR; i++)
+		decon_shadow_protect_win(ctx, i, true);
 }
 
 static void decon_update_plane(struct exynos_drm_crtc *crtc,
@@ -407,7 +408,7 @@
 	unsigned long val, alpha;
 	unsigned int last_x;
 	unsigned int last_y;
-	unsigned int win = plane->zpos;
+	unsigned int win = plane->index;
 	unsigned int bpp = fb->bits_per_pixel >> 3;
 	unsigned int pitch = fb->pitches[0];
 
@@ -498,7 +499,7 @@
 				struct exynos_drm_plane *plane)
 {
 	struct decon_context *ctx = crtc->ctx;
-	unsigned int win = plane->zpos;
+	unsigned int win = plane->index;
 	u32 val;
 
 	if (ctx->suspended)
@@ -517,15 +518,16 @@
 	writel(val, ctx->regs + DECON_UPDATE);
 }
 
-static void decon_atomic_flush(struct exynos_drm_crtc *crtc,
-					struct exynos_drm_plane *plane)
+static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
 {
 	struct decon_context *ctx = crtc->ctx;
+	int i;
 
 	if (ctx->suspended)
 		return;
 
-	decon_shadow_protect_win(ctx, plane->zpos, false);
+	for (i = 0; i < WINDOWS_NR; i++)
+		decon_shadow_protect_win(ctx, i, false);
 }
 
 static void decon_init(struct decon_context *ctx)
@@ -657,7 +659,7 @@
 		ctx->configs[i].zpos = i;
 		ctx->configs[i].type = decon_win_types[i];
 
-		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
+		ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
 					1 << ctx->pipe, &ctx->configs[i]);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 80f7974..e36579c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -55,6 +55,9 @@
 {
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 
+	if (!state->enable)
+		return 0;
+
 	if (exynos_crtc->ops->atomic_check)
 		return exynos_crtc->ops->atomic_check(exynos_crtc, state);
 
@@ -65,32 +68,20 @@
 				     struct drm_crtc_state *old_crtc_state)
 {
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-	struct drm_plane *plane;
 
 	exynos_crtc->event = crtc->state->event;
 
-	drm_atomic_crtc_for_each_plane(plane, crtc) {
-		struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
-
-		if (exynos_crtc->ops->atomic_begin)
-			exynos_crtc->ops->atomic_begin(exynos_crtc,
-							exynos_plane);
-	}
+	if (exynos_crtc->ops->atomic_begin)
+		exynos_crtc->ops->atomic_begin(exynos_crtc);
 }
 
 static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
 				     struct drm_crtc_state *old_crtc_state)
 {
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-	struct drm_plane *plane;
 
-	drm_atomic_crtc_for_each_plane(plane, crtc) {
-		struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
-
-		if (exynos_crtc->ops->atomic_flush)
-			exynos_crtc->ops->atomic_flush(exynos_crtc,
-							exynos_plane);
-	}
+	if (exynos_crtc->ops->atomic_flush)
+		exynos_crtc->ops->atomic_flush(exynos_crtc);
 }
 
 static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
@@ -212,29 +203,6 @@
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 }
 
-void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
-{
-	struct exynos_drm_crtc *exynos_crtc;
-	struct drm_device *dev = fb->dev;
-	struct drm_crtc *crtc;
-
-	/*
-	 * make sure that overlay data are updated to real hardware
-	 * for all encoders.
-	 */
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		exynos_crtc = to_exynos_crtc(crtc);
-
-		/*
-		 * wait for vblank interrupt
-		 * - this makes sure that overlay data are updated to
-		 *	real hardware.
-		 */
-		if (exynos_crtc->ops->wait_for_vblank)
-			exynos_crtc->ops->wait_for_vblank(exynos_crtc);
-	}
-}
-
 int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
 				       enum exynos_drm_output_type out_type)
 {
@@ -258,3 +226,29 @@
 	if (exynos_crtc->ops->te_handler)
 		exynos_crtc->ops->te_handler(exynos_crtc);
 }
+
+void exynos_drm_crtc_cancel_page_flip(struct drm_crtc *crtc,
+					struct drm_file *file)
+{
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct drm_pending_vblank_event *e;
+	unsigned long flags;
+
+	spin_lock_irqsave(&crtc->dev->event_lock, flags);
+	e = exynos_crtc->event;
+	if (e && e->base.file_priv == file) {
+		exynos_crtc->event = NULL;
+		/*
+		 * event will be destroyed by core part
+		 * so below line should be removed later with core changes
+		 */
+		e->base.destroy(&e->base);
+		/*
+		 * event_space will be increased by core part
+		 * so below line should be removed later with core changes.
+		 */
+		file->event_space += sizeof(e->event);
+		atomic_dec(&exynos_crtc->pending_update);
+	}
+	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index f9f365b..cfdcf3e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -28,7 +28,6 @@
 void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc);
 void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
 				   struct exynos_drm_plane *exynos_plane);
-void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
 
 /* This function gets pipe value to crtc device matched with out_type. */
 int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
@@ -41,4 +40,8 @@
  */
 void exynos_drm_crtc_te_handler(struct drm_crtc *crtc);
 
+/* This function cancels a page flip request. */
+void exynos_drm_crtc_cancel_page_flip(struct drm_crtc *crtc,
+					struct drm_file *file);
+
 #endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 9756797a..68f0f36 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -330,7 +330,12 @@
 static void exynos_drm_preclose(struct drm_device *dev,
 					struct drm_file *file)
 {
+	struct drm_crtc *crtc;
+
 	exynos_drm_subdrv_close(dev, file);
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		exynos_drm_crtc_cancel_page_flip(crtc, file);
 }
 
 static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 82bbd7f..17b5ded 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -64,6 +64,7 @@
 	struct exynos_drm_rect src;
 	unsigned int h_ratio;
 	unsigned int v_ratio;
+	unsigned int zpos;
 };
 
 static inline struct exynos_drm_plane_state *
@@ -76,7 +77,7 @@
  * Exynos drm common overlay structure.
  *
  * @base: plane object
- * @zpos: order of overlay layer(z position).
+ * @index: hardware index of the overlay layer
  *
  * this structure is common to exynos SoC and its contents would be copied
  * to hardware specific overlay info.
@@ -85,17 +86,18 @@
 struct exynos_drm_plane {
 	struct drm_plane base;
 	const struct exynos_drm_plane_config *config;
-	unsigned int zpos;
+	unsigned int index;
 	struct drm_framebuffer *pending_fb;
 };
 
 #define EXYNOS_DRM_PLANE_CAP_DOUBLE	(1 << 0)
 #define EXYNOS_DRM_PLANE_CAP_SCALE	(1 << 1)
+#define EXYNOS_DRM_PLANE_CAP_ZPOS	(1 << 2)
 
 /*
  * Exynos DRM plane configuration structure.
  *
- * @zpos: z-position of the plane.
+ * @zpos: initial z-position of the plane.
  * @type: type of the plane (primary, cursor or overlay).
  * @pixel_formats: supported pixel formats.
  * @num_pixel_formats: number of elements in 'pixel_formats'.
@@ -121,8 +123,8 @@
  * @wait_for_vblank: wait for vblank interrupt to make sure that
  *	hardware overlay is updated.
  * @atomic_check: validate state
- * @atomic_begin: prepare a window to receive a update
- * @atomic_flush: mark the end of a window update
+ * @atomic_begin: prepare device to receive an update
+ * @atomic_flush: mark the end of device update
  * @update_plane: apply hardware specific overlay data to registers.
  * @disable_plane: disable hardware specific overlay.
  * @te_handler: trigger to transfer video image at the tearing effect
@@ -142,14 +144,12 @@
 	void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
 	int (*atomic_check)(struct exynos_drm_crtc *crtc,
 			    struct drm_crtc_state *state);
-	void (*atomic_begin)(struct exynos_drm_crtc *crtc,
-			      struct exynos_drm_plane *plane);
+	void (*atomic_begin)(struct exynos_drm_crtc *crtc);
 	void (*update_plane)(struct exynos_drm_crtc *crtc,
 			     struct exynos_drm_plane *plane);
 	void (*disable_plane)(struct exynos_drm_crtc *crtc,
 			      struct exynos_drm_plane *plane);
-	void (*atomic_flush)(struct exynos_drm_crtc *crtc,
-			      struct exynos_drm_plane *plane);
+	void (*atomic_flush)(struct exynos_drm_crtc *crtc);
 	void (*te_handler)(struct exynos_drm_crtc *crtc);
 	void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable);
 };
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index cbbb1a8..d614194 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -71,9 +71,6 @@
 	struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
 	unsigned int i;
 
-	/* make sure that overlay data are updated before relesing fb. */
-	exynos_drm_crtc_complete_scanout(fb);
-
 	drm_framebuffer_cleanup(fb);
 
 	for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem); i++) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 2e224712..70194d0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -622,26 +622,28 @@
 	writel(val, ctx->regs + reg);
 }
 
-static void fimd_atomic_begin(struct exynos_drm_crtc *crtc,
-			       struct exynos_drm_plane *plane)
+static void fimd_atomic_begin(struct exynos_drm_crtc *crtc)
 {
 	struct fimd_context *ctx = crtc->ctx;
+	int i;
 
 	if (ctx->suspended)
 		return;
 
-	fimd_shadow_protect_win(ctx, plane->zpos, true);
+	for (i = 0; i < WINDOWS_NR; i++)
+		fimd_shadow_protect_win(ctx, i, true);
 }
 
-static void fimd_atomic_flush(struct exynos_drm_crtc *crtc,
-			       struct exynos_drm_plane *plane)
+static void fimd_atomic_flush(struct exynos_drm_crtc *crtc)
 {
 	struct fimd_context *ctx = crtc->ctx;
+	int i;
 
 	if (ctx->suspended)
 		return;
 
-	fimd_shadow_protect_win(ctx, plane->zpos, false);
+	for (i = 0; i < WINDOWS_NR; i++)
+		fimd_shadow_protect_win(ctx, i, false);
 }
 
 static void fimd_update_plane(struct exynos_drm_crtc *crtc,
@@ -654,7 +656,7 @@
 	dma_addr_t dma_addr;
 	unsigned long val, size, offset;
 	unsigned int last_x, last_y, buf_offsize, line_size;
-	unsigned int win = plane->zpos;
+	unsigned int win = plane->index;
 	unsigned int bpp = fb->bits_per_pixel >> 3;
 	unsigned int pitch = fb->pitches[0];
 
@@ -740,7 +742,7 @@
 			       struct exynos_drm_plane *plane)
 {
 	struct fimd_context *ctx = crtc->ctx;
-	unsigned int win = plane->zpos;
+	unsigned int win = plane->index;
 
 	if (ctx->suspended)
 		return;
@@ -944,7 +946,7 @@
 		ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats);
 		ctx->configs[i].zpos = i;
 		ctx->configs[i].type = fimd_win_types[i];
-		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
+		ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
 					1 << ctx->pipe, &ctx->configs[i]);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index e668fcd..d862272 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -124,6 +124,7 @@
 
 static void exynos_drm_plane_reset(struct drm_plane *plane)
 {
+	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
 	struct exynos_drm_plane_state *exynos_state;
 
 	if (plane->state) {
@@ -136,6 +137,7 @@
 
 	exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL);
 	if (exynos_state) {
+		exynos_state->zpos = exynos_plane->config->zpos;
 		plane->state = &exynos_state->base;
 		plane->state->plane = plane;
 	}
@@ -153,6 +155,7 @@
 		return NULL;
 
 	__drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
+	copy->zpos = exynos_state->zpos;
 	return &copy->base;
 }
 
@@ -165,13 +168,53 @@
 	kfree(old_exynos_state);
 }
 
+static int exynos_drm_plane_atomic_set_property(struct drm_plane *plane,
+						struct drm_plane_state *state,
+						struct drm_property *property,
+						uint64_t val)
+{
+	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
+	struct exynos_drm_plane_state *exynos_state =
+					to_exynos_plane_state(state);
+	struct exynos_drm_private *dev_priv = plane->dev->dev_private;
+	const struct exynos_drm_plane_config *config = exynos_plane->config;
+
+	if (property == dev_priv->plane_zpos_property &&
+	    (config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS))
+		exynos_state->zpos = val;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int exynos_drm_plane_atomic_get_property(struct drm_plane *plane,
+					  const struct drm_plane_state *state,
+					  struct drm_property *property,
+					  uint64_t *val)
+{
+	const struct exynos_drm_plane_state *exynos_state =
+		container_of(state, const struct exynos_drm_plane_state, base);
+	struct exynos_drm_private *dev_priv = plane->dev->dev_private;
+
+	if (property == dev_priv->plane_zpos_property)
+		*val = exynos_state->zpos;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
 static struct drm_plane_funcs exynos_plane_funcs = {
 	.update_plane	= drm_atomic_helper_update_plane,
 	.disable_plane	= drm_atomic_helper_disable_plane,
 	.destroy	= drm_plane_cleanup,
+	.set_property	= drm_atomic_helper_plane_set_property,
 	.reset		= exynos_drm_plane_reset,
 	.atomic_duplicate_state = exynos_drm_plane_duplicate_state,
 	.atomic_destroy_state = exynos_drm_plane_destroy_state,
+	.atomic_set_property = exynos_drm_plane_atomic_set_property,
+	.atomic_get_property = exynos_drm_plane_atomic_get_property,
 };
 
 static int
@@ -267,8 +310,8 @@
 
 	prop = dev_priv->plane_zpos_property;
 	if (!prop) {
-		prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE,
-						 "zpos", 0, MAX_PLANE - 1);
+		prop = drm_property_create_range(dev, 0, "zpos",
+						 0, MAX_PLANE - 1);
 		if (!prop)
 			return;
 
@@ -280,7 +323,7 @@
 
 int exynos_plane_init(struct drm_device *dev,
 		      struct exynos_drm_plane *exynos_plane,
-		      unsigned long possible_crtcs,
+		      unsigned int index, unsigned long possible_crtcs,
 		      const struct exynos_drm_plane_config *config)
 {
 	int err;
@@ -298,12 +341,10 @@
 
 	drm_plane_helper_add(&exynos_plane->base, &plane_helper_funcs);
 
-	exynos_plane->zpos = config->zpos;
+	exynos_plane->index = index;
 	exynos_plane->config = config;
 
-	if (config->type == DRM_PLANE_TYPE_OVERLAY)
-		exynos_plane_attach_zpos_property(&exynos_plane->base,
-						  config->zpos);
+	exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 0dd0965..9aafad1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -10,6 +10,6 @@
  */
 
 int exynos_plane_init(struct drm_device *dev,
-		      struct exynos_drm_plane *exynos_plane,
+		      struct exynos_drm_plane *exynos_plane, unsigned int index,
 		      unsigned long possible_crtcs,
 		      const struct exynos_drm_plane_config *config);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 0be29c1..62ac4e5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -461,7 +461,7 @@
 		plane_config.zpos = i;
 		plane_config.type = vidi_win_types[i];
 
-		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
+		ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
 					1 << ctx->pipe, &plane_config);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index dfb35e2..b5fbc1c 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -76,7 +76,9 @@
 
 static const uint32_t mixer_formats[] = {
 	DRM_FORMAT_XRGB4444,
+	DRM_FORMAT_ARGB4444,
 	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_ARGB1555,
 	DRM_FORMAT_RGB565,
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
@@ -117,19 +119,22 @@
 		.type = DRM_PLANE_TYPE_PRIMARY,
 		.pixel_formats = mixer_formats,
 		.num_pixel_formats = ARRAY_SIZE(mixer_formats),
-		.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE,
+		.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
+				EXYNOS_DRM_PLANE_CAP_ZPOS,
 	}, {
 		.zpos = 1,
 		.type = DRM_PLANE_TYPE_CURSOR,
 		.pixel_formats = mixer_formats,
 		.num_pixel_formats = ARRAY_SIZE(mixer_formats),
-		.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE,
+		.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
+				EXYNOS_DRM_PLANE_CAP_ZPOS,
 	}, {
 		.zpos = 2,
 		.type = DRM_PLANE_TYPE_OVERLAY,
 		.pixel_formats = vp_formats,
 		.num_pixel_formats = ARRAY_SIZE(vp_formats),
-		.capabilities = EXYNOS_DRM_PLANE_CAP_SCALE,
+		.capabilities = EXYNOS_DRM_PLANE_CAP_SCALE |
+				EXYNOS_DRM_PLANE_CAP_ZPOS,
 	},
 };
 
@@ -162,6 +167,18 @@
 	70,	59,	48,	37,	27,	19,	11,	5,
 };
 
+static inline bool is_alpha_format(unsigned int pixel_format)
+{
+	switch (pixel_format) {
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_ARGB4444:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
 {
 	return readl(res->vp_regs + reg_id);
@@ -291,6 +308,37 @@
 		filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
 }
 
+static void mixer_cfg_gfx_blend(struct mixer_context *ctx, unsigned int win,
+				bool alpha)
+{
+	struct mixer_resources *res = &ctx->mixer_res;
+	u32 val;
+
+	val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
+	if (alpha) {
+		/* blending based on pixel alpha */
+		val |= MXR_GRP_CFG_BLEND_PRE_MUL;
+		val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
+	}
+	mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
+			    val, MXR_GRP_CFG_MISC_MASK);
+}
+
+static void mixer_cfg_vp_blend(struct mixer_context *ctx)
+{
+	struct mixer_resources *res = &ctx->mixer_res;
+	u32 val;
+
+	/*
+	 * No blending at the moment since the NV12/NV21 pixelformats don't
+	 * have an alpha channel. However the mixer supports a global alpha
+	 * value for a layer. Once this functionality is exposed, we can
+	 * support blending of the video layer through this.
+	 */
+	val = 0;
+	mixer_reg_write(res, MXR_VIDEO_CFG, val);
+}
+
 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
 {
 	struct mixer_resources *res = &ctx->mixer_res;
@@ -372,7 +420,7 @@
 }
 
 static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win,
-				bool enable)
+			    unsigned int priority, bool enable)
 {
 	struct mixer_resources *res = &ctx->mixer_res;
 	u32 val = enable ? ~0 : 0;
@@ -380,20 +428,24 @@
 	switch (win) {
 	case 0:
 		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
+		mixer_reg_writemask(res, MXR_LAYER_CFG,
+				    MXR_LAYER_CFG_GRP0_VAL(priority),
+				    MXR_LAYER_CFG_GRP0_MASK);
 		break;
 	case 1:
 		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
+		mixer_reg_writemask(res, MXR_LAYER_CFG,
+				    MXR_LAYER_CFG_GRP1_VAL(priority),
+				    MXR_LAYER_CFG_GRP1_MASK);
 		break;
-	case 2:
+	case VP_DEFAULT_WIN:
 		if (ctx->vp_enabled) {
 			vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
 			mixer_reg_writemask(res, MXR_CFG, val,
 				MXR_CFG_VP_ENABLE);
-
-			/* control blending of graphic layer 0 */
-			mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
-					MXR_GRP_CFG_BLEND_PRE_MUL |
-					MXR_GRP_CFG_PIXEL_BLEND_EN);
+			mixer_reg_writemask(res, MXR_LAYER_CFG,
+					    MXR_LAYER_CFG_VP_VAL(priority),
+					    MXR_LAYER_CFG_VP_MASK);
 		}
 		break;
 	}
@@ -464,7 +516,6 @@
 	}
 
 	spin_lock_irqsave(&res->reg_slock, flags);
-	mixer_vsync_set_update(ctx, false);
 
 	/* interlace or progressive scan mode */
 	val = (ctx->interlace ? ~0 : 0);
@@ -511,10 +562,10 @@
 
 	mixer_cfg_scan(ctx, mode->vdisplay);
 	mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
-	mixer_cfg_layer(ctx, plane->zpos, true);
+	mixer_cfg_layer(ctx, plane->index, state->zpos + 1, true);
+	mixer_cfg_vp_blend(ctx);
 	mixer_run(ctx);
 
-	mixer_vsync_set_update(ctx, true);
 	spin_unlock_irqrestore(&res->reg_slock, flags);
 
 	mixer_regs_dump(ctx);
@@ -537,7 +588,7 @@
 	struct mixer_resources *res = &ctx->mixer_res;
 	struct drm_framebuffer *fb = state->base.fb;
 	unsigned long flags;
-	unsigned int win = plane->zpos;
+	unsigned int win = plane->index;
 	unsigned int x_ratio = 0, y_ratio = 0;
 	unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
 	dma_addr_t dma_addr;
@@ -546,10 +597,12 @@
 
 	switch (fb->pixel_format) {
 	case DRM_FORMAT_XRGB4444:
+	case DRM_FORMAT_ARGB4444:
 		fmt = MXR_FORMAT_ARGB4444;
 		break;
 
 	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_ARGB1555:
 		fmt = MXR_FORMAT_ARGB1555;
 		break;
 
@@ -587,7 +640,6 @@
 		ctx->interlace = false;
 
 	spin_lock_irqsave(&res->reg_slock, flags);
-	mixer_vsync_set_update(ctx, false);
 
 	/* setup format */
 	mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
@@ -626,7 +678,8 @@
 
 	mixer_cfg_scan(ctx, mode->vdisplay);
 	mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
-	mixer_cfg_layer(ctx, win, true);
+	mixer_cfg_layer(ctx, win, state->zpos + 1, true);
+	mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format));
 
 	/* layer update mandatory for mixer 16.0.33.0 */
 	if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
@@ -635,7 +688,6 @@
 
 	mixer_run(ctx);
 
-	mixer_vsync_set_update(ctx, true);
 	spin_unlock_irqrestore(&res->reg_slock, flags);
 
 	mixer_regs_dump(ctx);
@@ -660,10 +712,8 @@
 {
 	struct mixer_resources *res = &ctx->mixer_res;
 	unsigned long flags;
-	u32 val; /* value stored to register */
 
 	spin_lock_irqsave(&res->reg_slock, flags);
-	mixer_vsync_set_update(ctx, false);
 
 	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
 
@@ -674,40 +724,14 @@
 	mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
 		MXR_STATUS_BURST_MASK);
 
-	/* setting default layer priority: layer1 > layer0 > video
-	 * because typical usage scenario would be
-	 * layer1 - OSD
-	 * layer0 - framebuffer
-	 * video - video overlay
-	 */
-	val = MXR_LAYER_CFG_GRP1_VAL(3);
-	val |= MXR_LAYER_CFG_GRP0_VAL(2);
-	if (ctx->vp_enabled)
-		val |= MXR_LAYER_CFG_VP_VAL(1);
-	mixer_reg_write(res, MXR_LAYER_CFG, val);
+	/* reset default layer priority */
+	mixer_reg_write(res, MXR_LAYER_CFG, 0);
 
 	/* setting background color */
 	mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
 	mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
 	mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
 
-	/* setting graphical layers */
-	val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
-	val |= MXR_GRP_CFG_WIN_BLEND_EN;
-	val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
-
-	/* Don't blend layer 0 onto the mixer background */
-	mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
-
-	/* Blend layer 1 into layer 0 */
-	val |= MXR_GRP_CFG_BLEND_PRE_MUL;
-	val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
-	mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
-
-	/* setting video layers */
-	val = MXR_GRP_CFG_ALPHA_VAL(0);
-	mixer_reg_write(res, MXR_VIDEO_CFG, val);
-
 	if (ctx->vp_enabled) {
 		/* configuration of Video Processor Registers */
 		vp_win_reset(ctx);
@@ -720,7 +744,6 @@
 	if (ctx->vp_enabled)
 		mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
 
-	mixer_vsync_set_update(ctx, true);
 	spin_unlock_irqrestore(&res->reg_slock, flags);
 }
 
@@ -951,17 +974,27 @@
 	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 }
 
+static void mixer_atomic_begin(struct exynos_drm_crtc *crtc)
+{
+	struct mixer_context *mixer_ctx = crtc->ctx;
+
+	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
+		return;
+
+	mixer_vsync_set_update(mixer_ctx, false);
+}
+
 static void mixer_update_plane(struct exynos_drm_crtc *crtc,
 			       struct exynos_drm_plane *plane)
 {
 	struct mixer_context *mixer_ctx = crtc->ctx;
 
-	DRM_DEBUG_KMS("win: %d\n", plane->zpos);
+	DRM_DEBUG_KMS("win: %d\n", plane->index);
 
 	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
 		return;
 
-	if (plane->zpos > 1 && mixer_ctx->vp_enabled)
+	if (plane->index == VP_DEFAULT_WIN)
 		vp_video_buffer(mixer_ctx, plane);
 	else
 		mixer_graph_buffer(mixer_ctx, plane);
@@ -974,18 +1007,24 @@
 	struct mixer_resources *res = &mixer_ctx->mixer_res;
 	unsigned long flags;
 
-	DRM_DEBUG_KMS("win: %d\n", plane->zpos);
+	DRM_DEBUG_KMS("win: %d\n", plane->index);
 
 	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
 		return;
 
 	spin_lock_irqsave(&res->reg_slock, flags);
-	mixer_vsync_set_update(mixer_ctx, false);
+	mixer_cfg_layer(mixer_ctx, plane->index, 0, false);
+	spin_unlock_irqrestore(&res->reg_slock, flags);
+}
 
-	mixer_cfg_layer(mixer_ctx, plane->zpos, false);
+static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
+{
+	struct mixer_context *mixer_ctx = crtc->ctx;
+
+	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
+		return;
 
 	mixer_vsync_set_update(mixer_ctx, true);
-	spin_unlock_irqrestore(&res->reg_slock, flags);
 }
 
 static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
@@ -1026,6 +1065,8 @@
 
 	pm_runtime_get_sync(ctx->dev);
 
+	mixer_vsync_set_update(ctx, false);
+
 	mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
 
 	if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) {
@@ -1034,6 +1075,8 @@
 	}
 	mixer_win_reset(ctx);
 
+	mixer_vsync_set_update(ctx, true);
+
 	set_bit(MXR_BIT_POWERED, &ctx->flags);
 }
 
@@ -1084,8 +1127,10 @@
 	.enable_vblank		= mixer_enable_vblank,
 	.disable_vblank		= mixer_disable_vblank,
 	.wait_for_vblank	= mixer_wait_for_vblank,
+	.atomic_begin		= mixer_atomic_begin,
 	.update_plane		= mixer_update_plane,
 	.disable_plane		= mixer_disable_plane,
+	.atomic_flush		= mixer_atomic_flush,
 	.atomic_check		= mixer_atomic_check,
 };
 
@@ -1160,7 +1205,7 @@
 		if (i == VP_DEFAULT_WIN && !ctx->vp_enabled)
 			continue;
 
-		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
+		ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
 					1 << ctx->pipe, &plane_configs[i]);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h
index ac60260..7f22df5 100644
--- a/drivers/gpu/drm/exynos/regs-mixer.h
+++ b/drivers/gpu/drm/exynos/regs-mixer.h
@@ -113,6 +113,7 @@
 #define MXR_GRP_CFG_BLEND_PRE_MUL	(1 << 20)
 #define MXR_GRP_CFG_WIN_BLEND_EN	(1 << 17)
 #define MXR_GRP_CFG_PIXEL_BLEND_EN	(1 << 16)
+#define MXR_GRP_CFG_MISC_MASK		((3 << 16) | (3 << 20))
 #define MXR_GRP_CFG_FORMAT_VAL(x)	MXR_MASK_VAL(x, 11, 8)
 #define MXR_GRP_CFG_FORMAT_MASK		MXR_GRP_CFG_FORMAT_VAL(~0)
 #define MXR_GRP_CFG_ALPHA_VAL(x)	MXR_MASK_VAL(x, 7, 0)
@@ -145,8 +146,11 @@
 
 /* bit for MXR_LAYER_CFG */
 #define MXR_LAYER_CFG_GRP1_VAL(x)	MXR_MASK_VAL(x, 11, 8)
+#define MXR_LAYER_CFG_GRP1_MASK		MXR_LAYER_CFG_GRP1_VAL(~0)
 #define MXR_LAYER_CFG_GRP0_VAL(x)	MXR_MASK_VAL(x, 7, 4)
+#define MXR_LAYER_CFG_GRP0_MASK		MXR_LAYER_CFG_GRP0_VAL(~0)
 #define MXR_LAYER_CFG_VP_VAL(x)		MXR_MASK_VAL(x, 3, 0)
+#define MXR_LAYER_CFG_VP_MASK		MXR_LAYER_CFG_VP_VAL(~0)
 
 #endif /* SAMSUNG_REGS_MIXER_H */
 
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 7885859..34e3874 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -22,6 +22,7 @@
 #include <sound/asoundef.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
@@ -866,7 +867,10 @@
 static int tda998x_connector_mode_valid(struct drm_connector *connector,
 					struct drm_display_mode *mode)
 {
-	if (mode->clock > 150000)
+	/* TDA19988 dotclock can go up to 165MHz */
+	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
+
+	if (mode->clock > ((priv->rev == TDA19988) ? 165000 : 150000))
 		return MODE_CLOCK_HIGH;
 	if (mode->htotal >= BIT(13))
 		return MODE_BAD_HVALUE;
@@ -1379,10 +1383,13 @@
 }
 
 static const struct drm_connector_funcs tda998x_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = tda998x_connector_detect,
 	.destroy = tda998x_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static int tda998x_bind(struct device *dev, struct device *master, void *data)
@@ -1457,6 +1464,7 @@
 {
 	struct tda998x_priv *priv = dev_get_drvdata(dev);
 
+	drm_connector_unregister(&priv->connector);
 	drm_connector_cleanup(&priv->connector);
 	drm_encoder_cleanup(&priv->encoder);
 	tda998x_destroy(priv);
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
index 13dea42..5e6a301 100644
--- a/drivers/gpu/drm/i915/dvo.h
+++ b/drivers/gpu/drm/i915/dvo.h
@@ -129,11 +129,11 @@
 	void (*dump_regs)(struct intel_dvo_device *dvo);
 };
 
-extern struct intel_dvo_dev_ops sil164_ops;
-extern struct intel_dvo_dev_ops ch7xxx_ops;
-extern struct intel_dvo_dev_ops ivch_ops;
-extern struct intel_dvo_dev_ops tfp410_ops;
-extern struct intel_dvo_dev_ops ch7017_ops;
-extern struct intel_dvo_dev_ops ns2501_ops;
+extern const struct intel_dvo_dev_ops sil164_ops;
+extern const struct intel_dvo_dev_ops ch7xxx_ops;
+extern const struct intel_dvo_dev_ops ivch_ops;
+extern const struct intel_dvo_dev_ops tfp410_ops;
+extern const struct intel_dvo_dev_ops ch7017_ops;
+extern const struct intel_dvo_dev_ops ns2501_ops;
 
 #endif /* _INTEL_DVO_H */
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
index cbb2202..b3c7c19 100644
--- a/drivers/gpu/drm/i915/dvo_ch7017.c
+++ b/drivers/gpu/drm/i915/dvo_ch7017.c
@@ -402,7 +402,7 @@
 	}
 }
 
-struct intel_dvo_dev_ops ch7017_ops = {
+const struct intel_dvo_dev_ops ch7017_ops = {
 	.init = ch7017_init,
 	.detect = ch7017_detect,
 	.mode_valid = ch7017_mode_valid,
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
index 4b4acc1..44b3159 100644
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -356,7 +356,7 @@
 	}
 }
 
-struct intel_dvo_dev_ops ch7xxx_ops = {
+const struct intel_dvo_dev_ops ch7xxx_ops = {
 	.init = ch7xxx_init,
 	.detect = ch7xxx_detect,
 	.mode_valid = ch7xxx_mode_valid,
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
index ff9f1b0..4950b82 100644
--- a/drivers/gpu/drm/i915/dvo_ivch.c
+++ b/drivers/gpu/drm/i915/dvo_ivch.c
@@ -490,7 +490,7 @@
 	}
 }
 
-struct intel_dvo_dev_ops ivch_ops = {
+const struct intel_dvo_dev_ops ivch_ops = {
 	.init = ivch_init,
 	.dpms = ivch_dpms,
 	.get_hw_state = ivch_get_hw_state,
diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c
index 063859f..2379c33 100644
--- a/drivers/gpu/drm/i915/dvo_ns2501.c
+++ b/drivers/gpu/drm/i915/dvo_ns2501.c
@@ -698,7 +698,7 @@
 	}
 }
 
-struct intel_dvo_dev_ops ns2501_ops = {
+const struct intel_dvo_dev_ops ns2501_ops = {
 	.init = ns2501_init,
 	.detect = ns2501_detect,
 	.mode_valid = ns2501_mode_valid,
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
index 26f13eb..1c1a067 100644
--- a/drivers/gpu/drm/i915/dvo_sil164.c
+++ b/drivers/gpu/drm/i915/dvo_sil164.c
@@ -267,7 +267,7 @@
 	}
 }
 
-struct intel_dvo_dev_ops sil164_ops = {
+const struct intel_dvo_dev_ops sil164_ops = {
 	.init = sil164_init,
 	.detect = sil164_detect,
 	.mode_valid = sil164_mode_valid,
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
index 6f1a0a6..31e181d 100644
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -306,7 +306,7 @@
 	}
 }
 
-struct intel_dvo_dev_ops tfp410_ops = {
+const struct intel_dvo_dev_ops tfp410_ops = {
 	.init = tfp410_init,
 	.detect = tfp410_detect,
 	.mode_valid = tfp410_mode_valid,
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a8721fc..0fc38bb 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1142,8 +1142,34 @@
 			   MEMSTAT_VID_SHIFT);
 		seq_printf(m, "Current P-state: %d\n",
 			   (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
-	} else if (IS_GEN6(dev) || (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) ||
-		   IS_BROADWELL(dev) || IS_GEN9(dev)) {
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+		u32 freq_sts;
+
+		mutex_lock(&dev_priv->rps.hw_lock);
+		freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+		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);
+
+		seq_printf(m, "actual GPU freq: %d MHz\n",
+			   intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
+
+		seq_printf(m, "current GPU freq: %d MHz\n",
+			   intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
+
+		seq_printf(m, "max GPU freq: %d MHz\n",
+			   intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
+
+		seq_printf(m, "min GPU freq: %d MHz\n",
+			   intel_gpu_freq(dev_priv, dev_priv->rps.min_freq));
+
+		seq_printf(m, "idle GPU freq: %d MHz\n",
+			   intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq));
+
+		seq_printf(m,
+			   "efficient (RPe) frequency: %d MHz\n",
+			   intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
+		mutex_unlock(&dev_priv->rps.hw_lock);
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		u32 rp_state_limits;
 		u32 gt_perf_status;
 		u32 rp_state_cap;
@@ -1284,33 +1310,6 @@
 		seq_printf(m,
 			   "efficient (RPe) frequency: %d MHz\n",
 			   intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
-	} else if (IS_VALLEYVIEW(dev)) {
-		u32 freq_sts;
-
-		mutex_lock(&dev_priv->rps.hw_lock);
-		freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
-		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);
-
-		seq_printf(m, "actual GPU freq: %d MHz\n",
-			   intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
-
-		seq_printf(m, "current GPU freq: %d MHz\n",
-			   intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
-
-		seq_printf(m, "max GPU freq: %d MHz\n",
-			   intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
-
-		seq_printf(m, "min GPU freq: %d MHz\n",
-			   intel_gpu_freq(dev_priv, dev_priv->rps.min_freq));
-
-		seq_printf(m, "idle GPU freq: %d MHz\n",
-			   intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq));
-
-		seq_printf(m,
-			   "efficient (RPe) frequency: %d MHz\n",
-			   intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
-		mutex_unlock(&dev_priv->rps.hw_lock);
 	} else {
 		seq_puts(m, "no P-state info available\n");
 	}
@@ -1602,7 +1601,7 @@
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		return vlv_drpc_info(m);
 	else if (INTEL_INFO(dev)->gen >= 6)
 		return gen6_drpc_info(m);
@@ -1743,7 +1742,7 @@
 		sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
 	else if (IS_PINEVIEW(dev))
 		sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
-	else if (IS_VALLEYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
 
 	intel_runtime_pm_put(dev_priv);
@@ -1843,25 +1842,31 @@
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_opregion *opregion = &dev_priv->opregion;
-	void *data = kmalloc(OPREGION_SIZE, GFP_KERNEL);
 	int ret;
 
-	if (data == NULL)
-		return -ENOMEM;
-
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		goto out;
 
-	if (opregion->header) {
-		memcpy(data, opregion->header, OPREGION_SIZE);
-		seq_write(m, data, OPREGION_SIZE);
-	}
+	if (opregion->header)
+		seq_write(m, opregion->header, OPREGION_SIZE);
 
 	mutex_unlock(&dev->struct_mutex);
 
 out:
-	kfree(data);
+	return 0;
+}
+
+static int i915_vbt(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_opregion *opregion = &dev_priv->opregion;
+
+	if (opregion->vbt)
+		seq_write(m, opregion->vbt, opregion->vbt_size);
+
 	return 0;
 }
 
@@ -2850,6 +2855,20 @@
 		intel_panel_info(m, &intel_connector->panel);
 }
 
+static void intel_dp_mst_info(struct seq_file *m,
+			  struct intel_connector *intel_connector)
+{
+	struct intel_encoder *intel_encoder = intel_connector->encoder;
+	struct intel_dp_mst_encoder *intel_mst =
+		enc_to_mst(&intel_encoder->base);
+	struct intel_digital_port *intel_dig_port = intel_mst->primary;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	bool has_audio = drm_dp_mst_port_has_audio(&intel_dp->mst_mgr,
+					intel_connector->port);
+
+	seq_printf(m, "\taudio support: %s\n", yesno(has_audio));
+}
+
 static void intel_hdmi_info(struct seq_file *m,
 			    struct intel_connector *intel_connector)
 {
@@ -2893,6 +2912,8 @@
 			intel_hdmi_info(m, intel_connector);
 		else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
 			intel_lvds_info(m, intel_connector);
+		else if (intel_encoder->type == INTEL_OUTPUT_DP_MST)
+			intel_dp_mst_info(m, intel_connector);
 	}
 
 	seq_printf(m, "\tmodes:\n");
@@ -3983,7 +4004,7 @@
 		ret = i8xx_pipe_crc_ctl_reg(&source, &val);
 	else if (INTEL_INFO(dev)->gen < 5)
 		ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val);
-	else if (IS_VALLEYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		ret = vlv_pipe_crc_ctl_reg(dev, pipe, &source, &val);
 	else if (IS_GEN5(dev) || IS_GEN6(dev))
 		ret = ilk_pipe_crc_ctl_reg(&source, &val);
@@ -4052,7 +4073,7 @@
 
 		if (IS_G4X(dev))
 			g4x_undo_pipe_scramble_reset(dev, pipe);
-		else if (IS_VALLEYVIEW(dev))
+		else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 			vlv_undo_pipe_scramble_reset(dev, pipe);
 		else if (IS_HASWELL(dev) && pipe == PIPE_A)
 			hsw_trans_edp_pipe_A_crc_wa(dev, false);
@@ -4442,7 +4463,8 @@
 		 * - WM1+ latency values in 0.5us units
 		 * - latencies are in us on gen9/vlv/chv
 		 */
-		if (INTEL_INFO(dev)->gen >= 9 || IS_VALLEYVIEW(dev))
+		if (INTEL_INFO(dev)->gen >= 9 || IS_VALLEYVIEW(dev) ||
+		    IS_CHERRYVIEW(dev))
 			latency *= 10;
 		else if (level > 0)
 			latency *= 5;
@@ -5316,6 +5338,7 @@
 	{"i915_ips_status", i915_ips_status, 0},
 	{"i915_sr_status", i915_sr_status, 0},
 	{"i915_opregion", i915_opregion, 0},
+	{"i915_vbt", i915_vbt, 0},
 	{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
 	{"i915_context_status", i915_context_status, 0},
 	{"i915_dump_lrc", i915_dump_lrc, 0},
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index aace060..d70d96f 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -169,6 +169,9 @@
 	case I915_PARAM_HAS_RESOURCE_STREAMER:
 		value = HAS_RESOURCE_STREAMER(dev);
 		break;
+	case I915_PARAM_HAS_EXEC_SOFTPIN:
+		value = 1;
+		break;
 	default:
 		DRM_DEBUG("Unknown parameter %d\n", param->param);
 		return -EINVAL;
@@ -256,7 +259,7 @@
 	u32 temp;
 	bool enabled;
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		return;
 
 	dev_priv->mchbar_need_disable = false;
@@ -367,7 +370,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	ret = intel_parse_bios(dev);
+	ret = intel_bios_init(dev_priv);
 	if (ret)
 		DRM_INFO("failed to find VBIOS tables\n");
 
@@ -782,7 +785,7 @@
 		info->num_sprites[PIPE_A] = 2;
 		info->num_sprites[PIPE_B] = 2;
 		info->num_sprites[PIPE_C] = 1;
-	} else if (IS_VALLEYVIEW(dev))
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		for_each_pipe(dev_priv, pipe)
 			info->num_sprites[pipe] = 2;
 	else
@@ -794,7 +797,7 @@
 		info->num_pipes = 0;
 	} else if (info->num_pipes > 0 &&
 		   (INTEL_INFO(dev)->gen == 7 || INTEL_INFO(dev)->gen == 8) &&
-		   !IS_VALLEYVIEW(dev)) {
+		   HAS_PCH_SPLIT(dev)) {
 		u32 fuse_strap = I915_READ(FUSE_STRAP);
 		u32 sfuse_strap = I915_READ(SFUSE_STRAP);
 
@@ -839,9 +842,6 @@
 
 static void intel_init_dpio(struct drm_i915_private *dev_priv)
 {
-	if (!IS_VALLEYVIEW(dev_priv))
-		return;
-
 	/*
 	 * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
 	 * CHV x1 PHY (DP/HDMI D)
@@ -850,7 +850,7 @@
 	if (IS_CHERRYVIEW(dev_priv)) {
 		DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
 		DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
-	} else {
+	} else if (IS_VALLEYVIEW(dev_priv)) {
 		DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
 	}
 }
@@ -899,6 +899,8 @@
 
 	intel_pm_setup(dev);
 
+	intel_runtime_pm_get(dev_priv);
+
 	intel_display_crc_init(dev);
 
 	i915_dump_device_info(dev_priv);
@@ -1087,6 +1089,8 @@
 
 	i915_audio_component_init(dev_priv);
 
+	intel_runtime_pm_put(dev_priv);
+
 	return 0;
 
 out_power_well:
@@ -1121,6 +1125,9 @@
 	kmem_cache_destroy(dev_priv->requests);
 	kmem_cache_destroy(dev_priv->vmas);
 	kmem_cache_destroy(dev_priv->objects);
+
+	intel_runtime_pm_put(dev_priv);
+
 	kfree(dev_priv);
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index e6935f1..3ac616d 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -311,7 +311,7 @@
 	.gen = 8, .num_pipes = 3,
 	.need_gfx_hws = 1, .has_hotplug = 1,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
-	.is_valleyview = 1,
+	.is_cherryview = 1,
 	.display_mmio_offset = VLV_DISPLAY_BASE,
 	GEN_CHV_PIPEOFFSETS,
 	CURSOR_OFFSETS,
@@ -543,15 +543,12 @@
 static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
-	struct drm_encoder *encoder;
+	struct intel_encoder *encoder;
 
 	drm_modeset_lock_all(dev);
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
-
-		if (intel_encoder->suspend)
-			intel_encoder->suspend(intel_encoder);
-	}
+	for_each_intel_encoder(dev, encoder)
+		if (encoder->suspend)
+			encoder->suspend(encoder);
 	drm_modeset_unlock_all(dev);
 }
 
@@ -580,6 +577,8 @@
 	dev_priv->modeset_restore = MODESET_SUSPENDED;
 	mutex_unlock(&dev_priv->modeset_restore_lock);
 
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	/* We do a lot of poking in a lot of registers, make sure they work
 	 * properly. */
 	intel_display_set_init_power(dev_priv, true);
@@ -592,7 +591,7 @@
 	if (error) {
 		dev_err(&dev->pdev->dev,
 			"GEM idle failed, resume might fail\n");
-		return error;
+		goto out;
 	}
 
 	intel_guc_suspend(dev);
@@ -635,7 +634,10 @@
 	if (HAS_CSR(dev_priv))
 		flush_work(&dev_priv->csr.work);
 
-	return 0;
+out:
+	enable_rpm_wakeref_asserts(dev_priv);
+
+	return error;
 }
 
 static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
@@ -644,6 +646,8 @@
 	bool fw_csr;
 	int ret;
 
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	fw_csr = suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;
 	/*
 	 * In case of firmware assisted context save/restore don't manually
@@ -662,7 +666,7 @@
 		if (!fw_csr)
 			intel_power_domains_init_hw(dev_priv, true);
 
-		return ret;
+		goto out;
 	}
 
 	pci_disable_device(drm_dev->pdev);
@@ -683,7 +687,10 @@
 
 	dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
 
-	return 0;
+out:
+	enable_rpm_wakeref_asserts(dev_priv);
+
+	return ret;
 }
 
 int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state)
@@ -714,6 +721,8 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	mutex_lock(&dev->struct_mutex);
 	i915_gem_restore_gtt_mappings(dev);
 	mutex_unlock(&dev->struct_mutex);
@@ -778,6 +787,8 @@
 
 	drm_kms_helper_poll_enable(dev);
 
+	enable_rpm_wakeref_asserts(dev_priv);
+
 	return 0;
 }
 
@@ -802,7 +813,9 @@
 
 	pci_set_master(dev->pdev);
 
-	if (IS_VALLEYVIEW(dev_priv))
+	disable_rpm_wakeref_asserts(dev_priv);
+
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		ret = vlv_resume_prepare(dev_priv, false);
 	if (ret)
 		DRM_ERROR("Resume prepare failed: %d, continuing anyway\n",
@@ -823,6 +836,8 @@
 out:
 	dev_priv->suspended_to_idle = false;
 
+	enable_rpm_wakeref_asserts(dev_priv);
+
 	return ret;
 }
 
@@ -1455,6 +1470,9 @@
 
 		return -EAGAIN;
 	}
+
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	/*
 	 * We are safe here against re-faults, since the fault handler takes
 	 * an RPM reference.
@@ -1462,6 +1480,8 @@
 	i915_gem_release_all_mmaps(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
+	cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
+
 	intel_guc_suspend(dev);
 
 	intel_suspend_gt_powersave(dev);
@@ -1472,11 +1492,15 @@
 		DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
 		intel_runtime_pm_enable_interrupts(dev_priv);
 
+		enable_rpm_wakeref_asserts(dev_priv);
+
 		return ret;
 	}
 
-	cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
 	intel_uncore_forcewake_reset(dev, false);
+
+	enable_rpm_wakeref_asserts(dev_priv);
+	WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
 	dev_priv->pm.suspended = true;
 
 	/*
@@ -1520,6 +1544,9 @@
 
 	DRM_DEBUG_KMS("Resuming device\n");
 
+	WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	intel_opregion_notify_adapter(dev, PCI_D0);
 	dev_priv->pm.suspended = false;
 
@@ -1532,7 +1559,7 @@
 		ret = bxt_resume_prepare(dev_priv);
 	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		hsw_disable_pc8(dev_priv);
-	else if (IS_VALLEYVIEW(dev_priv))
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		ret = vlv_resume_prepare(dev_priv, true);
 
 	/*
@@ -1549,11 +1576,13 @@
 	 * power well, so hpd is reinitialized from there. For
 	 * everyone else do it here.
 	 */
-	if (!IS_VALLEYVIEW(dev_priv))
+	if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
 		intel_hpd_init(dev_priv);
 
 	intel_enable_gt_powersave(dev);
 
+	enable_rpm_wakeref_asserts(dev_priv);
+
 	if (ret)
 		DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
 	else
@@ -1574,7 +1603,7 @@
 		ret = bxt_suspend_complete(dev_priv);
 	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		ret = hsw_suspend_complete(dev_priv);
-	else if (IS_VALLEYVIEW(dev_priv))
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		ret = vlv_suspend_complete(dev_priv);
 	else
 		ret = 0;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f1a8a53..f0f75d7 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -33,6 +33,7 @@
 #include <uapi/drm/i915_drm.h>
 #include <uapi/drm/drm_fourcc.h>
 
+#include <drm/drmP.h>
 #include "i915_reg.h"
 #include "intel_bios.h"
 #include "intel_ringbuffer.h"
@@ -57,7 +58,7 @@
 
 #define DRIVER_NAME		"i915"
 #define DRIVER_DESC		"Intel Graphics"
-#define DRIVER_DATE		"20151204"
+#define DRIVER_DATE		"20151218"
 
 #undef WARN_ON
 /* Many gcc seem to no see through this and fall over :( */
@@ -457,7 +458,9 @@
 	u32 swsci_gbda_sub_functions;
 	u32 swsci_sbcb_sub_functions;
 	struct opregion_asle *asle;
-	void *vbt;
+	void *rvda;
+	const void *vbt;
+	u32 vbt_size;
 	u32 *lid_state;
 	struct work_struct asle_work;
 };
@@ -763,6 +766,7 @@
 	func(is_crestline) sep \
 	func(is_ivybridge) sep \
 	func(is_valleyview) sep \
+	func(is_cherryview) sep \
 	func(is_haswell) sep \
 	func(is_skylake) sep \
 	func(is_broxton) sep \
@@ -1601,6 +1605,8 @@
  * For more, read the Documentation/power/runtime_pm.txt.
  */
 struct i915_runtime_pm {
+	atomic_t wakeref_count;
+	atomic_t atomic_seq;
 	bool suspended;
 	bool irqs_enabled;
 };
@@ -1944,6 +1950,8 @@
 	/* perform PHY state sanity checks? */
 	bool chv_phy_assert[2];
 
+	struct intel_encoder *dig_port_map[I915_MAX_PORTS];
+
 	/*
 	 * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
 	 * will be rejected. Instead look for a better place.
@@ -2181,8 +2189,17 @@
 	struct drm_i915_private *i915;
 	struct intel_engine_cs *ring;
 
-	/** GEM sequence number associated with this request. */
-	uint32_t seqno;
+	 /** GEM sequence number associated with the previous request,
+	  * when the HWS breadcrumb is equal to this the GPU is processing
+	  * this request.
+	  */
+	u32 previous_seqno;
+
+	 /** GEM sequence number associated with this request,
+	  * when the HWS breadcrumb is equal or greater than this the GPU
+	  * has finished processing this request.
+	  */
+	u32 seqno;
 
 	/** Position in the ringbuffer of the start of the request */
 	u32 head;
@@ -2455,9 +2472,9 @@
 				 INTEL_DEVID(dev) == 0x0152 || \
 				 INTEL_DEVID(dev) == 0x015a)
 #define IS_VALLEYVIEW(dev)	(INTEL_INFO(dev)->is_valleyview)
-#define IS_CHERRYVIEW(dev)	(INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
+#define IS_CHERRYVIEW(dev)	(INTEL_INFO(dev)->is_cherryview)
 #define IS_HASWELL(dev)	(INTEL_INFO(dev)->is_haswell)
-#define IS_BROADWELL(dev)	(!INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
+#define IS_BROADWELL(dev)	(!INTEL_INFO(dev)->is_cherryview && IS_GEN8(dev))
 #define IS_SKYLAKE(dev)	(INTEL_INFO(dev)->is_skylake)
 #define IS_BROXTON(dev)		(INTEL_INFO(dev)->is_broxton)
 #define IS_KABYLAKE(dev)	(INTEL_INFO(dev)->is_kabylake)
@@ -2488,6 +2505,14 @@
 #define IS_SKL_ULX(dev)		(INTEL_DEVID(dev) == 0x190E || \
 				 INTEL_DEVID(dev) == 0x1915 || \
 				 INTEL_DEVID(dev) == 0x191E)
+#define IS_KBL_ULT(dev)		(INTEL_DEVID(dev) == 0x5906 || \
+				 INTEL_DEVID(dev) == 0x5913 || \
+				 INTEL_DEVID(dev) == 0x5916 || \
+				 INTEL_DEVID(dev) == 0x5921 || \
+				 INTEL_DEVID(dev) == 0x5926)
+#define IS_KBL_ULX(dev)		(INTEL_DEVID(dev) == 0x590E || \
+				 INTEL_DEVID(dev) == 0x5915 || \
+				 INTEL_DEVID(dev) == 0x591E)
 #define IS_SKL_GT3(dev)		(IS_SKYLAKE(dev) && \
 				 (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
 #define IS_SKL_GT4(dev)		(IS_SKYLAKE(dev) && \
@@ -2584,20 +2609,22 @@
 				 IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
 #define HAS_RUNTIME_PM(dev)	(IS_GEN6(dev) || IS_HASWELL(dev) || \
 				 IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \
-				 IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+				 IS_CHERRYVIEW(dev) || IS_SKYLAKE(dev) || \
+				 IS_KABYLAKE(dev))
 #define HAS_RC6(dev)		(INTEL_INFO(dev)->gen >= 6)
 #define HAS_RC6p(dev)		(INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
 
 #define HAS_CSR(dev)	(IS_GEN9(dev))
 
-#define HAS_GUC_UCODE(dev)	(IS_GEN9(dev))
-#define HAS_GUC_SCHED(dev)	(IS_GEN9(dev))
+#define HAS_GUC_UCODE(dev)	(IS_GEN9(dev) && !IS_KABYLAKE(dev))
+#define HAS_GUC_SCHED(dev)	(IS_GEN9(dev) && !IS_KABYLAKE(dev))
 
 #define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
 				    INTEL_INFO(dev)->gen >= 8)
 
 #define HAS_CORE_RING_FREQ(dev)	(INTEL_INFO(dev)->gen >= 6 && \
-				 !IS_VALLEYVIEW(dev) && !IS_BROXTON(dev))
+				 !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && \
+				 !IS_BROXTON(dev))
 
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
@@ -2620,7 +2647,8 @@
 #define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP)
 #define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE)
 
-#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev))
+#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || \
+			       IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 
 /* DPF == dynamic parity feature */
 #define HAS_L3_DPF(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
@@ -2860,6 +2888,7 @@
 #define PIN_UPDATE	(1<<5)
 #define PIN_ZONE_4G	(1<<6)
 #define PIN_HIGH	(1<<7)
+#define PIN_OFFSET_FIXED	(1<<8)
 #define PIN_OFFSET_MASK (~4095)
 int __must_check
 i915_gem_object_pin(struct drm_i915_gem_object *obj,
@@ -2874,6 +2903,7 @@
 
 int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
 		  u32 flags);
+void __i915_vma_set_map_and_fenceable(struct i915_vma *vma);
 int __must_check i915_vma_unbind(struct i915_vma *vma);
 /*
  * BEWARE: Do not use the function below unless you can _absolutely_
@@ -2894,6 +2924,9 @@
 	return sg->length >> PAGE_SHIFT;
 }
 
+struct page *
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n);
+
 static inline struct page *
 i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
 {
@@ -2945,15 +2978,17 @@
 	return (int32_t)(seq1 - seq2) >= 0;
 }
 
+static inline bool i915_gem_request_started(struct drm_i915_gem_request *req,
+					   bool lazy_coherency)
+{
+	u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
+	return i915_seqno_passed(seqno, req->previous_seqno);
+}
+
 static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req,
 					      bool lazy_coherency)
 {
-	u32 seqno;
-
-	BUG_ON(req == NULL);
-
-	seqno = req->ring->get_seqno(req->ring, lazy_coherency);
-
+	u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
 	return i915_seqno_passed(seqno, req->seqno);
 }
 
@@ -3205,6 +3240,7 @@
 					  unsigned long start,
 					  unsigned long end,
 					  unsigned flags);
+int __must_check i915_gem_evict_for_vma(struct i915_vma *target);
 int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
 
 /* belongs in i915_gem_gtt.h */
@@ -3333,6 +3369,10 @@
 }
 extern void intel_i2c_reset(struct drm_device *dev);
 
+/* intel_bios.c */
+int intel_bios_init(struct drm_i915_private *dev_priv);
+bool intel_bios_is_valid_vbt(const void *buf, size_t size);
+
 /* intel_opregion.c */
 #ifdef CONFIG_ACPI
 extern int intel_opregion_setup(struct drm_device *dev);
@@ -3511,7 +3551,7 @@
 
 static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev)
 {
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		return VLV_VGACNTRL;
 	else if (INTEL_INFO(dev)->gen >= 5)
 		return CPU_VGACNTRL;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index b7d7cec..6c60e04 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1146,23 +1146,74 @@
 	return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings);
 }
 
-static int __i915_spin_request(struct drm_i915_gem_request *req)
+static unsigned long local_clock_us(unsigned *cpu)
+{
+	unsigned long t;
+
+	/* Cheaply and approximately convert from nanoseconds to microseconds.
+	 * The result and subsequent calculations are also defined in the same
+	 * approximate microseconds units. The principal source of timing
+	 * error here is from the simple truncation.
+	 *
+	 * Note that local_clock() is only defined wrt to the current CPU;
+	 * the comparisons are no longer valid if we switch CPUs. Instead of
+	 * blocking preemption for the entire busywait, we can detect the CPU
+	 * switch and use that as indicator of system load and a reason to
+	 * stop busywaiting, see busywait_stop().
+	 */
+	*cpu = get_cpu();
+	t = local_clock() >> 10;
+	put_cpu();
+
+	return t;
+}
+
+static bool busywait_stop(unsigned long timeout, unsigned cpu)
+{
+	unsigned this_cpu;
+
+	if (time_after(local_clock_us(&this_cpu), timeout))
+		return true;
+
+	return this_cpu != cpu;
+}
+
+static int __i915_spin_request(struct drm_i915_gem_request *req, int state)
 {
 	unsigned long timeout;
+	unsigned cpu;
 
-	if (i915_gem_request_get_ring(req)->irq_refcount)
+	/* When waiting for high frequency requests, e.g. during synchronous
+	 * rendering split between the CPU and GPU, the finite amount of time
+	 * required to set up the irq and wait upon it limits the response
+	 * rate. By busywaiting on the request completion for a short while we
+	 * can service the high frequency waits as quick as possible. However,
+	 * if it is a slow request, we want to sleep as quickly as possible.
+	 * The tradeoff between waiting and sleeping is roughly the time it
+	 * takes to sleep on a request, on the order of a microsecond.
+	 */
+
+	if (req->ring->irq_refcount)
 		return -EBUSY;
 
-	timeout = jiffies + 1;
+	/* Only spin if we know the GPU is processing this request */
+	if (!i915_gem_request_started(req, true))
+		return -EAGAIN;
+
+	timeout = local_clock_us(&cpu) + 5;
 	while (!need_resched()) {
 		if (i915_gem_request_completed(req, true))
 			return 0;
 
-		if (time_after_eq(jiffies, timeout))
+		if (signal_pending_state(state, current))
+			break;
+
+		if (busywait_stop(timeout, cpu))
 			break;
 
 		cpu_relax_lowlatency();
 	}
+
 	if (i915_gem_request_completed(req, false))
 		return 0;
 
@@ -1197,6 +1248,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	const bool irq_test_in_progress =
 		ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
+	int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
 	DEFINE_WAIT(wait);
 	unsigned long timeout_expire;
 	s64 before, now;
@@ -1229,7 +1281,7 @@
 	before = ktime_get_raw_ns();
 
 	/* Optimistic spin for the next jiffie before touching IRQs */
-	ret = __i915_spin_request(req);
+	ret = __i915_spin_request(req, state);
 	if (ret == 0)
 		goto out;
 
@@ -1241,8 +1293,7 @@
 	for (;;) {
 		struct timer_list timer;
 
-		prepare_to_wait(&ring->irq_queue, &wait,
-				interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		prepare_to_wait(&ring->irq_queue, &wait, state);
 
 		/* We need to check whether any gpu reset happened in between
 		 * the caller grabbing the seqno and now ... */
@@ -1260,7 +1311,7 @@
 			break;
 		}
 
-		if (interruptible && signal_pending(current)) {
+		if (signal_pending_state(state, current)) {
 			ret = -ERESTARTSYS;
 			break;
 		}
@@ -2554,6 +2605,7 @@
 	request->batch_obj = obj;
 
 	request->emitted_jiffies = jiffies;
+	request->previous_seqno = ring->last_submitted_seqno;
 	ring->last_submitted_seqno = request->seqno;
 	list_add_tail(&request->list, &ring->request_list);
 
@@ -2765,20 +2817,13 @@
 
 	if (i915.enable_execlists) {
 		spin_lock_irq(&ring->execlist_lock);
-		while (!list_empty(&ring->execlist_queue)) {
-			struct drm_i915_gem_request *submit_req;
 
-			submit_req = list_first_entry(&ring->execlist_queue,
-					struct drm_i915_gem_request,
-					execlist_link);
-			list_del(&submit_req->execlist_link);
+		/* list_splice_tail_init checks for empty lists */
+		list_splice_tail_init(&ring->execlist_queue,
+				      &ring->execlist_retired_req_list);
 
-			if (submit_req->ctx != ring->default_context)
-				intel_lr_context_unpin(submit_req);
-
-			i915_gem_request_unreference(submit_req);
-		}
 		spin_unlock_irq(&ring->execlist_lock);
+		intel_execlists_retire_requests(ring);
 	}
 
 	/*
@@ -3480,30 +3525,50 @@
 	if (IS_ERR(vma))
 		goto err_unpin;
 
-	if (flags & PIN_HIGH) {
-		search_flag = DRM_MM_SEARCH_BELOW;
-		alloc_flag = DRM_MM_CREATE_TOP;
+	if (flags & PIN_OFFSET_FIXED) {
+		uint64_t offset = flags & PIN_OFFSET_MASK;
+
+		if (offset & (alignment - 1) || offset + size > end) {
+			ret = -EINVAL;
+			goto err_free_vma;
+		}
+		vma->node.start = offset;
+		vma->node.size = size;
+		vma->node.color = obj->cache_level;
+		ret = drm_mm_reserve_node(&vm->mm, &vma->node);
+		if (ret) {
+			ret = i915_gem_evict_for_vma(vma);
+			if (ret == 0)
+				ret = drm_mm_reserve_node(&vm->mm, &vma->node);
+		}
+		if (ret)
+			goto err_free_vma;
 	} else {
-		search_flag = DRM_MM_SEARCH_DEFAULT;
-		alloc_flag = DRM_MM_CREATE_DEFAULT;
-	}
+		if (flags & PIN_HIGH) {
+			search_flag = DRM_MM_SEARCH_BELOW;
+			alloc_flag = DRM_MM_CREATE_TOP;
+		} else {
+			search_flag = DRM_MM_SEARCH_DEFAULT;
+			alloc_flag = DRM_MM_CREATE_DEFAULT;
+		}
 
 search_free:
-	ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
-						  size, alignment,
-						  obj->cache_level,
-						  start, end,
-						  search_flag,
-						  alloc_flag);
-	if (ret) {
-		ret = i915_gem_evict_something(dev, vm, size, alignment,
-					       obj->cache_level,
-					       start, end,
-					       flags);
-		if (ret == 0)
-			goto search_free;
+		ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
+							  size, alignment,
+							  obj->cache_level,
+							  start, end,
+							  search_flag,
+							  alloc_flag);
+		if (ret) {
+			ret = i915_gem_evict_something(dev, vm, size, alignment,
+						       obj->cache_level,
+						       start, end,
+						       flags);
+			if (ret == 0)
+				goto search_free;
 
-		goto err_free_vma;
+			goto err_free_vma;
+		}
 	}
 	if (WARN_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level))) {
 		ret = -EINVAL;
@@ -4094,9 +4159,36 @@
 	    vma->node.start < (flags & PIN_OFFSET_MASK))
 		return true;
 
+	if (flags & PIN_OFFSET_FIXED &&
+	    vma->node.start != (flags & PIN_OFFSET_MASK))
+		return true;
+
 	return false;
 }
 
+void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
+{
+	struct drm_i915_gem_object *obj = vma->obj;
+	bool mappable, fenceable;
+	u32 fence_size, fence_alignment;
+
+	fence_size = i915_gem_get_gtt_size(obj->base.dev,
+					   obj->base.size,
+					   obj->tiling_mode);
+	fence_alignment = i915_gem_get_gtt_alignment(obj->base.dev,
+						     obj->base.size,
+						     obj->tiling_mode,
+						     true);
+
+	fenceable = (vma->node.size == fence_size &&
+		     (vma->node.start & (fence_alignment - 1)) == 0);
+
+	mappable = (vma->node.start + fence_size <=
+		    to_i915(obj->base.dev)->gtt.mappable_end);
+
+	obj->map_and_fenceable = mappable && fenceable;
+}
+
 static int
 i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
 		       struct i915_address_space *vm,
@@ -4164,25 +4256,7 @@
 
 	if (ggtt_view && ggtt_view->type == I915_GGTT_VIEW_NORMAL &&
 	    (bound ^ vma->bound) & GLOBAL_BIND) {
-		bool mappable, fenceable;
-		u32 fence_size, fence_alignment;
-
-		fence_size = i915_gem_get_gtt_size(obj->base.dev,
-						   obj->base.size,
-						   obj->tiling_mode);
-		fence_alignment = i915_gem_get_gtt_alignment(obj->base.dev,
-							     obj->base.size,
-							     obj->tiling_mode,
-							     true);
-
-		fenceable = (vma->node.size == fence_size &&
-			     (vma->node.start & (fence_alignment - 1)) == 0);
-
-		mappable = (vma->node.start + fence_size <=
-			    dev_priv->gtt.mappable_end);
-
-		obj->map_and_fenceable = mappable && fenceable;
-
+		__i915_vma_set_map_and_fenceable(vma);
 		WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable);
 	}
 
@@ -4842,14 +4916,6 @@
 
 	mutex_lock(&dev->struct_mutex);
 
-	if (IS_VALLEYVIEW(dev)) {
-		/* VLVA0 (potential hack), BIOS isn't actually waking us */
-		I915_WRITE(VLV_GTLC_WAKE_CTRL, VLV_GTLC_ALLOWWAKEREQ);
-		if (wait_for((I915_READ(VLV_GTLC_PW_STATUS) &
-			      VLV_GTLC_ALLOWWAKEACK), 10))
-			DRM_DEBUG_DRIVER("allow wake ack timed out\n");
-	}
-
 	if (!i915.enable_execlists) {
 		dev_priv->gt.execbuf_submit = i915_gem_ringbuffer_submission;
 		dev_priv->gt.init_rings = i915_gem_init_rings;
@@ -4967,7 +5033,7 @@
 
 	dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
 
-	if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev))
+	if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev))
 		dev_priv->num_fence_regs = 32;
 	else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
 		dev_priv->num_fence_regs = 16;
@@ -5188,6 +5254,21 @@
 	return false;
 }
 
+/* Like i915_gem_object_get_page(), but mark the returned page dirty */
+struct page *
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n)
+{
+	struct page *page;
+
+	/* Only default objects have per-page dirty tracking */
+	if (WARN_ON(obj->ops != &i915_gem_object_ops))
+		return NULL;
+
+	page = i915_gem_object_get_page(obj, n);
+	set_page_dirty(page);
+	return page;
+}
+
 /* Allocate a new GEM object and fill it with the supplied data */
 struct drm_i915_gem_object *
 i915_gem_object_create_from_data(struct drm_device *dev,
@@ -5213,6 +5294,7 @@
 	i915_gem_object_pin_pages(obj);
 	sg = obj->pages;
 	bytes = sg_copy_from_buffer(sg->sgl, sg->nents, (void *)data, size);
+	obj->dirty = 1;		/* Backing store is now out of date */
 	i915_gem_object_unpin_pages(obj);
 
 	if (WARN_ON(bytes != size)) {
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 43761c5..900ffd0 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -189,8 +189,15 @@
 	 * shouldn't touch the cache level, especially as that
 	 * would make the object snooped which might have a
 	 * negative performance impact.
+	 *
+	 * Snooping is required on non-llc platforms in execlist
+	 * mode, but since all GGTT accesses use PAT entry 0 we
+	 * get snooping anyway regardless of cache_level.
+	 *
+	 * This is only applicable for Ivy Bridge devices since
+	 * later platforms don't have L3 control bits in the PTE.
 	 */
-	if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev)) {
+	if (IS_IVYBRIDGE(dev)) {
 		ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC);
 		/* Failure shouldn't ever happen this early */
 		if (WARN_ON(ret)) {
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index d71a133..07c6e4d 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -199,6 +199,45 @@
 	return ret;
 }
 
+int
+i915_gem_evict_for_vma(struct i915_vma *target)
+{
+	struct drm_mm_node *node, *next;
+
+	list_for_each_entry_safe(node, next,
+			&target->vm->mm.head_node.node_list,
+			node_list) {
+		struct i915_vma *vma;
+		int ret;
+
+		if (node->start + node->size <= target->node.start)
+			continue;
+		if (node->start >= target->node.start + target->node.size)
+			break;
+
+		vma = container_of(node, typeof(*vma), node);
+
+		if (vma->pin_count) {
+			if (!vma->exec_entry || (vma->pin_count > 1))
+				/* Object is pinned for some other use */
+				return -EBUSY;
+
+			/* We need to evict a buffer in the same batch */
+			if (vma->exec_entry->flags & EXEC_OBJECT_PINNED)
+				/* Overlapping fixed objects in the same batch */
+				return -EINVAL;
+
+			return -ENOSPC;
+		}
+
+		ret = i915_vma_unbind(vma);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 /**
  * i915_gem_evict_vm - Evict all idle vmas from a vm
  * @vm: Address space to cleanse
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index a4c243c..5d01ea6 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -264,7 +264,7 @@
 	if (ret)
 		return ret;
 
-	vaddr = kmap_atomic(i915_gem_object_get_page(obj,
+	vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
 				reloc->offset >> PAGE_SHIFT));
 	*(uint32_t *)(vaddr + page_offset) = lower_32_bits(delta);
 
@@ -273,7 +273,7 @@
 
 		if (page_offset == 0) {
 			kunmap_atomic(vaddr);
-			vaddr = kmap_atomic(i915_gem_object_get_page(obj,
+			vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
 			    (reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT));
 		}
 
@@ -355,7 +355,7 @@
 	if (ret)
 		return ret;
 
-	vaddr = kmap_atomic(i915_gem_object_get_page(obj,
+	vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
 				reloc->offset >> PAGE_SHIFT));
 	clflush_write32(vaddr + page_offset, lower_32_bits(delta));
 
@@ -364,7 +364,7 @@
 
 		if (page_offset == 0) {
 			kunmap_atomic(vaddr);
-			vaddr = kmap_atomic(i915_gem_object_get_page(obj,
+			vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
 			    (reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT));
 		}
 
@@ -599,6 +599,8 @@
 			flags |= PIN_GLOBAL | PIN_MAPPABLE;
 		if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS)
 			flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS;
+		if (entry->flags & EXEC_OBJECT_PINNED)
+			flags |= entry->offset | PIN_OFFSET_FIXED;
 		if ((flags & PIN_MAPPABLE) == 0)
 			flags |= PIN_HIGH;
 	}
@@ -670,6 +672,10 @@
 	    vma->node.start & (entry->alignment - 1))
 		return true;
 
+	if (entry->flags & EXEC_OBJECT_PINNED &&
+	    vma->node.start != entry->offset)
+		return true;
+
 	if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS &&
 	    vma->node.start < BATCH_OFFSET_BIAS)
 		return true;
@@ -695,6 +701,7 @@
 	struct i915_vma *vma;
 	struct i915_address_space *vm;
 	struct list_head ordered_vmas;
+	struct list_head pinned_vmas;
 	bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
 	int retry;
 
@@ -703,6 +710,7 @@
 	vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm;
 
 	INIT_LIST_HEAD(&ordered_vmas);
+	INIT_LIST_HEAD(&pinned_vmas);
 	while (!list_empty(vmas)) {
 		struct drm_i915_gem_exec_object2 *entry;
 		bool need_fence, need_mappable;
@@ -721,7 +729,9 @@
 			obj->tiling_mode != I915_TILING_NONE;
 		need_mappable = need_fence || need_reloc_mappable(vma);
 
-		if (need_mappable) {
+		if (entry->flags & EXEC_OBJECT_PINNED)
+			list_move_tail(&vma->exec_list, &pinned_vmas);
+		else if (need_mappable) {
 			entry->flags |= __EXEC_OBJECT_NEEDS_MAP;
 			list_move(&vma->exec_list, &ordered_vmas);
 		} else
@@ -731,6 +741,7 @@
 		obj->base.pending_write_domain = 0;
 	}
 	list_splice(&ordered_vmas, vmas);
+	list_splice(&pinned_vmas, vmas);
 
 	/* Attempt to pin all of the buffers into the GTT.
 	 * This is done in 3 phases:
@@ -1317,7 +1328,8 @@
 	 * Note that actual hangs have only been observed on gen7, but for
 	 * paranoia do it everywhere.
 	 */
-	vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS;
+	if ((vma->exec_entry->flags & EXEC_OBJECT_PINNED) == 0)
+		vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS;
 
 	return vma->obj;
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 1f7e6b9..52bc6c3 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -140,8 +140,7 @@
 #endif
 
 	/* Early VLV doesn't have this */
-	if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
-	    dev->pdev->revision < 0xb) {
+	if (IS_VALLEYVIEW(dev) && dev->pdev->revision < 0xb) {
 		DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n");
 		return 0;
 	}
@@ -770,10 +769,10 @@
 		gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length,
 					   scratch_pte);
 	} else {
-		uint64_t templ4, pml4e;
+		uint64_t pml4e;
 		struct i915_page_directory_pointer *pdp;
 
-		gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) {
+		gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
 			gen8_ppgtt_clear_pte_range(vm, pdp, start, length,
 						   scratch_pte);
 		}
@@ -839,10 +838,10 @@
 					      cache_level);
 	} else {
 		struct i915_page_directory_pointer *pdp;
-		uint64_t templ4, pml4e;
+		uint64_t pml4e;
 		uint64_t length = (uint64_t)pages->orig_nents << PAGE_SHIFT;
 
-		gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) {
+		gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
 			gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter,
 						      start, cache_level);
 		}
@@ -1020,10 +1019,9 @@
 {
 	struct drm_device *dev = vm->dev;
 	struct i915_page_table *pt;
-	uint64_t temp;
 	uint32_t pde;
 
-	gen8_for_each_pde(pt, pd, start, length, temp, pde) {
+	gen8_for_each_pde(pt, pd, start, length, pde) {
 		/* Don't reallocate page tables */
 		if (test_bit(pde, pd->used_pdes)) {
 			/* Scratch is never allocated this way */
@@ -1082,13 +1080,12 @@
 {
 	struct drm_device *dev = vm->dev;
 	struct i915_page_directory *pd;
-	uint64_t temp;
 	uint32_t pdpe;
 	uint32_t pdpes = I915_PDPES_PER_PDP(dev);
 
 	WARN_ON(!bitmap_empty(new_pds, pdpes));
 
-	gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
+	gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
 		if (test_bit(pdpe, pdp->used_pdpes))
 			continue;
 
@@ -1136,12 +1133,11 @@
 {
 	struct drm_device *dev = vm->dev;
 	struct i915_page_directory_pointer *pdp;
-	uint64_t temp;
 	uint32_t pml4e;
 
 	WARN_ON(!bitmap_empty(new_pdps, GEN8_PML4ES_PER_PML4));
 
-	gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) {
+	gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
 		if (!test_bit(pml4e, pml4->used_pml4es)) {
 			pdp = alloc_pdp(dev);
 			if (IS_ERR(pdp))
@@ -1225,7 +1221,6 @@
 	struct i915_page_directory *pd;
 	const uint64_t orig_start = start;
 	const uint64_t orig_length = length;
-	uint64_t temp;
 	uint32_t pdpe;
 	uint32_t pdpes = I915_PDPES_PER_PDP(dev);
 	int ret;
@@ -1252,7 +1247,7 @@
 	}
 
 	/* For every page directory referenced, allocate page tables */
-	gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
+	gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
 		ret = gen8_ppgtt_alloc_pagetabs(vm, pd, start, length,
 						new_page_tables + pdpe * BITS_TO_LONGS(I915_PDES));
 		if (ret)
@@ -1264,7 +1259,7 @@
 
 	/* Allocations have completed successfully, so set the bitmaps, and do
 	 * the mappings. */
-	gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
+	gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
 		gen8_pde_t *const page_directory = kmap_px(pd);
 		struct i915_page_table *pt;
 		uint64_t pd_len = length;
@@ -1274,7 +1269,7 @@
 		/* Every pd should be allocated, we just did that above. */
 		WARN_ON(!pd);
 
-		gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) {
+		gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
 			/* Same reasoning as pd */
 			WARN_ON(!pt);
 			WARN_ON(!pd_len);
@@ -1311,6 +1306,8 @@
 
 err_out:
 	while (pdpe--) {
+		unsigned long temp;
+
 		for_each_set_bit(temp, new_page_tables + pdpe *
 				BITS_TO_LONGS(I915_PDES), I915_PDES)
 			free_pt(dev, pdp->page_directory[pdpe]->page_table[temp]);
@@ -1333,7 +1330,7 @@
 	struct i915_hw_ppgtt *ppgtt =
 			container_of(vm, struct i915_hw_ppgtt, base);
 	struct i915_page_directory_pointer *pdp;
-	uint64_t temp, pml4e;
+	uint64_t pml4e;
 	int ret = 0;
 
 	/* Do the pml4 allocations first, so we don't need to track the newly
@@ -1352,7 +1349,7 @@
 	     "The allocation has spanned more than 512GB. "
 	     "It is highly likely this is incorrect.");
 
-	gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) {
+	gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
 		WARN_ON(!pdp);
 
 		ret = gen8_alloc_va_range_3lvl(vm, pdp, start, length);
@@ -1392,10 +1389,9 @@
 			  struct seq_file *m)
 {
 	struct i915_page_directory *pd;
-	uint64_t temp;
 	uint32_t pdpe;
 
-	gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
+	gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
 		struct i915_page_table *pt;
 		uint64_t pd_len = length;
 		uint64_t pd_start = start;
@@ -1405,7 +1401,7 @@
 			continue;
 
 		seq_printf(m, "\tPDPE #%d\n", pdpe);
-		gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) {
+		gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
 			uint32_t  pte;
 			gen8_pte_t *pt_vaddr;
 
@@ -1455,11 +1451,11 @@
 	if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
 		gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m);
 	} else {
-		uint64_t templ4, pml4e;
+		uint64_t pml4e;
 		struct i915_pml4 *pml4 = &ppgtt->pml4;
 		struct i915_page_directory_pointer *pdp;
 
-		gen8_for_each_pml4e(pdp, pml4, start, length, templ4, pml4e) {
+		gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
 			if (!test_bit(pml4e, pml4->used_pml4es))
 				continue;
 
@@ -2355,6 +2351,9 @@
 	int i = 0;
 	struct sg_page_iter sg_iter;
 	dma_addr_t addr = 0; /* shut up gcc */
+	int rpm_atomic_seq;
+
+	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
 	for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
 		addr = sg_dma_address(sg_iter.sg) +
@@ -2381,6 +2380,8 @@
 	 */
 	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
+
+	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 /*
@@ -2401,6 +2402,9 @@
 	int i = 0;
 	struct sg_page_iter sg_iter;
 	dma_addr_t addr = 0;
+	int rpm_atomic_seq;
+
+	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
 	for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
 		addr = sg_page_iter_dma_address(&sg_iter);
@@ -2425,6 +2429,8 @@
 	 */
 	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
+
+	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void gen8_ggtt_clear_range(struct i915_address_space *vm,
@@ -2439,6 +2445,9 @@
 		(gen8_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
 	const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
 	int i;
+	int rpm_atomic_seq;
+
+	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
 	if (WARN(num_entries > max_entries,
 		 "First entry = %d; Num entries = %d (max=%d)\n",
@@ -2451,6 +2460,8 @@
 	for (i = 0; i < num_entries; i++)
 		gen8_set_pte(&gtt_base[i], scratch_pte);
 	readl(gtt_base);
+
+	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void gen6_ggtt_clear_range(struct i915_address_space *vm,
@@ -2465,6 +2476,9 @@
 		(gen6_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
 	const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
 	int i;
+	int rpm_atomic_seq;
+
+	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
 	if (WARN(num_entries > max_entries,
 		 "First entry = %d; Num entries = %d (max=%d)\n",
@@ -2477,6 +2491,8 @@
 	for (i = 0; i < num_entries; i++)
 		iowrite32(scratch_pte, &gtt_base[i]);
 	readl(gtt_base);
+
+	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void i915_ggtt_insert_entries(struct i915_address_space *vm,
@@ -2484,11 +2500,17 @@
 				     uint64_t start,
 				     enum i915_cache_level cache_level, u32 unused)
 {
+	struct drm_i915_private *dev_priv = vm->dev->dev_private;
 	unsigned int flags = (cache_level == I915_CACHE_NONE) ?
 		AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
+	int rpm_atomic_seq;
+
+	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
 	intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags);
 
+	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
+
 }
 
 static void i915_ggtt_clear_range(struct i915_address_space *vm,
@@ -2496,9 +2518,16 @@
 				  uint64_t length,
 				  bool unused)
 {
+	struct drm_i915_private *dev_priv = vm->dev->dev_private;
 	unsigned first_entry = start >> PAGE_SHIFT;
 	unsigned num_entries = length >> PAGE_SHIFT;
+	int rpm_atomic_seq;
+
+	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
+
 	intel_gtt_clear_range(first_entry, num_entries);
+
+	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static int ggtt_bind_vma(struct i915_vma *vma,
@@ -2699,6 +2728,7 @@
 			return ret;
 		}
 		vma->bound |= GLOBAL_BIND;
+		__i915_vma_set_map_and_fenceable(vma);
 		list_add_tail(&vma->mm_list, &ggtt_vm->inactive_list);
 	}
 
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 877c32c..b448ad8 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -455,32 +455,29 @@
  * between from start until start + length. On gen8+ it simply iterates
  * over every page directory entry in a page directory.
  */
-#define gen8_for_each_pde(pt, pd, start, length, temp, iter)		\
-	for (iter = gen8_pde_index(start); \
-	     length > 0 && iter < I915_PDES ? \
-			(pt = (pd)->page_table[iter]), 1 : 0; \
-	     iter++,				\
-	     temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT) - start,	\
-	     temp = min(temp, length),					\
-	     start += temp, length -= temp)
+#define gen8_for_each_pde(pt, pd, start, length, iter)			\
+	for (iter = gen8_pde_index(start);				\
+	     length > 0 && iter < I915_PDES &&				\
+		(pt = (pd)->page_table[iter], true);			\
+	     ({ u64 temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT);		\
+		    temp = min(temp - start, length);			\
+		    start += temp, length -= temp; }), ++iter)
 
-#define gen8_for_each_pdpe(pd, pdp, start, length, temp, iter)	\
-	for (iter = gen8_pdpe_index(start); \
-	     length > 0 && (iter < I915_PDPES_PER_PDP(dev)) ? \
-			(pd = (pdp)->page_directory[iter]), 1 : 0; \
-	     iter++,				\
-	     temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT) - start,	\
-	     temp = min(temp, length),					\
-	     start += temp, length -= temp)
+#define gen8_for_each_pdpe(pd, pdp, start, length, iter)		\
+	for (iter = gen8_pdpe_index(start);				\
+	     length > 0 && iter < I915_PDPES_PER_PDP(dev) &&		\
+		(pd = (pdp)->page_directory[iter], true);		\
+	     ({ u64 temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT);	\
+		    temp = min(temp - start, length);			\
+		    start += temp, length -= temp; }), ++iter)
 
-#define gen8_for_each_pml4e(pdp, pml4, start, length, temp, iter)	\
-	for (iter = gen8_pml4e_index(start);	\
-	     length > 0 && iter < GEN8_PML4ES_PER_PML4 ? \
-			(pdp = (pml4)->pdps[iter]), 1 : 0; \
-	     iter++,				\
-	     temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT) - start,	\
-	     temp = min(temp, length),					\
-	     start += temp, length -= temp)
+#define gen8_for_each_pml4e(pdp, pml4, start, length, iter)		\
+	for (iter = gen8_pml4e_index(start);				\
+	     length > 0 && iter < GEN8_PML4ES_PER_PML4 &&		\
+		(pdp = (pml4)->pdps[iter], true);			\
+	     ({ u64 temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT);	\
+		    temp = min(temp - start, length);			\
+		    start += temp, length -= temp; }), ++iter)
 
 static inline uint32_t gen8_pte_index(uint64_t address)
 {
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c
index 5026a62..fc7e6d5 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.c
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.c
@@ -103,7 +103,7 @@
 	if (ret)
 		return ret;
 
-	page = sg_page(so->obj->pages->sgl);
+	page = i915_gem_object_get_dirty_page(so->obj, 0);
 	d = kmap(page);
 
 	while (i < rodata->batch_items) {
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 598ed2f..3476877 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -688,6 +688,7 @@
 		}
 
 		vma->bound |= GLOBAL_BIND;
+		__i915_vma_set_map_and_fenceable(vma);
 		list_add_tail(&vma->mm_list, &ggtt->inactive_list);
 	}
 
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 0d23785b..05aa7e6 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -568,7 +568,7 @@
 	WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
 	WARN_ON(!i915_gem_obj_is_pinned(rb_obj));
 
-	page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+	page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
 	reg_state = kmap_atomic(page);
 
 	reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index e88d692..3f8c753 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -581,7 +581,7 @@
 {
 	u32 enable_mask;
 
-	if (IS_VALLEYVIEW(dev_priv->dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
 							   status_mask);
 	else
@@ -595,7 +595,7 @@
 {
 	u32 enable_mask;
 
-	if (IS_VALLEYVIEW(dev_priv->dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
 							   status_mask);
 	else
@@ -1103,6 +1103,14 @@
 		spin_unlock_irq(&dev_priv->irq_lock);
 		return;
 	}
+
+	/*
+	 * The RPS work is synced during runtime suspend, we don't require a
+	 * wakeref. TODO: instead of disabling the asserts make sure that we
+	 * always hold an RPM reference while the work is running.
+	 */
+	DISABLE_RPM_WAKEREF_ASSERTS(dev_priv);
+
 	pm_iir = dev_priv->rps.pm_iir;
 	dev_priv->rps.pm_iir = 0;
 	/* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */
@@ -1115,7 +1123,7 @@
 	WARN_ON(pm_iir & ~dev_priv->pm_rps_events);
 
 	if ((pm_iir & dev_priv->pm_rps_events) == 0 && !client_boost)
-		return;
+		goto out;
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 
@@ -1170,6 +1178,8 @@
 	intel_set_rps(dev_priv->dev, new_delay);
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
+out:
+	ENABLE_RPM_WAKEREF_ASSERTS(dev_priv);
 }
 
 
@@ -1723,7 +1733,7 @@
 	 */
 	POSTING_READ(PORT_HOTPLUG_STAT);
 
-	if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
+	if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
 
 		if (hotplug_trigger) {
@@ -1758,6 +1768,9 @@
 	if (!intel_irqs_enabled(dev_priv))
 		return IRQ_NONE;
 
+	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	while (true) {
 		/* Find, clear, then process each source of interrupt */
 
@@ -1792,6 +1805,8 @@
 	}
 
 out:
+	enable_rpm_wakeref_asserts(dev_priv);
+
 	return ret;
 }
 
@@ -1805,6 +1820,9 @@
 	if (!intel_irqs_enabled(dev_priv))
 		return IRQ_NONE;
 
+	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	for (;;) {
 		master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
 		iir = I915_READ(VLV_IIR);
@@ -1835,6 +1853,8 @@
 		POSTING_READ(GEN8_MASTER_IRQ);
 	}
 
+	enable_rpm_wakeref_asserts(dev_priv);
+
 	return ret;
 }
 
@@ -2165,6 +2185,9 @@
 	if (!intel_irqs_enabled(dev_priv))
 		return IRQ_NONE;
 
+	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	/* We get interrupts on unclaimed registers, so check for this before we
 	 * do any I915_{READ,WRITE}. */
 	intel_uncore_check_errors(dev);
@@ -2223,6 +2246,9 @@
 		POSTING_READ(SDEIER);
 	}
 
+	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
+	enable_rpm_wakeref_asserts(dev_priv);
+
 	return ret;
 }
 
@@ -2255,6 +2281,9 @@
 	if (!intel_irqs_enabled(dev_priv))
 		return IRQ_NONE;
 
+	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	if (INTEL_INFO(dev_priv)->gen >= 9)
 		aux_mask |=  GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
 			GEN9_AUX_CHANNEL_D;
@@ -2262,7 +2291,7 @@
 	master_ctl = I915_READ_FW(GEN8_MASTER_IRQ);
 	master_ctl &= ~GEN8_MASTER_IRQ_CONTROL;
 	if (!master_ctl)
-		return IRQ_NONE;
+		goto out;
 
 	I915_WRITE_FW(GEN8_MASTER_IRQ, 0);
 
@@ -2393,6 +2422,9 @@
 	I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
 	POSTING_READ_FW(GEN8_MASTER_IRQ);
 
+out:
+	enable_rpm_wakeref_asserts(dev_priv);
+
 	return ret;
 }
 
@@ -2989,6 +3021,13 @@
 	if (!i915.enable_hangcheck)
 		return;
 
+	/*
+	 * The hangcheck work is synced during runtime suspend, we don't
+	 * require a wakeref. TODO: instead of disabling the asserts make
+	 * sure that we hold a reference when this work is running.
+	 */
+	DISABLE_RPM_WAKEREF_ASSERTS(dev_priv);
+
 	for_each_ring(ring, dev_priv, i) {
 		u64 acthd;
 		u32 seqno;
@@ -3080,13 +3119,18 @@
 		}
 	}
 
-	if (rings_hung)
-		return i915_handle_error(dev, true, "Ring hung");
+	if (rings_hung) {
+		i915_handle_error(dev, true, "Ring hung");
+		goto out;
+	}
 
 	if (busy_count)
 		/* Reset timer case chip hangs without another request
 		 * being added */
 		i915_queue_hangcheck(dev);
+
+out:
+	ENABLE_RPM_WAKEREF_ASSERTS(dev_priv);
 }
 
 void i915_queue_hangcheck(struct drm_device *dev)
@@ -3878,13 +3922,18 @@
 	u16 flip_mask =
 		I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
 		I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+	irqreturn_t ret;
 
 	if (!intel_irqs_enabled(dev_priv))
 		return IRQ_NONE;
 
+	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
+	disable_rpm_wakeref_asserts(dev_priv);
+
+	ret = IRQ_NONE;
 	iir = I915_READ16(IIR);
 	if (iir == 0)
-		return IRQ_NONE;
+		goto out;
 
 	while (iir & ~flip_mask) {
 		/* Can't rely on pipestat interrupt bit in iir as it might
@@ -3933,8 +3982,12 @@
 
 		iir = new_iir;
 	}
+	ret = IRQ_HANDLED;
 
-	return IRQ_HANDLED;
+out:
+	enable_rpm_wakeref_asserts(dev_priv);
+
+	return ret;
 }
 
 static void i8xx_irq_uninstall(struct drm_device * dev)
@@ -4063,6 +4116,9 @@
 	if (!intel_irqs_enabled(dev_priv))
 		return IRQ_NONE;
 
+	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	iir = I915_READ(IIR);
 	do {
 		bool irq_received = (iir & ~flip_mask) != 0;
@@ -4145,6 +4201,8 @@
 		iir = new_iir;
 	} while (iir & ~flip_mask);
 
+	enable_rpm_wakeref_asserts(dev_priv);
+
 	return ret;
 }
 
@@ -4284,6 +4342,9 @@
 	if (!intel_irqs_enabled(dev_priv))
 		return IRQ_NONE;
 
+	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
+	disable_rpm_wakeref_asserts(dev_priv);
+
 	iir = I915_READ(IIR);
 
 	for (;;) {
@@ -4369,6 +4430,8 @@
 		iir = new_iir;
 	}
 
+	enable_rpm_wakeref_asserts(dev_priv);
+
 	return ret;
 }
 
@@ -4412,7 +4475,7 @@
 	INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
 
 	/* Let's track the enabled rps events */
-	if (IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
+	if (IS_VALLEYVIEW(dev_priv))
 		/* WaGsvRC0ResidencyMethod:vlv */
 		dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED;
 	else
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 1dae5ac..007ae83 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -7327,6 +7327,7 @@
 #define  SBI_READY			(0x0<<0)
 
 /* SBI offsets */
+#define  SBI_SSCDIVINTPHASE			0x0200
 #define  SBI_SSCDIVINTPHASE6			0x0600
 #define   SBI_SSCDIVINTPHASE_DIVSEL_MASK	((0x7f)<<1)
 #define   SBI_SSCDIVINTPHASE_DIVSEL(x)		((x)<<1)
@@ -7334,6 +7335,7 @@
 #define   SBI_SSCDIVINTPHASE_INCVAL(x)		((x)<<8)
 #define   SBI_SSCDIVINTPHASE_DIR(x)		((x)<<15)
 #define   SBI_SSCDIVINTPHASE_PROPAGATE		(1<<0)
+#define  SBI_SSCDITHPHASE			0x0204
 #define  SBI_SSCCTL				0x020c
 #define  SBI_SSCCTL6				0x060C
 #define   SBI_SSCCTL_PATHALT			(1<<3)
@@ -8100,9 +8102,7 @@
 #define  RGB_FLIP_TO_BGR				(1 << 2)
 
 #define  BXT_PIPE_SELECT_MASK				(7 << 7)
-#define  BXT_PIPE_SELECT_C				(2 << 7)
-#define  BXT_PIPE_SELECT_B				(1 << 7)
-#define  BXT_PIPE_SELECT_A				(0 << 7)
+#define  BXT_PIPE_SELECT(pipe)				((pipe) << 7)
 
 #define _MIPIA_DATA_ADDRESS		(dev_priv->mipi_mmio_base + 0xb108)
 #define _MIPIC_DATA_ADDRESS		(dev_priv->mipi_mmio_base + 0xb908)
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 2d91821..a2aa09c 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -49,7 +49,7 @@
 		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
 		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
 		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
-	} else if (!IS_VALLEYVIEW(dev)) {
+	} else if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
 		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
 		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
 		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
@@ -84,7 +84,7 @@
 		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
 		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
 		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
-	} else if (!IS_VALLEYVIEW(dev)) {
+	} else if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
 		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
 		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
 		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index f929c61..37e3f0d 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -49,7 +49,7 @@
 	intel_runtime_pm_get(dev_priv);
 
 	/* On VLV and CHV, residency time is in CZ units rather than 1.28us */
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		units = 1;
 		div = dev_priv->czclk_freq;
 
@@ -284,7 +284,7 @@
 	intel_runtime_pm_get(dev_priv);
 
 	mutex_lock(&dev_priv->rps.hw_lock);
-	if (IS_VALLEYVIEW(dev_priv->dev)) {
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		u32 freq;
 		freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
 		ret = intel_gpu_freq(dev_priv, (freq >> 8) & 0xff);
@@ -598,7 +598,7 @@
 		if (ret)
 			DRM_ERROR("RC6p residency sysfs setup failed\n");
 	}
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		ret = sysfs_merge_group(&dev->primary->kdev->kobj,
 					&media_rc6_attr_group);
 		if (ret)
@@ -619,7 +619,7 @@
 	}
 
 	ret = 0;
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		ret = sysfs_create_files(&dev->primary->kdev->kobj, vlv_attrs);
 	else if (INTEL_INFO(dev)->gen >= 6)
 		ret = sysfs_create_files(&dev->primary->kdev->kobj, gen6_attrs);
@@ -635,7 +635,7 @@
 void i915_teardown_sysfs(struct drm_device *dev)
 {
 	sysfs_remove_bin_file(&dev->primary->kdev->kobj, &error_state_attr);
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		sysfs_remove_files(&dev->primary->kdev->kobj, vlv_attrs);
 	else
 		sysfs_remove_files(&dev->primary->kdev->kobj, gen6_attrs);
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 643f342..d0b1c9a 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -95,6 +95,8 @@
 
 	crtc_state->update_pipe = false;
 	crtc_state->disable_lp_wm = false;
+	crtc_state->disable_cxsr = false;
+	crtc_state->wm_changed = false;
 
 	return &crtc_state->base;
 }
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 9aa83e7..31f6d21 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -262,7 +262,8 @@
 	tmp |= AUD_CONFIG_N_PROG_ENABLE;
 	tmp &= ~AUD_CONFIG_UPPER_N_MASK;
 	tmp &= ~AUD_CONFIG_LOWER_N_MASK;
-	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
+	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+	    intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST))
 		tmp |= AUD_CONFIG_N_VALUE_INDEX;
 	I915_WRITE(HSW_AUD_CFG(pipe), tmp);
 
@@ -375,7 +376,7 @@
 	if (HAS_PCH_IBX(dev_priv->dev)) {
 		aud_config = IBX_AUD_CFG(pipe);
 		aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
-	} else if (IS_VALLEYVIEW(dev_priv)) {
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		aud_config = VLV_AUD_CFG(pipe);
 		aud_cntrl_st2 = VLV_AUD_CNTL_ST2;
 	} else {
@@ -435,7 +436,8 @@
 		aud_config = IBX_AUD_CFG(pipe);
 		aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
 		aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
-	} else if (IS_VALLEYVIEW(connector->dev)) {
+	} else if (IS_VALLEYVIEW(connector->dev) ||
+		   IS_CHERRYVIEW(connector->dev)) {
 		hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe);
 		aud_config = VLV_AUD_CFG(pipe);
 		aud_cntl_st = VLV_AUD_CNTL_ST(pipe);
@@ -474,7 +476,8 @@
 	tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
 	tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
 	tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
-	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
+	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+	    intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST))
 		tmp |= AUD_CONFIG_N_VALUE_INDEX;
 	else
 		tmp |= audio_config_hdmi_pixel_clock(adjusted_mode);
@@ -512,7 +515,8 @@
 
 	/* ELD Conn_Type */
 	connector->eld[5] &= ~(3 << 2);
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+	    intel_pipe_has_type(crtc, INTEL_OUTPUT_DP_MST))
 		connector->eld[5] |= (1 << 2);
 
 	connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
@@ -521,6 +525,10 @@
 		dev_priv->display.audio_codec_enable(connector, intel_encoder,
 						     adjusted_mode);
 
+	mutex_lock(&dev_priv->av_mutex);
+	intel_dig_port->audio_connector = connector;
+	mutex_unlock(&dev_priv->av_mutex);
+
 	if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
 		acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
 }
@@ -544,6 +552,10 @@
 	if (dev_priv->display.audio_codec_disable)
 		dev_priv->display.audio_codec_disable(intel_encoder);
 
+	mutex_lock(&dev_priv->av_mutex);
+	intel_dig_port->audio_connector = NULL;
+	mutex_unlock(&dev_priv->av_mutex);
+
 	if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
 		acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
 }
@@ -559,7 +571,7 @@
 	if (IS_G4X(dev)) {
 		dev_priv->display.audio_codec_enable = g4x_audio_codec_enable;
 		dev_priv->display.audio_codec_disable = g4x_audio_codec_disable;
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		dev_priv->display.audio_codec_enable = ilk_audio_codec_enable;
 		dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
 	} else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) {
@@ -628,15 +640,14 @@
 						int port, int rate)
 {
 	struct drm_i915_private *dev_priv = dev_to_i915(dev);
-	struct drm_device *drm_dev = dev_priv->dev;
 	struct intel_encoder *intel_encoder;
-	struct intel_digital_port *intel_dig_port;
 	struct intel_crtc *crtc;
 	struct drm_display_mode *mode;
 	struct i915_audio_component *acomp = dev_priv->audio_component;
-	enum pipe pipe = -1;
+	enum pipe pipe = INVALID_PIPE;
 	u32 tmp;
 	int n;
+	int err = 0;
 
 	/* HSW, BDW, SKL, KBL need this fix */
 	if (!IS_SKYLAKE(dev_priv) &&
@@ -647,26 +658,22 @@
 
 	mutex_lock(&dev_priv->av_mutex);
 	/* 1. get the pipe */
-	for_each_intel_encoder(drm_dev, intel_encoder) {
-		if (intel_encoder->type != INTEL_OUTPUT_HDMI)
-			continue;
-		intel_dig_port = enc_to_dig_port(&intel_encoder->base);
-		if (port == intel_dig_port->port) {
-			crtc = to_intel_crtc(intel_encoder->base.crtc);
-			if (!crtc) {
-				DRM_DEBUG_KMS("%s: crtc is NULL\n", __func__);
-				continue;
-			}
-			pipe = crtc->pipe;
-			break;
-		}
+	intel_encoder = dev_priv->dig_port_map[port];
+	/* intel_encoder might be NULL for DP MST */
+	if (!intel_encoder || !intel_encoder->base.crtc ||
+	    intel_encoder->type != INTEL_OUTPUT_HDMI) {
+		DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
+		err = -ENODEV;
+		goto unlock;
 	}
-
+	crtc = to_intel_crtc(intel_encoder->base.crtc);
+	pipe = crtc->pipe;
 	if (pipe == INVALID_PIPE) {
 		DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port));
-		mutex_unlock(&dev_priv->av_mutex);
-		return -ENODEV;
+		err = -ENODEV;
+		goto unlock;
 	}
+
 	DRM_DEBUG_KMS("pipe %c connects port %c\n",
 				  pipe_name(pipe), port_name(port));
 	mode = &crtc->config->base.adjusted_mode;
@@ -679,8 +686,7 @@
 		tmp = I915_READ(HSW_AUD_CFG(pipe));
 		tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
 		I915_WRITE(HSW_AUD_CFG(pipe), tmp);
-		mutex_unlock(&dev_priv->av_mutex);
-		return 0;
+		goto unlock;
 	}
 
 	n = audio_config_get_n(mode, rate);
@@ -690,8 +696,7 @@
 		tmp = I915_READ(HSW_AUD_CFG(pipe));
 		tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
 		I915_WRITE(HSW_AUD_CFG(pipe), tmp);
-		mutex_unlock(&dev_priv->av_mutex);
-		return 0;
+		goto unlock;
 	}
 
 	/* 3. set the N/CTS/M */
@@ -699,8 +704,37 @@
 	tmp = audio_config_setup_n_reg(n, tmp);
 	I915_WRITE(HSW_AUD_CFG(pipe), tmp);
 
+ unlock:
 	mutex_unlock(&dev_priv->av_mutex);
-	return 0;
+	return err;
+}
+
+static int i915_audio_component_get_eld(struct device *dev, int port,
+					bool *enabled,
+					unsigned char *buf, int max_bytes)
+{
+	struct drm_i915_private *dev_priv = dev_to_i915(dev);
+	struct intel_encoder *intel_encoder;
+	struct intel_digital_port *intel_dig_port;
+	const u8 *eld;
+	int ret = -EINVAL;
+
+	mutex_lock(&dev_priv->av_mutex);
+	intel_encoder = dev_priv->dig_port_map[port];
+	/* intel_encoder might be NULL for DP MST */
+	if (intel_encoder) {
+		ret = 0;
+		intel_dig_port = enc_to_dig_port(&intel_encoder->base);
+		*enabled = intel_dig_port->audio_connector != NULL;
+		if (*enabled) {
+			eld = intel_dig_port->audio_connector->eld;
+			ret = drm_eld_size(eld);
+			memcpy(buf, eld, min(max_bytes, ret));
+		}
+	}
+
+	mutex_unlock(&dev_priv->av_mutex);
+	return ret;
 }
 
 static const struct i915_audio_component_ops i915_audio_component_ops = {
@@ -710,6 +744,7 @@
 	.codec_wake_override = i915_audio_component_codec_wake_override,
 	.get_cdclk_freq	= i915_audio_component_get_cdclk_freq,
 	.sync_audio_rate = i915_audio_component_sync_audio_rate,
+	.get_eld	= i915_audio_component_get_eld,
 };
 
 static int i915_audio_component_bind(struct device *i915_dev,
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 070470f..eba3e0f 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -24,7 +24,7 @@
  *    Eric Anholt <eric@anholt.net>
  *
  */
-#include <linux/dmi.h>
+
 #include <drm/drm_dp_helper.h>
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
@@ -332,10 +332,10 @@
 	drm_mode_debug_printmodeline(panel_fixed_mode);
 }
 
-static int intel_bios_ssc_frequency(struct drm_device *dev,
+static int intel_bios_ssc_frequency(struct drm_i915_private *dev_priv,
 				    bool alternate)
 {
-	switch (INTEL_INFO(dev)->gen) {
+	switch (INTEL_INFO(dev_priv)->gen) {
 	case 2:
 		return alternate ? 66667 : 48000;
 	case 3:
@@ -350,29 +350,29 @@
 parse_general_features(struct drm_i915_private *dev_priv,
 		       const struct bdb_header *bdb)
 {
-	struct drm_device *dev = dev_priv->dev;
 	const struct bdb_general_features *general;
 
 	general = find_section(bdb, BDB_GENERAL_FEATURES);
-	if (general) {
-		dev_priv->vbt.int_tv_support = general->int_tv_support;
-		/* int_crt_support can't be trusted on earlier platforms */
-		if (bdb->version >= 155 &&
-		    (HAS_DDI(dev_priv) || IS_VALLEYVIEW(dev_priv)))
-			dev_priv->vbt.int_crt_support = general->int_crt_support;
-		dev_priv->vbt.lvds_use_ssc = general->enable_ssc;
-		dev_priv->vbt.lvds_ssc_freq =
-			intel_bios_ssc_frequency(dev, general->ssc_freq);
-		dev_priv->vbt.display_clock_mode = general->display_clock_mode;
-		dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
-		DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
-			      dev_priv->vbt.int_tv_support,
-			      dev_priv->vbt.int_crt_support,
-			      dev_priv->vbt.lvds_use_ssc,
-			      dev_priv->vbt.lvds_ssc_freq,
-			      dev_priv->vbt.display_clock_mode,
-			      dev_priv->vbt.fdi_rx_polarity_inverted);
-	}
+	if (!general)
+		return;
+
+	dev_priv->vbt.int_tv_support = general->int_tv_support;
+	/* int_crt_support can't be trusted on earlier platforms */
+	if (bdb->version >= 155 &&
+	    (HAS_DDI(dev_priv) || IS_VALLEYVIEW(dev_priv)))
+		dev_priv->vbt.int_crt_support = general->int_crt_support;
+	dev_priv->vbt.lvds_use_ssc = general->enable_ssc;
+	dev_priv->vbt.lvds_ssc_freq =
+		intel_bios_ssc_frequency(dev_priv, general->ssc_freq);
+	dev_priv->vbt.display_clock_mode = general->display_clock_mode;
+	dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
+	DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
+		      dev_priv->vbt.int_tv_support,
+		      dev_priv->vbt.int_crt_support,
+		      dev_priv->vbt.lvds_use_ssc,
+		      dev_priv->vbt.lvds_ssc_freq,
+		      dev_priv->vbt.display_clock_mode,
+		      dev_priv->vbt.fdi_rx_polarity_inverted);
 }
 
 static void
@@ -1057,10 +1057,9 @@
 static void parse_ddi_ports(struct drm_i915_private *dev_priv,
 			    const struct bdb_header *bdb)
 {
-	struct drm_device *dev = dev_priv->dev;
 	enum port port;
 
-	if (!HAS_DDI(dev))
+	if (!HAS_DDI(dev_priv))
 		return;
 
 	if (!dev_priv->vbt.child_dev_num)
@@ -1173,7 +1172,6 @@
 static void
 init_vbt_defaults(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
 	enum port port;
 
 	dev_priv->vbt.crt_ddc_pin = GMBUS_PIN_VGADDC;
@@ -1198,8 +1196,8 @@
 	 * Core/SandyBridge/IvyBridge use alternative (120MHz) reference
 	 * clock for LVDS.
 	 */
-	dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev,
-			!HAS_PCH_SPLIT(dev));
+	dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev_priv,
+			!HAS_PCH_SPLIT(dev_priv));
 	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++) {
@@ -1214,88 +1212,79 @@
 	}
 }
 
-static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
+static const struct bdb_header *get_bdb_header(const struct vbt_header *vbt)
 {
-	DRM_DEBUG_KMS("Falling back to manually reading VBT from "
-		      "VBIOS ROM for %s\n",
-		      id->ident);
-	return 1;
+	const void *_vbt = vbt;
+
+	return _vbt + vbt->bdb_offset;
 }
 
-static const struct dmi_system_id intel_no_opregion_vbt[] = {
-	{
-		.callback = intel_no_opregion_vbt_callback,
-		.ident = "ThinkCentre A57",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
-		},
-	},
-	{ }
-};
-
-static const struct bdb_header *validate_vbt(const void *base,
-					     size_t size,
-					     const void *_vbt,
-					     const char *source)
+/**
+ * intel_bios_is_valid_vbt - does the given buffer contain a valid VBT
+ * @buf:	pointer to a buffer to validate
+ * @size:	size of the buffer
+ *
+ * Returns true on valid VBT.
+ */
+bool intel_bios_is_valid_vbt(const void *buf, size_t size)
 {
-	size_t offset = _vbt - base;
-	const struct vbt_header *vbt = _vbt;
+	const struct vbt_header *vbt = buf;
 	const struct bdb_header *bdb;
 
-	if (offset + sizeof(struct vbt_header) > size) {
+	if (!vbt)
+		return false;
+
+	if (sizeof(struct vbt_header) > size) {
 		DRM_DEBUG_DRIVER("VBT header incomplete\n");
-		return NULL;
+		return false;
 	}
 
 	if (memcmp(vbt->signature, "$VBT", 4)) {
 		DRM_DEBUG_DRIVER("VBT invalid signature\n");
-		return NULL;
+		return false;
 	}
 
-	offset += vbt->bdb_offset;
-	if (offset + sizeof(struct bdb_header) > size) {
+	if (vbt->bdb_offset + sizeof(struct bdb_header) > size) {
 		DRM_DEBUG_DRIVER("BDB header incomplete\n");
-		return NULL;
+		return false;
 	}
 
-	bdb = base + offset;
-	if (offset + bdb->bdb_size > size) {
+	bdb = get_bdb_header(vbt);
+	if (vbt->bdb_offset + bdb->bdb_size > size) {
 		DRM_DEBUG_DRIVER("BDB incomplete\n");
-		return NULL;
+		return false;
 	}
 
-	DRM_DEBUG_KMS("Using VBT from %s: %20s\n",
-		      source, vbt->signature);
-	return bdb;
+	return vbt;
 }
 
-static const struct bdb_header *find_vbt(void __iomem *bios, size_t size)
+static const struct vbt_header *find_vbt(void __iomem *bios, size_t size)
 {
-	const struct bdb_header *bdb = NULL;
 	size_t i;
 
 	/* Scour memory looking for the VBT signature. */
 	for (i = 0; i + 4 < size; i++) {
-		if (ioread32(bios + i) == *((const u32 *) "$VBT")) {
-			/*
-			 * This is the one place where we explicitly discard the
-			 * address space (__iomem) of the BIOS/VBT. From now on
-			 * everything is based on 'base', and treated as regular
-			 * memory.
-			 */
-			void *_bios = (void __force *) bios;
+		void *vbt;
 
-			bdb = validate_vbt(_bios, size, _bios + i, "PCI ROM");
-			break;
-		}
+		if (ioread32(bios + i) != *((const u32 *) "$VBT"))
+			continue;
+
+		/*
+		 * This is the one place where we explicitly discard the address
+		 * space (__iomem) of the BIOS/VBT.
+		 */
+		vbt = (void __force *) bios + i;
+		if (intel_bios_is_valid_vbt(vbt, size - i))
+			return vbt;
+
+		break;
 	}
 
-	return bdb;
+	return NULL;
 }
 
 /**
- * intel_parse_bios - find VBT and initialize settings from the BIOS
+ * intel_bios_init - find VBT and initialize settings from the BIOS
  * @dev: DRM device
  *
  * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
@@ -1304,37 +1293,39 @@
  * Returns 0 on success, nonzero on failure.
  */
 int
-intel_parse_bios(struct drm_device *dev)
+intel_bios_init(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct pci_dev *pdev = dev->pdev;
-	const struct bdb_header *bdb = NULL;
+	struct pci_dev *pdev = dev_priv->dev->pdev;
+	const struct vbt_header *vbt = dev_priv->opregion.vbt;
+	const struct bdb_header *bdb;
 	u8 __iomem *bios = NULL;
 
-	if (HAS_PCH_NOP(dev))
+	if (HAS_PCH_NOP(dev_priv))
 		return -ENODEV;
 
 	init_vbt_defaults(dev_priv);
 
-	/* XXX Should this validation be moved to intel_opregion.c? */
-	if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt)
-		bdb = validate_vbt(dev_priv->opregion.header, OPREGION_SIZE,
-				   dev_priv->opregion.vbt, "OpRegion");
-
-	if (bdb == NULL) {
+	if (!vbt) {
 		size_t size;
 
 		bios = pci_map_rom(pdev, &size);
 		if (!bios)
 			return -1;
 
-		bdb = find_vbt(bios, size);
-		if (!bdb) {
+		vbt = find_vbt(bios, size);
+		if (!vbt) {
 			pci_unmap_rom(pdev, bios);
 			return -1;
 		}
+
+		DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n");
 	}
 
+	bdb = get_bdb_header(vbt);
+
+	DRM_DEBUG_KMS("VBT signature \"%.*s\", BDB version %d\n",
+		      (int)sizeof(vbt->signature), vbt->signature, bdb->version);
+
 	/* Grab useful general definitions */
 	parse_general_features(dev_priv, bdb);
 	parse_general_definitions(dev_priv, bdb);
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index 7ec8c9a..54eac10 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -28,8 +28,6 @@
 #ifndef _I830_BIOS_H_
 #define _I830_BIOS_H_
 
-#include <drm/drmP.h>
-
 struct vbt_header {
 	u8 signature[20];		/**< Always starts with 'VBT$' */
 	u16 version;			/**< decimal */
@@ -588,8 +586,6 @@
 	struct psr_table psr_table[16];
 } __packed;
 
-int intel_parse_bios(struct drm_device *dev);
-
 /*
  * Driver<->VBIOS interaction occurs through scratch bits in
  * GR18 & SWF*.
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 9285fc1..9c89df1 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -844,7 +844,7 @@
 	crt->adpa_reg = adpa_reg;
 
 	crt->base.compute_config = intel_crt_compute_config;
-	if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		crt->base.disable = pch_disable_crt;
 		crt->base.post_disable = pch_post_disable_crt;
 	} else {
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index 6c6a669..9bb63a8 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -166,6 +166,14 @@
 	char substepping;
 };
 
+/*
+ * Kabylake derivated from Skylake H0, so SKL H0
+ * is the right firmware for KBL A0 (revid 0).
+ */
+static const struct stepping_info kbl_stepping_info[] = {
+	{'H', '0'}, {'I', '0'}
+};
+
 static const struct stepping_info skl_stepping_info[] = {
 	{'A', '0'}, {'B', '0'}, {'C', '0'},
 	{'D', '0'}, {'E', '0'}, {'F', '0'},
@@ -182,7 +190,10 @@
 	const struct stepping_info *si;
 	unsigned int size;
 
-	if (IS_SKYLAKE(dev)) {
+	if (IS_KABYLAKE(dev)) {
+		size = ARRAY_SIZE(kbl_stepping_info);
+		si = kbl_stepping_info;
+	} else if (IS_SKYLAKE(dev)) {
 		size = ARRAY_SIZE(skl_stepping_info);
 		si = skl_stepping_info;
 	} else if (IS_BROXTON(dev)) {
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 4afb310..e6408e5 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -353,10 +353,10 @@
 {
 	const struct ddi_buf_trans *ddi_translations;
 
-	if (IS_SKL_ULX(dev)) {
+	if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) {
 		ddi_translations = skl_y_ddi_translations_dp;
 		*n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
-	} else if (IS_SKL_ULT(dev)) {
+	} else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) {
 		ddi_translations = skl_u_ddi_translations_dp;
 		*n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp);
 	} else {
@@ -373,7 +373,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	const struct ddi_buf_trans *ddi_translations;
 
-	if (IS_SKL_ULX(dev)) {
+	if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) {
 		if (dev_priv->edp_low_vswing) {
 			ddi_translations = skl_y_ddi_translations_edp;
 			*n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp);
@@ -381,7 +381,7 @@
 			ddi_translations = skl_y_ddi_translations_dp;
 			*n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
 		}
-	} else if (IS_SKL_ULT(dev)) {
+	} else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) {
 		if (dev_priv->edp_low_vswing) {
 			ddi_translations = skl_u_ddi_translations_edp;
 			*n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp);
@@ -408,7 +408,7 @@
 {
 	const struct ddi_buf_trans *ddi_translations;
 
-	if (IS_SKL_ULX(dev)) {
+	if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) {
 		ddi_translations = skl_y_ddi_translations_hdmi;
 		*n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi);
 	} else {
@@ -675,15 +675,16 @@
 		temp = I915_READ(DP_TP_STATUS(PORT_E));
 		if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) {
 			DRM_DEBUG_KMS("FDI link training done on step %d\n", i);
+			break;
+		}
 
-			/* Enable normal pixel sending for FDI */
-			I915_WRITE(DP_TP_CTL(PORT_E),
-				   DP_TP_CTL_FDI_AUTOTRAIN |
-				   DP_TP_CTL_LINK_TRAIN_NORMAL |
-				   DP_TP_CTL_ENHANCED_FRAME_ENABLE |
-				   DP_TP_CTL_ENABLE);
-
-			return;
+		/*
+		 * Leave things enabled even if we failed to train FDI.
+		 * Results in less fireworks from the state checker.
+		 */
+		if (i == ARRAY_SIZE(hsw_ddi_translations_fdi) * 2 - 1) {
+			DRM_ERROR("FDI link training failed!\n");
+			break;
 		}
 
 		temp = I915_READ(DDI_BUF_CTL(PORT_E));
@@ -712,7 +713,12 @@
 		POSTING_READ(FDI_RX_MISC(PIPE_A));
 	}
 
-	DRM_ERROR("FDI link training failed!\n");
+	/* Enable normal pixel sending for FDI */
+	I915_WRITE(DP_TP_CTL(PORT_E),
+		   DP_TP_CTL_FDI_AUTOTRAIN |
+		   DP_TP_CTL_LINK_TRAIN_NORMAL |
+		   DP_TP_CTL_ENHANCED_FRAME_ENABLE |
+		   DP_TP_CTL_ENABLE);
 }
 
 void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder)
@@ -3108,6 +3114,19 @@
 	I915_WRITE(FDI_RX_CTL(PIPE_A), val);
 }
 
+bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
+				 struct intel_crtc *intel_crtc)
+{
+	u32 temp;
+
+	if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
+		temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
+		if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe))
+			return true;
+	}
+	return false;
+}
+
 void intel_ddi_get_config(struct intel_encoder *encoder,
 			  struct intel_crtc_state *pipe_config)
 {
@@ -3168,11 +3187,8 @@
 		break;
 	}
 
-	if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
-		temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
-		if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe))
-			pipe_config->has_audio = true;
-	}
+	pipe_config->has_audio =
+		intel_ddi_is_audio_enabled(dev_priv, intel_crtc);
 
 	if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp &&
 	    pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
@@ -3295,6 +3311,7 @@
 	intel_encoder->get_config = intel_ddi_get_config;
 
 	intel_dig_port->port = port;
+	dev_priv->dig_port_map[port] = intel_encoder;
 	intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
 					  (DDI_BUF_PORT_REVERSAL |
 					   DDI_A_4_LANES);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1e3461f..ceaea7a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -118,6 +118,7 @@
 static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
 static void ironlake_pfit_enable(struct intel_crtc *crtc);
 static void intel_modeset_setup_hw_state(struct drm_device *dev);
+static void intel_pre_disable_primary(struct drm_crtc *crtc);
 
 typedef struct {
 	int	min, max;
@@ -187,7 +188,7 @@
 	uint32_t clkcfg;
 
 	/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		return 200;
 
 	clkcfg = I915_READ(CLKCFG);
@@ -215,7 +216,7 @@
 
 static void intel_update_czclk(struct drm_i915_private *dev_priv)
 {
-	if (!IS_VALLEYVIEW(dev_priv))
+	if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
 		return;
 
 	dev_priv->czclk_freq = vlv_get_cck_clock_hpll(dev_priv, "czclk",
@@ -716,11 +717,12 @@
 	if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
 		INTELPllInvalid("m1 out of range\n");
 
-	if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) && !IS_BROXTON(dev))
+	if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) &&
+	    !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev))
 		if (clock->m1 <= clock->m2)
 			INTELPllInvalid("m1 <= m2\n");
 
-	if (!IS_VALLEYVIEW(dev) && !IS_BROXTON(dev)) {
+	if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) {
 		if (clock->p < limit->p.min || limit->p.max < clock->p)
 			INTELPllInvalid("p out of range\n");
 		if (clock->m < limit->m.min || limit->m.max < clock->m)
@@ -1305,7 +1307,7 @@
 		    I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
 			panel_pipe = PIPE_B;
 		/* XXX: else fix for eDP */
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		/* presumably write lock depends on pipe, not port select */
 		pp_reg = VLV_PIPE_PP_CONTROL(pipe);
 		panel_pipe = pipe;
@@ -1423,7 +1425,7 @@
 			     "plane %d assertion failure, should be off on pipe %c but is still active\n",
 			     sprite, pipe_name(pipe));
 		}
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		for_each_sprite(dev_priv, pipe, sprite) {
 			u32 val = I915_READ(SPCNTR(pipe, sprite));
 			I915_STATE_WARN(val & SP_ENABLE,
@@ -1606,9 +1608,6 @@
 
 	assert_pipe_disabled(dev_priv, crtc->pipe);
 
-	/* No really, not for ILK+ */
-	BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
-
 	/* PLL is protected by panel, make sure we can write it */
 	if (IS_MOBILE(dev_priv->dev))
 		assert_panel_unlocked(dev_priv, crtc->pipe);
@@ -1646,8 +1645,6 @@
 
 	assert_pipe_disabled(dev_priv, crtc->pipe);
 
-	BUG_ON(!IS_CHERRYVIEW(dev_priv->dev));
-
 	mutex_lock(&dev_priv->sb_lock);
 
 	/* Enable back the 10bit clock to display controller */
@@ -2319,7 +2316,7 @@
 	if (INTEL_INFO(dev_priv)->gen >= 9)
 		return 256 * 1024;
 	else if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv) ||
-		 IS_VALLEYVIEW(dev_priv))
+		 IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		return 128 * 1024;
 	else if (INTEL_INFO(dev_priv)->gen >= 4)
 		return 4 * 1024;
@@ -2599,6 +2596,8 @@
 	struct drm_i915_gem_object *obj;
 	struct drm_plane *primary = intel_crtc->base.primary;
 	struct drm_plane_state *plane_state = primary->state;
+	struct drm_crtc_state *crtc_state = intel_crtc->base.state;
+	struct intel_plane *intel_plane = to_intel_plane(primary);
 	struct drm_framebuffer *fb;
 
 	if (!plane_config->fb)
@@ -2635,6 +2634,18 @@
 		}
 	}
 
+	/*
+	 * We've failed to reconstruct the BIOS FB.  Current display state
+	 * indicates that the primary plane is visible, but has a NULL FB,
+	 * which will lead to problems later if we don't fix it up.  The
+	 * simplest solution is to just disable the primary plane now and
+	 * pretend the BIOS never had it enabled.
+	 */
+	to_intel_plane_state(plane_state)->visible = false;
+	crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
+	intel_pre_disable_primary(&intel_crtc->base);
+	intel_plane->disable_plane(primary, &intel_crtc->base);
+
 	return;
 
 valid_fb:
@@ -3940,6 +3951,21 @@
 	return 0;
 }
 
+static void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
+{
+	u32 temp;
+
+	I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
+
+	mutex_lock(&dev_priv->sb_lock);
+
+	temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
+	temp |= SBI_SSCCTL_DISABLE;
+	intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
+
+	mutex_unlock(&dev_priv->sb_lock);
+}
+
 /* Program iCLKIP clock to the desired frequency */
 static void lpt_program_iclkip(struct drm_crtc *crtc)
 {
@@ -3949,18 +3975,7 @@
 	u32 divsel, phaseinc, auxdiv, phasedir = 0;
 	u32 temp;
 
-	mutex_lock(&dev_priv->sb_lock);
-
-	/* It is necessary to ungate the pixclk gate prior to programming
-	 * the divisors, and gate it back when it is done.
-	 */
-	I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
-
-	/* Disable SSCCTL */
-	intel_sbi_write(dev_priv, SBI_SSCCTL6,
-			intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK) |
-				SBI_SSCCTL_DISABLE,
-			SBI_ICLK);
+	lpt_disable_iclkip(dev_priv);
 
 	/* 20MHz is a corner case which is out of range for the 7-bit divisor */
 	if (clock == 20000) {
@@ -3978,7 +3993,7 @@
 		u32 iclk_pi_range = 64;
 		u32 desired_divisor, msb_divisor_value, pi_value;
 
-		desired_divisor = (iclk_virtual_root_freq / clock);
+		desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, clock);
 		msb_divisor_value = desired_divisor / iclk_pi_range;
 		pi_value = desired_divisor % iclk_pi_range;
 
@@ -4000,6 +4015,8 @@
 			phasedir,
 			phaseinc);
 
+	mutex_lock(&dev_priv->sb_lock);
+
 	/* Program SSCDIVINTPHASE6 */
 	temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
 	temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK;
@@ -4021,12 +4038,12 @@
 	temp &= ~SBI_SSCCTL_DISABLE;
 	intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
 
+	mutex_unlock(&dev_priv->sb_lock);
+
 	/* Wait for initialization time */
 	udelay(24);
 
 	I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
-
-	mutex_unlock(&dev_priv->sb_lock);
 }
 
 static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
@@ -4709,14 +4726,6 @@
 	int pipe = intel_crtc->pipe;
 
 	/*
-	 * BDW signals flip done immediately if the plane
-	 * is disabled, even if the plane enable is already
-	 * armed to occur at the next vblank :(
-	 */
-	if (IS_BROADWELL(dev))
-		intel_wait_for_vblank(dev, pipe);
-
-	/*
 	 * FIXME IPS should be fine as long as one plane is
 	 * enabled, but in practice it seems to have problems
 	 * when going from primary only to sprite only and vice
@@ -4793,6 +4802,8 @@
 static void intel_post_plane_update(struct intel_crtc *crtc)
 {
 	struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
+	struct intel_crtc_state *pipe_config =
+		to_intel_crtc_state(crtc->base.state);
 	struct drm_device *dev = crtc->base.dev;
 
 	if (atomic->wait_vblank)
@@ -4800,10 +4811,9 @@
 
 	intel_frontbuffer_flip(dev, atomic->fb_bits);
 
-	if (atomic->disable_cxsr)
-		crtc->wm.cxsr_allowed = true;
+	crtc->wm.cxsr_allowed = true;
 
-	if (crtc->atomic.update_wm_post)
+	if (pipe_config->wm_changed && pipe_config->base.active)
 		intel_update_watermarks(&crtc->base);
 
 	if (atomic->update_fbc)
@@ -4820,6 +4830,8 @@
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
+	struct intel_crtc_state *pipe_config =
+		to_intel_crtc_state(crtc->base.state);
 
 	if (atomic->disable_fbc)
 		intel_fbc_deactivate(crtc);
@@ -4830,10 +4842,13 @@
 	if (atomic->pre_disable_primary)
 		intel_pre_disable_primary(&crtc->base);
 
-	if (atomic->disable_cxsr) {
+	if (pipe_config->disable_cxsr) {
 		crtc->wm.cxsr_allowed = false;
 		intel_set_memory_cxsr(dev_priv, false);
 	}
+
+	if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed)
+		intel_update_watermarks(&crtc->base);
 }
 
 static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask)
@@ -5166,18 +5181,18 @@
 	if (!intel_crtc->config->has_dsi_encoder)
 		intel_ddi_disable_pipe_clock(intel_crtc);
 
-	if (intel_crtc->config->has_pch_encoder) {
-		lpt_disable_pch_transcoder(dev_priv);
-		intel_ddi_fdi_disable(crtc);
-	}
-
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->post_disable)
 			encoder->post_disable(encoder);
 
-	if (intel_crtc->config->has_pch_encoder)
+	if (intel_crtc->config->has_pch_encoder) {
+		lpt_disable_pch_transcoder(dev_priv);
+		lpt_disable_iclkip(dev_priv);
+		intel_ddi_fdi_disable(crtc);
+
 		intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
 						      true);
+	}
 
 	intel_fbc_disable_crtc(intel_crtc);
 }
@@ -5457,7 +5472,7 @@
 	 * BSpec erroneously claims we should aim for 4MHz, but
 	 * in fact 1MHz is the correct frequency.
 	 */
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		/*
 		 * Program the gmbus_freq based on the cdclk frequency.
 		 * BSpec erroneously claims we should aim for 4MHz, but
@@ -6354,9 +6369,11 @@
 		WARN_ON(intel_crtc->unpin_work);
 
 		intel_pre_disable_primary(crtc);
+
+		intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
+		to_intel_plane_state(crtc->primary->state)->visible = false;
 	}
 
-	intel_crtc_disable_planes(crtc, crtc->state->plane_mask);
 	dev_priv->display.crtc_disable(crtc);
 	intel_crtc->active = false;
 	intel_update_watermarks(crtc);
@@ -7180,7 +7197,7 @@
 
 	WARN_ON(!crtc_state->base.state);
 
-	if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) {
 		refclk = 100000;
 	} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
 	    intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
@@ -7879,7 +7896,7 @@
 		pipeconf |= PIPECONF_DOUBLE_WIDE;
 
 	/* only g4x and later have fancy bpc/dither controls */
-	if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
+	if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		/* Bspec claims that we can't use dithering for 30bpp pipes. */
 		if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30)
 			pipeconf |= PIPECONF_DITHER_EN |
@@ -7919,7 +7936,8 @@
 	} else
 		pipeconf |= PIPECONF_PROGRESSIVE;
 
-	if (IS_VALLEYVIEW(dev) && intel_crtc->config->limited_color_range)
+	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+	     intel_crtc->config->limited_color_range)
 		pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
 
 	I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf);
@@ -8166,7 +8184,7 @@
 	if (!(tmp & PIPECONF_ENABLE))
 		return false;
 
-	if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
+	if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		switch (tmp & PIPECONF_BPC_MASK) {
 		case PIPECONF_6BPC:
 			pipe_config->pipe_bpp = 18;
@@ -8182,7 +8200,8 @@
 		}
 	}
 
-	if (IS_VALLEYVIEW(dev) && (tmp & PIPECONF_COLOR_RANGE_SELECT))
+	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+	    (tmp & PIPECONF_COLOR_RANGE_SELECT))
 		pipe_config->limited_color_range = true;
 
 	if (INTEL_INFO(dev)->gen < 4)
@@ -8210,7 +8229,7 @@
 		pipe_config->pixel_multiplier = 1;
 	}
 	pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
-	if (!IS_VALLEYVIEW(dev)) {
+	if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
 		/*
 		 * DPLL_DVO_2X_MODE must be enabled for both DPLLs
 		 * on 830. Filter it out here so that we don't
@@ -8562,6 +8581,67 @@
 	mutex_unlock(&dev_priv->sb_lock);
 }
 
+#define BEND_IDX(steps) ((50 + (steps)) / 5)
+
+static const uint16_t sscdivintphase[] = {
+	[BEND_IDX( 50)] = 0x3B23,
+	[BEND_IDX( 45)] = 0x3B23,
+	[BEND_IDX( 40)] = 0x3C23,
+	[BEND_IDX( 35)] = 0x3C23,
+	[BEND_IDX( 30)] = 0x3D23,
+	[BEND_IDX( 25)] = 0x3D23,
+	[BEND_IDX( 20)] = 0x3E23,
+	[BEND_IDX( 15)] = 0x3E23,
+	[BEND_IDX( 10)] = 0x3F23,
+	[BEND_IDX(  5)] = 0x3F23,
+	[BEND_IDX(  0)] = 0x0025,
+	[BEND_IDX( -5)] = 0x0025,
+	[BEND_IDX(-10)] = 0x0125,
+	[BEND_IDX(-15)] = 0x0125,
+	[BEND_IDX(-20)] = 0x0225,
+	[BEND_IDX(-25)] = 0x0225,
+	[BEND_IDX(-30)] = 0x0325,
+	[BEND_IDX(-35)] = 0x0325,
+	[BEND_IDX(-40)] = 0x0425,
+	[BEND_IDX(-45)] = 0x0425,
+	[BEND_IDX(-50)] = 0x0525,
+};
+
+/*
+ * Bend CLKOUT_DP
+ * steps -50 to 50 inclusive, in steps of 5
+ * < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz)
+ * change in clock period = -(steps / 10) * 5.787 ps
+ */
+static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
+{
+	uint32_t tmp;
+	int idx = BEND_IDX(steps);
+
+	if (WARN_ON(steps % 5 != 0))
+		return;
+
+	if (WARN_ON(idx >= ARRAY_SIZE(sscdivintphase)))
+		return;
+
+	mutex_lock(&dev_priv->sb_lock);
+
+	if (steps % 10 != 0)
+		tmp = 0xAAAAAAAB;
+	else
+		tmp = 0x00000000;
+	intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK);
+
+	tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK);
+	tmp &= 0xffff0000;
+	tmp |= sscdivintphase[idx];
+	intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK);
+
+	mutex_unlock(&dev_priv->sb_lock);
+}
+
+#undef BEND_IDX
+
 static void lpt_init_pch_refclk(struct drm_device *dev)
 {
 	struct intel_encoder *encoder;
@@ -8577,10 +8657,12 @@
 		}
 	}
 
-	if (has_vga)
+	if (has_vga) {
+		lpt_bend_clkout_dp(to_i915(dev), 0);
 		lpt_enable_clkout_dp(dev, true, true);
-	else
+	} else {
 		lpt_disable_clkout_dp(dev);
+	}
 }
 
 /*
@@ -9944,14 +10026,14 @@
 	return true;
 }
 
-static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
+static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	uint32_t cntl = 0, size = 0;
 
-	if (base) {
+	if (on) {
 		unsigned int width = intel_crtc->base.cursor->state->crtc_w;
 		unsigned int height = intel_crtc->base.cursor->state->crtc_h;
 		unsigned int stride = roundup_pow_of_two(width) * 4;
@@ -10006,16 +10088,15 @@
 	}
 }
 
-static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
+static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	uint32_t cntl;
+	uint32_t cntl = 0;
 
-	cntl = 0;
-	if (base) {
+	if (on) {
 		cntl = MCURSOR_GAMMA_ENABLE;
 		switch (intel_crtc->base.cursor->state->crtc_w) {
 			case 64:
@@ -10066,18 +10147,17 @@
 	int y = cursor_state->crtc_y;
 	u32 base = 0, pos = 0;
 
-	if (on)
-		base = intel_crtc->cursor_addr;
+	base = intel_crtc->cursor_addr;
 
 	if (x >= intel_crtc->config->pipe_src_w)
-		base = 0;
+		on = false;
 
 	if (y >= intel_crtc->config->pipe_src_h)
-		base = 0;
+		on = false;
 
 	if (x < 0) {
 		if (x + cursor_state->crtc_w <= 0)
-			base = 0;
+			on = false;
 
 		pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
 		x = -x;
@@ -10086,16 +10166,13 @@
 
 	if (y < 0) {
 		if (y + cursor_state->crtc_h <= 0)
-			base = 0;
+			on = false;
 
 		pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
 		y = -y;
 	}
 	pos |= y << CURSOR_Y_SHIFT;
 
-	if (base == 0 && intel_crtc->cursor_base == 0)
-		return;
-
 	I915_WRITE(CURPOS(pipe), pos);
 
 	/* ILK+ do this automagically */
@@ -10106,9 +10183,9 @@
 	}
 
 	if (IS_845G(dev) || IS_I865G(dev))
-		i845_update_cursor(crtc, base);
+		i845_update_cursor(crtc, base, on);
 	else
-		i9xx_update_cursor(crtc, base);
+		i9xx_update_cursor(crtc, base, on);
 }
 
 static bool cursor_size_ok(struct drm_device *dev,
@@ -11537,7 +11614,7 @@
 	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
 		work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		ring = &dev_priv->ring[BCS];
 		if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode)
 			/* vlv: DISPLAY_FLIP fails to change tiling */
@@ -11693,9 +11770,14 @@
 	struct intel_plane_state *cur = to_intel_plane_state(plane->state);
 
 	/* Update watermarks on tiling or size changes. */
-	if (!plane->state->fb || !state->fb ||
-	    plane->state->fb->modifier[0] != state->fb->modifier[0] ||
-	    plane->state->rotation != state->rotation ||
+	if (new->visible != cur->visible)
+		return true;
+
+	if (!cur->base.fb || !new->base.fb)
+		return false;
+
+	if (cur->base.fb->modifier[0] != new->base.fb->modifier[0] ||
+	    cur->base.rotation != new->base.rotation ||
 	    drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
 	    drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
 	    drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
@@ -11718,6 +11800,7 @@
 int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 				    struct drm_plane_state *plane_state)
 {
+	struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
 	struct drm_crtc *crtc = crtc_state->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_plane *plane = plane_state->plane;
@@ -11764,25 +11847,17 @@
 			 plane->base.id, was_visible, visible,
 			 turn_off, turn_on, mode_changed);
 
-	if (turn_on) {
-		intel_crtc->atomic.update_wm_pre = true;
-		/* must disable cxsr around plane enable/disable */
-		if (plane->type != DRM_PLANE_TYPE_CURSOR) {
-			intel_crtc->atomic.disable_cxsr = true;
-			/* to potentially re-enable cxsr */
-			intel_crtc->atomic.wait_vblank = true;
-			intel_crtc->atomic.update_wm_post = true;
-		}
-	} else if (turn_off) {
-		intel_crtc->atomic.update_wm_post = true;
+	if (turn_on || turn_off) {
+		pipe_config->wm_changed = true;
+
 		/* must disable cxsr around plane enable/disable */
 		if (plane->type != DRM_PLANE_TYPE_CURSOR) {
 			if (is_crtc_enabled)
 				intel_crtc->atomic.wait_vblank = true;
-			intel_crtc->atomic.disable_cxsr = true;
+			pipe_config->disable_cxsr = true;
 		}
 	} else if (intel_wm_need_update(plane, plane_state)) {
-		intel_crtc->atomic.update_wm_pre = true;
+		pipe_config->wm_changed = true;
 	}
 
 	if (visible || was_visible)
@@ -11927,7 +12002,7 @@
 	}
 
 	if (mode_changed && !crtc_state->active)
-		intel_crtc->atomic.update_wm_post = true;
+		pipe_config->wm_changed = true;
 
 	if (mode_changed && crtc_state->enable &&
 	    dev_priv->display.crtc_compute_clock &&
@@ -12018,7 +12093,7 @@
 	struct drm_connector_state *connector_state;
 	int bpp, i;
 
-	if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)))
+	if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)))
 		bpp = 10*3;
 	else if (INTEL_INFO(dev)->gen >= 5)
 		bpp = 12*3;
@@ -12628,7 +12703,7 @@
 	PIPE_CONF_CHECK_I(pixel_multiplier);
 	PIPE_CONF_CHECK_I(has_hdmi_sink);
 	if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) ||
-	    IS_VALLEYVIEW(dev))
+	    IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		PIPE_CONF_CHECK_I(limited_color_range);
 	PIPE_CONF_CHECK_I(has_infoframe);
 
@@ -13414,6 +13489,9 @@
 			 */
 			intel_check_cpu_fifo_underruns(dev_priv);
 			intel_check_pch_fifo_underruns(dev_priv);
+
+			if (!crtc->state->active)
+				intel_update_watermarks(crtc);
 		}
 	}
 
@@ -13849,9 +13927,6 @@
 		to_intel_crtc_state(old_crtc_state);
 	bool modeset = needs_modeset(crtc->state);
 
-	if (intel_crtc->atomic.update_wm_pre)
-		intel_update_watermarks(crtc);
-
 	/* Perform vblank evasion around commit operation */
 	intel_pipe_update_start(intel_crtc);
 
@@ -13982,6 +14057,7 @@
 	struct drm_crtc *crtc = crtc_state->base.crtc;
 	struct drm_framebuffer *fb = state->base.fb;
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	enum pipe pipe = to_intel_plane(plane)->pipe;
 	unsigned stride;
 	int ret;
 
@@ -14015,6 +14091,22 @@
 		return -EINVAL;
 	}
 
+	/*
+	 * There's something wrong with the cursor on CHV pipe C.
+	 * If it straddles the left edge of the screen then
+	 * moving it away from the edge or disabling it often
+	 * results in a pipe underrun, and often that can lead to
+	 * dead pipe (constant underrun reported, and it scans
+	 * out just a solid color). To recover from that, the
+	 * display power well must be turned off and on again.
+	 * Refuse the put the cursor into that compromised position.
+	 */
+	if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C &&
+	    state->visible && state->base.crtc_x < 0) {
+		DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -14038,9 +14130,6 @@
 	crtc = crtc ? crtc : plane->crtc;
 	intel_crtc = to_intel_crtc(crtc);
 
-	if (intel_crtc->cursor_bo == obj)
-		goto update;
-
 	if (!obj)
 		addr = 0;
 	else if (!INTEL_INFO(dev)->cursor_needs_physical)
@@ -14049,10 +14138,9 @@
 		addr = obj->phys_handle->busaddr;
 
 	intel_crtc->cursor_addr = addr;
-	intel_crtc->cursor_bo = obj;
 
-update:
-	intel_crtc_update_cursor(crtc, state->visible);
+	if (crtc->state->active)
+		intel_crtc_update_cursor(crtc, state->visible);
 }
 
 static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
@@ -14380,7 +14468,7 @@
 
 		if (I915_READ(PCH_DP_D) & DP_DETECTED)
 			intel_dp_init(dev, PCH_DP_D, PORT_D);
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		/*
 		 * The DP_DETECTED bit is the latched state of the DDC
 		 * SDA pin at boot. However since eDP doesn't require DDC
@@ -14529,7 +14617,7 @@
 		 *  pixels and 32K bytes."
 		 */
 		 return min(8192*drm_format_plane_cpp(pixel_format, 0), 32768);
-	} else if (gen >= 5 && !IS_VALLEYVIEW(dev)) {
+	} else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
 		return 32*1024;
 	} else if (gen >= 4) {
 		if (fb_modifier == I915_FORMAT_MOD_X_TILED)
@@ -14633,7 +14721,8 @@
 		}
 		break;
 	case DRM_FORMAT_ABGR8888:
-		if (!IS_VALLEYVIEW(dev) && INTEL_INFO(dev)->gen < 9) {
+		if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
+		    INTEL_INFO(dev)->gen < 9) {
 			DRM_DEBUG("unsupported pixel format: %s\n",
 				  drm_get_format_name(mode_cmd->pixel_format));
 			return -EINVAL;
@@ -14649,7 +14738,7 @@
 		}
 		break;
 	case DRM_FORMAT_ABGR2101010:
-		if (!IS_VALLEYVIEW(dev)) {
+		if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
 			DRM_DEBUG("unsupported pixel format: %s\n",
 				  drm_get_format_name(mode_cmd->pixel_format));
 			return -EINVAL;
@@ -14777,7 +14866,7 @@
 		dev_priv->display.crtc_disable = ironlake_crtc_disable;
 		dev_priv->display.update_primary_plane =
 			ironlake_update_primary_plane;
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
 		dev_priv->display.get_initial_plane_config =
 			i9xx_get_initial_plane_config;
@@ -14810,7 +14899,7 @@
 	else if (IS_HASWELL(dev))
 		dev_priv->display.get_display_clock_speed =
 			haswell_get_display_clock_speed;
-	else if (IS_VALLEYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		dev_priv->display.get_display_clock_speed =
 			valleyview_get_display_clock_speed;
 	else if (IS_GEN5(dev))
@@ -14868,7 +14957,7 @@
 			dev_priv->display.modeset_calc_cdclk =
 				broadwell_modeset_calc_cdclk;
 		}
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		dev_priv->display.modeset_commit_cdclk =
 			valleyview_modeset_commit_cdclk;
 		dev_priv->display.modeset_calc_cdclk =
@@ -15657,7 +15746,7 @@
 		pll->on = false;
 	}
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		vlv_wm_get_hw_state(dev);
 	else if (IS_GEN9(dev))
 		skl_wm_get_hw_state(dev);
@@ -15780,7 +15869,7 @@
 void intel_modeset_cleanup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_connector *connector;
+	struct intel_connector *connector;
 
 	intel_disable_gt_powersave(dev);
 
@@ -15807,12 +15896,8 @@
 	flush_scheduled_work();
 
 	/* destroy the backlight and sysfs files before encoders/connectors */
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		struct intel_connector *intel_connector;
-
-		intel_connector = to_intel_connector(connector);
-		intel_connector->unregister(intel_connector);
-	}
+	for_each_intel_connector(dev, connector)
+		connector->unregister(connector);
 
 	drm_mode_config_cleanup(dev);
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0f0573a..796e3d3 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -389,8 +389,7 @@
 	 * We don't have power sequencer currently.
 	 * Pick one that's not used by other ports.
 	 */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
-			    base.head) {
+	for_each_intel_encoder(dev, encoder) {
 		struct intel_dp *tmp;
 
 		if (encoder->type != INTEL_OUTPUT_EDP)
@@ -517,7 +516,7 @@
 	struct drm_device *dev = dev_priv->dev;
 	struct intel_encoder *encoder;
 
-	if (WARN_ON(!IS_VALLEYVIEW(dev)))
+	if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)))
 		return;
 
 	/*
@@ -530,7 +529,7 @@
 	 * should use them always.
 	 */
 
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+	for_each_intel_encoder(dev, encoder) {
 		struct intel_dp *intel_dp;
 
 		if (encoder->type != INTEL_OUTPUT_EDP)
@@ -582,7 +581,7 @@
 
 	pps_lock(intel_dp);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
 		i915_reg_t pp_ctrl_reg, pp_div_reg;
 		u32 pp_div;
@@ -610,7 +609,7 @@
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	if (IS_VALLEYVIEW(dev) &&
+	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
 	    intel_dp->pps_pipe == INVALID_PIPE)
 		return false;
 
@@ -624,7 +623,7 @@
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	if (IS_VALLEYVIEW(dev) &&
+	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
 	    intel_dp->pps_pipe == INVALID_PIPE)
 		return false;
 
@@ -915,6 +914,27 @@
 	/* Unload any bytes sent back from the other side */
 	recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
 		      DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
+
+	/*
+	 * By BSpec: "Message sizes of 0 or >20 are not allowed."
+	 * We have no idea of what happened so we return -EBUSY so
+	 * drm layer takes care for the necessary retries.
+	 */
+	if (recv_bytes == 0 || recv_bytes > 20) {
+		DRM_DEBUG_KMS("Forbidden recv_bytes = %d on aux transaction\n",
+			      recv_bytes);
+		/*
+		 * FIXME: This patch was created on top of a series that
+		 * organize the retries at drm level. There EBUSY should
+		 * also take care for 1ms wait before retrying.
+		 * That aux retries re-org is still needed and after that is
+		 * merged we remove this sleep from here.
+		 */
+		usleep_range(1000, 1500);
+		ret = -EBUSY;
+		goto out;
+	}
+
 	if (recv_bytes > recv_size)
 		recv_bytes = recv_size;
 
@@ -1723,7 +1743,7 @@
 		I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp);
 	} else {
 		if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) &&
-		    crtc->config->limited_color_range)
+		    !IS_CHERRYVIEW(dev) && crtc->config->limited_color_range)
 			intel_dp->DP |= DP_COLOR_RANGE_16_235;
 
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -2418,7 +2438,7 @@
 	pipe_config->base.adjusted_mode.flags |= flags;
 
 	if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) &&
-	    tmp & DP_COLOR_RANGE_16_235)
+	    !IS_CHERRYVIEW(dev) && tmp & DP_COLOR_RANGE_16_235)
 		pipe_config->limited_color_range = true;
 
 	pipe_config->has_dp_encoder = true;
@@ -2694,7 +2714,7 @@
 
 	pps_lock(intel_dp);
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		vlv_init_panel_power_sequencer(intel_dp);
 
 	/*
@@ -2728,7 +2748,7 @@
 
 	pps_unlock(intel_dp);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		unsigned int lane_mask = 0x0;
 
 		if (IS_CHERRYVIEW(dev))
@@ -2829,8 +2849,7 @@
 	if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
 		return;
 
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
-			    base.head) {
+	for_each_intel_encoder(dev, encoder) {
 		struct intel_dp *intel_dp;
 		enum port port;
 
@@ -3218,7 +3237,7 @@
 		if (dev_priv->edp_low_vswing && port == PORT_A)
 			return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
-	} else if (IS_VALLEYVIEW(dev))
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
 	else if (IS_GEN7(dev) && port == PORT_A)
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
@@ -3259,7 +3278,7 @@
 		default:
 			return DP_TRAIN_PRE_EMPH_LEVEL_0;
 		}
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 		case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
 			return DP_TRAIN_PRE_EMPH_LEVEL_3;
@@ -4539,7 +4558,7 @@
 		return cpt_digital_port_connected(dev_priv, port);
 	else if (IS_BROXTON(dev_priv))
 		return bxt_digital_port_connected(dev_priv, port);
-	else if (IS_VALLEYVIEW(dev_priv))
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		return vlv_digital_port_connected(dev_priv, port);
 	else
 		return g4x_digital_port_connected(dev_priv, port);
@@ -4933,7 +4952,7 @@
 	 * Read out the current power sequencer assignment,
 	 * in case the BIOS did something with it.
 	 */
-	if (IS_VALLEYVIEW(encoder->dev))
+	if (IS_VALLEYVIEW(encoder->dev) || IS_CHERRYVIEW(encoder->dev))
 		vlv_initial_power_sequencer_setup(intel_dp);
 
 	intel_edp_panel_vdd_sanitize(intel_dp);
@@ -5293,7 +5312,7 @@
 
 	/* Haswell doesn't have any port selection bits for the panel
 	 * power sequencer any more. */
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		port_sel = PANEL_PORT_SELECT_VLV(port);
 	} else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
 		if (port == PORT_A)
@@ -5405,12 +5424,12 @@
 
 		val = I915_READ(reg);
 		if (index > DRRS_HIGH_RR) {
-			if (IS_VALLEYVIEW(dev))
+			if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 				val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
 			else
 				val |= PIPECONF_EDP_RR_MODE_SWITCH;
 		} else {
-			if (IS_VALLEYVIEW(dev))
+			if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 				val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
 			else
 				val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
@@ -5777,7 +5796,7 @@
 	}
 	mutex_unlock(&dev->mode_config.mutex);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		intel_dp->edp_notifier.notifier_call = edp_notify_handler;
 		register_reboot_notifier(&intel_dp->edp_notifier);
 
@@ -5825,7 +5844,7 @@
 	/* intel_dp vfuncs */
 	if (INTEL_INFO(dev)->gen >= 9)
 		intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
-	else if (IS_VALLEYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
 	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
@@ -5860,8 +5879,8 @@
 		intel_encoder->type = INTEL_OUTPUT_EDP;
 
 	/* eDP only on port B and/or C on vlv/chv */
-	if (WARN_ON(IS_VALLEYVIEW(dev) && is_edp(intel_dp) &&
-		    port != PORT_B && port != PORT_C))
+	if (WARN_ON((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+		    is_edp(intel_dp) && port != PORT_B && port != PORT_C))
 		return false;
 
 	DRM_DEBUG_KMS("Adding %s connector on port %c\n",
@@ -5912,7 +5931,7 @@
 	if (is_edp(intel_dp)) {
 		pps_lock(intel_dp);
 		intel_dp_init_panel_power_timestamps(intel_dp);
-		if (IS_VALLEYVIEW(dev))
+		if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 			vlv_initial_power_sequencer_setup(intel_dp);
 		else
 			intel_dp_init_panel_power_sequencer(dev, intel_dp);
@@ -5988,8 +6007,9 @@
 	intel_encoder = &intel_dig_port->base;
 	encoder = &intel_encoder->base;
 
-	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+	if (drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
+			     DRM_MODE_ENCODER_TMDS, NULL))
+		goto err_encoder_init;
 
 	intel_encoder->compute_config = intel_dp_compute_config;
 	intel_encoder->disable = intel_disable_dp;
@@ -6015,6 +6035,7 @@
 	}
 
 	intel_dig_port->port = port;
+	dev_priv->dig_port_map[port] = intel_encoder;
 	intel_dig_port->dp.output_reg = output_reg;
 
 	intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
@@ -6038,6 +6059,7 @@
 
 err_init_connector:
 	drm_encoder_cleanup(encoder);
+err_encoder_init:
 	kfree(intel_connector);
 err_connector_alloc:
 	kfree(intel_dig_port);
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 9ae1a4f..fa0dabf 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -78,6 +78,8 @@
 		return false;
 	}
 
+	if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, found->port))
+		pipe_config->has_audio = true;
 	mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp);
 
 	pipe_config->pbn = mst_pbn;
@@ -102,6 +104,11 @@
 	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
 	struct intel_digital_port *intel_dig_port = intel_mst->primary;
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = encoder->base.crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
 	int ret;
 
 	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
@@ -112,6 +119,10 @@
 	if (ret) {
 		DRM_ERROR("failed to update payload %d\n", ret);
 	}
+	if (intel_crtc->config->has_audio) {
+		intel_audio_codec_disable(encoder);
+		intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
+	}
 }
 
 static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
@@ -208,6 +219,7 @@
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 	enum port port = intel_dig_port->port;
 	int ret;
 
@@ -220,6 +232,13 @@
 	ret = drm_dp_check_act_status(&intel_dp->mst_mgr);
 
 	ret = drm_dp_update_payload_part2(&intel_dp->mst_mgr);
+
+	if (crtc->config->has_audio) {
+		DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
+				 pipe_name(crtc->pipe));
+		intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
+		intel_audio_codec_enable(encoder);
+	}
 }
 
 static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
@@ -245,6 +264,9 @@
 
 	pipe_config->has_dp_encoder = true;
 
+	pipe_config->has_audio =
+		intel_ddi_is_audio_enabled(dev_priv, crtc);
+
 	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
 	if (temp & TRANS_DDI_PHSYNC)
 		flags |= DRM_MODE_FLAG_PHSYNC;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 50f83d2..d523ebb 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -365,7 +365,9 @@
 #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS	(1<<0) /* unreliable sync mode.flags */
 	unsigned long quirks;
 
-	bool update_pipe;
+	bool update_pipe; /* can a fast modeset be performed? */
+	bool disable_cxsr;
+	bool wm_changed; /* watermarks are updated */
 
 	/* Pipe source size (ie. panel fitter input size)
 	 * All planes will be positioned inside this space,
@@ -531,9 +533,7 @@
 	/* Sleepable operations to perform before commit */
 	bool disable_fbc;
 	bool disable_ips;
-	bool disable_cxsr;
 	bool pre_disable_primary;
-	bool update_wm_pre, update_wm_post;
 
 	/* Sleepable operations to perform after commit */
 	unsigned fb_bits;
@@ -568,7 +568,6 @@
 	int adjusted_x;
 	int adjusted_y;
 
-	struct drm_i915_gem_object *cursor_bo;
 	uint32_t cursor_addr;
 	uint32_t cursor_cntl;
 	uint32_t cursor_size;
@@ -818,6 +817,8 @@
 	struct intel_hdmi hdmi;
 	enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
 	bool release_cl2_override;
+	/* for communication with audio component; protected by av_mutex */
+	const struct drm_connector *audio_connector;
 };
 
 struct intel_dp_mst_encoder {
@@ -1012,6 +1013,8 @@
 void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp);
 bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
 void intel_ddi_fdi_disable(struct drm_crtc *crtc);
+bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
+				 struct intel_crtc *intel_crtc);
 void intel_ddi_get_config(struct intel_encoder *encoder,
 			  struct intel_crtc_state *pipe_config);
 struct intel_encoder *
@@ -1427,6 +1430,87 @@
 			     enum intel_display_power_domain domain);
 void intel_display_power_put(struct drm_i915_private *dev_priv,
 			     enum intel_display_power_domain domain);
+
+static inline void
+assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv)
+{
+	WARN_ONCE(dev_priv->pm.suspended,
+		  "Device suspended during HW access\n");
+}
+
+static inline void
+assert_rpm_wakelock_held(struct drm_i915_private *dev_priv)
+{
+	assert_rpm_device_not_suspended(dev_priv);
+	WARN_ONCE(!atomic_read(&dev_priv->pm.wakeref_count),
+		  "RPM wakelock ref not held during HW access");
+}
+
+static inline int
+assert_rpm_atomic_begin(struct drm_i915_private *dev_priv)
+{
+	int seq = atomic_read(&dev_priv->pm.atomic_seq);
+
+	assert_rpm_wakelock_held(dev_priv);
+
+	return seq;
+}
+
+static inline void
+assert_rpm_atomic_end(struct drm_i915_private *dev_priv, int begin_seq)
+{
+	WARN_ONCE(atomic_read(&dev_priv->pm.atomic_seq) != begin_seq,
+		  "HW access outside of RPM atomic section\n");
+}
+
+/**
+ * disable_rpm_wakeref_asserts - disable the RPM assert checks
+ * @dev_priv: i915 device instance
+ *
+ * This function disable asserts that check if we hold an RPM wakelock
+ * reference, while keeping the device-not-suspended checks still enabled.
+ * It's meant to be used only in special circumstances where our rule about
+ * the wakelock refcount wrt. the device power state doesn't hold. According
+ * to this rule at any point where we access the HW or want to keep the HW in
+ * an active state we must hold an RPM wakelock reference acquired via one of
+ * the intel_runtime_pm_get() helpers. Currently there are a few special spots
+ * where this rule doesn't hold: the IRQ and suspend/resume handlers, the
+ * forcewake release timer, and the GPU RPS and hangcheck works. All other
+ * users should avoid using this function.
+ *
+ * Any calls to this function must have a symmetric call to
+ * enable_rpm_wakeref_asserts().
+ */
+static inline void
+disable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
+{
+	atomic_inc(&dev_priv->pm.wakeref_count);
+}
+
+/**
+ * enable_rpm_wakeref_asserts - re-enable the RPM assert checks
+ * @dev_priv: i915 device instance
+ *
+ * This function re-enables the RPM assert checks after disabling them with
+ * disable_rpm_wakeref_asserts. It's meant to be used only in special
+ * circumstances otherwise its use should be avoided.
+ *
+ * Any calls to this function must have a symmetric call to
+ * disable_rpm_wakeref_asserts().
+ */
+static inline void
+enable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
+{
+	atomic_dec(&dev_priv->pm.wakeref_count);
+}
+
+/* TODO: convert users of these to rely instead on proper RPM refcounting */
+#define DISABLE_RPM_WAKEREF_ASSERTS(dev_priv)	\
+	disable_rpm_wakeref_asserts(dev_priv)
+
+#define ENABLE_RPM_WAKEREF_ASSERTS(dev_priv)	\
+	enable_rpm_wakeref_asserts(dev_priv)
+
 void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index fff9a66..44742fa 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -369,7 +369,7 @@
 {
 	struct drm_device *dev = encoder->base.dev;
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		vlv_dsi_device_ready(encoder);
 	else if (IS_BROXTON(dev))
 		bxt_dsi_device_ready(encoder);
@@ -487,7 +487,7 @@
 
 	msleep(intel_dsi->panel_on_delay);
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		/*
 		 * Disable DPOunit clock gating, can stall pipe
 		 * and we need DPLL REFA always enabled
@@ -684,8 +684,7 @@
 		 * Enable bit does not get set. To check whether DSI Port C
 		 * was enabled in BIOS, check the Pipe B enable bit
 		 */
-		if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
-		    (port == PORT_C))
+		if (IS_VALLEYVIEW(dev) && port == PORT_C)
 			dpi_enabled = I915_READ(PIPECONF(PIPE_B)) &
 							PIPECONF_ENABLE;
 
@@ -716,7 +715,8 @@
 
 	if (IS_BROXTON(encoder->base.dev))
 		pclk = bxt_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
-	else if (IS_VALLEYVIEW(encoder->base.dev))
+	else if (IS_VALLEYVIEW(encoder->base.dev) ||
+		 IS_CHERRYVIEW(encoder->base.dev))
 		pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
 
 	if (!pclk)
@@ -869,7 +869,7 @@
 	}
 
 	for_each_dsi_port(port, intel_dsi->ports) {
-		if (IS_VALLEYVIEW(dev)) {
+		if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 			/*
 			 * escape clock divider, 20MHz, shared for A and C.
 			 * device ready must be off when doing this! txclkesc?
@@ -885,21 +885,12 @@
 			I915_WRITE(MIPI_CTRL(port), tmp |
 					READ_REQUEST_PRIORITY_HIGH);
 		} else if (IS_BROXTON(dev)) {
-			/*
-			 * FIXME:
-			 * BXT can connect any PIPE to any MIPI port.
-			 * Select the pipe based on the MIPI port read from
-			 * VBT for now. Pick PIPE A for MIPI port A and C
-			 * for port C.
-			 */
+			enum pipe pipe = intel_crtc->pipe;
+
 			tmp = I915_READ(MIPI_CTRL(port));
 			tmp &= ~BXT_PIPE_SELECT_MASK;
 
-			if (port == PORT_A)
-				tmp |= BXT_PIPE_SELECT_A;
-			else if (port == PORT_C)
-				tmp |= BXT_PIPE_SELECT_C;
-
+			tmp |= BXT_PIPE_SELECT(pipe);
 			I915_WRITE(MIPI_CTRL(port), tmp);
 		}
 
@@ -1129,7 +1120,7 @@
 	if (!dev_priv->vbt.has_mipi)
 		return;
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
 	} else {
 		DRM_ERROR("Unsupported Mipi device to reg base");
diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
index cb3cf39..fbd2b51 100644
--- a/drivers/gpu/drm/i915/intel_dsi_pll.c
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -561,7 +561,7 @@
 {
 	struct drm_device *dev = encoder->base.dev;
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		vlv_enable_dsi_pll(encoder);
 	else if (IS_BROXTON(dev))
 		bxt_enable_dsi_pll(encoder);
@@ -571,7 +571,7 @@
 {
 	struct drm_device *dev = encoder->base.dev;
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		vlv_disable_dsi_pll(encoder);
 	else if (IS_BROXTON(dev))
 		bxt_disable_dsi_pll(encoder);
@@ -599,6 +599,6 @@
 
 	if (IS_BROXTON(dev))
 		bxt_dsi_reset_clocks(encoder, port);
-	else if (IS_VALLEYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		vlv_dsi_reset_clocks(encoder, port);
 }
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 7ccde58..bea75ca 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -163,13 +163,6 @@
 		goto out;
 	}
 
-	/* Flush everything out, we'll be doing GTT only from now on */
-	ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL);
-	if (ret) {
-		DRM_ERROR("failed to pin obj: %d\n", ret);
-		goto out;
-	}
-
 	mutex_unlock(&dev->struct_mutex);
 
 	ifbdev->fb = to_intel_framebuffer(fb);
@@ -225,6 +218,14 @@
 
 	mutex_lock(&dev->struct_mutex);
 
+	/* Pin the GGTT vma for our access via info->screen_base.
+	 * This also validates that any existing fb inherited from the
+	 * BIOS is suitable for own access.
+	 */
+	ret = intel_pin_and_fence_fb_obj(NULL, &ifbdev->fb->base, NULL);
+	if (ret)
+		goto out_unlock;
+
 	info = drm_fb_helper_alloc_fbi(helper);
 	if (IS_ERR(info)) {
 		DRM_ERROR("Failed to allocate fb_info\n");
@@ -287,6 +288,7 @@
 	drm_fb_helper_release_fbi(helper);
 out_unpin:
 	i915_gem_object_ggtt_unpin(obj);
+out_unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
@@ -524,6 +526,10 @@
 static void intel_fbdev_destroy(struct drm_device *dev,
 				struct intel_fbdev *ifbdev)
 {
+	/* We rely on the object-free to release the VMA pinning for
+	 * the info->screen_base mmaping. Leaking the VMA is simpler than
+	 * trying to rectify all the possible error paths leading here.
+	 */
 
 	drm_fb_helper_unregister_fbi(&ifbdev->helper);
 	drm_fb_helper_release_fbi(&ifbdev->helper);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 00d065f..6214175 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -78,7 +78,7 @@
 	case HDMI_INFOFRAME_TYPE_VENDOR:
 		return VIDEO_DIP_SELECT_VENDOR;
 	default:
-		DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
+		MISSING_CASE(type);
 		return 0;
 	}
 }
@@ -93,7 +93,7 @@
 	case HDMI_INFOFRAME_TYPE_VENDOR:
 		return VIDEO_DIP_ENABLE_VENDOR;
 	default:
-		DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
+		MISSING_CASE(type);
 		return 0;
 	}
 }
@@ -108,7 +108,7 @@
 	case HDMI_INFOFRAME_TYPE_VENDOR:
 		return VIDEO_DIP_ENABLE_VS_HSW;
 	default:
-		DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
+		MISSING_CASE(type);
 		return 0;
 	}
 }
@@ -127,7 +127,7 @@
 	case HDMI_INFOFRAME_TYPE_VENDOR:
 		return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i);
 	default:
-		DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
+		MISSING_CASE(type);
 		return INVALID_MMIO_REG;
 	}
 }
@@ -375,8 +375,6 @@
 	u32 val = I915_READ(ctl_reg);
 
 	data_reg = hsw_dip_data_reg(dev_priv, cpu_transcoder, type, 0);
-	if (i915_mmio_reg_valid(data_reg))
-		return;
 
 	val &= ~hsw_infoframe_enable(type);
 	I915_WRITE(ctl_reg, val);
@@ -638,7 +636,7 @@
 
 	if (HAS_DDI(dev_priv))
 		reg = HSW_TVIDEO_DIP_GCP(crtc->config->cpu_transcoder);
-	else if (IS_VALLEYVIEW(dev_priv))
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		reg = VLV_TVIDEO_DIP_GCP(crtc->pipe);
 	else if (HAS_PCH_SPLIT(dev_priv->dev))
 		reg = TVIDEO_DIP_GCP(crtc->pipe);
@@ -1387,17 +1385,18 @@
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	bool live_status = false;
-	unsigned int retry = 3;
+	unsigned int try;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, connector->name);
 
 	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
-	while (!live_status && --retry) {
+	for (try = 0; !live_status && try < 4; try++) {
+		if (try)
+			msleep(10);
 		live_status = intel_digital_port_connected(dev_priv,
 				hdmi_to_dig_port(intel_hdmi));
-		mdelay(10);
 	}
 
 	if (!live_status)
@@ -2100,7 +2099,7 @@
 		BUG();
 	}
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		intel_hdmi->write_infoframe = vlv_write_infoframe;
 		intel_hdmi->set_infoframes = vlv_set_infoframes;
 		intel_hdmi->infoframe_enabled = vlv_infoframe_enabled;
@@ -2147,6 +2146,7 @@
 void intel_hdmi_init(struct drm_device *dev,
 		     i915_reg_t hdmi_reg, enum port port)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_digital_port *intel_dig_port;
 	struct intel_encoder *intel_encoder;
 	struct intel_connector *intel_connector;
@@ -2215,6 +2215,7 @@
 		intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI;
 
 	intel_dig_port->port = port;
+	dev_priv->dig_port_map[port] = intel_encoder;
 	intel_dig_port->hdmi.hdmi_reg = hdmi_reg;
 	intel_dig_port->dp.output_reg = INVALID_MMIO_REG;
 
diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
index b177857..a294a3c 100644
--- a/drivers/gpu/drm/i915/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
@@ -407,7 +407,7 @@
 			 * hotplug bits itself. So only WARN about unexpected
 			 * interrupts on saner platforms.
 			 */
-			WARN_ONCE(INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev),
+			WARN_ONCE(!HAS_GMCH_DISPLAY(dev),
 				  "Received HPD interrupt on pin %d although disabled\n", i);
 			continue;
 		}
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index e26e22a..25254b5 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -636,7 +636,7 @@
 	if (HAS_PCH_NOP(dev))
 		return 0;
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE;
 	else if (!HAS_GMCH_DISPLAY(dev_priv))
 		dev_priv->gpio_mmio_base =
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 4ebafab..3aa6147 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -372,7 +372,7 @@
 	WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
 	WARN_ON(!i915_gem_obj_is_pinned(rb_obj));
 
-	page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+	page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
 	reg_state = kmap_atomic(page);
 
 	reg_state[CTX_RING_TAIL+1] = rq->tail;
@@ -1425,7 +1425,7 @@
 		return ret;
 	}
 
-	page = i915_gem_object_get_page(wa_ctx->obj, 0);
+	page = i915_gem_object_get_dirty_page(wa_ctx->obj, 0);
 	batch = kmap_atomic(page);
 	offset = 0;
 
@@ -1894,8 +1894,10 @@
 
 	dev_priv = ring->dev->dev_private;
 
-	intel_logical_ring_stop(ring);
-	WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
+	if (ring->buffer) {
+		intel_logical_ring_stop(ring);
+		WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
+	}
 
 	if (ring->cleanup)
 		ring->cleanup(ring);
@@ -1909,6 +1911,7 @@
 	}
 
 	lrc_destroy_wa_ctx_obj(ring);
+	ring->dev = NULL;
 }
 
 static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring)
@@ -1931,11 +1934,11 @@
 
 	ret = i915_cmd_parser_init_ring(ring);
 	if (ret)
-		return ret;
+		goto error;
 
 	ret = intel_lr_context_deferred_alloc(ring->default_context, ring);
 	if (ret)
-		return ret;
+		goto error;
 
 	/* As this is the default context, always pin it */
 	ret = intel_lr_context_do_pin(
@@ -1946,9 +1949,13 @@
 		DRM_ERROR(
 			"Failed to pin and map ringbuffer %s: %d\n",
 			ring->name, ret);
-		return ret;
+		goto error;
 	}
 
+	return 0;
+
+error:
+	intel_logical_ring_cleanup(ring);
 	return ret;
 }
 
@@ -2257,7 +2264,7 @@
 
 	/* The second page of the context object contains some fields which must
 	 * be set up prior to the first execution. */
-	page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+	page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
 	reg_state = kmap_atomic(page);
 
 	/* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM
@@ -2343,9 +2350,6 @@
 	}
 
 	kunmap_atomic(reg_state);
-
-	ctx_obj->dirty = 1;
-	set_page_dirty(page);
 	i915_gem_object_unpin_pages(ctx_obj);
 
 	return 0;
@@ -2529,7 +2533,7 @@
 			WARN(1, "Failed get_pages for context obj\n");
 			continue;
 		}
-		page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+		page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
 		reg_state = kmap_atomic(page);
 
 		reg_state[CTX_RING_HEAD+1] = 0;
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index e362a30..c15718b 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -26,6 +26,7 @@
  */
 
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <acpi/video.h>
 
 #include <drm/drmP.h>
@@ -46,6 +47,7 @@
 #define OPREGION_SWSCI_OFFSET  0x200
 #define OPREGION_ASLE_OFFSET   0x300
 #define OPREGION_VBT_OFFSET    0x400
+#define OPREGION_ASLE_EXT_OFFSET	0x1C00
 
 #define OPREGION_SIGNATURE "IntelGraphicsMem"
 #define MBOX_ACPI      (1<<0)
@@ -120,7 +122,16 @@
 	u64 fdss;
 	u32 fdsp;
 	u32 stat;
-	u8 rsvd[70];
+	u64 rvda;	/* Physical address of raw vbt data */
+	u32 rvds;	/* Size of raw vbt data */
+	u8 rsvd[58];
+} __packed;
+
+/* OpRegion mailbox #5: ASLE ext */
+struct opregion_asle_ext {
+	u32 phed;	/* Panel Header */
+	u8 bddc[256];	/* Panel EDID */
+	u8 rsvd[764];
 } __packed;
 
 /* Driver readiness indicator */
@@ -411,7 +422,7 @@
 static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_connector *intel_connector;
+	struct intel_connector *connector;
 	struct opregion_asle *asle = dev_priv->opregion.asle;
 
 	DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
@@ -435,8 +446,8 @@
 	 * only one).
 	 */
 	DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
-	list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head)
-		intel_panel_set_backlight_acpi(intel_connector, bclp, 255);
+	for_each_intel_connector(dev, connector)
+		intel_panel_set_backlight_acpi(connector, bclp, 255);
 	asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID;
 
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
@@ -826,6 +837,10 @@
 
 	/* just clear all opregion memory pointers now */
 	memunmap(opregion->header);
+	if (opregion->rvda) {
+		memunmap(opregion->rvda);
+		opregion->rvda = NULL;
+	}
 	opregion->header = NULL;
 	opregion->acpi = NULL;
 	opregion->swsci = NULL;
@@ -894,6 +909,25 @@
 static inline void swsci_setup(struct drm_device *dev) {}
 #endif  /* CONFIG_ACPI */
 
+static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
+{
+	DRM_DEBUG_KMS("Falling back to manually reading VBT from "
+		      "VBIOS ROM for %s\n", id->ident);
+	return 1;
+}
+
+static const struct dmi_system_id intel_no_opregion_vbt[] = {
+	{
+		.callback = intel_no_opregion_vbt_callback,
+		.ident = "ThinkCentre A57",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
+		},
+	},
+	{ }
+};
+
 int intel_opregion_setup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -907,6 +941,7 @@
 	BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100);
 	BUILD_BUG_ON(sizeof(struct opregion_swsci) != 0x100);
 	BUILD_BUG_ON(sizeof(struct opregion_asle) != 0x100);
+	BUILD_BUG_ON(sizeof(struct opregion_asle_ext) != 0x400);
 
 	pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
 	DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
@@ -931,8 +966,6 @@
 		goto err_out;
 	}
 	opregion->header = base;
-	opregion->vbt = base + OPREGION_VBT_OFFSET;
-
 	opregion->lid_state = base + ACPI_CLID;
 
 	mboxes = opregion->header->mboxes;
@@ -946,6 +979,7 @@
 		opregion->swsci = base + OPREGION_SWSCI_OFFSET;
 		swsci_setup(dev);
 	}
+
 	if (mboxes & MBOX_ASLE) {
 		DRM_DEBUG_DRIVER("ASLE supported\n");
 		opregion->asle = base + OPREGION_ASLE_OFFSET;
@@ -953,6 +987,37 @@
 		opregion->asle->ardy = ASLE_ARDY_NOT_READY;
 	}
 
+	if (mboxes & MBOX_ASLE_EXT)
+		DRM_DEBUG_DRIVER("ASLE extension supported\n");
+
+	if (!dmi_check_system(intel_no_opregion_vbt)) {
+		const void *vbt = NULL;
+		u32 vbt_size = 0;
+
+		if (opregion->header->opregion_ver >= 2 && opregion->asle &&
+		    opregion->asle->rvda && opregion->asle->rvds) {
+			opregion->rvda = memremap(opregion->asle->rvda,
+						  opregion->asle->rvds,
+						  MEMREMAP_WB);
+			vbt = opregion->rvda;
+			vbt_size = opregion->asle->rvds;
+		}
+
+		if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
+			DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (RVDA)\n");
+			opregion->vbt = vbt;
+			opregion->vbt_size = vbt_size;
+		} else {
+			vbt = base + OPREGION_VBT_OFFSET;
+			vbt_size = OPREGION_ASLE_EXT_OFFSET - OPREGION_VBT_OFFSET;
+			if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
+				DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (Mailbox #4)\n");
+				opregion->vbt = vbt;
+				opregion->vbt_size = vbt_size;
+			}
+		}
+	}
+
 	return 0;
 
 err_out:
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index ae808b6..21ee647 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -461,8 +461,7 @@
 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 drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 
 	WARN_ON(panel->backlight.max == 0);
@@ -480,45 +479,40 @@
 
 static u32 lpt_get_backlight(struct intel_connector *connector)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 
 	return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
 }
 
 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;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 
 	return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
 }
 
 static u32 i9xx_get_backlight(struct intel_connector *connector)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 val;
 
 	val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
-	if (INTEL_INFO(dev)->gen < 4)
+	if (INTEL_INFO(dev_priv)->gen < 4)
 		val >>= 1;
 
 	if (panel->backlight.combination_mode) {
 		u8 lbpc;
 
-		pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
+		pci_read_config_byte(dev_priv->dev->pdev, PCI_LBPC, &lbpc);
 		val *= lbpc;
 	}
 
 	return val;
 }
 
-static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
+static u32 _vlv_get_backlight(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
 		return 0;
 
@@ -527,17 +521,16 @@
 
 static u32 vlv_get_backlight(struct intel_connector *connector)
 {
-	struct drm_device *dev = connector->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	enum pipe pipe = intel_get_pipe_from_connector(connector);
 
-	return _vlv_get_backlight(dev, pipe);
+	return _vlv_get_backlight(dev_priv, pipe);
 }
 
 static u32 bxt_get_backlight(struct intel_connector *connector)
 {
-	struct drm_device *dev = connector->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	return I915_READ(BXT_BLC_PWM_DUTY(panel->backlight.controller));
 }
@@ -553,8 +546,7 @@
 
 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;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 val = 0;
 
@@ -573,16 +565,14 @@
 
 static void lpt_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 drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
 	I915_WRITE(BLC_PWM_PCH_CTL2, val | 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;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	u32 tmp;
 
 	tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
@@ -591,8 +581,7 @@
 
 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;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 tmp, mask;
 
@@ -603,10 +592,10 @@
 
 		lbpc = level * 0xfe / panel->backlight.max + 1;
 		level /= lbpc;
-		pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
+		pci_write_config_byte(dev_priv->dev->pdev, PCI_LBPC, lbpc);
 	}
 
-	if (IS_GEN4(dev)) {
+	if (IS_GEN4(dev_priv)) {
 		mask = BACKLIGHT_DUTY_CYCLE_MASK;
 	} else {
 		level <<= 1;
@@ -619,8 +608,7 @@
 
 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;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	enum pipe pipe = intel_get_pipe_from_connector(connector);
 	u32 tmp;
 
@@ -633,8 +621,7 @@
 
 static void bxt_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 drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 
 	I915_WRITE(BXT_BLC_PWM_DUTY(panel->backlight.controller), level);
@@ -663,8 +650,7 @@
 static void intel_panel_set_backlight(struct intel_connector *connector,
 				      u32 user_level, u32 user_max)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 hw_level;
 
@@ -690,8 +676,7 @@
 void intel_panel_set_backlight_acpi(struct intel_connector *connector,
 				    u32 user_level, u32 user_max)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	enum pipe pipe = intel_get_pipe_from_connector(connector);
 	u32 hw_level;
@@ -726,8 +711,7 @@
 
 static void lpt_disable_backlight(struct intel_connector *connector)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	u32 tmp;
 
 	intel_panel_actually_set_backlight(connector, 0);
@@ -752,8 +736,7 @@
 
 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;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	u32 tmp;
 
 	intel_panel_actually_set_backlight(connector, 0);
@@ -772,8 +755,7 @@
 
 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;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	u32 tmp;
 
 	intel_panel_actually_set_backlight(connector, 0);
@@ -784,8 +766,7 @@
 
 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;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	enum pipe pipe = intel_get_pipe_from_connector(connector);
 	u32 tmp;
 
@@ -800,8 +781,7 @@
 
 static void bxt_disable_backlight(struct intel_connector *connector)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 tmp, val;
 
@@ -830,8 +810,7 @@
 
 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 drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 
 	if (!panel->backlight.present)
@@ -843,7 +822,7 @@
 	 * backlight. This will leave the backlight on unnecessarily when
 	 * another client is not activated.
 	 */
-	if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
+	if (dev_priv->dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
 		DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
 		return;
 	}
@@ -860,8 +839,7 @@
 
 static void lpt_enable_backlight(struct intel_connector *connector)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 pch_ctl1, pch_ctl2;
 
@@ -893,8 +871,7 @@
 
 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 drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	enum pipe pipe = intel_get_pipe_from_connector(connector);
 	enum transcoder cpu_transcoder =
@@ -940,8 +917,7 @@
 
 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 drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 ctl, freq;
 
@@ -958,7 +934,7 @@
 	ctl = freq << 17;
 	if (panel->backlight.combination_mode)
 		ctl |= BLM_LEGACY_MODE;
-	if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
+	if (IS_PINEVIEW(dev_priv) && panel->backlight.active_low_pwm)
 		ctl |= BLM_POLARITY_PNV;
 
 	I915_WRITE(BLC_PWM_CTL, ctl);
@@ -972,14 +948,13 @@
 	 * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2
 	 * that has backlight.
 	 */
-	if (IS_GEN2(dev))
+	if (IS_GEN2(dev_priv))
 		I915_WRITE(BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE);
 }
 
 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 drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	enum pipe pipe = intel_get_pipe_from_connector(connector);
 	u32 ctl, ctl2, freq;
@@ -1012,8 +987,7 @@
 
 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 drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	enum pipe pipe = intel_get_pipe_from_connector(connector);
 	u32 ctl, ctl2;
@@ -1044,8 +1018,7 @@
 
 static void bxt_enable_backlight(struct intel_connector *connector)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	enum pipe pipe = intel_get_pipe_from_connector(connector);
 	u32 pwm_ctl, val;
@@ -1102,8 +1075,7 @@
 
 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 drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	enum pipe pipe = intel_get_pipe_from_connector(connector);
 
@@ -1278,8 +1250,7 @@
  */
 static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	u32 mul, clock;
 
 	if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY)
@@ -1299,8 +1270,7 @@
  */
 static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	u32 mul, clock;
 
 	if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY)
@@ -1393,8 +1363,7 @@
 
 static u32 get_backlight_max_vbt(struct intel_connector *connector)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz;
 	u32 pwm;
@@ -1427,8 +1396,7 @@
  */
 static u32 get_backlight_min_vbt(struct intel_connector *connector)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	int min;
 
@@ -1453,8 +1421,7 @@
 
 static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 pch_ctl1, pch_ctl2, val;
 
@@ -1483,8 +1450,7 @@
 
 static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
 
@@ -1514,17 +1480,16 @@
 
 static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 ctl, val;
 
 	ctl = I915_READ(BLC_PWM_CTL);
 
-	if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev))
+	if (IS_GEN2(dev_priv) || IS_I915GM(dev_priv) || IS_I945GM(dev_priv))
 		panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
 
-	if (IS_PINEVIEW(dev))
+	if (IS_PINEVIEW(dev_priv))
 		panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
 
 	panel->backlight.max = ctl >> 17;
@@ -1552,8 +1517,7 @@
 
 static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 ctl, ctl2, val;
 
@@ -1586,8 +1550,7 @@
 
 static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 ctl, ctl2, val;
 
@@ -1608,7 +1571,7 @@
 
 	panel->backlight.min = get_backlight_min_vbt(connector);
 
-	val = _vlv_get_backlight(dev, pipe);
+	val = _vlv_get_backlight(dev_priv, pipe);
 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
 
 	panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
@@ -1620,8 +1583,7 @@
 static int
 bxt_setup_backlight(struct intel_connector *connector, enum pipe unused)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_panel *panel = &connector->panel;
 	u32 pwm_ctl, val;
 
@@ -1699,8 +1661,7 @@
 
 int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
 {
-	struct drm_device *dev = connector->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct intel_panel *panel = &intel_connector->panel;
 	int ret;
@@ -1755,36 +1716,35 @@
 static void
 intel_panel_init_backlight_funcs(struct intel_panel *panel)
 {
-	struct intel_connector *intel_connector =
+	struct intel_connector *connector =
 		container_of(panel, struct intel_connector, panel);
-	struct drm_device *dev = intel_connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 
-	if (IS_BROXTON(dev)) {
+	if (IS_BROXTON(dev_priv)) {
 		panel->backlight.setup = bxt_setup_backlight;
 		panel->backlight.enable = bxt_enable_backlight;
 		panel->backlight.disable = bxt_disable_backlight;
 		panel->backlight.set = bxt_set_backlight;
 		panel->backlight.get = bxt_get_backlight;
 		panel->backlight.hz_to_pwm = bxt_hz_to_pwm;
-	} else if (HAS_PCH_LPT(dev) || HAS_PCH_SPT(dev)) {
+	} else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_SPT(dev_priv)) {
 		panel->backlight.setup = lpt_setup_backlight;
 		panel->backlight.enable = lpt_enable_backlight;
 		panel->backlight.disable = lpt_disable_backlight;
 		panel->backlight.set = lpt_set_backlight;
 		panel->backlight.get = lpt_get_backlight;
-		if (HAS_PCH_LPT(dev))
+		if (HAS_PCH_LPT(dev_priv))
 			panel->backlight.hz_to_pwm = lpt_hz_to_pwm;
 		else
 			panel->backlight.hz_to_pwm = spt_hz_to_pwm;
-	} else if (HAS_PCH_SPLIT(dev)) {
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		panel->backlight.setup = pch_setup_backlight;
 		panel->backlight.enable = pch_enable_backlight;
 		panel->backlight.disable = pch_disable_backlight;
 		panel->backlight.set = pch_set_backlight;
 		panel->backlight.get = pch_get_backlight;
 		panel->backlight.hz_to_pwm = pch_hz_to_pwm;
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		if (dev_priv->vbt.has_mipi) {
 			panel->backlight.setup = pwm_setup_backlight;
 			panel->backlight.enable = pwm_enable_backlight;
@@ -1799,7 +1759,7 @@
 			panel->backlight.get = vlv_get_backlight;
 			panel->backlight.hz_to_pwm = vlv_hz_to_pwm;
 		}
-	} else if (IS_GEN4(dev)) {
+	} else if (IS_GEN4(dev_priv)) {
 		panel->backlight.setup = i965_setup_backlight;
 		panel->backlight.enable = i965_enable_backlight;
 		panel->backlight.disable = i965_disable_backlight;
@@ -1845,7 +1805,7 @@
 {
 	struct intel_connector *connector;
 
-	list_for_each_entry(connector, &dev->mode_config.connector_list, base.head)
+	for_each_intel_connector(dev, connector)
 		intel_backlight_device_register(connector);
 }
 
@@ -1853,6 +1813,6 @@
 {
 	struct intel_connector *connector;
 
-	list_for_each_entry(connector, &dev->mode_config.connector_list, base.head)
+	for_each_intel_connector(dev, connector)
 		intel_backlight_device_unregister(connector);
 }
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ee05ce8..eb5fa05 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -291,7 +291,7 @@
 	struct drm_device *dev = dev_priv->dev;
 	u32 val;
 
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0);
 		POSTING_READ(FW_BLC_SELF_VLV);
 		dev_priv->wm.vlv.cxsr = enable;
@@ -3314,7 +3314,7 @@
 	struct drm_device *dev = dev_priv->dev;
 	struct intel_crtc *crtc;
 
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
+	for_each_intel_crtc(dev, crtc) {
 		int i, level, max_level = ilk_wm_max_level(dev);
 		enum pipe pipe = crtc->pipe;
 
@@ -3523,8 +3523,7 @@
 	 * Otherwise, because of this_crtc being freshly enabled/disabled, the
 	 * other active pipes need new DDB allocation and WM values.
 	 */
-	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
-				base.head) {
+	for_each_intel_crtc(dev, intel_crtc) {
 		struct skl_pipe_wm pipe_wm = {};
 		bool wm_changed;
 
@@ -4405,7 +4404,7 @@
 
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (dev_priv->rps.enabled) {
-		if (IS_VALLEYVIEW(dev))
+		if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 			vlv_set_rps_idle(dev_priv);
 		else
 			gen6_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
@@ -4458,7 +4457,7 @@
 
 void intel_set_rps(struct drm_device *dev, u8 val)
 {
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		valleyview_set_rps(dev, val);
 	else
 		gen6_set_rps(dev, val);
@@ -4502,7 +4501,7 @@
 
 static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
 {
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		if (mode & (GEN7_RC_CTL_TO_MODE | GEN6_RC_CTL_EI_MODE(1)))
 			mode = GEN6_RC_CTL_RC6_ENABLE;
 		else
@@ -4673,8 +4672,7 @@
 	/* 2b: Program RC6 thresholds.*/
 
 	/* WaRsDoubleRc6WrlWithCoarsePowerGating: Doubling WRL only when CPG is enabled */
-	if (IS_SKYLAKE(dev) && !((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) &&
-				 IS_SKL_REVID(dev, 0, SKL_REVID_E0)))
+	if (IS_SKYLAKE(dev))
 		I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 108 << 16);
 	else
 		I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
@@ -4715,9 +4713,8 @@
 	 * 3b: Enable Coarse Power Gating only when RC6 is enabled.
 	 * WaRsDisableCoarsePowerGating:skl,bxt - Render/Media PG need to be disabled with RC6.
 	 */
-	if (IS_BXT_REVID(dev, 0, BXT_REVID_A1) ||
-	    ((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) &&
-	     IS_SKL_REVID(dev, 0, SKL_REVID_E0)))
+	if ((IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) ||
+	    ((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && (INTEL_REVID(dev) <= SKL_REVID_F0)))
 		I915_WRITE(GEN9_PG_ENABLE, 0);
 	else
 		I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
@@ -5101,7 +5098,17 @@
 
 static int valleyview_rps_min_freq(struct drm_i915_private *dev_priv)
 {
-	return vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff;
+	u32 val;
+
+	val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff;
+	/*
+	 * According to the BYT Punit GPU turbo HAS 1.1.6.3 the minimum value
+	 * for the minimum frequency in GPLL mode is 0xc1. Contrary to this on
+	 * a BYT-M B0 the above register contains 0xbf. Moreover when setting
+	 * a frequency Punit will not allow values below 0xc0. Clamp it 0xc0
+	 * to make sure it matches what Punit accepts.
+	 */
+	return max_t(u32, val, 0xc0);
 }
 
 /* Check that the pctx buffer wasn't move under us. */
@@ -6006,7 +6013,17 @@
 
 void intel_init_gt_powersave(struct drm_device *dev)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
 	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
+	/*
+	 * RPM depends on RC6 to save restore the GT HW context, so make RC6 a
+	 * requirement.
+	 */
+	if (!i915.enable_rc6) {
+		DRM_INFO("RC6 disabled, disabling runtime PM support\n");
+		intel_runtime_pm_get(dev_priv);
+	}
 
 	if (IS_CHERRYVIEW(dev))
 		cherryview_init_gt_powersave(dev);
@@ -6016,10 +6033,15 @@
 
 void intel_cleanup_gt_powersave(struct drm_device *dev)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
 	if (IS_CHERRYVIEW(dev))
 		return;
 	else if (IS_VALLEYVIEW(dev))
 		valleyview_cleanup_gt_powersave(dev);
+
+	if (!i915.enable_rc6)
+		intel_runtime_pm_put(dev_priv);
 }
 
 static void gen6_suspend_rps(struct drm_device *dev)
@@ -7223,4 +7245,6 @@
 	INIT_LIST_HEAD(&dev_priv->rps.mmioflips.link);
 
 	dev_priv->pm.suspended = false;
+	atomic_set(&dev_priv->pm.wakeref_count, 0);
+	atomic_set(&dev_priv->pm.atomic_seq, 0);
 }
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index b6609e6..9ccff30 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -267,25 +267,20 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	uint32_t max_sleep_time = 0x1f;
-	/* Lately it was identified that depending on panel idle frame count
-	 * calculated at HW can be off by 1. So let's use what came
-	 * from VBT + 1.
-	 * There are also other cases where panel demands at least 4
-	 * but VBT is not being set. To cover these 2 cases lets use
-	 * at least 5 when VBT isn't set to be on the safest side.
+	/*
+	 * Let's respect VBT in case VBT asks a higher idle_frame value.
+	 * Let's use 6 as the minimum to cover all known cases including
+	 * the off-by-one issue that HW has in some cases. Also there are
+	 * cases where sink should be able to train
+	 * with the 5 or 6 idle patterns.
 	 */
-	uint32_t idle_frames = dev_priv->vbt.psr.idle_frames ?
-			       dev_priv->vbt.psr.idle_frames + 1 : 5;
+	uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
 	uint32_t val = 0x0;
-	const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
 
-	if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) {
-		/* Sink should be able to train with the 5 or 6 idle patterns */
-		idle_frames += 4;
-	}
+	if (IS_HASWELL(dev))
+		val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
 
 	I915_WRITE(EDP_PSR_CTL, val |
-		   (IS_BROADWELL(dev) ? 0 : link_entry_time) |
 		   max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT |
 		   idle_frames << EDP_PSR_IDLE_FRAME_SHIFT |
 		   EDP_PSR_ENABLE);
@@ -332,8 +327,8 @@
 		return false;
 	}
 
-	if (!IS_VALLEYVIEW(dev) && ((dev_priv->vbt.psr.full_link) ||
-				    (dig_port->port != PORT_A))) {
+	if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
+	    ((dev_priv->vbt.psr.full_link) || (dig_port->port != PORT_A))) {
 		DRM_DEBUG_KMS("PSR condition failed: Link Standby requested/needed but not supported on this platform\n");
 		return false;
 	}
@@ -650,7 +645,7 @@
 	 * Single frame update is already supported on BDW+ but it requires
 	 * many W/A and it isn't really needed.
 	 */
-	if (!IS_VALLEYVIEW(dev))
+	if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev))
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 57d78f2..339701d 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -27,29 +27,13 @@
  *
  */
 
+#include <linux/log2.h>
 #include <drm/drmP.h>
 #include "i915_drv.h"
 #include <drm/i915_drm.h>
 #include "i915_trace.h"
 #include "intel_drv.h"
 
-bool
-intel_ring_initialized(struct intel_engine_cs *ring)
-{
-	struct drm_device *dev = ring->dev;
-
-	if (!dev)
-		return false;
-
-	if (i915.enable_execlists) {
-		struct intel_context *dctx = ring->default_context;
-		struct intel_ringbuffer *ringbuf = dctx->engine[ring->id].ringbuf;
-
-		return ringbuf->obj;
-	} else
-		return ring->buffer && ring->buffer->obj;
-}
-
 int __intel_ring_space(int head, int tail, int size)
 {
 	int space = head - tail;
@@ -995,7 +979,7 @@
 		 * Only consider slices where one, and only one, subslice has 7
 		 * EUs
 		 */
-		if (hweight8(dev_priv->info.subslice_7eu[i]) != 1)
+		if (!is_power_of_2(dev_priv->info.subslice_7eu[i]))
 			continue;
 
 		/*
@@ -1034,10 +1018,6 @@
 		return ret;
 
 	if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) {
-		/* WaDisableHDCInvalidation:skl */
-		I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
-			   BDW_DISABLE_HDC_INVALIDATION);
-
 		/* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
 		I915_WRITE(FF_SLICE_CS_CHICKEN2,
 			   _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
@@ -1062,7 +1042,7 @@
 		WA_SET_BIT_MASKED(HIZ_CHICKEN,
 				  BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
 
-	if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) {
+	if (IS_SKL_REVID(dev, 0, SKL_REVID_F0)) {
 		/*
 		 *Use Force Non-Coherent whenever executing a 3D context. This
 		 * is a workaround for a possible hang in the unlikely event
@@ -1071,6 +1051,10 @@
 		/* WaForceEnableNonCoherent:skl */
 		WA_SET_BIT_MASKED(HDC_CHICKEN0,
 				  HDC_FORCE_NON_COHERENT);
+
+		/* WaDisableHDCInvalidation:skl */
+		I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
+			   BDW_DISABLE_HDC_INVALIDATION);
 	}
 
 	/* WaBarrierPerformanceFixDisable:skl */
@@ -2167,8 +2151,10 @@
 	init_waitqueue_head(&ring->irq_queue);
 
 	ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE);
-	if (IS_ERR(ringbuf))
-		return PTR_ERR(ringbuf);
+	if (IS_ERR(ringbuf)) {
+		ret = PTR_ERR(ringbuf);
+		goto error;
+	}
 	ring->buffer = ringbuf;
 
 	if (I915_NEED_GFX_HWS(dev)) {
@@ -2197,8 +2183,7 @@
 	return 0;
 
 error:
-	intel_ringbuffer_free(ringbuf);
-	ring->buffer = NULL;
+	intel_cleanup_ring_buffer(ring);
 	return ret;
 }
 
@@ -2211,12 +2196,14 @@
 
 	dev_priv = to_i915(ring->dev);
 
-	intel_stop_ring_buffer(ring);
-	WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
+	if (ring->buffer) {
+		intel_stop_ring_buffer(ring);
+		WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
 
-	intel_unpin_ringbuffer_obj(ring->buffer);
-	intel_ringbuffer_free(ring->buffer);
-	ring->buffer = NULL;
+		intel_unpin_ringbuffer_obj(ring->buffer);
+		intel_ringbuffer_free(ring->buffer);
+		ring->buffer = NULL;
+	}
 
 	if (ring->cleanup)
 		ring->cleanup(ring);
@@ -2225,6 +2212,7 @@
 
 	i915_cmd_parser_fini_ring(ring);
 	i915_gem_batch_pool_fini(&ring->batch_pool);
+	ring->dev = NULL;
 }
 
 static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 5d1eb20..49574ff 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -350,7 +350,11 @@
 	u32 (*get_cmd_length_mask)(u32 cmd_header);
 };
 
-bool intel_ring_initialized(struct intel_engine_cs *ring);
+static inline bool
+intel_ring_initialized(struct intel_engine_cs *ring)
+{
+	return ring->dev != NULL;
+}
 
 static inline unsigned
 intel_ring_flag(struct intel_engine_cs *ring)
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 2c2151f..ddbdbff 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -538,8 +538,7 @@
 
 	WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5),
 		  "DC5 already programmed to be enabled.\n");
-	WARN_ONCE(dev_priv->pm.suspended,
-		  "DC5 cannot be enabled, if platform is runtime-suspended.\n");
+	assert_rpm_wakelock_held(dev_priv);
 
 	assert_csr_loaded(dev_priv);
 }
@@ -553,8 +552,7 @@
 	if (dev_priv->power_domains.initializing)
 		return;
 
-	WARN_ONCE(dev_priv->pm.suspended,
-		"Disabling of DC5 while platform is runtime-suspended should never happen.\n");
+	assert_rpm_wakelock_held(dev_priv);
 }
 
 static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
@@ -1975,14 +1973,29 @@
  */
 void intel_power_domains_fini(struct drm_i915_private *dev_priv)
 {
-	/* The i915.ko module is still not prepared to be loaded when
+	struct device *device = &dev_priv->dev->pdev->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. */
+	 * we're going to unload/reload.
+	 * The following also reacquires the RPM reference the core passed
+	 * to the driver during loading, which is dropped in
+	 * intel_runtime_pm_enable(). We have to hand back the control of the
+	 * device to the core with this reference held.
+	 */
 	intel_display_set_init_power(dev_priv, true);
 
 	/* Remove the refcount we took to keep power well support disabled. */
 	if (!i915.disable_power_well)
 		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+
+	/*
+	 * Remove the refcount we took in intel_runtime_pm_enable() in case
+	 * the platform doesn't support runtime PM.
+	 */
+	if (!HAS_RUNTIME_PM(dev_priv))
+		pm_runtime_put(device);
 }
 
 static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)
@@ -2226,11 +2239,10 @@
 	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");
+
+	atomic_inc(&dev_priv->pm.wakeref_count);
+	assert_rpm_wakelock_held(dev_priv);
 }
 
 /**
@@ -2255,11 +2267,10 @@
 	struct drm_device *dev = dev_priv->dev;
 	struct device *device = &dev->pdev->dev;
 
-	if (!HAS_RUNTIME_PM(dev))
-		return;
-
-	WARN(dev_priv->pm.suspended, "Getting nosync-ref while suspended.\n");
+	assert_rpm_wakelock_held(dev_priv);
 	pm_runtime_get_noresume(device);
+
+	atomic_inc(&dev_priv->pm.wakeref_count);
 }
 
 /**
@@ -2275,8 +2286,9 @@
 	struct drm_device *dev = dev_priv->dev;
 	struct device *device = &dev->pdev->dev;
 
-	if (!HAS_RUNTIME_PM(dev))
-		return;
+	assert_rpm_wakelock_held(dev_priv);
+	if (atomic_dec_and_test(&dev_priv->pm.wakeref_count))
+		atomic_inc(&dev_priv->pm.atomic_seq);
 
 	pm_runtime_mark_last_busy(device);
 	pm_runtime_put_autosuspend(device);
@@ -2297,22 +2309,27 @@
 	struct drm_device *dev = dev_priv->dev;
 	struct device *device = &dev->pdev->dev;
 
-	if (!HAS_RUNTIME_PM(dev))
-		return;
-
-	/*
-	 * RPM depends on RC6 to save restore the GT HW context, so make RC6 a
-	 * requirement.
-	 */
-	if (!intel_enable_rc6(dev)) {
-		DRM_INFO("RC6 disabled, disabling runtime PM support\n");
-		return;
-	}
-
 	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
 	pm_runtime_mark_last_busy(device);
-	pm_runtime_use_autosuspend(device);
 
+	/*
+	 * Take a permanent reference to disable the RPM functionality and drop
+	 * it only when unloading the driver. Use the low level get/put helpers,
+	 * so the driver's own RPM reference tracking asserts also work on
+	 * platforms without RPM support.
+	 */
+	if (!HAS_RUNTIME_PM(dev)) {
+		pm_runtime_dont_use_autosuspend(device);
+		pm_runtime_get_sync(device);
+	} else {
+		pm_runtime_use_autosuspend(device);
+	}
+
+	/*
+	 * The core calls the driver load handler with an RPM reference held.
+	 * We drop that here and will reacquire it during unloading in
+	 * intel_power_domains_fini().
+	 */
 	pm_runtime_put_autosuspend(device);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index dbf4213..4ff7a1f 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -951,7 +951,7 @@
 	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
 		return -EINVAL;
 
-	if (IS_VALLEYVIEW(dev) &&
+	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
 	    set->flags & I915_SET_COLORKEY_DESTINATION)
 		return -EINVAL;
 
@@ -1086,7 +1086,7 @@
 			intel_plane->max_downscale = 1;
 		}
 
-		if (IS_VALLEYVIEW(dev)) {
+		if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 			intel_plane->update_plane = vlv_update_plane;
 			intel_plane->disable_plane = vlv_disable_plane;
 
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index c2358ba..277e60a 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -50,13 +50,6 @@
 	return "unknown";
 }
 
-static void
-assert_device_not_suspended(struct drm_i915_private *dev_priv)
-{
-	WARN_ONCE(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
-		  "Device suspended\n");
-}
-
 static inline void
 fw_domain_reset(const struct intel_uncore_forcewake_domain *d)
 {
@@ -236,7 +229,7 @@
 	struct intel_uncore_forcewake_domain *domain = (void *)arg;
 	unsigned long irqflags;
 
-	assert_device_not_suspended(domain->i915);
+	assert_rpm_device_not_suspended(domain->i915);
 
 	spin_lock_irqsave(&domain->i915->uncore.lock, irqflags);
 	if (WARN_ON(domain->wake_count == 0))
@@ -411,7 +404,7 @@
 	if (!dev_priv->uncore.funcs.force_wake_get)
 		return;
 
-	WARN_ON(dev_priv->pm.suspended);
+	assert_rpm_wakelock_held(dev_priv);
 
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 	__intel_uncore_forcewake_get(dev_priv, fw_domains);
@@ -628,7 +621,7 @@
 
 #define GEN2_READ_HEADER(x) \
 	u##x val = 0; \
-	assert_device_not_suspended(dev_priv);
+	assert_rpm_wakelock_held(dev_priv);
 
 #define GEN2_READ_FOOTER \
 	trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \
@@ -670,7 +663,7 @@
 	u32 offset = i915_mmio_reg_offset(reg); \
 	unsigned long irqflags; \
 	u##x val = 0; \
-	assert_device_not_suspended(dev_priv); \
+	assert_rpm_wakelock_held(dev_priv); \
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
 
 #define GEN6_READ_FOOTER \
@@ -803,7 +796,7 @@
 #define VGPU_READ_HEADER(x) \
 	unsigned long irqflags; \
 	u##x val = 0; \
-	assert_device_not_suspended(dev_priv); \
+	assert_rpm_device_not_suspended(dev_priv); \
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
 
 #define VGPU_READ_FOOTER \
@@ -830,7 +823,7 @@
 
 #define GEN2_WRITE_HEADER \
 	trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
-	assert_device_not_suspended(dev_priv); \
+	assert_rpm_wakelock_held(dev_priv); \
 
 #define GEN2_WRITE_FOOTER
 
@@ -870,7 +863,7 @@
 	u32 offset = i915_mmio_reg_offset(reg); \
 	unsigned long irqflags; \
 	trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
-	assert_device_not_suspended(dev_priv); \
+	assert_rpm_wakelock_held(dev_priv); \
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
 
 #define GEN6_WRITE_FOOTER \
@@ -1046,7 +1039,7 @@
 #define VGPU_WRITE_HEADER \
 	unsigned long irqflags; \
 	trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
-	assert_device_not_suspended(dev_priv); \
+	assert_rpm_device_not_suspended(dev_priv); \
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
 
 #define VGPU_WRITE_FOOTER \
@@ -1115,7 +1108,7 @@
 		d->val_clear = _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL);
 	}
 
-	if (IS_VALLEYVIEW(dev_priv))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		d->reg_post = FORCEWAKE_ACK_VLV;
 	else if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv) || IS_GEN8(dev_priv))
 		d->reg_post = ECOBUS;
@@ -1148,7 +1141,7 @@
 			       FORCEWAKE_ACK_BLITTER_GEN9);
 		fw_domain_init(dev_priv, FW_DOMAIN_ID_MEDIA,
 			       FORCEWAKE_MEDIA_GEN9, FORCEWAKE_ACK_MEDIA_GEN9);
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		dev_priv->uncore.funcs.force_wake_get = fw_domains_get;
 		if (!IS_CHERRYVIEW(dev))
 			dev_priv->uncore.funcs.force_wake_put =
diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild
index a34b437..2527bf4 100644
--- a/drivers/gpu/drm/nouveau/Kbuild
+++ b/drivers/gpu/drm/nouveau/Kbuild
@@ -24,7 +24,6 @@
 nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
 nouveau-y += nouveau_nvif.o
 nouveau-$(CONFIG_NOUVEAU_PLATFORM_DRIVER) += nouveau_platform.o
-nouveau-y += nouveau_sysfs.o
 nouveau-y += nouveau_usif.o # userspace <-> nvif
 nouveau-y += nouveau_vga.o
 
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0002.h b/drivers/gpu/drm/nouveau/include/nvif/cl0002.h
new file mode 100644
index 0000000..6d72ed3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl0002.h
@@ -0,0 +1,66 @@
+#ifndef __NVIF_CL0002_H__
+#define __NVIF_CL0002_H__
+
+struct nv_dma_v0 {
+	__u8  version;
+#define NV_DMA_V0_TARGET_VM                                                0x00
+#define NV_DMA_V0_TARGET_VRAM                                              0x01
+#define NV_DMA_V0_TARGET_PCI                                               0x02
+#define NV_DMA_V0_TARGET_PCI_US                                            0x03
+#define NV_DMA_V0_TARGET_AGP                                               0x04
+	__u8  target;
+#define NV_DMA_V0_ACCESS_VM                                                0x00
+#define NV_DMA_V0_ACCESS_RD                                                0x01
+#define NV_DMA_V0_ACCESS_WR                                                0x02
+#define NV_DMA_V0_ACCESS_RDWR                 (NV_DMA_V0_ACCESS_RD | NV_DMA_V0_ACCESS_WR)
+	__u8  access;
+	__u8  pad03[5];
+	__u64 start;
+	__u64 limit;
+	/* ... chipset-specific class data */
+};
+
+struct nv50_dma_v0 {
+	__u8  version;
+#define NV50_DMA_V0_PRIV_VM                                                0x00
+#define NV50_DMA_V0_PRIV_US                                                0x01
+#define NV50_DMA_V0_PRIV__S                                                0x02
+	__u8  priv;
+#define NV50_DMA_V0_PART_VM                                                0x00
+#define NV50_DMA_V0_PART_256                                               0x01
+#define NV50_DMA_V0_PART_1KB                                               0x02
+	__u8  part;
+#define NV50_DMA_V0_COMP_NONE                                              0x00
+#define NV50_DMA_V0_COMP_1                                                 0x01
+#define NV50_DMA_V0_COMP_2                                                 0x02
+#define NV50_DMA_V0_COMP_VM                                                0x03
+	__u8  comp;
+#define NV50_DMA_V0_KIND_PITCH                                             0x00
+#define NV50_DMA_V0_KIND_VM                                                0x7f
+	__u8  kind;
+	__u8  pad05[3];
+};
+
+struct gf100_dma_v0 {
+	__u8  version;
+#define GF100_DMA_V0_PRIV_VM                                               0x00
+#define GF100_DMA_V0_PRIV_US                                               0x01
+#define GF100_DMA_V0_PRIV__S                                               0x02
+	__u8  priv;
+#define GF100_DMA_V0_KIND_PITCH                                            0x00
+#define GF100_DMA_V0_KIND_VM                                               0xff
+	__u8  kind;
+	__u8  pad03[5];
+};
+
+struct gf119_dma_v0 {
+	__u8  version;
+#define GF119_DMA_V0_PAGE_LP                                               0x00
+#define GF119_DMA_V0_PAGE_SP                                               0x01
+	__u8  page;
+#define GF119_DMA_V0_KIND_PITCH                                            0x00
+#define GF119_DMA_V0_KIND_VM                                               0xff
+	__u8  kind;
+	__u8  pad03[5];
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0046.h b/drivers/gpu/drm/nouveau/include/nvif/cl0046.h
new file mode 100644
index 0000000..a6a71f4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl0046.h
@@ -0,0 +1,28 @@
+#ifndef __NVIF_CL0046_H__
+#define __NVIF_CL0046_H__
+
+#define NV04_DISP_NTFY_VBLANK                                              0x00
+#define NV04_DISP_NTFY_CONN                                                0x01
+
+struct nv04_disp_mthd_v0 {
+	__u8  version;
+#define NV04_DISP_SCANOUTPOS                                               0x00
+	__u8  method;
+	__u8  head;
+	__u8  pad03[5];
+};
+
+struct nv04_disp_scanoutpos_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__s64 time[2];
+	__u16 vblanks;
+	__u16 vblanke;
+	__u16 vtotal;
+	__u16 vline;
+	__u16 hblanks;
+	__u16 hblanke;
+	__u16 htotal;
+	__u16 hline;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl006b.h b/drivers/gpu/drm/nouveau/include/nvif/cl006b.h
new file mode 100644
index 0000000..309ab8a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl006b.h
@@ -0,0 +1,11 @@
+#ifndef __NVIF_CL006B_H__
+#define __NVIF_CL006B_H__
+
+struct nv03_channel_dma_v0 {
+	__u8  version;
+	__u8  chid;
+	__u8  pad02[2];
+	__u32 offset;
+	__u64 pushbuf;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h
new file mode 100644
index 0000000..331620a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h
@@ -0,0 +1,45 @@
+#ifndef __NVIF_CL0080_H__
+#define __NVIF_CL0080_H__
+
+struct nv_device_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__u64 device;	/* device identifier, ~0 for client default */
+};
+
+#define NV_DEVICE_V0_INFO                                                  0x00
+#define NV_DEVICE_V0_TIME                                                  0x01
+
+struct nv_device_info_v0 {
+	__u8  version;
+#define NV_DEVICE_INFO_V0_IGP                                              0x00
+#define NV_DEVICE_INFO_V0_PCI                                              0x01
+#define NV_DEVICE_INFO_V0_AGP                                              0x02
+#define NV_DEVICE_INFO_V0_PCIE                                             0x03
+#define NV_DEVICE_INFO_V0_SOC                                              0x04
+	__u8  platform;
+	__u16 chipset;	/* from NV_PMC_BOOT_0 */
+	__u8  revision;	/* from NV_PMC_BOOT_0 */
+#define NV_DEVICE_INFO_V0_TNT                                              0x01
+#define NV_DEVICE_INFO_V0_CELSIUS                                          0x02
+#define NV_DEVICE_INFO_V0_KELVIN                                           0x03
+#define NV_DEVICE_INFO_V0_RANKINE                                          0x04
+#define NV_DEVICE_INFO_V0_CURIE                                            0x05
+#define NV_DEVICE_INFO_V0_TESLA                                            0x06
+#define NV_DEVICE_INFO_V0_FERMI                                            0x07
+#define NV_DEVICE_INFO_V0_KEPLER                                           0x08
+#define NV_DEVICE_INFO_V0_MAXWELL                                          0x09
+	__u8  family;
+	__u8  pad06[2];
+	__u64 ram_size;
+	__u64 ram_user;
+	char  chip[16];
+	char  name[64];
+};
+
+struct nv_device_time_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__u64 time;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h b/drivers/gpu/drm/nouveau/include/nvif/cl506e.h
new file mode 100644
index 0000000..aa94b8c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl506e.h
@@ -0,0 +1,12 @@
+#ifndef __NVIF_CL506E_H__
+#define __NVIF_CL506E_H__
+
+struct nv50_channel_dma_v0 {
+	__u8  version;
+	__u8  chid;
+	__u8  pad02[6];
+	__u64 vm;
+	__u64 pushbuf;
+	__u64 offset;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h b/drivers/gpu/drm/nouveau/include/nvif/cl506f.h
new file mode 100644
index 0000000..3b71019
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl506f.h
@@ -0,0 +1,13 @@
+#ifndef __NVIF_CL506F_H__
+#define __NVIF_CL506F_H__
+
+struct nv50_channel_gpfifo_v0 {
+	__u8  version;
+	__u8  chid;
+	__u8  pad02[2];
+	__u32 ilength;
+	__u64 ioffset;
+	__u64 pushbuf;
+	__u64 vm;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
new file mode 100644
index 0000000..d15c296
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
@@ -0,0 +1,99 @@
+#ifndef __NVIF_CL5070_H__
+#define __NVIF_CL5070_H__
+
+#define NV50_DISP_MTHD                                                     0x00
+
+struct nv50_disp_mthd_v0 {
+	__u8  version;
+#define NV50_DISP_SCANOUTPOS                                               0x00
+	__u8  method;
+	__u8  head;
+	__u8  pad03[5];
+};
+
+struct nv50_disp_scanoutpos_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__s64 time[2];
+	__u16 vblanks;
+	__u16 vblanke;
+	__u16 vtotal;
+	__u16 vline;
+	__u16 hblanks;
+	__u16 hblanke;
+	__u16 htotal;
+	__u16 hline;
+};
+
+struct nv50_disp_mthd_v1 {
+	__u8  version;
+#define NV50_DISP_MTHD_V1_DAC_PWR                                          0x10
+#define NV50_DISP_MTHD_V1_DAC_LOAD                                         0x11
+#define NV50_DISP_MTHD_V1_SOR_PWR                                          0x20
+#define NV50_DISP_MTHD_V1_SOR_HDA_ELD                                      0x21
+#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR                                     0x22
+#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT                                  0x23
+#define NV50_DISP_MTHD_V1_SOR_DP_PWR                                       0x24
+#define NV50_DISP_MTHD_V1_PIOR_PWR                                         0x30
+	__u8  method;
+	__u16 hasht;
+	__u16 hashm;
+	__u8  pad06[2];
+};
+
+struct nv50_disp_dac_pwr_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  data;
+	__u8  vsync;
+	__u8  hsync;
+	__u8  pad05[3];
+};
+
+struct nv50_disp_dac_load_v0 {
+	__u8  version;
+	__u8  load;
+	__u8  pad02[2];
+	__u32 data;
+};
+
+struct nv50_disp_sor_pwr_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  pad02[6];
+};
+
+struct nv50_disp_sor_hda_eld_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__u8  data[];
+};
+
+struct nv50_disp_sor_hdmi_pwr_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  max_ac_packet;
+	__u8  rekey;
+	__u8  pad04[4];
+};
+
+struct nv50_disp_sor_lvds_script_v0 {
+	__u8  version;
+	__u8  pad01[1];
+	__u16 script;
+	__u8  pad04[4];
+};
+
+struct nv50_disp_sor_dp_pwr_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  pad02[6];
+};
+
+struct nv50_disp_pior_pwr_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  type;
+	__u8  pad03[5];
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507a.h b/drivers/gpu/drm/nouveau/include/nvif/cl507a.h
new file mode 100644
index 0000000..12e0643
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl507a.h
@@ -0,0 +1,11 @@
+#ifndef __NVIF_CL507A_H__
+#define __NVIF_CL507A_H__
+
+struct nv50_disp_cursor_v0 {
+	__u8  version;
+	__u8  head;
+	__u8  pad02[6];
+};
+
+#define NV50_DISP_CURSOR_V0_NTFY_UEVENT                                    0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507b.h b/drivers/gpu/drm/nouveau/include/nvif/cl507b.h
new file mode 100644
index 0000000..99e9d8c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl507b.h
@@ -0,0 +1,11 @@
+#ifndef __NVIF_CL507B_H__
+#define __NVIF_CL507B_H__
+
+struct nv50_disp_overlay_v0 {
+	__u8  version;
+	__u8  head;
+	__u8  pad02[6];
+};
+
+#define NV50_DISP_OVERLAY_V0_NTFY_UEVENT                                   0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507c.h b/drivers/gpu/drm/nouveau/include/nvif/cl507c.h
new file mode 100644
index 0000000..6af70db
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl507c.h
@@ -0,0 +1,12 @@
+#ifndef __NVIF_CL507C_H__
+#define __NVIF_CL507C_H__
+
+struct nv50_disp_base_channel_dma_v0 {
+	__u8  version;
+	__u8  head;
+	__u8  pad02[6];
+	__u64 pushbuf;
+};
+
+#define NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT                          0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507d.h b/drivers/gpu/drm/nouveau/include/nvif/cl507d.h
new file mode 100644
index 0000000..5ab0c9e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl507d.h
@@ -0,0 +1,11 @@
+#ifndef __NVIF_CL507D_H__
+#define __NVIF_CL507D_H__
+
+struct nv50_disp_core_channel_dma_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__u64 pushbuf;
+};
+
+#define NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT                          0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507e.h b/drivers/gpu/drm/nouveau/include/nvif/cl507e.h
new file mode 100644
index 0000000..c06209f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl507e.h
@@ -0,0 +1,12 @@
+#ifndef __NVIF_CL507E_H__
+#define __NVIF_CL507E_H__
+
+struct nv50_disp_overlay_channel_dma_v0 {
+	__u8  version;
+	__u8  head;
+	__u8  pad02[6];
+	__u64 pushbuf;
+};
+
+#define NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT                       0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h
new file mode 100644
index 0000000..05e6ef7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h
@@ -0,0 +1,14 @@
+#ifndef __NVIF_CL826E_H__
+#define __NVIF_CL826E_H__
+
+struct g82_channel_dma_v0 {
+	__u8  version;
+	__u8  chid;
+	__u8  pad02[6];
+	__u64 vm;
+	__u64 pushbuf;
+	__u64 offset;
+};
+
+#define G82_CHANNEL_DMA_V0_NTFY_UEVENT                                     0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h
new file mode 100644
index 0000000..cecafcb
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h
@@ -0,0 +1,15 @@
+#ifndef __NVIF_CL826F_H__
+#define __NVIF_CL826F_H__
+
+struct g82_channel_gpfifo_v0 {
+	__u8  version;
+	__u8  chid;
+	__u8  pad02[2];
+	__u32 ilength;
+	__u64 ioffset;
+	__u64 pushbuf;
+	__u64 vm;
+};
+
+#define G82_CHANNEL_GPFIFO_V0_NTFY_UEVENT                                  0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h
new file mode 100644
index 0000000..2caf083
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h
@@ -0,0 +1,14 @@
+#ifndef __NVIF_CL906F_H__
+#define __NVIF_CL906F_H__
+
+struct fermi_channel_gpfifo_v0 {
+	__u8  version;
+	__u8  chid;
+	__u8  pad02[2];
+	__u32 ilength;
+	__u64 ioffset;
+	__u64 vm;
+};
+
+#define FERMI_CHANNEL_GPFIFO_V0_NTFY_UEVENT                                0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl9097.h b/drivers/gpu/drm/nouveau/include/nvif/cl9097.h
new file mode 100644
index 0000000..4057676
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl9097.h
@@ -0,0 +1,44 @@
+#ifndef __NVIF_CL9097_H__
+#define __NVIF_CL9097_H__
+
+#define FERMI_A_ZBC_COLOR                                                  0x00
+#define FERMI_A_ZBC_DEPTH                                                  0x01
+
+struct fermi_a_zbc_color_v0 {
+	__u8  version;
+#define FERMI_A_ZBC_COLOR_V0_FMT_ZERO                                      0x01
+#define FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE                                 0x02
+#define FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32                       0x04
+#define FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16                           0x08
+#define FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16                       0x0c
+#define FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16                       0x10
+#define FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16                       0x14
+#define FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16                       0x16
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8                                  0x18
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8                               0x1c
+#define FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10                               0x20
+#define FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10                           0x24
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8                                  0x28
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8                               0x2c
+#define FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8                              0x30
+#define FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8                              0x34
+#define FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8                              0x38
+#define FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10                               0x3c
+#define FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11                              0x40
+	__u8  format;
+	__u8  index;
+	__u8  pad03[5];
+	__u32 ds[4];
+	__u32 l2[4];
+};
+
+struct fermi_a_zbc_depth_v0 {
+	__u8  version;
+#define FERMI_A_ZBC_DEPTH_V0_FMT_FP32                                      0x01
+	__u8  format;
+	__u8  index;
+	__u8  pad03[5];
+	__u32 ds;
+	__u32 l2;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h
new file mode 100644
index 0000000..85b7827
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h
@@ -0,0 +1,21 @@
+#ifndef __NVIF_CLA06F_H__
+#define __NVIF_CLA06F_H__
+
+struct kepler_channel_gpfifo_a_v0 {
+	__u8  version;
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR                               0x01
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPDEC                           0x02
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPPP                            0x04
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSVLD                            0x08
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0                              0x10
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1                              0x20
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_ENC                              0x40
+	__u8  engine;
+	__u16 chid;
+	__u32 ilength;
+	__u64 ioffset;
+	__u64 vm;
+};
+
+#define KEPLER_CHANNEL_GPFIFO_A_V0_NTFY_UEVENT                             0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h
index 95a64d8..4179cd6 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/class.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/class.h
@@ -1,16 +1,21 @@
 #ifndef __NVIF_CLASS_H__
 #define __NVIF_CLASS_H__
 
-/*******************************************************************************
- * class identifiers
- ******************************************************************************/
+/* these class numbers are made up by us, and not nvidia-assigned */
+#define NVIF_CLASS_CONTROL                                    /* if0001.h */ -1
+#define NVIF_CLASS_PERFMON                                    /* if0002.h */ -2
+#define NVIF_CLASS_PERFDOM                                    /* if0003.h */ -3
+#define NVIF_CLASS_SW_NV04                                    /* if0004.h */ -4
+#define NVIF_CLASS_SW_NV10                                    /* if0005.h */ -5
+#define NVIF_CLASS_SW_NV50                                    /* if0005.h */ -6
+#define NVIF_CLASS_SW_GF100                                   /* if0005.h */ -7
 
 /* the below match nvidia-assigned (either in hw, or sw) class numbers */
-#define NV_DEVICE                                                    0x00000080
+#define NV_DEVICE                                     /* cl0080.h */ 0x00000080
 
-#define NV_DMA_FROM_MEMORY                                           0x00000002
-#define NV_DMA_TO_MEMORY                                             0x00000003
-#define NV_DMA_IN_MEMORY                                             0x0000003d
+#define NV_DMA_FROM_MEMORY                            /* cl0002.h */ 0x00000002
+#define NV_DMA_TO_MEMORY                              /* cl0002.h */ 0x00000003
+#define NV_DMA_IN_MEMORY                              /* cl0002.h */ 0x0000003d
 
 #define FERMI_TWOD_A                                                 0x0000902d
 
@@ -19,85 +24,85 @@
 #define KEPLER_INLINE_TO_MEMORY_A                                    0x0000a040
 #define KEPLER_INLINE_TO_MEMORY_B                                    0x0000a140
 
-#define NV04_DISP                                                    0x00000046
+#define NV04_DISP                                     /* cl0046.h */ 0x00000046
 
-#define NV03_CHANNEL_DMA                                             0x0000006b
-#define NV10_CHANNEL_DMA                                             0x0000006e
-#define NV17_CHANNEL_DMA                                             0x0000176e
-#define NV40_CHANNEL_DMA                                             0x0000406e
-#define NV50_CHANNEL_DMA                                             0x0000506e
-#define G82_CHANNEL_DMA                                              0x0000826e
+#define NV03_CHANNEL_DMA                              /* cl506b.h */ 0x0000006b
+#define NV10_CHANNEL_DMA                              /* cl506b.h */ 0x0000006e
+#define NV17_CHANNEL_DMA                              /* cl506b.h */ 0x0000176e
+#define NV40_CHANNEL_DMA                              /* cl506b.h */ 0x0000406e
+#define NV50_CHANNEL_DMA                              /* cl506e.h */ 0x0000506e
+#define G82_CHANNEL_DMA                               /* cl826e.h */ 0x0000826e
 
-#define NV50_CHANNEL_GPFIFO                                          0x0000506f
-#define G82_CHANNEL_GPFIFO                                           0x0000826f
-#define FERMI_CHANNEL_GPFIFO                                         0x0000906f
-#define KEPLER_CHANNEL_GPFIFO_A                                      0x0000a06f
-#define MAXWELL_CHANNEL_GPFIFO_A                                     0x0000b06f
+#define NV50_CHANNEL_GPFIFO                           /* cl506f.h */ 0x0000506f
+#define G82_CHANNEL_GPFIFO                            /* cl826f.h */ 0x0000826f
+#define FERMI_CHANNEL_GPFIFO                          /* cl906f.h */ 0x0000906f
+#define KEPLER_CHANNEL_GPFIFO_A                       /* cla06f.h */ 0x0000a06f
+#define MAXWELL_CHANNEL_GPFIFO_A                      /* cla06f.h */ 0x0000b06f
 
-#define NV50_DISP                                                    0x00005070
-#define G82_DISP                                                     0x00008270
-#define GT200_DISP                                                   0x00008370
-#define GT214_DISP                                                   0x00008570
-#define GT206_DISP                                                   0x00008870
-#define GF110_DISP                                                   0x00009070
-#define GK104_DISP                                                   0x00009170
-#define GK110_DISP                                                   0x00009270
-#define GM107_DISP                                                   0x00009470
-#define GM204_DISP                                                   0x00009570
+#define NV50_DISP                                     /* cl5070.h */ 0x00005070
+#define G82_DISP                                      /* cl5070.h */ 0x00008270
+#define GT200_DISP                                    /* cl5070.h */ 0x00008370
+#define GT214_DISP                                    /* cl5070.h */ 0x00008570
+#define GT206_DISP                                    /* cl5070.h */ 0x00008870
+#define GF110_DISP                                    /* cl5070.h */ 0x00009070
+#define GK104_DISP                                    /* cl5070.h */ 0x00009170
+#define GK110_DISP                                    /* cl5070.h */ 0x00009270
+#define GM107_DISP                                    /* cl5070.h */ 0x00009470
+#define GM204_DISP                                    /* cl5070.h */ 0x00009570
 
 #define NV31_MPEG                                                    0x00003174
 #define G82_MPEG                                                     0x00008274
 
 #define NV74_VP2                                                     0x00007476
 
-#define NV50_DISP_CURSOR                                             0x0000507a
-#define G82_DISP_CURSOR                                              0x0000827a
-#define GT214_DISP_CURSOR                                            0x0000857a
-#define GF110_DISP_CURSOR                                            0x0000907a
-#define GK104_DISP_CURSOR                                            0x0000917a
+#define NV50_DISP_CURSOR                              /* cl507a.h */ 0x0000507a
+#define G82_DISP_CURSOR                               /* cl507a.h */ 0x0000827a
+#define GT214_DISP_CURSOR                             /* cl507a.h */ 0x0000857a
+#define GF110_DISP_CURSOR                             /* cl507a.h */ 0x0000907a
+#define GK104_DISP_CURSOR                             /* cl507a.h */ 0x0000917a
 
-#define NV50_DISP_OVERLAY                                            0x0000507b
-#define G82_DISP_OVERLAY                                             0x0000827b
-#define GT214_DISP_OVERLAY                                           0x0000857b
-#define GF110_DISP_OVERLAY                                           0x0000907b
-#define GK104_DISP_OVERLAY                                           0x0000917b
+#define NV50_DISP_OVERLAY                             /* cl507b.h */ 0x0000507b
+#define G82_DISP_OVERLAY                              /* cl507b.h */ 0x0000827b
+#define GT214_DISP_OVERLAY                            /* cl507b.h */ 0x0000857b
+#define GF110_DISP_OVERLAY                            /* cl507b.h */ 0x0000907b
+#define GK104_DISP_OVERLAY                            /* cl507b.h */ 0x0000917b
 
-#define NV50_DISP_BASE_CHANNEL_DMA                                   0x0000507c
-#define G82_DISP_BASE_CHANNEL_DMA                                    0x0000827c
-#define GT200_DISP_BASE_CHANNEL_DMA                                  0x0000837c
-#define GT214_DISP_BASE_CHANNEL_DMA                                  0x0000857c
-#define GF110_DISP_BASE_CHANNEL_DMA                                  0x0000907c
-#define GK104_DISP_BASE_CHANNEL_DMA                                  0x0000917c
-#define GK110_DISP_BASE_CHANNEL_DMA                                  0x0000927c
+#define NV50_DISP_BASE_CHANNEL_DMA                    /* cl507c.h */ 0x0000507c
+#define G82_DISP_BASE_CHANNEL_DMA                     /* cl507c.h */ 0x0000827c
+#define GT200_DISP_BASE_CHANNEL_DMA                   /* cl507c.h */ 0x0000837c
+#define GT214_DISP_BASE_CHANNEL_DMA                   /* cl507c.h */ 0x0000857c
+#define GF110_DISP_BASE_CHANNEL_DMA                   /* cl507c.h */ 0x0000907c
+#define GK104_DISP_BASE_CHANNEL_DMA                   /* cl507c.h */ 0x0000917c
+#define GK110_DISP_BASE_CHANNEL_DMA                   /* cl507c.h */ 0x0000927c
 
-#define NV50_DISP_CORE_CHANNEL_DMA                                   0x0000507d
-#define G82_DISP_CORE_CHANNEL_DMA                                    0x0000827d
-#define GT200_DISP_CORE_CHANNEL_DMA                                  0x0000837d
-#define GT214_DISP_CORE_CHANNEL_DMA                                  0x0000857d
-#define GT206_DISP_CORE_CHANNEL_DMA                                  0x0000887d
-#define GF110_DISP_CORE_CHANNEL_DMA                                  0x0000907d
-#define GK104_DISP_CORE_CHANNEL_DMA                                  0x0000917d
-#define GK110_DISP_CORE_CHANNEL_DMA                                  0x0000927d
-#define GM107_DISP_CORE_CHANNEL_DMA                                  0x0000947d
-#define GM204_DISP_CORE_CHANNEL_DMA                                  0x0000957d
+#define NV50_DISP_CORE_CHANNEL_DMA                    /* cl507d.h */ 0x0000507d
+#define G82_DISP_CORE_CHANNEL_DMA                     /* cl507d.h */ 0x0000827d
+#define GT200_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000837d
+#define GT214_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000857d
+#define GT206_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000887d
+#define GF110_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000907d
+#define GK104_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000917d
+#define GK110_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000927d
+#define GM107_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000947d
+#define GM204_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000957d
 
-#define NV50_DISP_OVERLAY_CHANNEL_DMA                                0x0000507e
-#define G82_DISP_OVERLAY_CHANNEL_DMA                                 0x0000827e
-#define GT200_DISP_OVERLAY_CHANNEL_DMA                               0x0000837e
-#define GT214_DISP_OVERLAY_CHANNEL_DMA                               0x0000857e
-#define GF110_DISP_OVERLAY_CONTROL_DMA                               0x0000907e
-#define GK104_DISP_OVERLAY_CONTROL_DMA                               0x0000917e
+#define NV50_DISP_OVERLAY_CHANNEL_DMA                 /* cl507e.h */ 0x0000507e
+#define G82_DISP_OVERLAY_CHANNEL_DMA                  /* cl507e.h */ 0x0000827e
+#define GT200_DISP_OVERLAY_CHANNEL_DMA                /* cl507e.h */ 0x0000837e
+#define GT214_DISP_OVERLAY_CHANNEL_DMA                /* cl507e.h */ 0x0000857e
+#define GF110_DISP_OVERLAY_CONTROL_DMA                /* cl507e.h */ 0x0000907e
+#define GK104_DISP_OVERLAY_CONTROL_DMA                /* cl507e.h */ 0x0000917e
 
-#define FERMI_A                                                      0x00009097
-#define FERMI_B                                                      0x00009197
-#define FERMI_C                                                      0x00009297
+#define FERMI_A                                       /* cl9097.h */ 0x00009097
+#define FERMI_B                                       /* cl9097.h */ 0x00009197
+#define FERMI_C                                       /* cl9097.h */ 0x00009297
 
-#define KEPLER_A                                                     0x0000a097
-#define KEPLER_B                                                     0x0000a197
-#define KEPLER_C                                                     0x0000a297
+#define KEPLER_A                                      /* cl9097.h */ 0x0000a097
+#define KEPLER_B                                      /* cl9097.h */ 0x0000a197
+#define KEPLER_C                                      /* cl9097.h */ 0x0000a297
 
-#define MAXWELL_A                                                    0x0000b097
-#define MAXWELL_B                                                    0x0000b197
+#define MAXWELL_A                                     /* cl9097.h */ 0x0000b097
+#define MAXWELL_B                                     /* cl9097.h */ 0x0000b197
 
 #define NV74_BSP                                                     0x000074b0
 
@@ -133,540 +138,4 @@
 #define MAXWELL_COMPUTE_B                                            0x0000b1c0
 
 #define NV74_CIPHER                                                  0x000074c1
-
-/*******************************************************************************
- * client
- ******************************************************************************/
-
-#define NV_CLIENT_DEVLIST                                                  0x00
-
-struct nv_client_devlist_v0 {
-	__u8  version;
-	__u8  count;
-	__u8  pad02[6];
-	__u64 device[];
-};
-
-
-/*******************************************************************************
- * device
- ******************************************************************************/
-
-struct nv_device_v0 {
-	__u8  version;
-	__u8  pad01[7];
-	__u64 device;	/* device identifier, ~0 for client default */
-};
-
-#define NV_DEVICE_V0_INFO                                                  0x00
-#define NV_DEVICE_V0_TIME                                                  0x01
-
-struct nv_device_info_v0 {
-	__u8  version;
-#define NV_DEVICE_INFO_V0_IGP                                              0x00
-#define NV_DEVICE_INFO_V0_PCI                                              0x01
-#define NV_DEVICE_INFO_V0_AGP                                              0x02
-#define NV_DEVICE_INFO_V0_PCIE                                             0x03
-#define NV_DEVICE_INFO_V0_SOC                                              0x04
-	__u8  platform;
-	__u16 chipset;	/* from NV_PMC_BOOT_0 */
-	__u8  revision;	/* from NV_PMC_BOOT_0 */
-#define NV_DEVICE_INFO_V0_TNT                                              0x01
-#define NV_DEVICE_INFO_V0_CELSIUS                                          0x02
-#define NV_DEVICE_INFO_V0_KELVIN                                           0x03
-#define NV_DEVICE_INFO_V0_RANKINE                                          0x04
-#define NV_DEVICE_INFO_V0_CURIE                                            0x05
-#define NV_DEVICE_INFO_V0_TESLA                                            0x06
-#define NV_DEVICE_INFO_V0_FERMI                                            0x07
-#define NV_DEVICE_INFO_V0_KEPLER                                           0x08
-#define NV_DEVICE_INFO_V0_MAXWELL                                          0x09
-	__u8  family;
-	__u8  pad06[2];
-	__u64 ram_size;
-	__u64 ram_user;
-	char  chip[16];
-	char  name[64];
-};
-
-struct nv_device_time_v0 {
-	__u8  version;
-	__u8  pad01[7];
-	__u64 time;
-};
-
-
-/*******************************************************************************
- * context dma
- ******************************************************************************/
-
-struct nv_dma_v0 {
-	__u8  version;
-#define NV_DMA_V0_TARGET_VM                                                0x00
-#define NV_DMA_V0_TARGET_VRAM                                              0x01
-#define NV_DMA_V0_TARGET_PCI                                               0x02
-#define NV_DMA_V0_TARGET_PCI_US                                            0x03
-#define NV_DMA_V0_TARGET_AGP                                               0x04
-	__u8  target;
-#define NV_DMA_V0_ACCESS_VM                                                0x00
-#define NV_DMA_V0_ACCESS_RD                                                0x01
-#define NV_DMA_V0_ACCESS_WR                                                0x02
-#define NV_DMA_V0_ACCESS_RDWR                 (NV_DMA_V0_ACCESS_RD | NV_DMA_V0_ACCESS_WR)
-	__u8  access;
-	__u8  pad03[5];
-	__u64 start;
-	__u64 limit;
-	/* ... chipset-specific class data */
-};
-
-struct nv50_dma_v0 {
-	__u8  version;
-#define NV50_DMA_V0_PRIV_VM                                                0x00
-#define NV50_DMA_V0_PRIV_US                                                0x01
-#define NV50_DMA_V0_PRIV__S                                                0x02
-	__u8  priv;
-#define NV50_DMA_V0_PART_VM                                                0x00
-#define NV50_DMA_V0_PART_256                                               0x01
-#define NV50_DMA_V0_PART_1KB                                               0x02
-	__u8  part;
-#define NV50_DMA_V0_COMP_NONE                                              0x00
-#define NV50_DMA_V0_COMP_1                                                 0x01
-#define NV50_DMA_V0_COMP_2                                                 0x02
-#define NV50_DMA_V0_COMP_VM                                                0x03
-	__u8  comp;
-#define NV50_DMA_V0_KIND_PITCH                                             0x00
-#define NV50_DMA_V0_KIND_VM                                                0x7f
-	__u8  kind;
-	__u8  pad05[3];
-};
-
-struct gf100_dma_v0 {
-	__u8  version;
-#define GF100_DMA_V0_PRIV_VM                                               0x00
-#define GF100_DMA_V0_PRIV_US                                               0x01
-#define GF100_DMA_V0_PRIV__S                                               0x02
-	__u8  priv;
-#define GF100_DMA_V0_KIND_PITCH                                            0x00
-#define GF100_DMA_V0_KIND_VM                                               0xff
-	__u8  kind;
-	__u8  pad03[5];
-};
-
-struct gf119_dma_v0 {
-	__u8  version;
-#define GF119_DMA_V0_PAGE_LP                                               0x00
-#define GF119_DMA_V0_PAGE_SP                                               0x01
-	__u8  page;
-#define GF119_DMA_V0_KIND_PITCH                                            0x00
-#define GF119_DMA_V0_KIND_VM                                               0xff
-	__u8  kind;
-	__u8  pad03[5];
-};
-
-
-/*******************************************************************************
- * perfmon
- ******************************************************************************/
-
-#define NVIF_PERFMON_V0_QUERY_DOMAIN                                       0x00
-#define NVIF_PERFMON_V0_QUERY_SIGNAL                                       0x01
-#define NVIF_PERFMON_V0_QUERY_SOURCE                                       0x02
-
-struct nvif_perfmon_query_domain_v0 {
-	__u8  version;
-	__u8  id;
-	__u8  counter_nr;
-	__u8  iter;
-	__u16 signal_nr;
-	__u8  pad05[2];
-	char  name[64];
-};
-
-struct nvif_perfmon_query_signal_v0 {
-	__u8  version;
-	__u8  domain;
-	__u16 iter;
-	__u8  signal;
-	__u8  source_nr;
-	__u8  pad05[2];
-	char  name[64];
-};
-
-struct nvif_perfmon_query_source_v0 {
-	__u8  version;
-	__u8  domain;
-	__u8  signal;
-	__u8  iter;
-	__u8  pad04[4];
-	__u32 source;
-	__u32 mask;
-	char  name[64];
-};
-
-
-/*******************************************************************************
- * perfdom
- ******************************************************************************/
-
-struct nvif_perfdom_v0 {
-	__u8  version;
-	__u8  domain;
-	__u8  mode;
-	__u8  pad03[1];
-	struct {
-		__u8  signal[4];
-		__u64 source[4][8];
-		__u16 logic_op;
-	} ctr[4];
-};
-
-#define NVIF_PERFDOM_V0_INIT                                               0x00
-#define NVIF_PERFDOM_V0_SAMPLE                                             0x01
-#define NVIF_PERFDOM_V0_READ                                               0x02
-
-struct nvif_perfdom_init {
-};
-
-struct nvif_perfdom_sample {
-};
-
-struct nvif_perfdom_read_v0 {
-	__u8  version;
-	__u8  pad01[7];
-	__u32 ctr[4];
-	__u32 clk;
-	__u8  pad04[4];
-};
-
-
-/*******************************************************************************
- * device control
- ******************************************************************************/
-
-#define NVIF_CONTROL_PSTATE_INFO                                           0x00
-#define NVIF_CONTROL_PSTATE_ATTR                                           0x01
-#define NVIF_CONTROL_PSTATE_USER                                           0x02
-
-struct nvif_control_pstate_info_v0 {
-	__u8  version;
-	__u8  count; /* out: number of power states */
-#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE                         (-1)
-#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_PERFMON                         (-2)
-	__s8  ustate_ac; /* out: target pstate index */
-	__s8  ustate_dc; /* out: target pstate index */
-	__s8  pwrsrc; /* out: current power source */
-#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN                         (-1)
-#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_PERFMON                         (-2)
-	__s8  pstate; /* out: current pstate index */
-	__u8  pad06[2];
-};
-
-struct nvif_control_pstate_attr_v0 {
-	__u8  version;
-#define NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT                          (-1)
-	__s8  state; /*  in: index of pstate to query
-		      * out: pstate identifier
-		      */
-	__u8  index; /*  in: index of attribute to query
-		      * out: index of next attribute, or 0 if no more
-		      */
-	__u8  pad03[5];
-	__u32 min;
-	__u32 max;
-	char  name[32];
-	char  unit[16];
-};
-
-struct nvif_control_pstate_user_v0 {
-	__u8  version;
-#define NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN                          (-1)
-#define NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON                          (-2)
-	__s8  ustate; /*  in: pstate identifier */
-	__s8  pwrsrc; /*  in: target power source */
-	__u8  pad03[5];
-};
-
-
-/*******************************************************************************
- * DMA FIFO channels
- ******************************************************************************/
-
-struct nv03_channel_dma_v0 {
-	__u8  version;
-	__u8  chid;
-	__u8  pad02[2];
-	__u32 offset;
-	__u64 pushbuf;
-};
-
-struct nv50_channel_dma_v0 {
-	__u8  version;
-	__u8  chid;
-	__u8  pad02[6];
-	__u64 vm;
-	__u64 pushbuf;
-	__u64 offset;
-};
-
-#define G82_CHANNEL_DMA_V0_NTFY_UEVENT                                     0x00
-
-/*******************************************************************************
- * GPFIFO channels
- ******************************************************************************/
-
-struct nv50_channel_gpfifo_v0 {
-	__u8  version;
-	__u8  chid;
-	__u8  pad02[2];
-	__u32 ilength;
-	__u64 ioffset;
-	__u64 pushbuf;
-	__u64 vm;
-};
-
-struct fermi_channel_gpfifo_v0 {
-	__u8  version;
-	__u8  chid;
-	__u8  pad02[2];
-	__u32 ilength;
-	__u64 ioffset;
-	__u64 vm;
-};
-
-struct kepler_channel_gpfifo_a_v0 {
-	__u8  version;
-#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR                               0x01
-#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPDEC                           0x02
-#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPPP                            0x04
-#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSVLD                            0x08
-#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0                              0x10
-#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1                              0x20
-#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_ENC                              0x40
-	__u8  engine;
-	__u16 chid;
-	__u32 ilength;
-	__u64 ioffset;
-	__u64 vm;
-};
-
-/*******************************************************************************
- * legacy display
- ******************************************************************************/
-
-#define NV04_DISP_NTFY_VBLANK                                              0x00
-#define NV04_DISP_NTFY_CONN                                                0x01
-
-struct nv04_disp_mthd_v0 {
-	__u8  version;
-#define NV04_DISP_SCANOUTPOS                                               0x00
-	__u8  method;
-	__u8  head;
-	__u8  pad03[5];
-};
-
-struct nv04_disp_scanoutpos_v0 {
-	__u8  version;
-	__u8  pad01[7];
-	__s64 time[2];
-	__u16 vblanks;
-	__u16 vblanke;
-	__u16 vtotal;
-	__u16 vline;
-	__u16 hblanks;
-	__u16 hblanke;
-	__u16 htotal;
-	__u16 hline;
-};
-
-/*******************************************************************************
- * display
- ******************************************************************************/
-
-#define NV50_DISP_MTHD                                                     0x00
-
-struct nv50_disp_mthd_v0 {
-	__u8  version;
-#define NV50_DISP_SCANOUTPOS                                               0x00
-	__u8  method;
-	__u8  head;
-	__u8  pad03[5];
-};
-
-struct nv50_disp_mthd_v1 {
-	__u8  version;
-#define NV50_DISP_MTHD_V1_DAC_PWR                                          0x10
-#define NV50_DISP_MTHD_V1_DAC_LOAD                                         0x11
-#define NV50_DISP_MTHD_V1_SOR_PWR                                          0x20
-#define NV50_DISP_MTHD_V1_SOR_HDA_ELD                                      0x21
-#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR                                     0x22
-#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT                                  0x23
-#define NV50_DISP_MTHD_V1_SOR_DP_PWR                                       0x24
-#define NV50_DISP_MTHD_V1_PIOR_PWR                                         0x30
-	__u8  method;
-	__u16 hasht;
-	__u16 hashm;
-	__u8  pad06[2];
-};
-
-struct nv50_disp_dac_pwr_v0 {
-	__u8  version;
-	__u8  state;
-	__u8  data;
-	__u8  vsync;
-	__u8  hsync;
-	__u8  pad05[3];
-};
-
-struct nv50_disp_dac_load_v0 {
-	__u8  version;
-	__u8  load;
-	__u8  pad02[2];
-	__u32 data;
-};
-
-struct nv50_disp_sor_pwr_v0 {
-	__u8  version;
-	__u8  state;
-	__u8  pad02[6];
-};
-
-struct nv50_disp_sor_hda_eld_v0 {
-	__u8  version;
-	__u8  pad01[7];
-	__u8  data[];
-};
-
-struct nv50_disp_sor_hdmi_pwr_v0 {
-	__u8  version;
-	__u8  state;
-	__u8  max_ac_packet;
-	__u8  rekey;
-	__u8  pad04[4];
-};
-
-struct nv50_disp_sor_lvds_script_v0 {
-	__u8  version;
-	__u8  pad01[1];
-	__u16 script;
-	__u8  pad04[4];
-};
-
-struct nv50_disp_sor_dp_pwr_v0 {
-	__u8  version;
-	__u8  state;
-	__u8  pad02[6];
-};
-
-struct nv50_disp_pior_pwr_v0 {
-	__u8  version;
-	__u8  state;
-	__u8  type;
-	__u8  pad03[5];
-};
-
-/* core */
-struct nv50_disp_core_channel_dma_v0 {
-	__u8  version;
-	__u8  pad01[7];
-	__u64 pushbuf;
-};
-
-#define NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT                          0x00
-
-/* cursor immediate */
-struct nv50_disp_cursor_v0 {
-	__u8  version;
-	__u8  head;
-	__u8  pad02[6];
-};
-
-#define NV50_DISP_CURSOR_V0_NTFY_UEVENT                                    0x00
-
-/* base */
-struct nv50_disp_base_channel_dma_v0 {
-	__u8  version;
-	__u8  head;
-	__u8  pad02[6];
-	__u64 pushbuf;
-};
-
-#define NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT                          0x00
-
-/* overlay */
-struct nv50_disp_overlay_channel_dma_v0 {
-	__u8  version;
-	__u8  head;
-	__u8  pad02[6];
-	__u64 pushbuf;
-};
-
-#define NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT                       0x00
-
-/* overlay immediate */
-struct nv50_disp_overlay_v0 {
-	__u8  version;
-	__u8  head;
-	__u8  pad02[6];
-};
-
-#define NV50_DISP_OVERLAY_V0_NTFY_UEVENT                                   0x00
-
-/*******************************************************************************
- * software
- ******************************************************************************/
-
-#define NVSW_NTFY_UEVENT                                                   0x00
-
-#define NV04_NVSW_GET_REF                                                  0x00
-
-struct nv04_nvsw_get_ref_v0 {
-	__u8  version;
-	__u8  pad01[3];
-	__u32 ref;
-};
-
-/*******************************************************************************
- * fermi
- ******************************************************************************/
-
-#define FERMI_A_ZBC_COLOR                                                  0x00
-#define FERMI_A_ZBC_DEPTH                                                  0x01
-
-struct fermi_a_zbc_color_v0 {
-	__u8  version;
-#define FERMI_A_ZBC_COLOR_V0_FMT_ZERO                                      0x01
-#define FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE                                 0x02
-#define FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32                       0x04
-#define FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16                           0x08
-#define FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16                       0x0c
-#define FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16                       0x10
-#define FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16                       0x14
-#define FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16                       0x16
-#define FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8                                  0x18
-#define FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8                               0x1c
-#define FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10                               0x20
-#define FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10                           0x24
-#define FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8                                  0x28
-#define FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8                               0x2c
-#define FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8                              0x30
-#define FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8                              0x34
-#define FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8                              0x38
-#define FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10                               0x3c
-#define FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11                              0x40
-	__u8  format;
-	__u8  index;
-	__u8  pad03[5];
-	__u32 ds[4];
-	__u32 l2[4];
-};
-
-struct fermi_a_zbc_depth_v0 {
-	__u8  version;
-#define FERMI_A_ZBC_DEPTH_V0_FMT_FP32                                      0x01
-	__u8  format;
-	__u8  index;
-	__u8  pad03[5];
-	__u32 ds;
-	__u32 l2;
-};
-
 #endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/device.h b/drivers/gpu/drm/nouveau/include/nvif/device.h
index 700a9b2..e0ed2f4 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/device.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/device.h
@@ -2,7 +2,7 @@
 #define __NVIF_DEVICE_H__
 
 #include <nvif/object.h>
-#include <nvif/class.h>
+#include <nvif/cl0080.h>
 
 struct nvif_device {
 	struct nvif_object object;
@@ -63,6 +63,7 @@
 #define nvxx_clk(a) nvxx_device(a)->clk
 #define nvxx_i2c(a) nvxx_device(a)->i2c
 #define nvxx_therm(a) nvxx_device(a)->therm
+#define nvxx_volt(a) nvxx_device(a)->volt
 
 #include <core/device.h>
 #include <engine/fifo.h>
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0000.h b/drivers/gpu/drm/nouveau/include/nvif/if0000.h
new file mode 100644
index 0000000..85c44e8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0000.h
@@ -0,0 +1,12 @@
+#ifndef __NVIF_IF0000_H__
+#define __NVIF_IF0000_H__
+
+#define NV_CLIENT_DEVLIST                                                  0x00
+
+struct nv_client_devlist_v0 {
+	__u8  version;
+	__u8  count;
+	__u8  pad02[6];
+	__u64 device[];
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0001.h b/drivers/gpu/drm/nouveau/include/nvif/if0001.h
new file mode 100644
index 0000000..bd5b641
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0001.h
@@ -0,0 +1,46 @@
+#ifndef __NVIF_IF0001_H__
+#define __NVIF_IF0001_H__
+
+#define NVIF_CONTROL_PSTATE_INFO                                           0x00
+#define NVIF_CONTROL_PSTATE_ATTR                                           0x01
+#define NVIF_CONTROL_PSTATE_USER                                           0x02
+
+struct nvif_control_pstate_info_v0 {
+	__u8  version;
+	__u8  count; /* out: number of power states */
+#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE                         (-1)
+#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_PERFMON                         (-2)
+	__s8  ustate_ac; /* out: target pstate index */
+	__s8  ustate_dc; /* out: target pstate index */
+	__s8  pwrsrc; /* out: current power source */
+#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN                         (-1)
+#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_PERFMON                         (-2)
+	__s8  pstate; /* out: current pstate index */
+	__u8  pad06[2];
+};
+
+struct nvif_control_pstate_attr_v0 {
+	__u8  version;
+#define NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT                          (-1)
+	__s8  state; /*  in: index of pstate to query
+		      * out: pstate identifier
+		      */
+	__u8  index; /*  in: index of attribute to query
+		      * out: index of next attribute, or 0 if no more
+		      */
+	__u8  pad03[5];
+	__u32 min;
+	__u32 max;
+	char  name[32];
+	char  unit[16];
+};
+
+struct nvif_control_pstate_user_v0 {
+	__u8  version;
+#define NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN                          (-1)
+#define NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON                          (-2)
+	__s8  ustate; /*  in: pstate identifier */
+	__s8  pwrsrc; /*  in: target power source */
+	__u8  pad03[5];
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0002.h b/drivers/gpu/drm/nouveau/include/nvif/if0002.h
new file mode 100644
index 0000000..c04c91d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0002.h
@@ -0,0 +1,38 @@
+#ifndef __NVIF_IF0002_H__
+#define __NVIF_IF0002_H__
+
+#define NVIF_PERFMON_V0_QUERY_DOMAIN                                       0x00
+#define NVIF_PERFMON_V0_QUERY_SIGNAL                                       0x01
+#define NVIF_PERFMON_V0_QUERY_SOURCE                                       0x02
+
+struct nvif_perfmon_query_domain_v0 {
+	__u8  version;
+	__u8  id;
+	__u8  counter_nr;
+	__u8  iter;
+	__u16 signal_nr;
+	__u8  pad05[2];
+	char  name[64];
+};
+
+struct nvif_perfmon_query_signal_v0 {
+	__u8  version;
+	__u8  domain;
+	__u16 iter;
+	__u8  signal;
+	__u8  source_nr;
+	__u8  pad05[2];
+	char  name[64];
+};
+
+struct nvif_perfmon_query_source_v0 {
+	__u8  version;
+	__u8  domain;
+	__u8  signal;
+	__u8  iter;
+	__u8  pad04[4];
+	__u32 source;
+	__u32 mask;
+	char  name[64];
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0003.h b/drivers/gpu/drm/nouveau/include/nvif/if0003.h
new file mode 100644
index 0000000..0cd03ef
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0003.h
@@ -0,0 +1,33 @@
+#ifndef __NVIF_IF0003_H__
+#define __NVIF_IF0003_H__
+
+struct nvif_perfdom_v0 {
+	__u8  version;
+	__u8  domain;
+	__u8  mode;
+	__u8  pad03[1];
+	struct {
+		__u8  signal[4];
+		__u64 source[4][8];
+		__u16 logic_op;
+	} ctr[4];
+};
+
+#define NVIF_PERFDOM_V0_INIT                                               0x00
+#define NVIF_PERFDOM_V0_SAMPLE                                             0x01
+#define NVIF_PERFDOM_V0_READ                                               0x02
+
+struct nvif_perfdom_init {
+};
+
+struct nvif_perfdom_sample {
+};
+
+struct nvif_perfdom_read_v0 {
+	__u8  version;
+	__u8  pad01[7];
+	__u32 ctr[4];
+	__u32 clk;
+	__u8  pad04[4];
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0004.h b/drivers/gpu/drm/nouveau/include/nvif/if0004.h
new file mode 100644
index 0000000..bd5cd42
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0004.h
@@ -0,0 +1,13 @@
+#ifndef __NVIF_IF0004_H__
+#define __NVIF_IF0004_H__
+
+#define NV04_NVSW_NTFY_UEVENT                                              0x00
+
+#define NV04_NVSW_GET_REF                                                  0x00
+
+struct nv04_nvsw_get_ref_v0 {
+	__u8  version;
+	__u8  pad01[3];
+	__u32 ref;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0005.h b/drivers/gpu/drm/nouveau/include/nvif/if0005.h
new file mode 100644
index 0000000..abfd373
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0005.h
@@ -0,0 +1,4 @@
+#ifndef __NVIF_IF0005_H__
+#define __NVIF_IF0005_H__
+#define NV10_NVSW_NTFY_UEVENT                                              0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
index b0ac021..c5f5eb8 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
@@ -55,14 +55,6 @@
 	__u64 token;
 	__u64 object;
 	__u32 handle;
-/* these class numbers are made up by us, and not nvidia-assigned */
-#define NVIF_IOCTL_NEW_V0_CONTROL                                            -1
-#define NVIF_IOCTL_NEW_V0_PERFMON                                            -2
-#define NVIF_IOCTL_NEW_V0_PERFDOM                                            -3
-#define NVIF_IOCTL_NEW_V0_SW_NV04                                            -4
-#define NVIF_IOCTL_NEW_V0_SW_NV10                                            -5
-#define NVIF_IOCTL_NEW_V0_SW_NV50                                            -6
-#define NVIF_IOCTL_NEW_V0_SW_GF100                                           -7
 	__s32 oclass;
 	__u8  data[];		/* class data (class.h) */
 };
diff --git a/drivers/gpu/drm/nouveau/include/nvif/unpack.h b/drivers/gpu/drm/nouveau/include/nvif/unpack.h
index 5933188..751bcf4 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/unpack.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/unpack.h
@@ -1,24 +1,28 @@
 #ifndef __NVIF_UNPACK_H__
 #define __NVIF_UNPACK_H__
 
-#define nvif_unvers(d) ({                                                      \
-	ret = (size == sizeof(d)) ? 0 : -ENOSYS;                               \
-	(ret == 0);                                                            \
+#define nvif_unvers(r,d,s,m) ({                                                \
+	void **_data = (d); __u32 *_size = (s); int _ret = (r);                \
+	if (_ret == -ENOSYS && *_size == sizeof(m)) {                          \
+		*_data = NULL;                                                 \
+		*_size = _ret = 0;                                             \
+	}                                                                      \
+	_ret;                                                                  \
 })
 
-#define nvif_unpack(d,vl,vh,m) ({                                              \
-	if ((vl) == 0 || ret == -ENOSYS) {                                     \
-		int _size = sizeof(d);                                         \
-		if (_size <= size && (d).version >= (vl) &&                    \
-				     (d).version <= (vh)) {                    \
-			data = (u8 *)data + _size;                             \
-			size = size - _size;                                   \
-			ret = ((m) || !size) ? 0 : -E2BIG;                     \
-		} else {                                                       \
-			ret = -ENOSYS;                                         \
+#define nvif_unpack(r,d,s,m,vl,vh,x) ({                                        \
+	void **_data = (d); __u32 *_size = (s);                                \
+	int _ret = (r), _vl = (vl), _vh = (vh);                                \
+	if (_ret == -ENOSYS && *_size >= sizeof(m) &&                          \
+	    (m).version >= _vl && (m).version <= _vh) {                        \
+		*_data = (__u8 *)*_data + sizeof(m);                           \
+		*_size = *_size - sizeof(m);                                   \
+		if (_ret = 0, !(x)) {                                          \
+			_ret = *_size ? -E2BIG : 0;                            \
+			*_data = NULL;                                         \
+			*_size = 0;                                            \
 		}                                                              \
 	}                                                                      \
-	(ret == 0);                                                            \
+	_ret;                                                                  \
 })
-
 #endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
index 8f76000..913192c 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
@@ -159,7 +159,6 @@
 struct nvkm_device_quirk {
 	u8 tv_pin_mask;
 	u8 tv_gpio;
-	bool War00C800_0;
 };
 
 struct nvkm_device_chip {
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h
index 7cc2bec..d3bd2501 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h
@@ -13,6 +13,8 @@
 	u32 vdec;
 	u32 disp;
 	u32 script;
+	u8  pcie_speed;
+	u8  pcie_width;
 };
 
 u16 nvbios_perf_entry(struct nvkm_bios *, int idx,
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
index 8708f0a..6b33bc0 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
@@ -2,6 +2,7 @@
 #define __NVKM_CLK_H__
 #include <core/subdev.h>
 #include <core/notify.h>
+#include <subdev/pci.h>
 struct nvbios_pll;
 struct nvkm_pll_vals;
 
@@ -38,7 +39,7 @@
 	nv_clk_src_hubk06,
 	nv_clk_src_hubk07,
 	nv_clk_src_copy,
-	nv_clk_src_daemon,
+	nv_clk_src_pmu,
 	nv_clk_src_disp,
 	nv_clk_src_vdec,
 
@@ -59,6 +60,8 @@
 	struct nvkm_cstate base;
 	u8 pstate;
 	u8 fanspeed;
+	enum nvkm_pcie_speed pcie_speed;
+	u8 pcie_width;
 };
 
 struct nvkm_domain {
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h
index c4dcd26..ea23e24 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h
@@ -6,4 +6,5 @@
 int gf117_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **);
 int gk104_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **);
 int gk20a_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **);
+int gm204_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **);
 #endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
index 3d4dbbf..0ffa2ec 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
@@ -37,4 +37,5 @@
 int gk104_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **);
 int gk20a_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **);
 int gm107_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **);
+int gm204_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **);
 #endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
index fee0a97..ddb9138 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
@@ -2,6 +2,12 @@
 #define __NVKM_PCI_H__
 #include <core/subdev.h>
 
+enum nvkm_pcie_speed {
+	NVKM_PCIE_SPEED_2_5,
+	NVKM_PCIE_SPEED_5_0,
+	NVKM_PCIE_SPEED_8_0,
+};
+
 struct nvkm_pci {
 	const struct nvkm_pci_func *func;
 	struct nvkm_subdev subdev;
@@ -18,6 +24,11 @@
 		bool acquired;
 	} agp;
 
+	struct {
+		enum nvkm_pcie_speed speed;
+		u8 width;
+	} pcie;
+
 	bool msi;
 };
 
@@ -34,4 +45,9 @@
 int g84_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
 int g94_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
 int gf100_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
+int gf106_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
+int gk104_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
+
+/* pcie functions */
+int nvkm_pcie_set_link(struct nvkm_pci *, enum nvkm_pcie_speed, u8 width);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index 7f50cf5..50f52ff 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -25,6 +25,8 @@
 #include <nvif/driver.h>
 #include <nvif/ioctl.h>
 #include <nvif/class.h>
+#include <nvif/cl0002.h>
+#include <nvif/cla06f.h>
 #include <nvif/unpack.h>
 
 #include "nouveau_drm.h"
@@ -87,18 +89,18 @@
 {
 	switch (drm->device.info.family) {
 	case NV_DEVICE_INFO_V0_TNT:
-		return NVIF_IOCTL_NEW_V0_SW_NV04;
+		return NVIF_CLASS_SW_NV04;
 	case NV_DEVICE_INFO_V0_CELSIUS:
 	case NV_DEVICE_INFO_V0_KELVIN:
 	case NV_DEVICE_INFO_V0_RANKINE:
 	case NV_DEVICE_INFO_V0_CURIE:
-		return NVIF_IOCTL_NEW_V0_SW_NV10;
+		return NVIF_CLASS_SW_NV10;
 	case NV_DEVICE_INFO_V0_TESLA:
-		return NVIF_IOCTL_NEW_V0_SW_NV50;
+		return NVIF_CLASS_SW_NV50;
 	case NV_DEVICE_INFO_V0_FERMI:
 	case NV_DEVICE_INFO_V0_KEPLER:
 	case NV_DEVICE_INFO_V0_MAXWELL:
-		return NVIF_IOCTL_NEW_V0_SW_GF100;
+		return NVIF_CLASS_SW_GF100;
 	}
 
 	return 0x0000;
@@ -355,9 +357,9 @@
 	} *args = data;
 	struct nouveau_abi16_chan *chan;
 	struct nouveau_abi16 *abi16;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		switch (args->v0.type) {
 		case NVIF_IOCTL_V0_NEW:
 		case NVIF_IOCTL_V0_MTHD:
@@ -433,10 +435,10 @@
 		/* nvsw: compatibility with older 0x*6e class identifier */
 		for (i = 0; !oclass && i < ret; i++) {
 			switch (sclass[i].oclass) {
-			case NVIF_IOCTL_NEW_V0_SW_NV04:
-			case NVIF_IOCTL_NEW_V0_SW_NV10:
-			case NVIF_IOCTL_NEW_V0_SW_NV50:
-			case NVIF_IOCTL_NEW_V0_SW_GF100:
+			case NVIF_CLASS_SW_NV04:
+			case NVIF_CLASS_SW_NV10:
+			case NVIF_CLASS_SW_NV50:
+			case NVIF_CLASS_SW_GF100:
 				oclass = sclass[i].oclass;
 				break;
 			default:
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index 1860f38..3f804a8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -24,6 +24,11 @@
 
 #include <nvif/os.h>
 #include <nvif/class.h>
+#include <nvif/cl0002.h>
+#include <nvif/cl006b.h>
+#include <nvif/cl506f.h>
+#include <nvif/cl906f.h>
+#include <nvif/cla06f.h>
 #include <nvif/ioctl.h>
 
 /*XXX*/
@@ -378,7 +383,7 @@
 	/* allocate software object class (used for fences on <= nv05) */
 	if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) {
 		ret = nvif_object_init(&chan->user, 0x006e,
-				       NVIF_IOCTL_NEW_V0_SW_NV04,
+				       NVIF_CLASS_SW_NV04,
 				       NULL, 0, &chan->nvsw);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 5dd1d01..fcebfae 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -42,6 +42,8 @@
 #include "nouveau_encoder.h"
 #include "nouveau_crtc.h"
 
+#include <nvif/class.h>
+#include <nvif/cl0046.h>
 #include <nvif/event.h>
 
 MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");
@@ -56,6 +58,10 @@
 int nouveau_duallink = 1;
 module_param_named(duallink, nouveau_duallink, int, 0400);
 
+MODULE_PARM_DESC(hdmimhz, "Force a maximum HDMI pixel clock (in MHz)");
+int nouveau_hdmimhz = 0;
+module_param_named(hdmimhz, nouveau_hdmimhz, int, 0400);
+
 struct nouveau_encoder *
 find_encoder(struct drm_connector *connector, int type)
 {
@@ -809,12 +815,23 @@
 }
 
 static unsigned
-get_tmds_link_bandwidth(struct drm_connector *connector)
+get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
 {
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
 	struct dcb_output *dcb = nv_connector->detected_encoder->dcb;
 
+	if (hdmi) {
+		if (nouveau_hdmimhz > 0)
+			return nouveau_hdmimhz * 1000;
+		/* Note: these limits are conservative, some Fermi's
+		 * can do 297 MHz. Unclear how this can be determined.
+		 */
+		if (drm->device.info.family >= NV_DEVICE_INFO_V0_KEPLER)
+			return 297000;
+		if (drm->device.info.family >= NV_DEVICE_INFO_V0_FERMI)
+			return 225000;
+	}
 	if (dcb->location != DCB_LOC_ON_CHIP ||
 	    drm->device.info.chipset >= 0x46)
 		return 165000;
@@ -835,6 +852,7 @@
 	struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
 	unsigned min_clock = 25000, max_clock = min_clock;
 	unsigned clock = mode->clock;
+	bool hdmi;
 
 	switch (nv_encoder->dcb->type) {
 	case DCB_OUTPUT_LVDS:
@@ -847,8 +865,10 @@
 		max_clock = 400000;
 		break;
 	case DCB_OUTPUT_TMDS:
-		max_clock = get_tmds_link_bandwidth(connector);
-		if (nouveau_duallink && nv_encoder->dcb->duallink_possible)
+		hdmi = drm_detect_hdmi_monitor(nv_connector->edid);
+		max_clock = get_tmds_link_bandwidth(connector, hdmi);
+		if (!hdmi && nouveau_duallink &&
+		    nv_encoder->dcb->duallink_possible)
 			max_clock *= 2;
 		break;
 	case DCB_OUTPUT_ANALOG:
@@ -963,10 +983,13 @@
 
 		NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
 
+		mutex_lock(&drm->dev->mode_config.mutex);
 		if (plugged)
 			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
 		else
 			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+		mutex_unlock(&drm->dev->mode_config.mutex);
+
 		drm_helper_hpd_irq_event(connector->dev);
 	}
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
index 5392e07..3d0dc19 100644
--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
@@ -28,6 +28,9 @@
  *  Ben Skeggs <bskeggs@redhat.com>
  */
 
+#include <linux/debugfs.h>
+#include <nvif/class.h>
+#include <nvif/if0001.h>
 #include "nouveau_debugfs.h"
 #include "nouveau_drm.h"
 
@@ -43,22 +46,233 @@
 	return 0;
 }
 
+static int
+nouveau_debugfs_pstate_get(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct nouveau_debugfs *debugfs = nouveau_debugfs(node->minor->dev);
+	struct nvif_object *ctrl = &debugfs->ctrl;
+	struct nvif_control_pstate_info_v0 info = {};
+	int ret, i;
+
+	if (!debugfs)
+		return -ENODEV;
+
+	ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_INFO, &info, sizeof(info));
+	if (ret)
+		return ret;
+
+	for (i = 0; i < info.count + 1; i++) {
+		const s32 state = i < info.count ? i :
+			NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT;
+		struct nvif_control_pstate_attr_v0 attr = {
+			.state = state,
+			.index = 0,
+		};
+
+		ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_ATTR,
+				&attr, sizeof(attr));
+		if (ret)
+			return ret;
+
+		if (i < info.count)
+			seq_printf(m, "%02x:", attr.state);
+		else
+			seq_printf(m, "%s:", info.pwrsrc == 0 ? "DC" :
+					     info.pwrsrc == 1 ? "AC" : "--");
+
+		attr.index = 0;
+		do {
+			attr.state = state;
+			ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_ATTR,
+					&attr, sizeof(attr));
+			if (ret)
+				return ret;
+
+			seq_printf(m, " %s %d", attr.name, attr.min);
+			if (attr.min != attr.max)
+				seq_printf(m, "-%d", attr.max);
+			seq_printf(m, " %s", attr.unit);
+		} while (attr.index);
+
+		if (state >= 0) {
+			if (info.ustate_ac == state)
+				seq_printf(m, " AC");
+			if (info.ustate_dc == state)
+				seq_printf(m, " DC");
+			if (info.pstate == state)
+				seq_printf(m, " *");
+		} else {
+			if (info.ustate_ac < -1)
+				seq_printf(m, " AC");
+			if (info.ustate_dc < -1)
+				seq_printf(m, " DC");
+		}
+
+		seq_printf(m, "\n");
+	}
+
+	return 0;
+}
+
+static ssize_t
+nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,
+			   size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct nouveau_debugfs *debugfs = nouveau_debugfs(node->minor->dev);
+	struct nvif_object *ctrl = &debugfs->ctrl;
+	struct nvif_control_pstate_user_v0 args = { .pwrsrc = -EINVAL };
+	char buf[32] = {}, *tmp, *cur = buf;
+	long value, ret;
+
+	if (!debugfs)
+		return -ENODEV;
+
+	if (len >= sizeof(buf))
+		return -EINVAL;
+
+	if (copy_from_user(buf, ubuf, len))
+		return -EFAULT;
+
+	if ((tmp = strchr(buf, '\n')))
+		*tmp = '\0';
+
+	if (!strncasecmp(cur, "dc:", 3)) {
+		args.pwrsrc = 0;
+		cur += 3;
+	} else
+	if (!strncasecmp(cur, "ac:", 3)) {
+		args.pwrsrc = 1;
+		cur += 3;
+	}
+
+	if (!strcasecmp(cur, "none"))
+		args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN;
+	else
+	if (!strcasecmp(cur, "auto"))
+		args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON;
+	else {
+		ret = kstrtol(cur, 16, &value);
+		if (ret)
+			return ret;
+		args.ustate = value;
+	}
+
+	ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_USER, &args, sizeof(args));
+	if (ret < 0)
+		return ret;
+
+	return len;
+}
+
+static int
+nouveau_debugfs_pstate_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, nouveau_debugfs_pstate_get, inode->i_private);
+}
+
+static const struct file_operations nouveau_pstate_fops = {
+	.owner = THIS_MODULE,
+	.open = nouveau_debugfs_pstate_open,
+	.read = seq_read,
+	.write = nouveau_debugfs_pstate_set,
+};
+
 static struct drm_info_list nouveau_debugfs_list[] = {
 	{ "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL },
 };
 #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)
 
-int
-nouveau_debugfs_init(struct drm_minor *minor)
+static const struct nouveau_debugfs_files {
+	const char *name;
+	const struct file_operations *fops;
+} nouveau_debugfs_files[] = {
+	{"pstate", &nouveau_pstate_fops},
+};
+
+static int
+nouveau_debugfs_create_file(struct drm_minor *minor,
+		const struct nouveau_debugfs_files *ndf)
 {
-	drm_debugfs_create_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES,
-				 minor->debugfs_root, minor);
+	struct drm_info_node *node;
+
+	node = kmalloc(sizeof(*node), GFP_KERNEL);
+	if (node == NULL)
+		return -ENOMEM;
+
+	node->minor = minor;
+	node->info_ent = (const void *)ndf->fops;
+	node->dent = debugfs_create_file(ndf->name, S_IRUGO | S_IWUSR,
+					 minor->debugfs_root, node, ndf->fops);
+	if (!node->dent) {
+		kfree(node);
+		return -ENOMEM;
+	}
+
+	mutex_lock(&minor->debugfs_lock);
+	list_add(&node->list, &minor->debugfs_list);
+	mutex_unlock(&minor->debugfs_lock);
+	return 0;
+}
+
+int
+nouveau_drm_debugfs_init(struct drm_minor *minor)
+{
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(nouveau_debugfs_files); i++) {
+		ret = nouveau_debugfs_create_file(minor,
+						  &nouveau_debugfs_files[i]);
+
+		if (ret)
+			return ret;
+	}
+
+	return drm_debugfs_create_files(nouveau_debugfs_list,
+					NOUVEAU_DEBUGFS_ENTRIES,
+					minor->debugfs_root, minor);
+}
+
+void
+nouveau_drm_debugfs_cleanup(struct drm_minor *minor)
+{
+	int i;
+
+	drm_debugfs_remove_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES,
+				 minor);
+
+	for (i = 0; i < ARRAY_SIZE(nouveau_debugfs_files); i++) {
+		drm_debugfs_remove_files((struct drm_info_list *)
+					 nouveau_debugfs_files[i].fops,
+					 1, minor);
+	}
+}
+
+int
+nouveau_debugfs_init(struct nouveau_drm *drm)
+{
+	int ret;
+
+	drm->debugfs = kzalloc(sizeof(*drm->debugfs), GFP_KERNEL);
+	if (!drm->debugfs)
+		return -ENOMEM;
+
+	ret = nvif_object_init(&drm->device.object, 0, NVIF_CLASS_CONTROL,
+			       NULL, 0, &drm->debugfs->ctrl);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
 void
-nouveau_debugfs_takedown(struct drm_minor *minor)
+nouveau_debugfs_fini(struct nouveau_drm *drm)
 {
-	drm_debugfs_remove_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES,
-				 minor);
+	if (drm->debugfs && drm->debugfs->ctrl.priv)
+		nvif_object_fini(&drm->debugfs->ctrl);
+
+	kfree(drm->debugfs);
+	drm->debugfs = NULL;
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.h b/drivers/gpu/drm/nouveau/nouveau_debugfs.h
index a62af6f..b8c03ff 100644
--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.h
+++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.h
@@ -4,16 +4,43 @@
 #include <drm/drmP.h>
 
 #if defined(CONFIG_DEBUG_FS)
-extern int  nouveau_debugfs_init(struct drm_minor *);
-extern void nouveau_debugfs_takedown(struct drm_minor *);
+
+#include "nouveau_drm.h"
+
+struct nouveau_debugfs {
+	struct nvif_object ctrl;
+};
+
+static inline struct nouveau_debugfs *
+nouveau_debugfs(struct drm_device *dev)
+{
+	return nouveau_drm(dev)->debugfs;
+}
+
+extern int  nouveau_drm_debugfs_init(struct drm_minor *);
+extern void nouveau_drm_debugfs_cleanup(struct drm_minor *);
+extern int  nouveau_debugfs_init(struct nouveau_drm *);
+extern void nouveau_debugfs_fini(struct nouveau_drm *);
 #else
 static inline int
-nouveau_debugfs_init(struct drm_minor *minor)
+nouveau_drm_debugfs_init(struct drm_minor *minor)
 {
        return 0;
 }
 
-static inline void nouveau_debugfs_takedown(struct drm_minor *minor)
+static inline void
+nouveau_drm_debugfs_cleanup(struct drm_minor *minor)
+{
+}
+
+static inline int
+nouveau_debugfs_init(struct nouveau_drm *drm)
+{
+	return 0;
+}
+
+static inline void
+nouveau_debugfs_fini(struct nouveau_drm *drm)
 {
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 18676b8..24be27d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -39,6 +39,7 @@
 
 #include "nouveau_fence.h"
 
+#include <nvif/cl0046.h>
 #include <nvif/event.h>
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index b3a563c..2f2f252 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -37,12 +37,16 @@
 #include <core/pci.h>
 #include <core/tegra.h>
 
+#include <nvif/class.h>
+#include <nvif/cl0002.h>
+#include <nvif/cla06f.h>
+#include <nvif/if0004.h>
+
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
 #include "nouveau_ttm.h"
 #include "nouveau_gem.h"
 #include "nouveau_vga.h"
-#include "nouveau_sysfs.h"
 #include "nouveau_hwmon.h"
 #include "nouveau_acpi.h"
 #include "nouveau_bios.h"
@@ -256,8 +260,8 @@
 		}
 
 		ret = nvif_notify_init(&drm->nvsw, nouveau_flip_complete,
-				       false, NVSW_NTFY_UEVENT, NULL, 0, 0,
-				       &drm->flip);
+				       false, NV04_NVSW_NTFY_UEVENT,
+				       NULL, 0, 0, &drm->flip);
 		if (ret == 0)
 			ret = nvif_notify_get(&drm->flip);
 		if (ret) {
@@ -448,7 +452,7 @@
 			goto fail_dispinit;
 	}
 
-	nouveau_sysfs_init(dev);
+	nouveau_debugfs_init(drm);
 	nouveau_hwmon_init(dev);
 	nouveau_accel_init(drm);
 	nouveau_fbcon_init(dev);
@@ -486,7 +490,7 @@
 	nouveau_fbcon_fini(dev);
 	nouveau_accel_fini(drm);
 	nouveau_hwmon_fini(dev);
-	nouveau_sysfs_fini(dev);
+	nouveau_debugfs_fini(drm);
 
 	if (dev->mode_config.num_crtc)
 		nouveau_display_fini(dev);
@@ -928,8 +932,8 @@
 	.lastclose = nouveau_vga_lastclose,
 
 #if defined(CONFIG_DEBUG_FS)
-	.debugfs_init = nouveau_debugfs_init,
-	.debugfs_cleanup = nouveau_debugfs_takedown,
+	.debugfs_init = nouveau_drm_debugfs_init,
+	.debugfs_cleanup = nouveau_drm_debugfs_cleanup,
 #endif
 
 	.get_vblank_counter = drm_vblank_no_hw_counter,
@@ -1003,7 +1007,6 @@
 	DRM_DEBUG_DRIVER("... modeset      : %d\n", nouveau_modeset);
 	DRM_DEBUG_DRIVER("... runpm        : %d\n", nouveau_runtime_pm);
 	DRM_DEBUG_DRIVER("... vram_pushbuf : %d\n", nouveau_vram_pushbuf);
-	DRM_DEBUG_DRIVER("... pstate       : %d\n", nouveau_pstate);
 }
 
 static const struct dev_pm_ops nouveau_pm_ops = {
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index a02813e..5c363ed 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -164,7 +164,7 @@
 
 	/* power management */
 	struct nouveau_hwmon *hwmon;
-	struct nouveau_sysfs *sysfs;
+	struct nouveau_debugfs *debugfs;
 
 	/* display power reference */
 	bool have_disp_power_ref;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 574c36b..9a8c5b7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -30,6 +30,7 @@
 #include <linux/hrtimer.h>
 #include <trace/events/fence.h>
 
+#include <nvif/cl826e.h>
 #include <nvif/notify.h>
 #include <nvif/event.h>
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
index 491c714..8e13467 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hwmon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
@@ -34,6 +34,8 @@
 #include "nouveau_drm.h"
 #include "nouveau_hwmon.h"
 
+#include <nvkm/subdev/volt.h>
+
 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 static ssize_t
 nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
@@ -512,6 +514,35 @@
 			  nouveau_hwmon_get_pwm1_max,
 			  nouveau_hwmon_set_pwm1_max, 0);
 
+static ssize_t
+nouveau_hwmon_get_in0_input(struct device *d,
+			    struct device_attribute *a, char *buf)
+{
+	struct drm_device *dev = dev_get_drvdata(d);
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nvkm_volt *volt = nvxx_volt(&drm->device);
+	int ret;
+
+	ret = nvkm_volt_get(volt);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%i\n", ret / 1000);
+}
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO,
+			  nouveau_hwmon_get_in0_input, NULL, 0);
+
+static ssize_t
+nouveau_hwmon_get_in0_label(struct device *d,
+			    struct device_attribute *a, char *buf)
+{
+	return sprintf(buf, "GPU core\n");
+}
+
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO,
+			  nouveau_hwmon_get_in0_label, NULL, 0);
+
 static struct attribute *hwmon_default_attributes[] = {
 	&sensor_dev_attr_name.dev_attr.attr,
 	&sensor_dev_attr_update_rate.dev_attr.attr,
@@ -542,6 +573,12 @@
 	NULL
 };
 
+static struct attribute *hwmon_in0_attributes[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_label.dev_attr.attr,
+	NULL
+};
+
 static const struct attribute_group hwmon_default_attrgroup = {
 	.attrs = hwmon_default_attributes,
 };
@@ -554,6 +591,9 @@
 static const struct attribute_group hwmon_pwm_fan_attrgroup = {
 	.attrs = hwmon_pwm_fan_attributes,
 };
+static const struct attribute_group hwmon_in0_attrgroup = {
+	.attrs = hwmon_in0_attributes,
+};
 #endif
 
 int
@@ -562,6 +602,7 @@
 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nvkm_therm *therm = nvxx_therm(&drm->device);
+	struct nvkm_volt *volt = nvxx_volt(&drm->device);
 	struct nouveau_hwmon *hwmon;
 	struct device *hwmon_dev;
 	int ret = 0;
@@ -613,6 +654,14 @@
 			goto error;
 	}
 
+	if (volt && nvkm_volt_get(volt) >= 0) {
+		ret = sysfs_create_group(&hwmon_dev->kobj,
+					 &hwmon_in0_attrgroup);
+
+		if (ret)
+			goto error;
+	}
+
 	hwmon->hwmon = hwmon_dev;
 
 	return 0;
@@ -638,6 +687,7 @@
 		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_temp_attrgroup);
 		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_pwm_fan_attrgroup);
 		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_fan_rpm_attrgroup);
+		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_in0_attrgroup);
 
 		hwmon_device_unregister(hwmon->hwmon);
 	}
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c
index 60e32c4..8a70cec 100644
--- a/drivers/gpu/drm/nouveau/nouveau_platform.c
+++ b/drivers/gpu/drm/nouveau/nouveau_platform.c
@@ -78,3 +78,14 @@
 	.probe = nouveau_platform_probe,
 	.remove = nouveau_platform_remove,
 };
+
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) || IS_ENABLED(CONFIG_ARCH_TEGRA_132_SOC)
+MODULE_FIRMWARE("nvidia/gk20a/fecs_data.bin");
+MODULE_FIRMWARE("nvidia/gk20a/fecs_inst.bin");
+MODULE_FIRMWARE("nvidia/gk20a/gpccs_data.bin");
+MODULE_FIRMWARE("nvidia/gk20a/gpccs_inst.bin");
+MODULE_FIRMWARE("nvidia/gk20a/sw_bundle_init.bin");
+MODULE_FIRMWARE("nvidia/gk20a/sw_ctx.bin");
+MODULE_FIRMWARE("nvidia/gk20a/sw_method_init.bin");
+MODULE_FIRMWARE("nvidia/gk20a/sw_nonctx.bin");
+#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/drivers/gpu/drm/nouveau/nouveau_sysfs.c
deleted file mode 100644
index 5dac354..0000000
--- a/drivers/gpu/drm/nouveau/nouveau_sysfs.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * 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 <nvif/os.h>
-#include <nvif/class.h>
-#include <nvif/ioctl.h>
-
-#include "nouveau_sysfs.h"
-
-MODULE_PARM_DESC(pstate, "enable sysfs pstate file, which will be moved in the future");
-int nouveau_pstate;
-module_param_named(pstate, nouveau_pstate, int, 0400);
-
-static inline struct drm_device *
-drm_device(struct device *d)
-{
-	return dev_get_drvdata(d);
-}
-
-#define snappendf(p,r,f,a...) do {                                             \
-	snprintf(p, r, f, ##a);                                                \
-	r -= strlen(p);                                                        \
-	p += strlen(p);                                                        \
-} while(0)
-
-static ssize_t
-nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b)
-{
-	struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d));
-	struct nvif_control_pstate_info_v0 info = {};
-	size_t cnt = PAGE_SIZE;
-	char *buf = b;
-	int ret, i;
-
-	ret = nvif_mthd(&sysfs->ctrl, NVIF_CONTROL_PSTATE_INFO,
-			&info, sizeof(info));
-	if (ret)
-		return ret;
-
-	for (i = 0; i < info.count + 1; i++) {
-		const s32 state = i < info.count ? i :
-			NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT;
-		struct nvif_control_pstate_attr_v0 attr = {
-			.state = state,
-			.index = 0,
-		};
-
-		ret = nvif_mthd(&sysfs->ctrl, NVIF_CONTROL_PSTATE_ATTR,
-				&attr, sizeof(attr));
-		if (ret)
-			return ret;
-
-		if (i < info.count)
-			snappendf(buf, cnt, "%02x:", attr.state);
-		else
-			snappendf(buf, cnt, "%s:", info.pwrsrc == 0 ? "DC" :
-						   info.pwrsrc == 1 ? "AC" :
-						   "--");
-
-		attr.index = 0;
-		do {
-			attr.state = state;
-			ret = nvif_mthd(&sysfs->ctrl,
-					NVIF_CONTROL_PSTATE_ATTR,
-					&attr, sizeof(attr));
-			if (ret)
-				return ret;
-
-			snappendf(buf, cnt, " %s %d", attr.name, attr.min);
-			if (attr.min != attr.max)
-				snappendf(buf, cnt, "-%d", attr.max);
-			snappendf(buf, cnt, " %s", attr.unit);
-		} while (attr.index);
-
-		if (state >= 0) {
-			if (info.ustate_ac == state)
-				snappendf(buf, cnt, " AC");
-			if (info.ustate_dc == state)
-				snappendf(buf, cnt, " DC");
-			if (info.pstate == state)
-				snappendf(buf, cnt, " *");
-		} else {
-			if (info.ustate_ac < -1)
-				snappendf(buf, cnt, " AC");
-			if (info.ustate_dc < -1)
-				snappendf(buf, cnt, " DC");
-		}
-
-		snappendf(buf, cnt, "\n");
-	}
-
-	return strlen(b);
-}
-
-static ssize_t
-nouveau_sysfs_pstate_set(struct device *d, struct device_attribute *a,
-			 const char *buf, size_t count)
-{
-	struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d));
-	struct nvif_control_pstate_user_v0 args = { .pwrsrc = -EINVAL };
-	long value, ret;
-	char *tmp;
-
-	if ((tmp = strchr(buf, '\n')))
-		*tmp = '\0';
-
-	if (!strncasecmp(buf, "dc:", 3)) {
-		args.pwrsrc = 0;
-		buf += 3;
-	} else
-	if (!strncasecmp(buf, "ac:", 3)) {
-		args.pwrsrc = 1;
-		buf += 3;
-	}
-
-	if (!strcasecmp(buf, "none"))
-		args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN;
-	else
-	if (!strcasecmp(buf, "auto"))
-		args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON;
-	else {
-		ret = kstrtol(buf, 16, &value);
-		if (ret)
-			return ret;
-		args.ustate = value;
-	}
-
-	ret = nvif_mthd(&sysfs->ctrl, NVIF_CONTROL_PSTATE_USER,
-			&args, sizeof(args));
-	if (ret < 0)
-		return ret;
-
-	return count;
-}
-
-static DEVICE_ATTR(pstate, S_IRUGO | S_IWUSR,
-		   nouveau_sysfs_pstate_get, nouveau_sysfs_pstate_set);
-
-void
-nouveau_sysfs_fini(struct drm_device *dev)
-{
-	struct nouveau_sysfs *sysfs = nouveau_sysfs(dev);
-	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nvif_device *device = &drm->device;
-
-	if (sysfs && sysfs->ctrl.priv) {
-		device_remove_file(nvxx_device(device)->dev, &dev_attr_pstate);
-		nvif_object_fini(&sysfs->ctrl);
-	}
-
-	drm->sysfs = NULL;
-	kfree(sysfs);
-}
-
-int
-nouveau_sysfs_init(struct drm_device *dev)
-{
-	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct nvif_device *device = &drm->device;
-	struct nouveau_sysfs *sysfs;
-	int ret;
-
-	if (!nouveau_pstate)
-		return 0;
-
-	sysfs = drm->sysfs = kzalloc(sizeof(*sysfs), GFP_KERNEL);
-	if (!sysfs)
-		return -ENOMEM;
-
-	ret = nvif_object_init(&device->object, 0, NVIF_IOCTL_NEW_V0_CONTROL,
-			       NULL, 0, &sysfs->ctrl);
-	if (ret == 0)
-		device_create_file(nvxx_device(device)->dev, &dev_attr_pstate);
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.h b/drivers/gpu/drm/nouveau/nouveau_sysfs.h
deleted file mode 100644
index 4e5ea92..0000000
--- a/drivers/gpu/drm/nouveau/nouveau_sysfs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __NOUVEAU_SYSFS_H__
-#define __NOUVEAU_SYSFS_H__
-
-#include "nouveau_drm.h"
-
-struct nouveau_sysfs {
-	struct nvif_object ctrl;
-};
-
-static inline struct nouveau_sysfs *
-nouveau_sysfs(struct drm_device *dev)
-{
-	return nouveau_drm(dev)->sysfs;
-}
-
-int  nouveau_sysfs_init(struct drm_device *);
-void nouveau_sysfs_fini(struct drm_device *);
-
-extern int nouveau_pstate;
-
-#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c
index 6ae1b34..e9f52ef 100644
--- a/drivers/gpu/drm/nouveau/nouveau_usif.c
+++ b/drivers/gpu/drm/nouveau/nouveau_usif.c
@@ -130,20 +130,21 @@
 		struct nvif_notify_req_v0 v0;
 	} *req;
 	struct usif_notify *ntfy;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		if (usif_notify_find(f, args->v0.index))
 			return -EEXIST;
 	} else
 		return ret;
 	req = data;
+	ret = -ENOSYS;
 
 	if (!(ntfy = kmalloc(sizeof(*ntfy), GFP_KERNEL)))
 		return -ENOMEM;
 	atomic_set(&ntfy->enabled, 0);
 
-	if (nvif_unpack(req->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, true))) {
 		ntfy->reply = sizeof(struct nvif_notify_rep_v0) + req->v0.reply;
 		ntfy->route = req->v0.route;
 		ntfy->token = req->v0.token;
@@ -171,9 +172,9 @@
 		struct nvif_ioctl_ntfy_del_v0 v0;
 	} *args = data;
 	struct usif_notify *ntfy;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		if (!(ntfy = usif_notify_find(f, args->v0.index)))
 			return -ENOENT;
 	} else
@@ -194,9 +195,9 @@
 		struct nvif_ioctl_ntfy_del_v0 v0;
 	} *args = data;
 	struct usif_notify *ntfy;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		if (!(ntfy = usif_notify_find(f, args->v0.index)))
 			return -ENOENT;
 	} else
@@ -233,9 +234,9 @@
 		struct nvif_ioctl_ntfy_put_v0 v0;
 	} *args = data;
 	struct usif_notify *ntfy;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		if (!(ntfy = usif_notify_find(f, args->v0.index)))
 			return -ENOENT;
 	} else
@@ -270,13 +271,13 @@
 		struct nvif_ioctl_new_v0 v0;
 	} *args = data;
 	struct usif_object *object;
-	int ret;
+	int ret = -ENOSYS;
 
 	if (!(object = kmalloc(sizeof(*object), GFP_KERNEL)))
 		return -ENOMEM;
 	list_add(&object->head, &cli->objects);
 
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		object->route = args->v0.route;
 		object->token = args->v0.token;
 		args->v0.route = NVDRM_OBJECT_USIF;
@@ -310,7 +311,7 @@
 	if (ret = -EFAULT, copy_from_user(argv, user, size))
 		goto done;
 
-	if (nvif_unpack(argv->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(-ENOSYS, &data, &size, argv->v0, 0, 0, true))) {
 		/* block access to objects not created via this interface */
 		owner = argv->v0.owner;
 		if (argv->v0.object == 0ULL)
diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c
index f3d705d..3022d24 100644
--- a/drivers/gpu/drm/nouveau/nv04_fence.c
+++ b/drivers/gpu/drm/nouveau/nv04_fence.c
@@ -26,6 +26,8 @@
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
 
+#include <nvif/if0004.h>
+
 struct nv04_fence_chan {
 	struct nouveau_fence_chan base;
 };
diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c
index 80b6eb8..6a141c9 100644
--- a/drivers/gpu/drm/nouveau/nv17_fence.c
+++ b/drivers/gpu/drm/nouveau/nv17_fence.c
@@ -24,6 +24,7 @@
 
 #include <nvif/os.h>
 #include <nvif/class.h>
+#include <nvif/cl0002.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 44e1952..ea39216 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -31,6 +31,13 @@
 #include <drm/drm_fb_helper.h>
 
 #include <nvif/class.h>
+#include <nvif/cl0002.h>
+#include <nvif/cl5070.h>
+#include <nvif/cl507a.h>
+#include <nvif/cl507b.h>
+#include <nvif/cl507c.h>
+#include <nvif/cl507d.h>
+#include <nvif/cl507e.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
@@ -774,7 +781,6 @@
 	 */
 	if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON ||
 			     (nv_connector->underscan == UNDERSCAN_AUTO &&
-			      nv_connector->edid &&
 			      drm_detect_hdmi_monitor(nv_connector->edid)))) {
 		u32 bX = nv_connector->underscan_hborder;
 		u32 bY = nv_connector->underscan_vborder;
@@ -1962,10 +1968,17 @@
 	switch (nv_encoder->dcb->type) {
 	case DCB_OUTPUT_TMDS:
 		if (nv_encoder->dcb->sorconf.link & 1) {
-			if (mode->clock < 165000)
-				proto = 0x1;
-			else
-				proto = 0x5;
+			proto = 0x1;
+			/* Only enable dual-link if:
+			 *  - Need to (i.e. rate > 165MHz)
+			 *  - DCB says we can
+			 *  - Not an HDMI monitor, since there's no dual-link
+			 *    on HDMI.
+			 */
+			if (mode->clock >= 165000 &&
+			    nv_encoder->dcb->duallink_possible &&
+			    !drm_detect_hdmi_monitor(nv_connector->edid))
+				proto |= 0x4;
 		} else {
 			proto = 0x2;
 		}
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c
index f0d96e5..3695ccce 100644
--- a/drivers/gpu/drm/nouveau/nv50_fence.c
+++ b/drivers/gpu/drm/nouveau/nv50_fence.c
@@ -24,6 +24,7 @@
 
 #include <nvif/os.h>
 #include <nvif/class.h>
+#include <nvif/cl0002.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c
index 297e1e9..e194391 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/client.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c
@@ -28,6 +28,7 @@
 
 #include <nvif/class.h>
 #include <nvif/event.h>
+#include <nvif/if0000.h>
 #include <nvif/unpack.h>
 
 struct nvkm_client_notify {
@@ -96,7 +97,7 @@
 		struct nvif_notify_req_v0 v0;
 	} *req = data;
 	u8  index, reply;
-	int ret;
+	int ret = -ENOSYS;
 
 	for (index = 0; index < ARRAY_SIZE(client->notify); index++) {
 		if (!client->notify[index])
@@ -111,7 +112,7 @@
 		return -ENOMEM;
 
 	nvif_ioctl(object, "notify new size %d\n", size);
-	if (nvif_unpack(req->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, true))) {
 		nvif_ioctl(object, "notify new vers %d reply %d route %02x "
 				   "token %llx\n", req->v0.version,
 			   req->v0.reply, req->v0.route, req->v0.token);
@@ -143,10 +144,10 @@
 	union {
 		struct nv_client_devlist_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "client devlist size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "client devlist vers %d count %d\n",
 			   args->v0.version, args->v0.count);
 		if (size == sizeof(args->v0.device[0]) * args->v0.count) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
index d87d6ab..b0db518 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
@@ -34,10 +34,10 @@
 	union {
 		struct nvif_ioctl_nop_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "nop size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "nop vers %lld\n", args->v0.version);
 		args->v0.version = NVIF_VERSION_LATEST;
 	}
@@ -52,10 +52,10 @@
 		struct nvif_ioctl_sclass_v0 v0;
 	} *args = data;
 	struct nvkm_oclass oclass;
-	int ret, i = 0;
+	int ret = -ENOSYS, i = 0;
 
 	nvif_ioctl(object, "sclass size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "sclass vers %d count %d\n",
 			   args->v0.version, args->v0.count);
 		if (size != args->v0.count * sizeof(args->v0.oclass[0]))
@@ -86,10 +86,10 @@
 	struct nvkm_client *client = parent->client;
 	struct nvkm_object *object = NULL;
 	struct nvkm_oclass oclass;
-	int ret, i = 0;
+	int ret = -ENOSYS, i = 0;
 
 	nvif_ioctl(parent, "new size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(parent, "new vers %d handle %08x class %08x "
 				   "route %02x token %llx object %016llx\n",
 			   args->v0.version, args->v0.handle, args->v0.oclass,
@@ -147,10 +147,10 @@
 	union {
 		struct nvif_ioctl_del none;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "delete size %d\n", size);
-	if (nvif_unvers(args->none)) {
+	if (!(ret = nvif_unvers(ret, &data, &size, args->none))) {
 		nvif_ioctl(object, "delete\n");
 		nvkm_object_fini(object, false);
 		nvkm_object_del(&object);
@@ -165,10 +165,10 @@
 	union {
 		struct nvif_ioctl_mthd_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "mthd size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "mthd vers %d mthd %02x\n",
 			   args->v0.version, args->v0.method);
 		ret = nvkm_object_mthd(object, args->v0.method, data, size);
@@ -189,10 +189,10 @@
 		u16 b16;
 		u32 b32;
 	} v;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "rd size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "rd vers %d size %d addr %016llx\n",
 			   args->v0.version, args->v0.size, args->v0.addr);
 		switch (args->v0.size) {
@@ -223,10 +223,10 @@
 	union {
 		struct nvif_ioctl_wr_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "wr size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object,
 			   "wr vers %d size %d addr %016llx data %08x\n",
 			   args->v0.version, args->v0.size, args->v0.addr,
@@ -251,10 +251,10 @@
 	union {
 		struct nvif_ioctl_map_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "map size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "map vers %d\n", args->v0.version);
 		ret = nvkm_object_map(object, &args->v0.handle,
 					      &args->v0.length);
@@ -269,10 +269,10 @@
 	union {
 		struct nvif_ioctl_unmap none;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "unmap size %d\n", size);
-	if (nvif_unvers(args->none)) {
+	if (!(ret = nvif_unvers(ret, &data, &size, args->none))) {
 		nvif_ioctl(object, "unmap\n");
 	}
 
@@ -286,10 +286,10 @@
 		struct nvif_ioctl_ntfy_new_v0 v0;
 	} *args = data;
 	struct nvkm_event *event;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "ntfy new size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "ntfy new vers %d event %02x\n",
 			   args->v0.version, args->v0.event);
 		ret = nvkm_object_ntfy(object, args->v0.event, &event);
@@ -312,10 +312,10 @@
 	union {
 		struct nvif_ioctl_ntfy_del_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "ntfy del size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "ntfy del vers %d index %d\n",
 			   args->v0.version, args->v0.index);
 		ret = nvkm_client_notify_del(client, args->v0.index);
@@ -331,10 +331,10 @@
 	union {
 		struct nvif_ioctl_ntfy_get_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "ntfy get size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "ntfy get vers %d index %d\n",
 			   args->v0.version, args->v0.index);
 		ret = nvkm_client_notify_get(client, args->v0.index);
@@ -350,10 +350,10 @@
 	union {
 		struct nvif_ioctl_ntfy_put_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "ntfy put size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "ntfy put vers %d index %d\n",
 			   args->v0.version, args->v0.index);
 		ret = nvkm_client_notify_put(client, args->v0.index);
@@ -421,12 +421,12 @@
 	union {
 		struct nvif_ioctl_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	client->super = supervisor;
 	nvif_ioctl(object, "size %d\n", size);
 
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object,
 			   "vers %d type %02x object %016llx owner %02x\n",
 			   args->v0.version, args->v0.type, args->v0.object,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c
index c541a1c..e2b944d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c
@@ -22,19 +22,65 @@
  * Authors: Ben Skeggs
  */
 #include "priv.h"
+#include <core/enum.h>
 
 #include <nvif/class.h>
 
+static const struct nvkm_enum
+gk104_ce_launcherr_report[] = {
+	{ 0x0, "NO_ERR" },
+	{ 0x1, "2D_LAYER_EXCEEDS_DEPTH" },
+	{ 0x2, "INVALID_ARGUMENT" },
+	{ 0x3, "MEM2MEM_RECT_OUT_OF_BOUNDS" },
+	{ 0x4, "SRC_LINE_EXCEEDS_PITCH" },
+	{ 0x5, "SRC_LINE_EXCEEDS_NEG_PITCH" },
+	{ 0x6, "DST_LINE_EXCEEDS_PITCH" },
+	{ 0x7, "DST_LINE_EXCEEDS_NEG_PITCH" },
+	{ 0x8, "BAD_SRC_PIXEL_COMP_REF" },
+	{ 0x9, "INVALID_VALUE" },
+	{ 0xa, "UNUSED_FIELD" },
+	{ 0xb, "INVALID_OPERATION" },
+	{}
+};
+
+static void
+gk104_ce_intr_launcherr(struct nvkm_engine *ce, const u32 base)
+{
+	struct nvkm_subdev *subdev = &ce->subdev;
+	struct nvkm_device *device = subdev->device;
+	u32 stat = nvkm_rd32(device, 0x104f14 + base);
+	const struct nvkm_enum *en =
+		nvkm_enum_find(gk104_ce_launcherr_report, stat & 0x0000000f);
+	nvkm_warn(subdev, "LAUNCHERR %08x [%s]\n", stat, en ? en->name : "");
+	nvkm_wr32(device, 0x104f14 + base, 0x00000000);
+}
+
 void
 gk104_ce_intr(struct nvkm_engine *ce)
 {
 	const u32 base = (ce->subdev.index - NVKM_ENGINE_CE0) * 0x1000;
 	struct nvkm_subdev *subdev = &ce->subdev;
 	struct nvkm_device *device = subdev->device;
-	u32 stat = nvkm_rd32(device, 0x104908 + base);
-	if (stat) {
-		nvkm_warn(subdev, "intr %08x\n", stat);
-		nvkm_wr32(device, 0x104908 + base, stat);
+	u32 mask = nvkm_rd32(device, 0x104904 + base);
+	u32 intr = nvkm_rd32(device, 0x104908 + base) & mask;
+	if (intr & 0x00000001) {
+		nvkm_warn(subdev, "BLOCKPIPE\n");
+		nvkm_wr32(device, 0x104908 + base, 0x00000001);
+		intr &= ~0x00000001;
+	}
+	if (intr & 0x00000002) {
+		nvkm_warn(subdev, "NONBLOCKPIPE\n");
+		nvkm_wr32(device, 0x104908 + base, 0x00000002);
+		intr &= ~0x00000002;
+	}
+	if (intr & 0x00000004) {
+		gk104_ce_intr_launcherr(ce, base);
+		nvkm_wr32(device, 0x104908 + base, 0x00000004);
+		intr &= ~0x00000004;
+	}
+	if (intr) {
+		nvkm_warn(subdev, "intr %08x\n", intr);
+		nvkm_wr32(device, 0x104908 + base, intr);
 	}
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index bbc9824..b1ba1c7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -1388,7 +1388,7 @@
 	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gf106_pci_new,
 	.pmu = gf100_pmu_new,
 	.therm = gt215_therm_new,
 	.timer = nv41_timer_new,
@@ -1423,7 +1423,7 @@
 	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gf106_pci_new,
 	.pmu = gf100_pmu_new,
 	.therm = gt215_therm_new,
 	.timer = nv41_timer_new,
@@ -1566,7 +1566,7 @@
 	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gf106_pci_new,
 	.pmu = gf100_pmu_new,
 	.therm = gt215_therm_new,
 	.timer = nv41_timer_new,
@@ -1601,7 +1601,7 @@
 	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gf106_pci_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
 	.ce[0] = gf100_ce_new,
@@ -1634,7 +1634,7 @@
 	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gf106_pci_new,
 	.pmu = gf119_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
@@ -1669,7 +1669,7 @@
 	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gk104_pci_new,
 	.pmu = gk104_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
@@ -1706,7 +1706,7 @@
 	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gk104_pci_new,
 	.pmu = gk104_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
@@ -1743,7 +1743,7 @@
 	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gk104_pci_new,
 	.pmu = gk104_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
@@ -1804,7 +1804,7 @@
 	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gk104_pci_new,
 	.pmu = gk110_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
@@ -1840,7 +1840,7 @@
 	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gk104_pci_new,
 	.pmu = gk110_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
@@ -1876,7 +1876,7 @@
 	.mc = gk20a_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gk104_pci_new,
 	.pmu = gk208_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
@@ -1912,7 +1912,7 @@
 	.mc = gk20a_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gk104_pci_new,
 	.pmu = gk208_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
@@ -1948,7 +1948,7 @@
 	.mc = gk20a_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gk104_pci_new,
 	.pmu = gm107_pmu_new,
 	.therm = gm107_therm_new,
 	.timer = gk20a_timer_new,
@@ -1973,13 +1973,13 @@
 	.fuse = gm107_fuse_new,
 	.gpio = gk104_gpio_new,
 	.i2c = gm204_i2c_new,
-	.ibus = gk104_ibus_new,
+	.ibus = gm204_ibus_new,
 	.imem = nv50_instmem_new,
-	.ltc = gm107_ltc_new,
+	.ltc = gm204_ltc_new,
 	.mc = gk20a_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gk104_pci_new,
 	.pmu = gm107_pmu_new,
 	.timer = gk20a_timer_new,
 	.volt = gk104_volt_new,
@@ -2004,13 +2004,13 @@
 	.fuse = gm107_fuse_new,
 	.gpio = gk104_gpio_new,
 	.i2c = gm204_i2c_new,
-	.ibus = gk104_ibus_new,
+	.ibus = gm204_ibus_new,
 	.imem = nv50_instmem_new,
-	.ltc = gm107_ltc_new,
+	.ltc = gm204_ltc_new,
 	.mc = gk20a_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
-	.pci = g94_pci_new,
+	.pci = gk104_pci_new,
 	.pmu = gm107_pmu_new,
 	.timer = gk20a_timer_new,
 	.volt = gk104_volt_new,
@@ -2033,7 +2033,7 @@
 	.fuse = gm107_fuse_new,
 	.ibus = gk20a_ibus_new,
 	.imem = gk20a_instmem_new,
-	.ltc = gm107_ltc_new,
+	.ltc = gm204_ltc_new,
 	.mc = gk20a_mc_new,
 	.mmu = gf100_mmu_new,
 	.timer = gk20a_timer_new,
@@ -2494,7 +2494,8 @@
 		device->pri = ioremap(mmio_base, mmio_size);
 		if (!device->pri) {
 			nvdev_error(device, "unable to map PRI\n");
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto done;
 		}
 	}
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c
index cf8bc06..b0ece71a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c
@@ -27,6 +27,7 @@
 #include <subdev/clk.h>
 
 #include <nvif/class.h>
+#include <nvif/if0001.h>
 #include <nvif/ioctl.h>
 #include <nvif/unpack.h>
 
@@ -37,10 +38,10 @@
 		struct nvif_control_pstate_info_v0 v0;
 	} *args = data;
 	struct nvkm_clk *clk = ctrl->device->clk;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(&ctrl->object, "control pstate info size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(&ctrl->object, "control pstate info vers %d\n",
 			   args->v0.version);
 	} else
@@ -75,10 +76,10 @@
 	struct nvkm_cstate *cstate;
 	int i = 0, j = -1;
 	u32 lo, hi;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(&ctrl->object, "control pstate attr size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(&ctrl->object,
 			   "control pstate attr vers %d state %d index %d\n",
 			   args->v0.version, args->v0.state, args->v0.index);
@@ -143,10 +144,10 @@
 		struct nvif_control_pstate_user_v0 v0;
 	} *args = data;
 	struct nvkm_clk *clk = ctrl->device->clk;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(&ctrl->object, "control pstate user size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(&ctrl->object,
 			   "control pstate user vers %d ustate %d pwrsrc %d\n",
 			   args->v0.version, args->v0.ustate, args->v0.pwrsrc);
@@ -204,7 +205,7 @@
 
 const struct nvkm_device_oclass
 nvkm_control_oclass = {
-	.base.oclass = NVIF_IOCTL_NEW_V0_CONTROL,
+	.base.oclass = NVIF_CLASS_CONTROL,
 	.base.minver = -1,
 	.base.maxver = -1,
 	.ctor = nvkm_control_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
index caf22b5..62ad030 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
@@ -259,12 +259,6 @@
 };
 
 static const struct nvkm_device_pci_vendor
-nvkm_device_pci_10de_0fcd[] = {
-	{ 0x17aa, 0x3801, NULL, { .War00C800_0 = true } }, /* Lenovo Y510P */
-	{}
-};
-
-static const struct nvkm_device_pci_vendor
 nvkm_device_pci_10de_0fd2[] = {
 	{ 0x1028, 0x0595, "GeForce GT 640M LE" },
 	{ 0x1028, 0x05b2, "GeForce GT 640M LE" },
@@ -279,12 +273,6 @@
 };
 
 static const struct nvkm_device_pci_vendor
-nvkm_device_pci_10de_0fe4[] = {
-	{ 0x144d, 0xc740, NULL, { .War00C800_0 = true } },
-	{}
-};
-
-static const struct nvkm_device_pci_vendor
 nvkm_device_pci_10de_104b[] = {
 	{ 0x1043, 0x844c, "GeForce GT 625" },
 	{ 0x1043, 0x846b, "GeForce GT 625" },
@@ -690,13 +678,6 @@
 static const struct nvkm_device_pci_vendor
 nvkm_device_pci_10de_1199[] = {
 	{ 0x1458, 0xd001, "GeForce GTX 760" },
-	{ 0x1462, 0x1106, "GeForce GTX 780M", { .War00C800_0 = true } }, /* Medion Erazer X7827 */
-	{}
-};
-
-static const struct nvkm_device_pci_vendor
-nvkm_device_pci_10de_11e0[] = {
-	{ 0x1558, 0x5106, NULL, { .War00C800_0 = true } },
 	{}
 };
 
@@ -707,14 +688,6 @@
 };
 
 static const struct nvkm_device_pci_vendor
-nvkm_device_pci_10de_11fc[] = {
-	{ 0x1179, 0x0001, NULL, { .War00C800_0 = true } }, /* Toshiba Tecra W50 */
-	{ 0x17aa, 0x2211, NULL, { .War00C800_0 = true } }, /* Lenovo W541 */
-	{ 0x17aa, 0x221e, NULL, { .War00C800_0 = true } }, /* Lenovo W541 */
-	{}
-};
-
-static const struct nvkm_device_pci_vendor
 nvkm_device_pci_10de_1247[] = {
 	{ 0x1043, 0x212a, "GeForce GT 635M" },
 	{ 0x1043, 0x212b, "GeForce GT 635M" },
@@ -1368,7 +1341,7 @@
 	{ 0x0fc6, "GeForce GTX 650" },
 	{ 0x0fc8, "GeForce GT 740" },
 	{ 0x0fc9, "GeForce GT 730" },
-	{ 0x0fcd, "GeForce GT 755M", nvkm_device_pci_10de_0fcd },
+	{ 0x0fcd, "GeForce GT 755M" },
 	{ 0x0fce, "GeForce GT 640M LE" },
 	{ 0x0fd1, "GeForce GT 650M" },
 	{ 0x0fd2, "GeForce GT 640M", nvkm_device_pci_10de_0fd2 },
@@ -1382,7 +1355,7 @@
 	{ 0x0fe1, "GeForce GT 730M" },
 	{ 0x0fe2, "GeForce GT 745M" },
 	{ 0x0fe3, "GeForce GT 745M", nvkm_device_pci_10de_0fe3 },
-	{ 0x0fe4, "GeForce GT 750M", nvkm_device_pci_10de_0fe4 },
+	{ 0x0fe4, "GeForce GT 750M" },
 	{ 0x0fe9, "GeForce GT 750M" },
 	{ 0x0fea, "GeForce GT 755M" },
 	{ 0x0fec, "GeForce 710A" },
@@ -1497,12 +1470,12 @@
 	{ 0x11c6, "GeForce GTX 650 Ti" },
 	{ 0x11c8, "GeForce GTX 650" },
 	{ 0x11cb, "GeForce GT 740" },
-	{ 0x11e0, "GeForce GTX 770M", nvkm_device_pci_10de_11e0 },
+	{ 0x11e0, "GeForce GTX 770M" },
 	{ 0x11e1, "GeForce GTX 765M" },
 	{ 0x11e2, "GeForce GTX 765M" },
 	{ 0x11e3, "GeForce GTX 760M", nvkm_device_pci_10de_11e3 },
 	{ 0x11fa, "Quadro K4000" },
-	{ 0x11fc, "Quadro K2100M", nvkm_device_pci_10de_11fc },
+	{ 0x11fc, "Quadro K2100M" },
 	{ 0x1200, "GeForce GTX 560 Ti" },
 	{ 0x1201, "GeForce GTX 560" },
 	{ 0x1203, "GeForce GTX 460 SE v2" },
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
index 1ae48f2..1370664 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
@@ -31,6 +31,7 @@
 #include <subdev/timer.h>
 
 #include <nvif/class.h>
+#include <nvif/cl0080.h>
 #include <nvif/unpack.h>
 
 struct nvkm_udevice {
@@ -48,10 +49,10 @@
 	union {
 		struct nv_device_info_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "device info size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "device info vers %d\n", args->v0.version);
 	} else
 		return ret;
@@ -123,13 +124,16 @@
 static int
 nvkm_udevice_time(struct nvkm_udevice *udev, void *data, u32 size)
 {
+	struct nvkm_object *object = &udev->object;
 	struct nvkm_device *device = udev->device;
 	union {
 		struct nv_device_time_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	nvif_ioctl(object, "device time size %d\n", size);
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+		nvif_ioctl(object, "device time vers %d\n", args->v0.version);
 		args->v0.time = nvkm_timer_read(device->timer);
 	}
 
@@ -140,6 +144,7 @@
 nvkm_udevice_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
 {
 	struct nvkm_udevice *udev = nvkm_udevice(object);
+	nvif_ioctl(object, "device mthd %08x\n", mthd);
 	switch (mthd) {
 	case NV_DEVICE_V0_INFO:
 		return nvkm_udevice_info(udev, data, size);
@@ -331,10 +336,10 @@
 	struct nvkm_object *parent = &client->object;
 	const struct nvkm_object_func *func;
 	struct nvkm_udevice *udev;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create device size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create device v%d device %016llx\n",
 			   args->v0.version, args->v0.device);
 	} else
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
index 44b6771..785fa76 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
@@ -32,6 +32,7 @@
 #include <subdev/bios/dcb.h>
 
 #include <nvif/class.h>
+#include <nvif/cl0046.h>
 #include <nvif/event.h>
 #include <nvif/unpack.h>
 
@@ -58,9 +59,9 @@
 	union {
 		struct nvif_notify_head_req_v0 v0;
 	} *req = data;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(req->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, false))) {
 		notify->size = sizeof(struct nvif_notify_head_rep_v0);
 		if (ret = -ENXIO, req->v0.head <= disp->vblank.index_nr) {
 			notify->types = 1;
@@ -96,9 +97,9 @@
 		struct nvif_notify_conn_req_v0 v0;
 	} *req = data;
 	struct nvkm_output *outp;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(req->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, false))) {
 		notify->size = sizeof(struct nvif_notify_conn_rep_v0);
 		list_for_each_entry(outp, &disp->outp, head) {
 			if (ret = -ENXIO, outp->conn->index == req->v0.conn) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c
index 1fd89ed..83f1523 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c
@@ -27,6 +27,7 @@
 #include <core/client.h>
 
 #include <nvif/class.h>
+#include <nvif/cl507c.h>
 #include <nvif/unpack.h>
 
 int
@@ -41,11 +42,11 @@
 	} *args = data;
 	struct nvkm_object *parent = oclass->parent;
 	struct nv50_disp *disp = root->disp;
-	int head, ret;
+	int head, ret = -ENOSYS;
 	u64 push;
 
 	nvif_ioctl(parent, "create disp base channel dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create disp base channel dma vers %d "
 				   "pushbuf %016llx head %d\n",
 			   args->v0.version, args->v0.pushbuf, args->v0.head);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
index 01803c0..dd2953b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
@@ -28,7 +28,7 @@
 #include <core/ramht.h>
 #include <engine/dma.h>
 
-#include <nvif/class.h>
+#include <nvif/cl507d.h>
 #include <nvif/event.h>
 #include <nvif/unpack.h>
 
@@ -134,9 +134,9 @@
 	union {
 		struct nvif_notify_uevent_req none;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unvers(args->none)) {
+	if (!(ret = nvif_unvers(ret, &data, &size, args->none))) {
 		notify->size  = sizeof(struct nvif_notify_uevent_rep);
 		notify->types = 1;
 		notify->index = chan->chid;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c
index db4a9b3..b547c8b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c
@@ -28,6 +28,7 @@
 #include <subdev/timer.h>
 
 #include <nvif/class.h>
+#include <nvif/cl507d.h>
 #include <nvif/unpack.h>
 
 int
@@ -42,10 +43,10 @@
 	} *args = data;
 	struct nvkm_object *parent = oclass->parent;
 	u64 push;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create disp core channel dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create disp core channel dma vers %d "
 				   "pushbuf %016llx\n",
 			   args->v0.version, args->v0.pushbuf);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c
index 225858e..8b13204 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c
@@ -27,6 +27,7 @@
 #include <core/client.h>
 
 #include <nvif/class.h>
+#include <nvif/cl507a.h>
 #include <nvif/unpack.h>
 
 int
@@ -41,10 +42,10 @@
 	} *args = data;
 	struct nvkm_object *parent = oclass->parent;
 	struct nv50_disp *disp = root->disp;
-	int head, ret;
+	int head, ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create disp cursor size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create disp cursor vers %d head %d\n",
 			   args->v0.version, args->v0.head);
 		if (args->v0.head > disp->base.head.nr)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c
index 9bfa9e7..c9b78b8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c
@@ -27,7 +27,7 @@
 #include <core/client.h>
 #include <subdev/timer.h>
 
-#include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -39,10 +39,10 @@
 		struct nv50_disp_dac_pwr_v0 v0;
 	} *args = data;
 	u32 stat;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp dac pwr size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp dac pwr vers %d state %d data %d "
 				   "vsync %d hsync %d\n",
 			   args->v0.version, args->v0.state, args->v0.data,
@@ -76,10 +76,10 @@
 	} *args = data;
 	const u32 doff = outp->or * 0x800;
 	u32 loadval;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp dac load size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp dac load vers %d data %08x\n",
 			   args->v0.version, args->v0.data);
 		if (args->v0.data & 0xfff00000)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
index 186fd3a..f031466 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
@@ -158,7 +158,7 @@
 	switch (outp->info.type) {
 	case DCB_OUTPUT_TMDS:
 		*conf = (ctrl & 0x00000f00) >> 8;
-		if (pclk >= 165000)
+		if (*conf == 5)
 			*conf |= 0x0100;
 		break;
 	case DCB_OUTPUT_LVDS:
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c
index af99efb..da6129b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c
@@ -29,7 +29,7 @@
 #include <subdev/bios/dcb.h>
 #include <subdev/timer.h>
 
-#include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -41,10 +41,10 @@
 	} *args = data;
 	const u32 soff = outp->or * 0x030;
 	const u32 hoff = head * 0x800;
-	int ret, i;
+	int ret = -ENOSYS, i;
 
 	nvif_ioctl(object, "disp sor hda eld size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "disp sor hda eld vers %d\n",
 			   args->v0.version);
 		if (size > 0x60)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c
index c1590b7..6f0436d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c
@@ -27,7 +27,7 @@
 #include <core/client.h>
 #include <subdev/timer.h>
 
-#include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -38,10 +38,10 @@
 		struct nv50_disp_sor_hda_eld_v0 v0;
 	} *args = data;
 	const u32 soff = outp->or * 0x800;
-	int ret, i;
+	int ret = -ENOSYS, i;
 
 	nvif_ioctl(object, "disp sor hda eld size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "disp sor hda eld vers %d\n",
 			   args->v0.version);
 		if (size > 0x60)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
index ee9e800..1c4256e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
@@ -25,7 +25,7 @@
 
 #include <core/client.h>
 
-#include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -37,10 +37,10 @@
 		struct nv50_disp_sor_hdmi_pwr_v0 v0;
 	} *args = data;
 	u32 ctrl;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
 				   "max_ac_packet %d rekey %d\n",
 			   args->v0.version, args->v0.state,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
index b5af025..632f02d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
@@ -25,7 +25,7 @@
 
 #include <core/client.h>
 
-#include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -37,10 +37,10 @@
 		struct nv50_disp_sor_hdmi_pwr_v0 v0;
 	} *args = data;
 	u32 ctrl;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
 				   "max_ac_packet %d rekey %d\n",
 			   args->v0.version, args->v0.state,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
index 110dc19..4e8067d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
@@ -25,7 +25,7 @@
 
 #include <core/client.h>
 
-#include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -38,10 +38,10 @@
 		struct nv50_disp_sor_hdmi_pwr_v0 v0;
 	} *args = data;
 	u32 ctrl;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
 				   "max_ac_packet %d rekey %d\n",
 			   args->v0.version, args->v0.state,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
index 61237db..f1afc16 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
@@ -26,7 +26,7 @@
 
 #include <core/client.h>
 
-#include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -38,10 +38,10 @@
 		struct nv50_disp_sor_hdmi_pwr_v0 v0;
 	} *args = data;
 	u32 ctrl;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
 				   "max_ac_packet %d rekey %d\n",
 			   args->v0.version, args->v0.state,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index 32e73a9..4226d21 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -391,7 +391,7 @@
 		switch (outp->info.type) {
 		case DCB_OUTPUT_TMDS:
 			*conf = (ctrl & 0x00000f00) >> 8;
-			if (pclk >= 165000)
+			if (*conf == 5)
 				*conf |= 0x0100;
 			break;
 		case DCB_OUTPUT_LVDS:
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c
index cd888a1e..3940b9c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c
@@ -27,6 +27,7 @@
 #include <core/client.h>
 
 #include <nvif/class.h>
+#include <nvif/cl507b.h>
 #include <nvif/unpack.h>
 
 int
@@ -41,10 +42,10 @@
 	} *args = data;
 	struct nvkm_object *parent = oclass->parent;
 	struct nv50_disp *disp = root->disp;
-	int head, ret;
+	int head, ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create disp overlay size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create disp overlay vers %d head %d\n",
 			   args->v0.version, args->v0.head);
 		if (args->v0.head > disp->base.head.nr)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c
index 6fa296c..2a49c46 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c
@@ -27,6 +27,7 @@
 #include <core/client.h>
 
 #include <nvif/class.h>
+#include <nvif/cl507e.h>
 #include <nvif/unpack.h>
 
 int
@@ -41,11 +42,11 @@
 	} *args = data;
 	struct nvkm_object *parent = oclass->parent;
 	struct nv50_disp *disp = root->disp;
-	int head, ret;
+	int head, ret = -ENOSYS;
 	u64 push;
 
 	nvif_ioctl(parent, "create disp overlay channel dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create disp overlay channel dma vers %d "
 				   "pushbuf %016llx head %d\n",
 			   args->v0.version, args->v0.pushbuf, args->v0.head);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
index ab524bd..6c532ea 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
@@ -28,7 +28,7 @@
 #include <subdev/i2c.h>
 #include <subdev/timer.h>
 
-#include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -40,10 +40,10 @@
 		struct nv50_disp_pior_pwr_v0 v0;
 	} *args = data;
 	u32 ctrl, type;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp pior pwr size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp pior pwr vers %d state %d type %x\n",
 			   args->v0.version, args->v0.state, args->v0.type);
 		if (args->v0.type > 0x0f)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c
index 8591726..335d888 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c
@@ -29,6 +29,7 @@
 #include <subdev/timer.h>
 
 #include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -39,12 +40,12 @@
 	const u32 blanke = nvkm_rd32(device, 0x64041c + (head * 0x300));
 	const u32 blanks = nvkm_rd32(device, 0x640420 + (head * 0x300));
 	union {
-		struct nv04_disp_scanoutpos_v0 v0;
+		struct nv50_disp_scanoutpos_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp scanoutpos size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp scanoutpos vers %d\n",
 			   args->v0.version);
 		args->v0.vblanke = (blanke & 0xffff0000) >> 16;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
index 2be8463..f535f43 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
@@ -27,6 +27,7 @@
 #include <core/client.h>
 
 #include <nvif/class.h>
+#include <nvif/cl0046.h>
 #include <nvif/unpack.h>
 
 struct nv04_disp_root {
@@ -45,10 +46,10 @@
 		struct nv04_disp_scanoutpos_v0 v0;
 	} *args = data;
 	u32 line;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp scanoutpos size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp scanoutpos vers %d\n",
 			   args->v0.version);
 		args->v0.vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0xffff;
@@ -85,10 +86,10 @@
 	union {
 		struct nv04_disp_mthd_v0 v0;
 	} *args = data;
-	int head, ret;
+	int head, ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp mthd size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
 			   args->v0.version, args->v0.method, args->v0.head);
 		mthd = args->v0.method;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
index 06fb24d..2f9cecd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
@@ -29,6 +29,7 @@
 #include <subdev/timer.h>
 
 #include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -39,12 +40,12 @@
 	const u32 blanks = nvkm_rd32(device, 0x610af4 + (head * 0x540));
 	const u32 total  = nvkm_rd32(device, 0x610afc + (head * 0x540));
 	union {
-		struct nv04_disp_scanoutpos_v0 v0;
+		struct nv50_disp_scanoutpos_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp scanoutpos size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp scanoutpos vers %d\n",
 			   args->v0.version);
 		args->v0.vblanke = (blanke & 0xffff0000) >> 16;
@@ -78,19 +79,19 @@
 	struct nvkm_output *outp = NULL;
 	struct nvkm_output *temp;
 	u16 type, mask = 0;
-	int head, ret;
+	int head, ret = -ENOSYS;
 
 	if (mthd != NV50_DISP_MTHD)
 		return -EINVAL;
 
 	nvif_ioctl(object, "disp mthd size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
 			   args->v0.version, args->v0.method, args->v0.head);
 		mthd = args->v0.method;
 		head = args->v0.head;
 	} else
-	if (nvif_unpack(args->v1, 1, 1, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v1, 1, 1, true))) {
 		nvif_ioctl(object, "disp mthd vers %d mthd %02x "
 				   "type %04x mask %04x\n",
 			   args->v1.version, args->v1.method,
@@ -143,8 +144,9 @@
 		union {
 			struct nv50_disp_sor_lvds_script_v0 v0;
 		} *args = data;
+		int ret = -ENOSYS;
 		nvif_ioctl(object, "disp sor lvds script size %d\n", size);
-		if (nvif_unpack(args->v0, 0, 0, false)) {
+		if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 			nvif_ioctl(object, "disp sor lvds script "
 					   "vers %d name %04x\n",
 				   args->v0.version, args->v0.script);
@@ -159,8 +161,9 @@
 		union {
 			struct nv50_disp_sor_dp_pwr_v0 v0;
 		} *args = data;
+		int ret = -ENOSYS;
 		nvif_ioctl(object, "disp sor dp pwr size %d\n", size);
-		if (nvif_unpack(args->v0, 0, 0, false)) {
+		if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 			nvif_ioctl(object, "disp sor dp pwr vers %d state %d\n",
 				   args->v0.version, args->v0.state);
 			if (args->v0.state == 0) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c
index 29e0d2a..53596be 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c
@@ -27,7 +27,7 @@
 #include <core/client.h>
 #include <subdev/timer.h>
 
-#include <nvif/class.h>
+#include <nvif/cl5070.h>
 #include <nvif/unpack.h>
 
 int
@@ -39,10 +39,10 @@
 	} *args = data;
 	const u32 soff = outp->or * 0x800;
 	u32 stat;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp sor pwr size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "disp sor pwr vers %d state %d\n",
 			   args->v0.version, args->v0.state);
 		stat = !!args->v0.state;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c
index 45ab062..13c661b1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c
@@ -28,7 +28,7 @@
 #include <subdev/fb.h>
 #include <subdev/instmem.h>
 
-#include <nvif/class.h>
+#include <nvif/cl0002.h>
 #include <nvif/unpack.h>
 
 static int
@@ -69,7 +69,7 @@
 	struct nvkm_fb *fb = device->fb;
 	void *data = *pdata;
 	u32 size = *psize;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvkm_object_ctor(&nvkm_dmaobj_func, oclass, &dmaobj->object);
 	dmaobj->func = func;
@@ -77,7 +77,7 @@
 	RB_CLEAR_NODE(&dmaobj->rb);
 
 	nvif_ioctl(parent, "create dma size %d\n", *psize);
-	if (nvif_unpack(args->v0, 0, 0, true)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(parent, "create dma vers %d target %d access %d "
 				   "start %016llx limit %016llx\n",
 			   args->v0.version, args->v0.target, args->v0.access,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf100.c
index 13e341c..ef7ac36 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf100.c
@@ -28,7 +28,7 @@
 #include <core/gpuobj.h>
 #include <subdev/fb.h>
 
-#include <nvif/class.h>
+#include <nvif/cl0002.h>
 #include <nvif/unpack.h>
 
 struct gf100_dmaobj {
@@ -87,10 +87,11 @@
 	if (ret)
 		return ret;
 
+	ret  = -ENOSYS;
 	args = data;
 
 	nvif_ioctl(parent, "create gf100 dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent,
 			   "create gf100 dma vers %d priv %d kind %02x\n",
 			   args->v0.version, args->v0.priv, args->v0.kind);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf119.c
index 0e1af8b..c068cee 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/dma/usergf119.c
@@ -28,7 +28,7 @@
 #include <core/gpuobj.h>
 #include <subdev/fb.h>
 
-#include <nvif/class.h>
+#include <nvif/cl0002.h>
 #include <nvif/unpack.h>
 
 struct gf119_dmaobj {
@@ -85,10 +85,11 @@
 	if (ret)
 		return ret;
 
+	ret  = -ENOSYS;
 	args = data;
 
 	nvif_ioctl(parent, "create gf119 dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent,
 			   "create gf100 dma vers %d page %d kind %02x\n",
 			   args->v0.version, args->v0.page, args->v0.kind);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv50.c
index 5b7ce31..6a85b5d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv50.c
@@ -28,7 +28,7 @@
 #include <core/gpuobj.h>
 #include <subdev/fb.h>
 
-#include <nvif/class.h>
+#include <nvif/cl0002.h>
 #include <nvif/unpack.h>
 
 struct nv50_dmaobj {
@@ -87,10 +87,11 @@
 	if (ret)
 		return ret;
 
+	ret  = -ENOSYS;
 	args = data;
 
 	nvif_ioctl(parent, "create nv50 dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create nv50 dma vers %d priv %d part %d "
 				   "comp %d kind %02x\n", args->v0.version,
 			   args->v0.priv, args->v0.part, args->v0.comp,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
index 1fbbfbe..cfc7d57 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
@@ -129,9 +129,9 @@
 	union {
 		struct nvif_notify_uevent_req none;
 	} *req = data;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unvers(req->none)) {
+	if (!(ret = nvif_unvers(ret, &data, &size, req->none))) {
 		notify->size  = sizeof(struct nvif_notify_uevent_rep);
 		notify->types = 1;
 		notify->index = 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
index 0430524..aeb3387 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
@@ -28,7 +28,7 @@
 #include <subdev/mmu.h>
 #include <subdev/timer.h>
 
-#include <nvif/class.h>
+#include <nvif/cl826e.h>
 
 int
 g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
index a5ca52c..caa9140 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
@@ -27,6 +27,7 @@
 #include <core/ramht.h>
 
 #include <nvif/class.h>
+#include <nvif/cl826e.h>
 #include <nvif/unpack.h>
 
 static int
@@ -35,14 +36,14 @@
 {
 	struct nvkm_object *parent = oclass->parent;
 	union {
-		struct nv50_channel_dma_v0 v0;
+		struct g82_channel_dma_v0 v0;
 	} *args = data;
 	struct nv50_fifo *fifo = nv50_fifo(base);
 	struct nv50_fifo_chan *chan;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create channel dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create channel dma vers %d vm %llx "
 				   "pushbuf %llx offset %016llx\n",
 			   args->v0.version, args->v0.vm, args->v0.pushbuf,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
index bfcc640..edec30f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
@@ -29,6 +29,7 @@
 #include <subdev/instmem.h>
 
 #include <nvif/class.h>
+#include <nvif/cl006b.h>
 #include <nvif/unpack.h>
 
 void
@@ -167,10 +168,10 @@
 	struct nv04_fifo_chan *chan = NULL;
 	struct nvkm_device *device = fifo->base.engine.subdev.device;
 	struct nvkm_instmem *imem = device->imem;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create channel dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
 				   "offset %08x\n", args->v0.version,
 			   args->v0.pushbuf, args->v0.offset);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c
index 34f68e5..f5f355f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c
@@ -29,6 +29,7 @@
 #include <subdev/instmem.h>
 
 #include <nvif/class.h>
+#include <nvif/cl006b.h>
 #include <nvif/unpack.h>
 
 static int
@@ -43,10 +44,10 @@
 	struct nv04_fifo_chan *chan = NULL;
 	struct nvkm_device *device = fifo->base.engine.subdev.device;
 	struct nvkm_instmem *imem = device->imem;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create channel dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
 				   "offset %08x\n", args->v0.version,
 			   args->v0.pushbuf, args->v0.offset);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c
index ed7cc9f..7edc6a5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c
@@ -29,6 +29,7 @@
 #include <subdev/instmem.h>
 
 #include <nvif/class.h>
+#include <nvif/cl006b.h>
 #include <nvif/unpack.h>
 
 static int
@@ -43,10 +44,10 @@
 	struct nv04_fifo_chan *chan = NULL;
 	struct nvkm_device *device = fifo->base.engine.subdev.device;
 	struct nvkm_instmem *imem = device->imem;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create channel dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
 				   "offset %08x\n", args->v0.version,
 			   args->v0.pushbuf, args->v0.offset);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
index 043b6c3..0ec179f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
@@ -29,6 +29,7 @@
 #include <subdev/instmem.h>
 
 #include <nvif/class.h>
+#include <nvif/cl006b.h>
 #include <nvif/unpack.h>
 
 static bool
@@ -188,10 +189,10 @@
 	struct nv04_fifo_chan *chan = NULL;
 	struct nvkm_device *device = fifo->base.engine.subdev.device;
 	struct nvkm_instmem *imem = device->imem;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create channel dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
 				   "offset %08x\n", args->v0.version,
 			   args->v0.pushbuf, args->v0.offset);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
index 6b3b15f..480bc37 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
@@ -27,6 +27,7 @@
 #include <core/ramht.h>
 
 #include <nvif/class.h>
+#include <nvif/cl506e.h>
 #include <nvif/unpack.h>
 
 static int
@@ -39,10 +40,10 @@
 	} *args = data;
 	struct nv50_fifo *fifo = nv50_fifo(base);
 	struct nv50_fifo_chan *chan;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create channel dma size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create channel dma vers %d vm %llx "
 				   "pushbuf %llx offset %016llx\n",
 			   args->v0.version, args->v0.vm, args->v0.pushbuf,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
index ff6fcbd..36a39c7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
@@ -47,7 +47,7 @@
 }
 
 void
-gf100_fifo_runlist_update(struct gf100_fifo *fifo)
+gf100_fifo_runlist_commit(struct gf100_fifo *fifo)
 {
 	struct gf100_fifo_chan *chan;
 	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
@@ -77,6 +77,22 @@
 	mutex_unlock(&subdev->mutex);
 }
 
+void
+gf100_fifo_runlist_remove(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan)
+{
+	mutex_lock(&fifo->base.engine.subdev.mutex);
+	list_del_init(&chan->head);
+	mutex_unlock(&fifo->base.engine.subdev.mutex);
+}
+
+void
+gf100_fifo_runlist_insert(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan)
+{
+	mutex_lock(&fifo->base.engine.subdev.mutex);
+	list_add_tail(&chan->head, &fifo->chan);
+	mutex_unlock(&fifo->base.engine.subdev.mutex);
+}
+
 static inline int
 gf100_fifo_engidx(struct gf100_fifo *fifo, u32 engn)
 {
@@ -139,7 +155,7 @@
 		}
 	}
 
-	gf100_fifo_runlist_update(fifo);
+	gf100_fifo_runlist_commit(fifo);
 	nvkm_wr32(device, 0x00262c, engm);
 	nvkm_mask(device, 0x002630, engm, 0x00000000);
 }
@@ -239,7 +255,7 @@
 	{ 0x14, "PMSPDEC", NULL, NVKM_ENGINE_MSPDEC },
 	{ 0x15, "PCE0", NULL, NVKM_ENGINE_CE0 },
 	{ 0x16, "PCE1", NULL, NVKM_ENGINE_CE1 },
-	{ 0x17, "PDAEMON" },
+	{ 0x17, "PMU" },
 	{}
 };
 
@@ -270,7 +286,7 @@
 	{ 0x0c, "PMSPPP" },
 	{ 0x0d, "PMSVLD" },
 	{ 0x11, "PCOUNTER" },
-	{ 0x12, "PDAEMON" },
+	{ 0x12, "PMU" },
 	{ 0x14, "CCACHE" },
 	{ 0x15, "CCACHE_POST" },
 	{}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
index c649ca9..08c33c3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
@@ -5,6 +5,7 @@
 
 #include <subdev/mmu.h>
 
+struct gf100_fifo_chan;
 struct gf100_fifo {
 	struct nvkm_fifo base;
 
@@ -27,5 +28,7 @@
 };
 
 void gf100_fifo_intr_engine(struct gf100_fifo *);
-void gf100_fifo_runlist_update(struct gf100_fifo *);
+void gf100_fifo_runlist_insert(struct gf100_fifo *, struct gf100_fifo_chan *);
+void gf100_fifo_runlist_remove(struct gf100_fifo *, struct gf100_fifo_chan *);
+void gf100_fifo_runlist_commit(struct gf100_fifo *);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index 98970a0..4fcd147d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -47,7 +47,7 @@
 }
 
 void
-gk104_fifo_runlist_update(struct gk104_fifo *fifo, u32 engine)
+gk104_fifo_runlist_commit(struct gk104_fifo *fifo, u32 engine)
 {
 	struct gk104_fifo_engn *engn = &fifo->engine[engine];
 	struct gk104_fifo_chan *chan;
@@ -78,6 +78,22 @@
 	mutex_unlock(&subdev->mutex);
 }
 
+void
+gk104_fifo_runlist_remove(struct gk104_fifo *fifo, struct gk104_fifo_chan *chan)
+{
+	mutex_lock(&fifo->base.engine.subdev.mutex);
+	list_del_init(&chan->head);
+	mutex_unlock(&fifo->base.engine.subdev.mutex);
+}
+
+void
+gk104_fifo_runlist_insert(struct gk104_fifo *fifo, struct gk104_fifo_chan *chan)
+{
+	mutex_lock(&fifo->base.engine.subdev.mutex);
+	list_add_tail(&chan->head, &fifo->engine[chan->engine].chan);
+	mutex_unlock(&fifo->base.engine.subdev.mutex);
+}
+
 static inline struct nvkm_engine *
 gk104_fifo_engine(struct gk104_fifo *fifo, u32 engn)
 {
@@ -112,7 +128,7 @@
 			nvkm_subdev_fini(&engine->subdev, false);
 			WARN_ON(nvkm_subdev_init(&engine->subdev));
 		}
-		gk104_fifo_runlist_update(fifo, gk104_fifo_subdev_engine(engn));
+		gk104_fifo_runlist_commit(fifo, gk104_fifo_subdev_engine(engn));
 	}
 
 	nvkm_wr32(device, 0x00262c, engm);
@@ -180,7 +196,7 @@
 
 	spin_lock_irqsave(&fifo->base.lock, flags);
 	for (engn = 0; engn < ARRAY_SIZE(fifo->engine); engn++) {
-		u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04));
+		u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x08));
 		u32 busy = (stat & 0x80000000);
 		u32 next = (stat & 0x07ff0000) >> 16;
 		u32 chsw = (stat & 0x00008000);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
index 5afd9b5..bec519d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
@@ -5,6 +5,7 @@
 
 #include <subdev/mmu.h>
 
+struct gk104_fifo_chan;
 struct gk104_fifo_engn {
 	struct nvkm_memory *runlist[2];
 	int cur_runlist;
@@ -35,7 +36,9 @@
 void gk104_fifo_intr(struct nvkm_fifo *);
 void gk104_fifo_uevent_init(struct nvkm_fifo *);
 void gk104_fifo_uevent_fini(struct nvkm_fifo *);
-void gk104_fifo_runlist_update(struct gk104_fifo *, u32 engine);
+void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *);
+void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *);
+void gk104_fifo_runlist_commit(struct gk104_fifo *, u32 engine);
 
 static inline u64
 gk104_fifo_engine_subdev(int engine)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
index 82013236..77c2f2a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
@@ -27,6 +27,7 @@
 #include <core/ramht.h>
 
 #include <nvif/class.h>
+#include <nvif/cl826f.h>
 #include <nvif/unpack.h>
 
 static int
@@ -35,15 +36,15 @@
 {
 	struct nvkm_object *parent = oclass->parent;
 	union {
-		struct nv50_channel_gpfifo_v0 v0;
+		struct g82_channel_gpfifo_v0 v0;
 	} *args = data;
 	struct nv50_fifo *fifo = nv50_fifo(base);
 	struct nv50_fifo_chan *chan;
 	u64 ioffset, ilength;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
 				   "pushbuf %llx ioffset %016llx "
 				   "ilength %08x\n",
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
index e7cbc13..cbc67f2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
@@ -29,6 +29,7 @@
 #include <subdev/timer.h>
 
 #include <nvif/class.h>
+#include <nvif/cl906f.h>
 #include <nvif/unpack.h>
 
 static u32
@@ -138,9 +139,9 @@
 	u32 coff = chan->base.chid * 8;
 
 	if (!list_empty(&chan->head) && !chan->killed) {
-		list_del_init(&chan->head);
+		gf100_fifo_runlist_remove(fifo, chan);
 		nvkm_mask(device, 0x003004 + coff, 0x00000001, 0x00000000);
-		gf100_fifo_runlist_update(fifo);
+		gf100_fifo_runlist_commit(fifo);
 	}
 
 	gf100_fifo_intr_engine(fifo);
@@ -160,9 +161,9 @@
 	nvkm_wr32(device, 0x003000 + coff, 0xc0000000 | addr);
 
 	if (list_empty(&chan->head) && !chan->killed) {
-		list_add_tail(&chan->head, &fifo->chan);
+		gf100_fifo_runlist_insert(fifo, chan);
 		nvkm_wr32(device, 0x003004 + coff, 0x001f0001);
-		gf100_fifo_runlist_update(fifo);
+		gf100_fifo_runlist_commit(fifo);
 	}
 }
 
@@ -199,10 +200,10 @@
 	struct nvkm_object *parent = oclass->parent;
 	struct gf100_fifo_chan *chan;
 	u64 usermem, ioffset, ilength;
-	int ret, i;
+	int ret = -ENOSYS, i;
 
 	nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
 				   "ioffset %016llx ilength %08x\n",
 			   args->v0.version, args->v0.vm, args->v0.ioffset,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
index 0b81754..2e1df01 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
@@ -30,6 +30,7 @@
 #include <subdev/timer.h>
 
 #include <nvif/class.h>
+#include <nvif/cla06f.h>
 #include <nvif/unpack.h>
 
 static int
@@ -151,9 +152,9 @@
 	u32 coff = chan->base.chid * 8;
 
 	if (!list_empty(&chan->head)) {
-		list_del_init(&chan->head);
+		gk104_fifo_runlist_remove(fifo, chan);
 		nvkm_mask(device, 0x800004 + coff, 0x00000800, 0x00000800);
-		gk104_fifo_runlist_update(fifo, chan->engine);
+		gk104_fifo_runlist_commit(fifo, chan->engine);
 	}
 
 	nvkm_wr32(device, 0x800000 + coff, 0x00000000);
@@ -172,9 +173,9 @@
 	nvkm_wr32(device, 0x800000 + coff, 0x80000000 | addr);
 
 	if (list_empty(&chan->head) && !chan->killed) {
-		list_add_tail(&chan->head, &fifo->engine[chan->engine].chan);
+		gk104_fifo_runlist_insert(fifo, chan);
 		nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
-		gk104_fifo_runlist_update(fifo, chan->engine);
+		gk104_fifo_runlist_commit(fifo, chan->engine);
 		nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
 	}
 }
@@ -213,10 +214,10 @@
 	struct gk104_fifo_chan *chan;
 	u64 usermem, ioffset, ilength;
 	u32 engines;
-	int ret, i;
+	int ret = -ENOSYS, i;
 
 	nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
 				   "ioffset %016llx ilength %08x engine %08x\n",
 			   args->v0.version, args->v0.vm, args->v0.ioffset,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
index a8c69f8..c5a7de9d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
@@ -27,6 +27,7 @@
 #include <core/ramht.h>
 
 #include <nvif/class.h>
+#include <nvif/cl506f.h>
 #include <nvif/unpack.h>
 
 static int
@@ -40,10 +41,10 @@
 	struct nv50_fifo *fifo = nv50_fifo(base);
 	struct nv50_fifo_chan *chan;
 	u64 ioffset, ilength;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
 				   "pushbuf %llx ioffset %016llx "
 				   "ilength %08x\n",
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c
index ddaa16a..ad0a6cf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c
@@ -55,7 +55,7 @@
 
 	gk104_grctx_generate_rop_active_fbps(gr);
 
-	nvkm_mask(device, 0x5044b0, 0x8000000, 0x8000000);
+	nvkm_mask(device, 0x5044b0, 0x08000000, 0x08000000);
 
 	gf100_gr_wait_idle(gr);
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc
index 7dacb3c..e168b83 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc
@@ -247,10 +247,7 @@
 	tpc_strand_info(-1);
 
 	ld b32 $r4 D[$r0 + #tpc_count]
-	mov $r5 NV_PGRAPH_GPC0_TPC0
-	ld b32 $r6 D[$r0 + #gpc_id]
-	shl b32 $r6 15
-	add b32 $r5 $r6
+	gpc_addr($r5, NV_PGRAPH_GPC0_TPC0)
 	tpc_strand_init_tpc_loop:
 		add b32 $r14 $r5 NV_TPC_STRAND_CNT
 		call(nv_rd32)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
index 11bf363..5136f91 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
@@ -289,7 +289,7 @@
 	0x020014fe,
 	0x12004002,
 	0xbd0002f6,
-	0x05b34104,
+	0x05ad4104,
 	0x400010fe,
 	0x00f60700,
 	0x0204bd00,
@@ -387,180 +387,180 @@
 	0x7e00008f,
 	0x98000314,
 	0x00850504,
-	0x06985040,
-	0x0f64b604,
-/* 0x04e3: tpc_strand_init_tpc_loop */
-	0xb80056bb,
-	0x0005705e,
-	0x0000657e,
-	0x74bdf6b2,
-/* 0x04f0: tpc_strand_init_idx_loop */
-	0x05605eb8,
-	0x7e7fb200,
-	0xb800008f,
-	0x0005885e,
-	0x7e082f95,
-	0xb800008f,
-	0x00058c5e,
-	0x7e082f95,
-	0xb800008f,
-	0x0005905e,
-	0x0000657e,
-	0xb606f5b6,
-	0xf4b601f0,
-	0x002fbb08,
-	0xb6003fbb,
-	0x62b60170,
-	0xbf1bf401,
-	0x080050b7,
-	0xf40142b6,
-	0x3f0fa81b,
+	0x55f05040,
+/* 0x04dd: tpc_strand_init_tpc_loop */
+	0x705eb801,
+	0x657e0005,
+	0xf6b20000,
+/* 0x04ea: tpc_strand_init_idx_loop */
+	0x5eb874bd,
+	0xb2000560,
+	0x008f7e7f,
+	0x885eb800,
+	0x2f950005,
+	0x008f7e08,
+	0x8c5eb800,
+	0x2f950005,
+	0x008f7e08,
+	0x905eb800,
+	0x657e0005,
+	0xf5b60000,
+	0x01f0b606,
+	0xbb08f4b6,
+	0x3fbb002f,
+	0x0170b600,
+	0xf40162b6,
+	0x50b7bf1b,
+	0x42b60800,
+	0xa81bf401,
+	0x608e3f0f,
+	0xe5f0501d,
+	0x7effb201,
+	0x0f00008f,
+	0x1da88e0d,
+	0x01e5f050,
+	0x8f7effb2,
+	0x147e0000,
+	0x00800003,
+	0x03f60201,
+	0xbd04bd00,
+	0x1f29f024,
+	0x02300080,
+	0xbd0002f6,
+/* 0x0571: main */
+	0x0031f404,
+	0x0d0028f4,
+	0x00377e24,
+	0xf401f400,
+	0xf404e4b0,
+	0x81fe1d18,
+	0xbd060201,
+	0x0412fd20,
+	0xfd01e4b6,
+	0x18fe051e,
+	0x06447e00,
+	0xd40ef400,
+/* 0x05a0: main_not_ctx_xfer */
+	0xf010ef94,
+	0xf87e01f5,
+	0x0ef40002,
+/* 0x05ad: ih */
+	0xfe80f9c7,
+	0x80f90188,
+	0xa0f990f9,
+	0xd0f9b0f9,
+	0xf0f9e0f9,
+	0x004a04bd,
+	0x00aacf02,
+	0xf404abc4,
+	0x240d1f0b,
+	0xcf1a004e,
+	0x004f00ee,
+	0x00ffcf19,
+	0x0000047e,
+	0x0040010e,
+	0x000ef61d,
+/* 0x05ea: ih_no_fifo */
+	0x004004bd,
+	0x000af601,
+	0xf0fc04bd,
+	0xd0fce0fc,
+	0xa0fcb0fc,
+	0x80fc90fc,
+	0xfc0088fe,
+	0x0032f480,
+/* 0x060a: hub_barrier_done */
+	0x010f01f8,
+	0xbb040e98,
+	0xffb204fe,
+	0x4094188e,
+	0x00008f7e,
+/* 0x061e: ctx_redswitch */
+	0x200f00f8,
+	0x01850080,
+	0xbd000ff6,
+/* 0x062b: ctx_redswitch_delay */
+	0xb6080e04,
+	0x1bf401e2,
+	0x00f5f1fd,
+	0x00f5f108,
+	0x85008002,
+	0x000ff601,
+	0x00f804bd,
+/* 0x0644: ctx_xfer */
+	0x02810080,
+	0xbd000ff6,
+	0x1dc48e04,
+	0x01e5f050,
+	0x8f7effb2,
+	0x11f40000,
+	0x061e7e07,
+/* 0x0661: ctx_xfer_not_load */
+	0x02167e00,
+	0x8024bd00,
+	0xf60247fc,
+	0x04bd0002,
+	0xb6012cf0,
+	0xfc800320,
+	0x02f6024a,
+	0x0f04bd00,
+	0x1da88e0c,
+	0x01e5f050,
+	0x8f7effb2,
+	0x147e0000,
+	0x3f0f0003,
 	0x501d608e,
 	0xb201e5f0,
 	0x008f7eff,
+	0x8e000f00,
+	0xf0501d9c,
+	0xffb201e5,
+	0x00008f7e,
+	0x147e010f,
+	0xfcf00003,
+	0x03f0b601,
+	0x501da88e,
+	0xb201e5f0,
+	0x008f7eff,
+	0x01acf000,
+	0x8b02a5f0,
+	0x98500000,
+	0xc4b6040c,
+	0x00bcbb0f,
+	0x98000c98,
+	0x000e010d,
+	0x00013d7e,
+	0x8b01acf0,
+	0x98504000,
+	0xc4b6040c,
+	0x00bcbb0f,
+	0x98010c98,
+	0x0f98020d,
+	0x08004e06,
+	0x00013d7e,
+	0xf001acf0,
+	0x008b04a5,
+	0x0c985030,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98020c,
+	0x080f9803,
+	0x7e02004e,
+	0x7e00013d,
+	0x7e00020a,
+	0xf4000314,
+	0x12f40601,
+/* 0x0739: ctx_xfer_post */
+	0x02277e1a,
 	0x8e0d0f00,
 	0xf0501da8,
 	0xffb201e5,
 	0x00008f7e,
 	0x0003147e,
-	0x02010080,
-	0xbd0003f6,
-	0xf024bd04,
-	0x00801f29,
-	0x02f60230,
-/* 0x0577: main */
-	0xf404bd00,
-	0x28f40031,
-	0x7e240d00,
-	0xf4000037,
-	0xe4b0f401,
-	0x1d18f404,
-	0x020181fe,
-	0xfd20bd06,
-	0xe4b60412,
-	0x051efd01,
-	0x7e0018fe,
-	0xf400064a,
-/* 0x05a6: main_not_ctx_xfer */
-	0xef94d40e,
-	0x01f5f010,
-	0x0002f87e,
-/* 0x05b3: ih */
-	0xf9c70ef4,
-	0x0188fe80,
-	0x90f980f9,
-	0xb0f9a0f9,
-	0xe0f9d0f9,
-	0x04bdf0f9,
-	0xcf02004a,
-	0xabc400aa,
-	0x1f0bf404,
-	0x004e240d,
-	0x00eecf1a,
-	0xcf19004f,
-	0x047e00ff,
-	0x010e0000,
-	0xf61d0040,
-	0x04bd000e,
-/* 0x05f0: ih_no_fifo */
-	0xf6010040,
-	0x04bd000a,
-	0xe0fcf0fc,
-	0xb0fcd0fc,
-	0x90fca0fc,
-	0x88fe80fc,
-	0xf480fc00,
-	0x01f80032,
-/* 0x0610: hub_barrier_done */
-	0x0e98010f,
-	0x04febb04,
-	0x188effb2,
-	0x8f7e4094,
-	0x00f80000,
-/* 0x0624: ctx_redswitch */
-	0x0080200f,
-	0x0ff60185,
-	0x0e04bd00,
-/* 0x0631: ctx_redswitch_delay */
-	0x01e2b608,
-	0xf1fd1bf4,
-	0xf10800f5,
-	0x800200f5,
-	0xf6018500,
-	0x04bd000f,
-/* 0x064a: ctx_xfer */
-	0x008000f8,
-	0x0ff60281,
-	0x8e04bd00,
-	0xf0501dc4,
-	0xffb201e5,
-	0x00008f7e,
-	0x7e0711f4,
-/* 0x0667: ctx_xfer_not_load */
-	0x7e000624,
-	0xbd000216,
-	0x47fc8024,
-	0x0002f602,
-	0x2cf004bd,
-	0x0320b601,
-	0x024afc80,
-	0xbd0002f6,
-	0x8e0c0f04,
-	0xf0501da8,
-	0xffb201e5,
-	0x00008f7e,
-	0x0003147e,
-	0x608e3f0f,
-	0xe5f0501d,
-	0x7effb201,
-	0x0f00008f,
-	0x1d9c8e00,
-	0x01e5f050,
-	0x8f7effb2,
-	0x010f0000,
-	0x0003147e,
-	0xb601fcf0,
-	0xa88e03f0,
-	0xe5f0501d,
-	0x7effb201,
-	0xf000008f,
-	0xa5f001ac,
-	0x00008b02,
-	0x040c9850,
-	0xbb0fc4b6,
-	0x0c9800bc,
-	0x010d9800,
-	0x3d7e000e,
-	0xacf00001,
-	0x40008b01,
-	0x040c9850,
-	0xbb0fc4b6,
-	0x0c9800bc,
-	0x020d9801,
-	0x4e060f98,
-	0x3d7e0800,
-	0xacf00001,
-	0x04a5f001,
-	0x5030008b,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x020c9800,
-	0x98030d98,
-	0x004e080f,
-	0x013d7e02,
-	0x020a7e00,
-	0x03147e00,
-	0x0601f400,
-/* 0x073f: ctx_xfer_post */
-	0x7e1a12f4,
-	0x0f000227,
-	0x1da88e0d,
-	0x01e5f050,
-	0x8f7effb2,
-	0x147e0000,
-/* 0x0756: ctx_xfer_done */
-	0x107e0003,
-	0x00f80006,
+/* 0x0750: ctx_xfer_done */
+	0x00060a7e,
+	0x000000f8,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index 9f5dfc8..1f81069 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -34,6 +34,7 @@
 #include <engine/fifo.h>
 
 #include <nvif/class.h>
+#include <nvif/cl9097.h>
 #include <nvif/unpack.h>
 
 /*******************************************************************************
@@ -139,6 +140,12 @@
 /*******************************************************************************
  * Graphics object classes
  ******************************************************************************/
+#define gf100_gr_object(p) container_of((p), struct gf100_gr_object, object)
+
+struct gf100_gr_object {
+	struct nvkm_object object;
+	struct gf100_gr_chan *chan;
+};
 
 static int
 gf100_fermi_mthd_zbc_color(struct nvkm_object *object, void *data, u32 size)
@@ -147,9 +154,9 @@
 	union {
 		struct fermi_a_zbc_color_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		switch (args->v0.format) {
 		case FERMI_A_ZBC_COLOR_V0_FMT_ZERO:
 		case FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE:
@@ -193,9 +200,9 @@
 	union {
 		struct fermi_a_zbc_depth_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		switch (args->v0.format) {
 		case FERMI_A_ZBC_DEPTH_V0_FMT_FP32:
 			ret = gf100_gr_zbc_depth_get(gr, args->v0.format,
@@ -213,6 +220,7 @@
 static int
 gf100_fermi_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
 {
+	nvif_ioctl(object, "fermi mthd %08x\n", mthd);
 	switch (mthd) {
 	case FERMI_A_ZBC_COLOR:
 		return gf100_fermi_mthd_zbc_color(object, data, size);
@@ -256,6 +264,27 @@
 	return false;
 }
 
+static const struct nvkm_object_func
+gf100_gr_object_func = {
+};
+
+static int
+gf100_gr_object_new(const struct nvkm_oclass *oclass, void *data, u32 size,
+		    struct nvkm_object **pobject)
+{
+	struct gf100_gr_chan *chan = gf100_gr_chan(oclass->parent);
+	struct gf100_gr_object *object;
+
+	if (!(object = kzalloc(sizeof(*object), GFP_KERNEL)))
+		return -ENOMEM;
+	*pobject = &object->object;
+
+	nvkm_object_ctor(oclass->base.func ? oclass->base.func :
+			 &gf100_gr_object_func, oclass, &object->object);
+	object->chan = chan;
+	return 0;
+}
+
 static int
 gf100_gr_object_get(struct nvkm_gr *base, int index, struct nvkm_sclass *sclass)
 {
@@ -265,6 +294,7 @@
 	while (gr->func->sclass[c].oclass) {
 		if (c++ == index) {
 			*sclass = gr->func->sclass[index];
+			sclass->ctor = gf100_gr_object_new;
 			return index;
 		}
 	}
@@ -826,7 +856,41 @@
 	return cfg;
 }
 
+static const struct nvkm_bitfield gf100_dispatch_error[] = {
+	{ 0x00000001, "INJECTED_BUNDLE_ERROR" },
+	{ 0x00000002, "CLASS_SUBCH_MISMATCH" },
+	{ 0x00000004, "SUBCHSW_DURING_NOTIFY" },
+	{}
+};
+
+static const struct nvkm_bitfield gf100_m2mf_error[] = {
+	{ 0x00000001, "PUSH_TOO_MUCH_DATA" },
+	{ 0x00000002, "PUSH_NOT_ENOUGH_DATA" },
+	{}
+};
+
+static const struct nvkm_bitfield gf100_unk6_error[] = {
+	{ 0x00000001, "TEMP_TOO_SMALL" },
+	{}
+};
+
+static const struct nvkm_bitfield gf100_ccache_error[] = {
+	{ 0x00000001, "INTR" },
+	{ 0x00000002, "LDCONST_OOB" },
+	{}
+};
+
+static const struct nvkm_bitfield gf100_macro_error[] = {
+	{ 0x00000001, "TOO_FEW_PARAMS" },
+	{ 0x00000002, "TOO_MANY_PARAMS" },
+	{ 0x00000004, "ILLEGAL_OPCODE" },
+	{ 0x00000008, "DOUBLE_BRANCH" },
+	{ 0x00000010, "WATCHDOG" },
+	{}
+};
+
 static const struct nvkm_bitfield gk104_sked_error[] = {
+	{ 0x00000040, "CTA_RESUME" },
 	{ 0x00000080, "CONSTANT_BUFFER_SIZE" },
 	{ 0x00000200, "LOCAL_MEMORY_SIZE_POS" },
 	{ 0x00000400, "LOCAL_MEMORY_SIZE_NEG" },
@@ -836,6 +900,8 @@
 	{ 0x00040000, "TOTAL_THREADS" },
 	{ 0x00100000, "PROGRAM_OFFSET" },
 	{ 0x00200000, "SHARED_MEMORY_SIZE" },
+	{ 0x00800000, "CTA_THREAD_DIMENSION_ZERO" },
+	{ 0x01000000, "MEMORY_WINDOW_OVERLAP" },
 	{ 0x02000000, "SHARED_CONFIG_TOO_SMALL" },
 	{ 0x04000000, "TOTAL_REGISTER_COUNT" },
 	{}
@@ -1005,12 +1071,16 @@
 {
 	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
+	char error[128];
 	u32 trap = nvkm_rd32(device, 0x400108);
 	int rop, gpc;
 
 	if (trap & 0x00000001) {
 		u32 stat = nvkm_rd32(device, 0x404000);
-		nvkm_error(subdev, "DISPATCH %08x\n", stat);
+
+		nvkm_snprintbf(error, sizeof(error), gf100_dispatch_error,
+			       stat & 0x3fffffff);
+		nvkm_error(subdev, "DISPATCH %08x [%s]\n", stat, error);
 		nvkm_wr32(device, 0x404000, 0xc0000000);
 		nvkm_wr32(device, 0x400108, 0x00000001);
 		trap &= ~0x00000001;
@@ -1018,7 +1088,11 @@
 
 	if (trap & 0x00000002) {
 		u32 stat = nvkm_rd32(device, 0x404600);
-		nvkm_error(subdev, "M2MF %08x\n", stat);
+
+		nvkm_snprintbf(error, sizeof(error), gf100_m2mf_error,
+			       stat & 0x3fffffff);
+		nvkm_error(subdev, "M2MF %08x [%s]\n", stat, error);
+
 		nvkm_wr32(device, 0x404600, 0xc0000000);
 		nvkm_wr32(device, 0x400108, 0x00000002);
 		trap &= ~0x00000002;
@@ -1026,7 +1100,10 @@
 
 	if (trap & 0x00000008) {
 		u32 stat = nvkm_rd32(device, 0x408030);
-		nvkm_error(subdev, "CCACHE %08x\n", stat);
+
+		nvkm_snprintbf(error, sizeof(error), gf100_m2mf_error,
+			       stat & 0x3fffffff);
+		nvkm_error(subdev, "CCACHE %08x [%s]\n", stat, error);
 		nvkm_wr32(device, 0x408030, 0xc0000000);
 		nvkm_wr32(device, 0x400108, 0x00000008);
 		trap &= ~0x00000008;
@@ -1034,7 +1111,8 @@
 
 	if (trap & 0x00000010) {
 		u32 stat = nvkm_rd32(device, 0x405840);
-		nvkm_error(subdev, "SHADER %08x\n", stat);
+		nvkm_error(subdev, "SHADER %08x, sph: 0x%06x, stage: 0x%02x\n",
+			   stat, stat & 0xffffff, (stat >> 24) & 0x3f);
 		nvkm_wr32(device, 0x405840, 0xc0000000);
 		nvkm_wr32(device, 0x400108, 0x00000010);
 		trap &= ~0x00000010;
@@ -1042,7 +1120,11 @@
 
 	if (trap & 0x00000040) {
 		u32 stat = nvkm_rd32(device, 0x40601c);
-		nvkm_error(subdev, "UNK6 %08x\n", stat);
+
+		nvkm_snprintbf(error, sizeof(error), gf100_unk6_error,
+			       stat & 0x3fffffff);
+		nvkm_error(subdev, "UNK6 %08x [%s]\n", stat, error);
+
 		nvkm_wr32(device, 0x40601c, 0xc0000000);
 		nvkm_wr32(device, 0x400108, 0x00000040);
 		trap &= ~0x00000040;
@@ -1050,7 +1132,16 @@
 
 	if (trap & 0x00000080) {
 		u32 stat = nvkm_rd32(device, 0x404490);
-		nvkm_error(subdev, "MACRO %08x\n", stat);
+		u32 pc = nvkm_rd32(device, 0x404494);
+		u32 op = nvkm_rd32(device, 0x40449c);
+
+		nvkm_snprintbf(error, sizeof(error), gf100_macro_error,
+			       stat & 0x1fffffff);
+		nvkm_error(subdev, "MACRO %08x [%s], pc: 0x%03x%s, op: 0x%08x\n",
+			   stat, error, pc & 0x7ff,
+			   (pc & 0x10000000) ? "" : " (invalid)",
+			   op);
+
 		nvkm_wr32(device, 0x404490, 0xc0000000);
 		nvkm_wr32(device, 0x400108, 0x00000080);
 		trap &= ~0x00000080;
@@ -1058,10 +1149,9 @@
 
 	if (trap & 0x00000100) {
 		u32 stat = nvkm_rd32(device, 0x407020) & 0x3fffffff;
-		char sked[128];
 
-		nvkm_snprintbf(sked, sizeof(sked), gk104_sked_error, stat);
-		nvkm_error(subdev, "SKED: %08x [%s]\n", stat, sked);
+		nvkm_snprintbf(error, sizeof(error), gk104_sked_error, stat);
+		nvkm_error(subdev, "SKED: %08x [%s]\n", stat, error);
 
 		if (stat)
 			nvkm_wr32(device, 0x407020, 0x40000000);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
index 2721592..f19fabe 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
@@ -27,6 +27,8 @@
 #include <core/option.h>
 
 #include <nvif/class.h>
+#include <nvif/if0002.h>
+#include <nvif/if0003.h>
 #include <nvif/ioctl.h>
 #include <nvif/unpack.h>
 
@@ -210,10 +212,10 @@
 	} *args = data;
 	struct nvkm_object *object = &dom->object;
 	struct nvkm_pm *pm = dom->perfmon->pm;
-	int ret, i;
+	int ret = -ENOSYS, i;
 
 	nvif_ioctl(object, "perfdom init size %d\n", size);
-	if (nvif_unvers(args->none)) {
+	if (!(ret = nvif_unvers(ret, &data, &size, args->none))) {
 		nvif_ioctl(object, "perfdom init\n");
 	} else
 		return ret;
@@ -240,10 +242,10 @@
 	} *args = data;
 	struct nvkm_object *object = &dom->object;
 	struct nvkm_pm *pm = dom->perfmon->pm;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "perfdom sample size %d\n", size);
-	if (nvif_unvers(args->none)) {
+	if (!(ret = nvif_unvers(ret, &data, &size, args->none))) {
 		nvif_ioctl(object, "perfdom sample\n");
 	} else
 		return ret;
@@ -264,10 +266,10 @@
 	} *args = data;
 	struct nvkm_object *object = &dom->object;
 	struct nvkm_pm *pm = dom->perfmon->pm;
-	int ret, i;
+	int ret = -ENOSYS, i;
 
 	nvif_ioctl(object, "perfdom read size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "perfdom read vers %d\n", args->v0.version);
 	} else
 		return ret;
@@ -374,10 +376,10 @@
 	struct nvkm_perfctr *ctr[4] = {};
 	struct nvkm_perfdom *dom;
 	int c, s, m;
-	int ret;
+	int ret = -ENOSYS;
 
 	nvif_ioctl(parent, "create perfdom size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(parent, "create perfdom vers %d dom %d mode %02x\n",
 			   args->v0.version, args->v0.domain, args->v0.mode);
 	} else
@@ -439,10 +441,10 @@
 	struct nvkm_pm *pm = perfmon->pm;
 	struct nvkm_perfdom *dom;
 	u8 domain_nr;
-	int di, ret;
+	int di, ret = -ENOSYS;
 
 	nvif_ioctl(object, "perfmon query domain size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object, "perfmon domain vers %d iter %02x\n",
 			   args->v0.version, args->v0.iter);
 		di = (args->v0.iter & 0xff) - 1;
@@ -490,10 +492,10 @@
 	struct nvkm_perfsig *sig;
 	const bool all = nvkm_boolopt(device->cfgopt, "NvPmShowAll", false);
 	const bool raw = nvkm_boolopt(device->cfgopt, "NvPmUnnamed", all);
-	int ret, si;
+	int ret = -ENOSYS, si;
 
 	nvif_ioctl(object, "perfmon query signal size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object,
 			   "perfmon query signal vers %d dom %d iter %04x\n",
 			   args->v0.version, args->v0.domain, args->v0.iter);
@@ -543,10 +545,10 @@
 	struct nvkm_perfsig *sig;
 	struct nvkm_perfsrc *src;
 	u8 source_nr = 0;
-	int si, ret;
+	int si, ret = -ENOSYS;
 
 	nvif_ioctl(object, "perfmon query source size %d\n", size);
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		nvif_ioctl(object,
 			   "perfmon source vers %d dom %d sig %02x iter %02x\n",
 			   args->v0.version, args->v0.domain, args->v0.signal,
@@ -612,7 +614,7 @@
 		       struct nvkm_oclass *oclass)
 {
 	if (index == 0) {
-		oclass->base.oclass = NVIF_IOCTL_NEW_V0_PERFDOM;
+		oclass->base.oclass = NVIF_CLASS_PERFDOM;
 		oclass->base.minver = 0;
 		oclass->base.maxver = 0;
 		oclass->ctor = nvkm_perfmon_child_new;
@@ -679,7 +681,7 @@
 
 static const struct nvkm_device_oclass
 nvkm_pm_oclass = {
-	.base.oclass = NVIF_IOCTL_NEW_V0_PERFMON,
+	.base.oclass = NVIF_CLASS_PERFMON,
 	.base.minver = -1,
 	.base.maxver = -1,
 	.ctor = nvkm_pm_oclass_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c
index d082f4f..f289670 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c
@@ -53,9 +53,9 @@
 	union {
 		struct nvif_notify_uevent_req none;
 	} *req = data;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unvers(req->none)) {
+	if (!(ret = nvif_unvers(ret, &data, &size, req->none))) {
 		notify->size  = sizeof(struct nvif_notify_uevent_rep);
 		notify->types = 1;
 		notify->index = 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c
index b01ef7e..ea8f424 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c
@@ -28,8 +28,8 @@
 #include <engine/disp.h>
 #include <engine/fifo.h>
 
+#include <nvif/class.h>
 #include <nvif/event.h>
-#include <nvif/ioctl.h>
 
 /*******************************************************************************
  * software context
@@ -143,7 +143,7 @@
 gf100_sw = {
 	.chan_new = gf100_sw_chan_new,
 	.sclass = {
-		{ nvkm_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_GF100 } },
+		{ nvkm_nvsw_new, { -1, -1, NVIF_CLASS_SW_GF100 } },
 		{}
 	}
 };
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c
index 445217f..b6675fe 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c
@@ -27,6 +27,7 @@
 #include "nvsw.h"
 
 #include <nvif/class.h>
+#include <nvif/if0004.h>
 #include <nvif/ioctl.h>
 #include <nvif/unpack.h>
 
@@ -46,9 +47,9 @@
 	union {
 		struct nv04_nvsw_get_ref_v0 v0;
 	} *args = data;
-	int ret;
+	int ret = -ENOSYS;
 
-	if (nvif_unpack(args->v0, 0, 0, false)) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
 		args->v0.ref = atomic_read(&chan->ref);
 	}
 
@@ -126,7 +127,7 @@
 nv04_sw = {
 	.chan_new = nv04_sw_chan_new,
 	.sclass = {
-		{ nv04_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_NV04 } },
+		{ nv04_nvsw_new, { -1, -1, NVIF_CLASS_SW_NV04 } },
 		{}
 	}
 };
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c
index adf70d9..09d22fc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c
@@ -25,7 +25,7 @@
 #include "chan.h"
 #include "nvsw.h"
 
-#include <nvif/ioctl.h>
+#include <nvif/class.h>
 
 /*******************************************************************************
  * software context
@@ -56,7 +56,7 @@
 nv10_sw = {
 	.chan_new = nv10_sw_chan_new,
 	.sclass = {
-		{ nvkm_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_NV10 } },
+		{ nvkm_nvsw_new, { -1, -1, NVIF_CLASS_SW_NV10 } },
 		{}
 	}
 };
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
index a381196..01573d1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
@@ -28,8 +28,8 @@
 #include <engine/fifo/chan.h>
 #include <subdev/bar.h>
 
+#include <nvif/class.h>
 #include <nvif/event.h>
-#include <nvif/ioctl.h>
 
 /*******************************************************************************
  * software context
@@ -136,7 +136,7 @@
 nv50_sw = {
 	.chan_new = nv50_sw_chan_new,
 	.sclass = {
-		{ nvkm_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_NV50 } },
+		{ nvkm_nvsw_new, { -1, -1, NVIF_CLASS_SW_NV50 } },
 		{}
 	}
 };
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c
index 66cf986..33dd03f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c
@@ -24,7 +24,7 @@
 #include "nvsw.h"
 #include "chan.h"
 
-#include <nvif/class.h>
+#include <nvif/if0004.h>
 
 static int
 nvkm_nvsw_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
@@ -41,7 +41,7 @@
 {
 	struct nvkm_nvsw *nvsw = nvkm_nvsw(object);
 	switch (mthd) {
-	case NVSW_NTFY_UEVENT:
+	case NV04_NVSW_NTFY_UEVENT:
 		*pevent = &nvsw->chan->event;
 		return 0;
 	default:
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dcb.c
index 8304b80..a8d5d67 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dcb.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dcb.c
@@ -143,16 +143,19 @@
 			switch (outp->type) {
 			case DCB_OUTPUT_DP:
 				switch (conf & 0x00e00000) {
-				case 0x00000000:
+				case 0x00000000: /* 1.62 */
 					outp->dpconf.link_bw = 0x06;
 					break;
-				case 0x00200000:
+				case 0x00200000: /* 2.7 */
 					outp->dpconf.link_bw = 0x0a;
 					break;
-				case 0x00400000:
-				default:
+				case 0x00400000: /* 5.4 */
 					outp->dpconf.link_bw = 0x14;
 					break;
+				case 0x00600000: /* 8.1 */
+				default:
+					outp->dpconf.link_bw = 0x1e;
+					break;
 				}
 
 				switch ((conf & 0x0f000000) >> 24) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c
index 43006db..80fed7e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c
@@ -83,6 +83,7 @@
 			fan->type = NVBIOS_THERM_FAN_UNK;
 		}
 
+		fan->fan_mode = NVBIOS_THERM_FAN_LINEAR;
 		fan->min_duty = nvbios_rd08(bios, data + 0x02);
 		fan->max_duty = nvbios_rd08(bios, data + 0x03);
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c
index aa7e33b..636bfb6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c
@@ -24,6 +24,7 @@
 #include <subdev/bios.h>
 #include <subdev/bios/bit.h>
 #include <subdev/bios/perf.h>
+#include <subdev/pci.h>
 
 u16
 nvbios_perf_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr,
@@ -145,6 +146,21 @@
 		break;
 	case 0x40:
 		info->voltage  = nvbios_rd08(bios, perf + 0x02);
+		switch (nvbios_rd08(bios, perf + 0xb) & 0x3) {
+		case 0:
+			info->pcie_speed = NVKM_PCIE_SPEED_5_0;
+			break;
+		case 3:
+		case 1:
+			info->pcie_speed = NVKM_PCIE_SPEED_2_5;
+			break;
+		case 2:
+			info->pcie_speed = NVKM_PCIE_SPEED_8_0;
+			break;
+		default:
+			break;
+		}
+		info->pcie_width = 0xff;
 		break;
 	default:
 		return 0x0000;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
index dc8682c..889cce2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
@@ -176,6 +176,7 @@
 {
 	struct nvkm_subdev *subdev = &clk->subdev;
 	struct nvkm_ram *ram = subdev->device->fb->ram;
+	struct nvkm_pci *pci = subdev->device->pci;
 	struct nvkm_pstate *pstate;
 	int ret, idx = 0;
 
@@ -187,6 +188,8 @@
 	nvkm_debug(subdev, "setting performance state %d\n", pstatei);
 	clk->pstate = pstatei;
 
+	nvkm_pcie_set_link(pci, pstate->pcie_speed, pstate->pcie_width);
+
 	if (ram && ram->func->calc) {
 		int khz = pstate->base.domain[nv_clk_src_mem];
 		do {
@@ -330,6 +333,8 @@
 
 	pstate->pstate = perfE.pstate;
 	pstate->fanspeed = perfE.fanspeed;
+	pstate->pcie_speed = perfE.pcie_speed;
+	pstate->pcie_width = perfE.pcie_width;
 	cstate->voltage = perfE.voltage;
 	cstate->domain[nv_clk_src_core] = perfE.core;
 	cstate->domain[nv_clk_src_shader] = perfE.shader;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c
index a52b7e7..78c449b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c
@@ -188,7 +188,7 @@
 		return read_clk(clk, 0x08);
 	case nv_clk_src_copy:
 		return read_clk(clk, 0x09);
-	case nv_clk_src_daemon:
+	case nv_clk_src_pmu:
 		return read_clk(clk, 0x0c);
 	case nv_clk_src_vdec:
 		return read_clk(clk, 0x0e);
@@ -325,7 +325,7 @@
 	    (ret = calc_clk(clk, cstate, 0x07, nv_clk_src_hubk06)) ||
 	    (ret = calc_clk(clk, cstate, 0x08, nv_clk_src_hubk01)) ||
 	    (ret = calc_clk(clk, cstate, 0x09, nv_clk_src_copy)) ||
-	    (ret = calc_clk(clk, cstate, 0x0c, nv_clk_src_daemon)) ||
+	    (ret = calc_clk(clk, cstate, 0x0c, nv_clk_src_pmu)) ||
 	    (ret = calc_clk(clk, cstate, 0x0e, nv_clk_src_vdec)))
 		return ret;
 
@@ -447,7 +447,7 @@
 		{ nv_clk_src_rop    , 0x04 },
 		{ nv_clk_src_mem    , 0x05, 0, "memory", 1000 },
 		{ nv_clk_src_vdec   , 0x06 },
-		{ nv_clk_src_daemon , 0x0a },
+		{ nv_clk_src_pmu    , 0x0a },
 		{ nv_clk_src_hubk07 , 0x0b },
 		{ nv_clk_src_max }
 	}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c
index 396f7e4..975c401 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c
@@ -209,7 +209,7 @@
 		return read_clk(clk, 0x07);
 	case nv_clk_src_hubk01:
 		return read_clk(clk, 0x08);
-	case nv_clk_src_daemon:
+	case nv_clk_src_pmu:
 		return read_clk(clk, 0x0c);
 	case nv_clk_src_vdec:
 		return read_clk(clk, 0x0e);
@@ -346,7 +346,7 @@
 	    (ret = calc_clk(clk, cstate, 0x02, nv_clk_src_hubk07)) ||
 	    (ret = calc_clk(clk, cstate, 0x07, nv_clk_src_hubk06)) ||
 	    (ret = calc_clk(clk, cstate, 0x08, nv_clk_src_hubk01)) ||
-	    (ret = calc_clk(clk, cstate, 0x0c, nv_clk_src_daemon)) ||
+	    (ret = calc_clk(clk, cstate, 0x0c, nv_clk_src_pmu)) ||
 	    (ret = calc_clk(clk, cstate, 0x0e, nv_clk_src_vdec)))
 		return ret;
 
@@ -492,7 +492,7 @@
 		{ nv_clk_src_hubk06 , 0x04, NVKM_CLK_DOM_FLAG_CORE },
 		{ nv_clk_src_hubk01 , 0x05 },
 		{ nv_clk_src_vdec   , 0x06 },
-		{ nv_clk_src_daemon , 0x07 },
+		{ nv_clk_src_pmu    , 0x07 },
 		{ nv_clk_src_max }
 	}
 };
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
index c233e3f..056702e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
@@ -158,7 +158,7 @@
 		return read_clk(clk, 0x20, false);
 	case nv_clk_src_vdec:
 		return read_clk(clk, 0x21, false);
-	case nv_clk_src_daemon:
+	case nv_clk_src_pmu:
 		return read_clk(clk, 0x25, false);
 	case nv_clk_src_host:
 		hsrc = (nvkm_rd32(device, 0xc040) & 0x30000000) >> 28;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
index f5edfad..1b5fb02 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
@@ -132,7 +132,7 @@
 	{ 0x0000000b, "PCOUNTER" },
 	{ 0x0000000c, "SEMAPHORE_BG" },
 	{ 0x0000000d, "PCE0" },
-	{ 0x0000000e, "PDAEMON" },
+	{ 0x0000000e, "PMU" },
 	{}
 };
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
index 9df4503..1fa3ade 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
@@ -216,11 +216,11 @@
 	ram_wr32(fuc, 0x1373ec, tmp | (v1 << 16));
 	ram_mask(fuc, 0x1373f0, (~ram->mode & 3), 0x00000000);
 	if (ram->mode == 2) {
-		ram_mask(fuc, 0x1373f4, 0x00000003, 0x000000002);
-		ram_mask(fuc, 0x1373f4, 0x00001100, 0x000000000);
+		ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000002);
+		ram_mask(fuc, 0x1373f4, 0x00001100, 0x00000000);
 	} else {
-		ram_mask(fuc, 0x1373f4, 0x00000003, 0x000000001);
-		ram_mask(fuc, 0x1373f4, 0x00010000, 0x000000000);
+		ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000001);
+		ram_mask(fuc, 0x1373f4, 0x00010000, 0x00000000);
 	}
 	ram_mask(fuc, 0x10f800, 0x00000030, (v0 ^ v1) << 4);
 }
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild
index de888fa..7e77a74 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild
@@ -2,3 +2,4 @@
 nvkm-y += nvkm/subdev/ibus/gf117.o
 nvkm-y += nvkm/subdev/ibus/gk104.o
 nvkm-y += nvkm/subdev/ibus/gk20a.o
+nvkm-y += nvkm/subdev/ibus/gm204.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c
index ba33609..b5cee3f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c
@@ -21,7 +21,7 @@
  *
  * Authors: Ben Skeggs
  */
-#include <subdev/ibus.h>
+#include "priv.h"
 
 static void
 gk104_ibus_intr_hub(struct nvkm_subdev *ibus, int i)
@@ -56,7 +56,7 @@
 	nvkm_mask(device, 0x128128 + (i * 0x0800), 0x00000200, 0x00000000);
 }
 
-static void
+void
 gk104_ibus_intr(struct nvkm_subdev *ibus)
 {
 	struct nvkm_device *device = ibus->device;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gm204.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gm204.c
new file mode 100644
index 0000000..b3839dc2
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gm204.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 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 "priv.h"
+
+static const struct nvkm_subdev_func
+gm204_ibus = {
+	.intr = gk104_ibus_intr,
+};
+
+int
+gm204_ibus_new(struct nvkm_device *device, int index,
+	       struct nvkm_subdev **pibus)
+{
+	struct nvkm_subdev *ibus;
+	if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL)))
+		return -ENOMEM;
+	nvkm_subdev_ctor(&gm204_ibus, device, index, 0, ibus);
+	return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h
index 48e1b63..01caf79 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h
@@ -4,4 +4,5 @@
 #include <subdev/ibus.h>
 
 void gf100_ibus_intr(struct nvkm_subdev *);
+void gk104_ibus_intr(struct nvkm_subdev *);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
index 14107b5..4c20fec 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
@@ -56,7 +56,6 @@
 
 	/* CPU mapping */
 	u32 *vaddr;
-	struct list_head vaddr_node;
 };
 #define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory)
 
@@ -66,7 +65,6 @@
 struct gk20a_instobj_dma {
 	struct gk20a_instobj base;
 
-	u32 *cpuaddr;
 	dma_addr_t handle;
 	struct nvkm_mm_node r;
 };
@@ -79,6 +77,11 @@
 struct gk20a_instobj_iommu {
 	struct gk20a_instobj base;
 
+	/* to link into gk20a_instmem::vaddr_lru */
+	struct list_head vaddr_node;
+	/* how many clients are using vaddr? */
+	u32 use_cpt;
+
 	/* will point to the higher half of pages */
 	dma_addr_t *dma_addrs;
 	/* array of base.mem->size pages (+ dma_addr_ts) */
@@ -107,8 +110,6 @@
 
 	/* Only used by DMA API */
 	struct dma_attrs attrs;
-
-	void __iomem * (*cpu_map)(struct nvkm_memory *);
 };
 #define gk20a_instmem(p) container_of((p), struct gk20a_instmem, base)
 
@@ -130,70 +131,58 @@
 	return (u64)gk20a_instobj(memory)->mem.size << 12;
 }
 
-static void __iomem *
-gk20a_instobj_cpu_map_dma(struct nvkm_memory *memory)
+/*
+ * Recycle the vaddr of obj. Must be called with gk20a_instmem::lock held.
+ */
+static void
+gk20a_instobj_iommu_recycle_vaddr(struct gk20a_instobj_iommu *obj)
 {
-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
-	struct gk20a_instobj_dma *node = gk20a_instobj_dma(memory);
-	struct device *dev = node->base.imem->base.subdev.device->dev;
-	int npages = nvkm_memory_size(memory) >> 12;
-	struct page *pages[npages];
-	int i;
-
-	/* we shouldn't see a gk20a on anything but arm/arm64 anyways */
-	/* phys_to_page does not exist on all platforms... */
-	pages[0] = pfn_to_page(dma_to_phys(dev, node->handle) >> PAGE_SHIFT);
-	for (i = 1; i < npages; i++)
-		pages[i] = pages[0] + i;
-
-	return vmap(pages, npages, VM_MAP, pgprot_writecombine(PAGE_KERNEL));
-#else
-	BUG();
-	return NULL;
-#endif
-}
-
-static void __iomem *
-gk20a_instobj_cpu_map_iommu(struct nvkm_memory *memory)
-{
-	struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory);
-	int npages = nvkm_memory_size(memory) >> 12;
-
-	return vmap(node->pages, npages, VM_MAP,
-		    pgprot_writecombine(PAGE_KERNEL));
+	struct gk20a_instmem *imem = obj->base.imem;
+	/* there should not be any user left... */
+	WARN_ON(obj->use_cpt);
+	list_del(&obj->vaddr_node);
+	vunmap(obj->base.vaddr);
+	obj->base.vaddr = NULL;
+	imem->vaddr_use -= nvkm_memory_size(&obj->base.memory);
+	nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n", imem->vaddr_use,
+		   imem->vaddr_max);
 }
 
 /*
- * Must be called while holding gk20a_instmem_lock
+ * Must be called while holding gk20a_instmem::lock
  */
 static void
 gk20a_instmem_vaddr_gc(struct gk20a_instmem *imem, const u64 size)
 {
 	while (imem->vaddr_use + size > imem->vaddr_max) {
-		struct gk20a_instobj *obj;
-
 		/* no candidate that can be unmapped, abort... */
 		if (list_empty(&imem->vaddr_lru))
 			break;
 
-		obj = list_first_entry(&imem->vaddr_lru, struct gk20a_instobj,
-				       vaddr_node);
-		list_del(&obj->vaddr_node);
-		vunmap(obj->vaddr);
-		obj->vaddr = NULL;
-		imem->vaddr_use -= nvkm_memory_size(&obj->memory);
-		nvkm_debug(&imem->base.subdev, "(GC) vaddr used: %x/%x\n",
-			   imem->vaddr_use, imem->vaddr_max);
-
+		gk20a_instobj_iommu_recycle_vaddr(
+				list_first_entry(&imem->vaddr_lru,
+				struct gk20a_instobj_iommu, vaddr_node));
 	}
 }
 
 static void __iomem *
-gk20a_instobj_acquire(struct nvkm_memory *memory)
+gk20a_instobj_acquire_dma(struct nvkm_memory *memory)
 {
 	struct gk20a_instobj *node = gk20a_instobj(memory);
 	struct gk20a_instmem *imem = node->imem;
 	struct nvkm_ltc *ltc = imem->base.subdev.device->ltc;
+
+	nvkm_ltc_flush(ltc);
+
+	return node->vaddr;
+}
+
+static void __iomem *
+gk20a_instobj_acquire_iommu(struct nvkm_memory *memory)
+{
+	struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory);
+	struct gk20a_instmem *imem = node->base.imem;
+	struct nvkm_ltc *ltc = imem->base.subdev.device->ltc;
 	const u64 size = nvkm_memory_size(memory);
 	unsigned long flags;
 
@@ -201,19 +190,21 @@
 
 	spin_lock_irqsave(&imem->lock, flags);
 
-	if (node->vaddr) {
-		/* remove us from the LRU list since we cannot be unmapped */
-		list_del(&node->vaddr_node);
-
+	if (node->base.vaddr) {
+		if (!node->use_cpt) {
+			/* remove from LRU list since mapping in use again */
+			list_del(&node->vaddr_node);
+		}
 		goto out;
 	}
 
 	/* try to free some address space if we reached the limit */
 	gk20a_instmem_vaddr_gc(imem, size);
 
-	node->vaddr = imem->cpu_map(memory);
-
-	if (!node->vaddr) {
+	/* map the pages */
+	node->base.vaddr = vmap(node->pages, size >> PAGE_SHIFT, VM_MAP,
+				pgprot_writecombine(PAGE_KERNEL));
+	if (!node->base.vaddr) {
 		nvkm_error(&imem->base.subdev, "cannot map instobj - "
 			   "this is not going to end well...\n");
 		goto out;
@@ -224,24 +215,41 @@
 		   imem->vaddr_use, imem->vaddr_max);
 
 out:
+	node->use_cpt++;
 	spin_unlock_irqrestore(&imem->lock, flags);
 
-	return node->vaddr;
+	return node->base.vaddr;
 }
 
 static void
-gk20a_instobj_release(struct nvkm_memory *memory)
+gk20a_instobj_release_dma(struct nvkm_memory *memory)
 {
 	struct gk20a_instobj *node = gk20a_instobj(memory);
 	struct gk20a_instmem *imem = node->imem;
 	struct nvkm_ltc *ltc = imem->base.subdev.device->ltc;
+
+	nvkm_ltc_invalidate(ltc);
+}
+
+static void
+gk20a_instobj_release_iommu(struct nvkm_memory *memory)
+{
+	struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory);
+	struct gk20a_instmem *imem = node->base.imem;
+	struct nvkm_ltc *ltc = imem->base.subdev.device->ltc;
 	unsigned long flags;
 
 	spin_lock_irqsave(&imem->lock, flags);
 
-	/* add ourselves to the LRU list so our CPU mapping can be freed */
-	list_add_tail(&node->vaddr_node, &imem->vaddr_lru);
+	/* we should at least have one user to release... */
+	if (WARN_ON(node->use_cpt == 0))
+		goto out;
 
+	/* add unused objs to the LRU list to recycle their mapping */
+	if (--node->use_cpt == 0)
+		list_add_tail(&node->vaddr_node, &imem->vaddr_lru);
+
+out:
 	spin_unlock_irqrestore(&imem->lock, flags);
 
 	wmb();
@@ -272,37 +280,6 @@
 	nvkm_vm_map_at(vma, offset, &node->mem);
 }
 
-/*
- * Clear the CPU mapping of an instobj if it exists
- */
-static void
-gk20a_instobj_dtor(struct gk20a_instobj *node)
-{
-	struct gk20a_instmem *imem = node->imem;
-	struct gk20a_instobj *obj;
-	unsigned long flags;
-
-	spin_lock_irqsave(&imem->lock, flags);
-
-	if (!node->vaddr)
-		goto out;
-
-	list_for_each_entry(obj, &imem->vaddr_lru, vaddr_node) {
-		if (obj == node) {
-			list_del(&obj->vaddr_node);
-			break;
-		}
-	}
-	vunmap(node->vaddr);
-	node->vaddr = NULL;
-	imem->vaddr_use -= nvkm_memory_size(&node->memory);
-	nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n",
-		   imem->vaddr_use, imem->vaddr_max);
-
-out:
-	spin_unlock_irqrestore(&imem->lock, flags);
-}
-
 static void *
 gk20a_instobj_dtor_dma(struct nvkm_memory *memory)
 {
@@ -310,12 +287,10 @@
 	struct gk20a_instmem *imem = node->base.imem;
 	struct device *dev = imem->base.subdev.device->dev;
 
-	gk20a_instobj_dtor(&node->base);
-
-	if (unlikely(!node->cpuaddr))
+	if (unlikely(!node->base.vaddr))
 		goto out;
 
-	dma_free_attrs(dev, node->base.mem.size << PAGE_SHIFT, node->cpuaddr,
+	dma_free_attrs(dev, node->base.mem.size << PAGE_SHIFT, node->base.vaddr,
 		       node->handle, &imem->attrs);
 
 out:
@@ -329,13 +304,20 @@
 	struct gk20a_instmem *imem = node->base.imem;
 	struct device *dev = imem->base.subdev.device->dev;
 	struct nvkm_mm_node *r;
+	unsigned long flags;
 	int i;
 
-	gk20a_instobj_dtor(&node->base);
-
 	if (unlikely(list_empty(&node->base.mem.regions)))
 		goto out;
 
+	spin_lock_irqsave(&imem->lock, flags);
+
+	/* vaddr has already been recycled */
+	if (node->base.vaddr)
+		gk20a_instobj_iommu_recycle_vaddr(node);
+
+	spin_unlock_irqrestore(&imem->lock, flags);
+
 	r = list_first_entry(&node->base.mem.regions, struct nvkm_mm_node,
 			     rl_entry);
 
@@ -366,8 +348,8 @@
 	.target = gk20a_instobj_target,
 	.addr = gk20a_instobj_addr,
 	.size = gk20a_instobj_size,
-	.acquire = gk20a_instobj_acquire,
-	.release = gk20a_instobj_release,
+	.acquire = gk20a_instobj_acquire_dma,
+	.release = gk20a_instobj_release_dma,
 	.rd32 = gk20a_instobj_rd32,
 	.wr32 = gk20a_instobj_wr32,
 	.map = gk20a_instobj_map,
@@ -379,8 +361,8 @@
 	.target = gk20a_instobj_target,
 	.addr = gk20a_instobj_addr,
 	.size = gk20a_instobj_size,
-	.acquire = gk20a_instobj_acquire,
-	.release = gk20a_instobj_release,
+	.acquire = gk20a_instobj_acquire_iommu,
+	.release = gk20a_instobj_release_iommu,
 	.rd32 = gk20a_instobj_rd32,
 	.wr32 = gk20a_instobj_wr32,
 	.map = gk20a_instobj_map,
@@ -400,10 +382,10 @@
 
 	nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.memory);
 
-	node->cpuaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT,
-					&node->handle, GFP_KERNEL,
-					&imem->attrs);
-	if (!node->cpuaddr) {
+	node->base.vaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT,
+					   &node->handle, GFP_KERNEL,
+					   &imem->attrs);
+	if (!node->base.vaddr) {
 		nvkm_error(subdev, "cannot allocate DMA memory\n");
 		return -ENOMEM;
 	}
@@ -609,18 +591,14 @@
 		imem->mm = &tdev->iommu.mm;
 		imem->domain = tdev->iommu.domain;
 		imem->iommu_pgshift = tdev->iommu.pgshift;
-		imem->cpu_map = gk20a_instobj_cpu_map_iommu;
 		imem->iommu_bit = tdev->func->iommu_bit;
 
 		nvkm_info(&imem->base.subdev, "using IOMMU\n");
 	} else {
 		init_dma_attrs(&imem->attrs);
-		/* We will access the memory through our own mapping */
 		dma_set_attr(DMA_ATTR_NON_CONSISTENT, &imem->attrs);
 		dma_set_attr(DMA_ATTR_WEAK_ORDERING, &imem->attrs);
 		dma_set_attr(DMA_ATTR_WRITE_COMBINE, &imem->attrs);
-		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &imem->attrs);
-		imem->cpu_map = gk20a_instobj_cpu_map_dma;
 
 		nvkm_info(&imem->base.subdev, "using DMA API\n");
 	}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild
index e5df3d8..f8108df 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild
@@ -2,3 +2,4 @@
 nvkm-y += nvkm/subdev/ltc/gf100.o
 nvkm-y += nvkm/subdev/ltc/gk104.o
 nvkm-y += nvkm/subdev/ltc/gm107.o
+nvkm-y += nvkm/subdev/ltc/gm204.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
index 3043bbf..2af1f9e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
@@ -26,16 +26,16 @@
 #include <subdev/fb.h>
 #include <subdev/timer.h>
 
-static void
+void
 gm107_ltc_cbc_clear(struct nvkm_ltc *ltc, u32 start, u32 limit)
 {
 	struct nvkm_device *device = ltc->subdev.device;
 	nvkm_wr32(device, 0x17e270, start);
 	nvkm_wr32(device, 0x17e274, limit);
-	nvkm_wr32(device, 0x17e26c, 0x00000004);
+	nvkm_mask(device, 0x17e26c, 0x00000000, 0x00000004);
 }
 
-static void
+void
 gm107_ltc_cbc_wait(struct nvkm_ltc *ltc)
 {
 	struct nvkm_device *device = ltc->subdev.device;
@@ -51,7 +51,7 @@
 	}
 }
 
-static void
+void
 gm107_ltc_zbc_clear_color(struct nvkm_ltc *ltc, int i, const u32 color[4])
 {
 	struct nvkm_device *device = ltc->subdev.device;
@@ -62,7 +62,7 @@
 	nvkm_wr32(device, 0x17e348, color[3]);
 }
 
-static void
+void
 gm107_ltc_zbc_clear_depth(struct nvkm_ltc *ltc, int i, const u32 depth)
 {
 	struct nvkm_device *device = ltc->subdev.device;
@@ -84,7 +84,7 @@
 	}
 }
 
-static void
+void
 gm107_ltc_intr(struct nvkm_ltc *ltc)
 {
 	struct nvkm_device *device = ltc->subdev.device;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm204.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm204.c
new file mode 100644
index 0000000..5ad6fb9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm204.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2015 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 "priv.h"
+
+#include <subdev/fb.h>
+#include <subdev/timer.h>
+
+static int
+gm204_ltc_oneinit(struct nvkm_ltc *ltc)
+{
+	struct nvkm_device *device = ltc->subdev.device;
+
+	ltc->ltc_nr = nvkm_rd32(device, 0x12006c);
+	ltc->lts_nr = nvkm_rd32(device, 0x17e280) >> 28;
+
+	return gf100_ltc_oneinit_tag_ram(ltc);
+}
+static void
+gm204_ltc_init(struct nvkm_ltc *ltc)
+{
+	nvkm_wr32(ltc->subdev.device, 0x17e278, ltc->tag_base);
+}
+
+static const struct nvkm_ltc_func
+gm204_ltc = {
+	.oneinit = gm204_ltc_oneinit,
+	.init = gm204_ltc_init,
+	.intr = gm107_ltc_intr, /*XXX: not validated */
+	.cbc_clear = gm107_ltc_cbc_clear,
+	.cbc_wait = gm107_ltc_cbc_wait,
+	.zbc = 16,
+	.zbc_clear_color = gm107_ltc_zbc_clear_color,
+	.zbc_clear_depth = gm107_ltc_zbc_clear_depth,
+	.invalidate = gf100_ltc_invalidate,
+	.flush = gf100_ltc_flush,
+};
+
+int
+gm204_ltc_new(struct nvkm_device *device, int index, struct nvkm_ltc **pltc)
+{
+	return nvkm_ltc_new_(&gm204_ltc, device, index, pltc);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
index 4e3755b..6d81c69 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
@@ -31,4 +31,10 @@
 void gf100_ltc_zbc_clear_depth(struct nvkm_ltc *, int, const u32);
 void gf100_ltc_invalidate(struct nvkm_ltc *);
 void gf100_ltc_flush(struct nvkm_ltc *);
+
+void gm107_ltc_intr(struct nvkm_ltc *);
+void gm107_ltc_cbc_clear(struct nvkm_ltc *, u32, u32);
+void gm107_ltc_cbc_wait(struct nvkm_ltc *);
+void gm107_ltc_zbc_clear_color(struct nvkm_ltc *, int, const u32[4]);
+void gm107_ltc_zbc_clear_depth(struct nvkm_ltc *, int, const u32);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild
index 4476ef7..3c2519f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild
@@ -1,5 +1,6 @@
 nvkm-y += nvkm/subdev/pci/agp.o
 nvkm-y += nvkm/subdev/pci/base.o
+nvkm-y += nvkm/subdev/pci/pcie.o
 nvkm-y += nvkm/subdev/pci/nv04.o
 nvkm-y += nvkm/subdev/pci/nv40.o
 nvkm-y += nvkm/subdev/pci/nv46.o
@@ -7,3 +8,5 @@
 nvkm-y += nvkm/subdev/pci/g84.o
 nvkm-y += nvkm/subdev/pci/g94.o
 nvkm-y += nvkm/subdev/pci/gf100.o
+nvkm-y += nvkm/subdev/pci/gf106.o
+nvkm-y += nvkm/subdev/pci/gk104.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
index d671dcf..65057c8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
@@ -107,6 +107,15 @@
 }
 
 static int
+nvkm_pci_oneinit(struct nvkm_subdev *subdev)
+{
+	struct nvkm_pci *pci = nvkm_pci(subdev);
+	if (pci_is_pcie(pci->pdev))
+		return nvkm_pcie_oneinit(pci);
+	return 0;
+}
+
+static int
 nvkm_pci_init(struct nvkm_subdev *subdev)
 {
 	struct nvkm_pci *pci = nvkm_pci(subdev);
@@ -117,6 +126,8 @@
 		ret = nvkm_agp_init(pci);
 		if (ret)
 			return ret;
+	} else if (pci_is_pcie(pci->pdev)) {
+		nvkm_pcie_init(pci);
 	}
 
 	if (pci->func->init)
@@ -143,6 +154,7 @@
 static const struct nvkm_subdev_func
 nvkm_pci_func = {
 	.dtor = nvkm_pci_dtor,
+	.oneinit = nvkm_pci_oneinit,
 	.preinit = nvkm_pci_preinit,
 	.init = nvkm_pci_init,
 	.fini = nvkm_pci_fini,
@@ -160,6 +172,8 @@
 	pci->func = func;
 	pci->pdev = device->func->pci(device)->pdev;
 	pci->irq = -1;
+	pci->pcie.speed = -1;
+	pci->pcie.width = -1;
 
 	if (device->type == NVKM_DEVICE_AGP)
 		nvkm_agp_ctor(pci);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c
index 3faa6bf..62438d8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c
@@ -25,6 +25,80 @@
 
 #include <core/pci.h>
 
+static int
+g84_pcie_version_supported(struct nvkm_pci *pci)
+{
+	/* g84 and g86 report wrong information about what they support */
+	return 1;
+}
+
+int
+g84_pcie_version(struct nvkm_pci *pci)
+{
+	struct nvkm_device *device = pci->subdev.device;
+	return (nvkm_rd32(device, 0x00154c) & 0x1) + 1;
+}
+
+void
+g84_pcie_set_version(struct nvkm_pci *pci, u8 ver)
+{
+	struct nvkm_device *device = pci->subdev.device;
+	nvkm_mask(device, 0x00154c, 0x1, (ver >= 2 ? 0x1 : 0x0));
+}
+
+static void
+g84_pcie_set_cap_speed(struct nvkm_pci *pci, bool full_speed)
+{
+	struct nvkm_device *device = pci->subdev.device;
+	nvkm_mask(device, 0x00154c, 0x80, full_speed ? 0x80 : 0x0);
+}
+
+enum nvkm_pcie_speed
+g84_pcie_cur_speed(struct nvkm_pci *pci)
+{
+	u32 reg_v = nvkm_pci_rd32(pci, 0x88) & 0x30000;
+	switch (reg_v) {
+	case 0x30000:
+		return NVKM_PCIE_SPEED_8_0;
+	case 0x20000:
+		return NVKM_PCIE_SPEED_5_0;
+	case 0x10000:
+	default:
+		return NVKM_PCIE_SPEED_2_5;
+	}
+}
+
+enum nvkm_pcie_speed
+g84_pcie_max_speed(struct nvkm_pci *pci)
+{
+	u32 reg_v = nvkm_pci_rd32(pci, 0x460) & 0x3300;
+	if (reg_v == 0x2200)
+		return NVKM_PCIE_SPEED_5_0;
+	return NVKM_PCIE_SPEED_2_5;
+}
+
+void
+g84_pcie_set_link_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
+{
+	u32 mask_value;
+
+	if (speed == NVKM_PCIE_SPEED_5_0)
+		mask_value = 0x20;
+	else
+		mask_value = 0x10;
+
+	nvkm_pci_mask(pci, 0x460, 0x30, mask_value);
+	nvkm_pci_mask(pci, 0x460, 0x1, 0x1);
+}
+
+int
+g84_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
+{
+	g84_pcie_set_cap_speed(pci, speed == NVKM_PCIE_SPEED_5_0);
+	g84_pcie_set_link_speed(pci, speed);
+	return 0;
+}
+
 void
 g84_pci_init(struct nvkm_pci *pci)
 {
@@ -48,6 +122,14 @@
 		nvkm_pci_mask(pci, 0x041c, 0x00000060, 0x00000000);
 }
 
+int
+g84_pcie_init(struct nvkm_pci *pci)
+{
+	bool full_speed = g84_pcie_cur_speed(pci) == NVKM_PCIE_SPEED_5_0;
+	g84_pcie_set_cap_speed(pci, full_speed);
+	return 0;
+}
+
 static const struct nvkm_pci_func
 g84_pci_func = {
 	.init = g84_pci_init,
@@ -55,6 +137,16 @@
 	.wr08 = nv40_pci_wr08,
 	.wr32 = nv40_pci_wr32,
 	.msi_rearm = nv46_pci_msi_rearm,
+
+	.pcie.init = g84_pcie_init,
+	.pcie.set_link = g84_pcie_set_link,
+
+	.pcie.max_speed = g84_pcie_max_speed,
+	.pcie.cur_speed = g84_pcie_cur_speed,
+
+	.pcie.set_version = g84_pcie_set_version,
+	.pcie.version = g84_pcie_version,
+	.pcie.version_supported = g84_pcie_version_supported,
 };
 
 int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c
index cd311ee..4344412 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c
@@ -23,6 +23,14 @@
  */
 #include "priv.h"
 
+int
+g94_pcie_version_supported(struct nvkm_pci *pci)
+{
+	if ((nvkm_pci_rd32(pci, 0x460) & 0x200) == 0x200)
+		return 2;
+	return 1;
+}
+
 static const struct nvkm_pci_func
 g94_pci_func = {
 	.init = g84_pci_init,
@@ -30,6 +38,16 @@
 	.wr08 = nv40_pci_wr08,
 	.wr32 = nv40_pci_wr32,
 	.msi_rearm = nv40_pci_msi_rearm,
+
+	.pcie.init = g84_pcie_init,
+	.pcie.set_link = g84_pcie_set_link,
+
+	.pcie.max_speed = g84_pcie_max_speed,
+	.pcie.cur_speed = g84_pcie_cur_speed,
+
+	.pcie.set_version = g84_pcie_set_version,
+	.pcie.version = g84_pcie_version,
+	.pcie.version_supported = g94_pcie_version_supported,
 };
 
 int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c
index 25e1ae7..e30ea67 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c
@@ -29,6 +29,53 @@
 	nvkm_pci_wr08(pci, 0x0704, 0xff);
 }
 
+void
+gf100_pcie_set_version(struct nvkm_pci *pci, u8 ver)
+{
+	struct nvkm_device *device = pci->subdev.device;
+	nvkm_mask(device, 0x02241c, 0x1, ver > 1 ? 1 : 0);
+}
+
+int
+gf100_pcie_version(struct nvkm_pci *pci)
+{
+	struct nvkm_device *device = pci->subdev.device;
+	return (nvkm_rd32(device, 0x02241c) & 0x1) + 1;
+}
+
+void
+gf100_pcie_set_cap_speed(struct nvkm_pci *pci, bool full_speed)
+{
+	struct nvkm_device *device = pci->subdev.device;
+	nvkm_mask(device, 0x02241c, 0x80, full_speed ? 0x80 : 0x0);
+}
+
+int
+gf100_pcie_cap_speed(struct nvkm_pci *pci)
+{
+	struct nvkm_device *device = pci->subdev.device;
+	u8 punits_pci_cap_speed = nvkm_rd32(device, 0x02241c) & 0x80;
+	if (punits_pci_cap_speed == 0x80)
+		return 1;
+	return 0;
+}
+
+int
+gf100_pcie_init(struct nvkm_pci *pci)
+{
+	bool full_speed = g84_pcie_cur_speed(pci) == NVKM_PCIE_SPEED_5_0;
+	gf100_pcie_set_cap_speed(pci, full_speed);
+	return 0;
+}
+
+int
+gf100_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
+{
+	gf100_pcie_set_cap_speed(pci, speed == NVKM_PCIE_SPEED_5_0);
+	g84_pcie_set_link_speed(pci, speed);
+	return 0;
+}
+
 static const struct nvkm_pci_func
 gf100_pci_func = {
 	.init = g84_pci_init,
@@ -36,6 +83,16 @@
 	.wr08 = nv40_pci_wr08,
 	.wr32 = nv40_pci_wr32,
 	.msi_rearm = gf100_pci_msi_rearm,
+
+	.pcie.init = gf100_pcie_init,
+	.pcie.set_link = gf100_pcie_set_link,
+
+	.pcie.max_speed = g84_pcie_max_speed,
+	.pcie.cur_speed = g84_pcie_cur_speed,
+
+	.pcie.set_version = gf100_pcie_set_version,
+	.pcie.version = gf100_pcie_version,
+	.pcie.version_supported = g94_pcie_version_supported,
 };
 
 int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf106.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf106.c
new file mode 100644
index 0000000..c3b798c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf106.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 Karol Herbst <nouveau@karolherbst.de>
+ *
+ * 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: Karol Herbst <nouveau@karolherbst.de>
+ */
+#include "priv.h"
+
+static const struct nvkm_pci_func
+gf106_pci_func = {
+	.init = g84_pci_init,
+	.rd32 = nv40_pci_rd32,
+	.wr08 = nv40_pci_wr08,
+	.wr32 = nv40_pci_wr32,
+	.msi_rearm = nv40_pci_msi_rearm,
+
+	.pcie.init = gf100_pcie_init,
+	.pcie.set_link = gf100_pcie_set_link,
+
+	.pcie.max_speed = g84_pcie_max_speed,
+	.pcie.cur_speed = g84_pcie_cur_speed,
+
+	.pcie.set_version = gf100_pcie_set_version,
+	.pcie.version = gf100_pcie_version,
+	.pcie.version_supported = g94_pcie_version_supported,
+};
+
+int
+gf106_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci)
+{
+	return nvkm_pci_new_(&gf106_pci_func, device, index, ppci);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gk104.c
new file mode 100644
index 0000000..e680305
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gk104.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2015 Karol Herbst <nouveau@karolherbst.de>
+ *
+ * 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: Karol Herbst <nouveau@karolherbst.de>
+ */
+#include "priv.h"
+
+static int
+gk104_pcie_version_supported(struct nvkm_pci *pci)
+{
+	return (nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x4) == 0x4 ? 2 : 1;
+}
+
+static void
+gk104_pcie_set_cap_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
+{
+	struct nvkm_device *device = pci->subdev.device;
+
+	switch (speed) {
+	case NVKM_PCIE_SPEED_2_5:
+		gf100_pcie_set_cap_speed(pci, false);
+		nvkm_mask(device, 0x8c1c0, 0x30000, 0x10000);
+		break;
+	case NVKM_PCIE_SPEED_5_0:
+		gf100_pcie_set_cap_speed(pci, true);
+		nvkm_mask(device, 0x8c1c0, 0x30000, 0x20000);
+		break;
+	case NVKM_PCIE_SPEED_8_0:
+		gf100_pcie_set_cap_speed(pci, true);
+		nvkm_mask(device, 0x8c1c0, 0x30000, 0x30000);
+		break;
+	}
+}
+
+static enum nvkm_pcie_speed
+gk104_pcie_cap_speed(struct nvkm_pci *pci)
+{
+	int speed = gf100_pcie_cap_speed(pci);
+
+	if (speed == 0)
+		return NVKM_PCIE_SPEED_2_5;
+
+	if (speed >= 1) {
+		int speed2 = nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x30000;
+		switch (speed2) {
+		case 0x00000:
+		case 0x10000:
+			return NVKM_PCIE_SPEED_2_5;
+		case 0x20000:
+			return NVKM_PCIE_SPEED_5_0;
+		case 0x30000:
+			return NVKM_PCIE_SPEED_8_0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static void
+gk104_pcie_set_lnkctl_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
+{
+	u8 reg_v = 0;
+	switch (speed) {
+	case NVKM_PCIE_SPEED_2_5:
+		reg_v = 1;
+		break;
+	case NVKM_PCIE_SPEED_5_0:
+		reg_v = 2;
+		break;
+	case NVKM_PCIE_SPEED_8_0:
+		reg_v = 3;
+		break;
+	}
+	nvkm_pci_mask(pci, 0xa8, 0x3, reg_v);
+}
+
+static enum nvkm_pcie_speed
+gk104_pcie_lnkctl_speed(struct nvkm_pci *pci)
+{
+	u8 reg_v = nvkm_pci_rd32(pci, 0xa8) & 0x3;
+	switch (reg_v) {
+	case 0:
+	case 1:
+		return NVKM_PCIE_SPEED_2_5;
+	case 2:
+		return NVKM_PCIE_SPEED_5_0;
+	case 3:
+		return NVKM_PCIE_SPEED_8_0;
+	}
+	return -1;
+}
+
+static enum nvkm_pcie_speed
+gk104_pcie_max_speed(struct nvkm_pci *pci)
+{
+	u32 max_speed = nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x300000;
+	switch (max_speed) {
+	case 0x000000:
+		return NVKM_PCIE_SPEED_8_0;
+	case 0x100000:
+		return NVKM_PCIE_SPEED_5_0;
+	case 0x200000:
+		return NVKM_PCIE_SPEED_2_5;
+	}
+	return NVKM_PCIE_SPEED_2_5;
+}
+
+static void
+gk104_pcie_set_link_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
+{
+	struct nvkm_device *device = pci->subdev.device;
+	u32 mask_value;
+
+	switch (speed) {
+	case NVKM_PCIE_SPEED_8_0:
+		mask_value = 0x00000;
+		break;
+	case NVKM_PCIE_SPEED_5_0:
+		mask_value = 0x40000;
+		break;
+	case NVKM_PCIE_SPEED_2_5:
+	default:
+		mask_value = 0x80000;
+		break;
+	}
+
+	nvkm_mask(device, 0x8c040, 0xc0000, mask_value);
+	nvkm_mask(device, 0x8c040, 0x1, 0x1);
+}
+
+static int
+gk104_pcie_init(struct nvkm_pci * pci)
+{
+	enum nvkm_pcie_speed lnkctl_speed, max_speed, cap_speed;
+	struct nvkm_subdev *subdev = &pci->subdev;
+
+	if (gf100_pcie_version(pci) < 2)
+		return 0;
+
+	lnkctl_speed = gk104_pcie_lnkctl_speed(pci);
+	max_speed = gk104_pcie_max_speed(pci);
+	cap_speed = gk104_pcie_cap_speed(pci);
+
+	if (cap_speed != max_speed) {
+		nvkm_trace(subdev, "adjusting cap to max speed\n");
+		gk104_pcie_set_cap_speed(pci, max_speed);
+		cap_speed = gk104_pcie_cap_speed(pci);
+		if (cap_speed != max_speed)
+			nvkm_warn(subdev, "failed to adjust cap speed\n");
+	}
+
+	if (lnkctl_speed != max_speed) {
+		nvkm_debug(subdev, "adjusting lnkctl to max speed\n");
+		gk104_pcie_set_lnkctl_speed(pci, max_speed);
+		lnkctl_speed = gk104_pcie_lnkctl_speed(pci);
+		if (lnkctl_speed != max_speed)
+			nvkm_error(subdev, "failed to adjust lnkctl speed\n");
+	}
+
+	return 0;
+}
+
+static int
+gk104_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
+{
+	struct nvkm_subdev *subdev = &pci->subdev;
+	enum nvkm_pcie_speed lnk_ctl_speed = gk104_pcie_lnkctl_speed(pci);
+	enum nvkm_pcie_speed lnk_cap_speed = gk104_pcie_cap_speed(pci);
+
+	if (speed > lnk_cap_speed) {
+		speed = lnk_cap_speed;
+		nvkm_warn(subdev, "dropping requested speed due too low cap"
+			  " speed\n");
+	}
+
+	if (speed > lnk_ctl_speed) {
+		speed = lnk_ctl_speed;
+		nvkm_warn(subdev, "dropping requested speed due too low"
+			  " lnkctl speed\n");
+	}
+
+	gk104_pcie_set_link_speed(pci, speed);
+	return 0;
+}
+
+
+static const struct nvkm_pci_func
+gk104_pci_func = {
+	.init = g84_pci_init,
+	.rd32 = nv40_pci_rd32,
+	.wr08 = nv40_pci_wr08,
+	.wr32 = nv40_pci_wr32,
+	.msi_rearm = nv40_pci_msi_rearm,
+
+	.pcie.init = gk104_pcie_init,
+	.pcie.set_link = gk104_pcie_set_link,
+
+	.pcie.max_speed = gk104_pcie_max_speed,
+	.pcie.cur_speed = g84_pcie_cur_speed,
+
+	.pcie.set_version = gf100_pcie_set_version,
+	.pcie.version = gf100_pcie_version,
+	.pcie.version_supported = gk104_pcie_version_supported,
+};
+
+int
+gk104_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci)
+{
+	return nvkm_pci_new_(&gk104_pci_func, device, index, ppci);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/pcie.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/pcie.c
new file mode 100644
index 0000000..d71e5db
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/pcie.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2015 Karol Herbst <nouveau@karolherbst.de>
+ *
+ * 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: Karol Herbst <git@karolherbst.de>
+ */
+#include "priv.h"
+
+static char *nvkm_pcie_speeds[] = {
+	"2.5GT/s",
+	"5.0GT/s",
+	"8.0GT/s",
+};
+
+static enum nvkm_pcie_speed
+nvkm_pcie_speed(enum pci_bus_speed speed)
+{
+	switch (speed) {
+	case PCIE_SPEED_2_5GT:
+		return NVKM_PCIE_SPEED_2_5;
+	case PCIE_SPEED_5_0GT:
+		return NVKM_PCIE_SPEED_5_0;
+	case PCIE_SPEED_8_0GT:
+		return NVKM_PCIE_SPEED_8_0;
+	default:
+		/* XXX 0x16 is 8_0, assume 0x17 will be 16_0 for now */
+		if (speed == 0x17)
+			return NVKM_PCIE_SPEED_8_0;
+		return -1;
+	}
+}
+
+static int
+nvkm_pcie_get_version(struct nvkm_pci *pci)
+{
+	if (!pci->func->pcie.version)
+		return -ENOSYS;
+
+	return pci->func->pcie.version(pci);
+}
+
+static int
+nvkm_pcie_get_max_version(struct nvkm_pci *pci)
+{
+	if (!pci->func->pcie.version_supported)
+		return -ENOSYS;
+
+	return pci->func->pcie.version_supported(pci);
+}
+
+static int
+nvkm_pcie_set_version(struct nvkm_pci *pci, int version)
+{
+	if (!pci->func->pcie.set_version)
+		return -ENOSYS;
+
+	nvkm_trace(&pci->subdev, "set to version %i\n", version);
+	pci->func->pcie.set_version(pci, version);
+	return nvkm_pcie_get_version(pci);
+}
+
+int
+nvkm_pcie_oneinit(struct nvkm_pci *pci)
+{
+	if (pci->func->pcie.max_speed)
+		nvkm_debug(&pci->subdev, "pcie max speed: %s\n",
+			   nvkm_pcie_speeds[pci->func->pcie.max_speed(pci)]);
+	return 0;
+}
+
+int
+nvkm_pcie_init(struct nvkm_pci *pci)
+{
+	struct nvkm_subdev *subdev = &pci->subdev;
+	int ret;
+
+	/* raise pcie version first */
+	ret = nvkm_pcie_get_version(pci);
+	if (ret > 0) {
+		int max_version = nvkm_pcie_get_max_version(pci);
+		if (max_version > 0 && max_version > ret)
+			ret = nvkm_pcie_set_version(pci, max_version);
+
+		if (ret < max_version)
+			nvkm_error(subdev, "couldn't raise version: %i\n", ret);
+	}
+
+	if (pci->func->pcie.init)
+		pci->func->pcie.init(pci);
+
+	if (pci->pcie.speed != -1)
+		nvkm_pcie_set_link(pci, pci->pcie.speed, pci->pcie.width);
+
+	return 0;
+}
+
+int
+nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
+{
+	struct nvkm_subdev *subdev = &pci->subdev;
+	enum nvkm_pcie_speed cur_speed, max_speed;
+	struct pci_bus *pbus;
+	int ret;
+
+	if (!pci || !pci_is_pcie(pci->pdev))
+		return 0;
+	pbus = pci->pdev->bus;
+
+	if (!pci->func->pcie.set_link)
+		return -ENOSYS;
+
+	nvkm_trace(subdev, "requested %s\n", nvkm_pcie_speeds[speed]);
+
+	if (pci->func->pcie.version(pci) < 2) {
+		nvkm_error(subdev, "setting link failed due to low version\n");
+		return -ENODEV;
+	}
+
+	cur_speed = pci->func->pcie.cur_speed(pci);
+	max_speed = min(nvkm_pcie_speed(pbus->max_bus_speed),
+			pci->func->pcie.max_speed(pci));
+
+	nvkm_trace(subdev, "current speed: %s\n", nvkm_pcie_speeds[cur_speed]);
+
+	if (speed > max_speed) {
+		nvkm_debug(subdev, "%s not supported by bus or card, dropping"
+			   "requested speed to %s", nvkm_pcie_speeds[speed],
+			   nvkm_pcie_speeds[max_speed]);
+		speed = max_speed;
+	}
+
+	pci->pcie.speed = speed;
+	pci->pcie.width = width;
+
+	if (speed == cur_speed) {
+		nvkm_debug(subdev, "requested matches current speed\n");
+		return speed;
+	}
+
+	nvkm_debug(subdev, "set link to %s x%i\n",
+		   nvkm_pcie_speeds[speed], width);
+
+	ret = pci->func->pcie.set_link(pci, speed, width);
+	if (ret < 0)
+		nvkm_error(subdev, "setting link failed: %i\n", ret);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h
index cf46d38..23de318 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h
@@ -12,6 +12,18 @@
 	void (*wr08)(struct nvkm_pci *, u16 addr, u8 data);
 	void (*wr32)(struct nvkm_pci *, u16 addr, u32 data);
 	void (*msi_rearm)(struct nvkm_pci *);
+
+	struct {
+		int (*init)(struct nvkm_pci *);
+		int (*set_link)(struct nvkm_pci *, enum nvkm_pcie_speed, u8);
+
+		enum nvkm_pcie_speed (*max_speed)(struct nvkm_pci *);
+		enum nvkm_pcie_speed (*cur_speed)(struct nvkm_pci *);
+
+		void (*set_version)(struct nvkm_pci *, u8);
+		int (*version)(struct nvkm_pci *);
+		int (*version_supported)(struct nvkm_pci *);
+	} pcie;
 };
 
 u32 nv40_pci_rd32(struct nvkm_pci *, u16);
@@ -22,4 +34,25 @@
 void nv46_pci_msi_rearm(struct nvkm_pci *);
 
 void g84_pci_init(struct nvkm_pci *pci);
+
+/* pcie functions */
+void g84_pcie_set_version(struct nvkm_pci *, u8);
+int g84_pcie_version(struct nvkm_pci *);
+void g84_pcie_set_link_speed(struct nvkm_pci *, enum nvkm_pcie_speed);
+enum nvkm_pcie_speed g84_pcie_cur_speed(struct nvkm_pci *);
+enum nvkm_pcie_speed g84_pcie_max_speed(struct nvkm_pci *);
+int g84_pcie_init(struct nvkm_pci *);
+int g84_pcie_set_link(struct nvkm_pci *, enum nvkm_pcie_speed, u8);
+
+int g94_pcie_version_supported(struct nvkm_pci *);
+
+void gf100_pcie_set_version(struct nvkm_pci *, u8);
+int gf100_pcie_version(struct nvkm_pci *);
+void gf100_pcie_set_cap_speed(struct nvkm_pci *, bool);
+int gf100_pcie_cap_speed(struct nvkm_pci *);
+int gf100_pcie_init(struct nvkm_pci *);
+int gf100_pcie_set_link(struct nvkm_pci *, enum nvkm_pcie_speed, u8);
+
+int nvkm_pcie_oneinit(struct nvkm_pci *);
+int nvkm_pcie_init(struct nvkm_pci *);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h
index 302557c..7702944 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h
@@ -24,8 +24,8 @@
 	0x00000000,
 /* 0x0058: proc_list_head */
 	0x54534f48,
-	0x00000512,
-	0x000004af,
+	0x00000507,
+	0x000004a4,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -46,8 +46,8 @@
 	0x00000000,
 	0x00000000,
 	0x584d454d,
-	0x0000075e,
-	0x00000750,
+	0x00000753,
+	0x00000745,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -68,8 +68,8 @@
 	0x00000000,
 	0x00000000,
 	0x46524550,
-	0x00000762,
-	0x00000760,
+	0x00000757,
+	0x00000755,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -90,8 +90,8 @@
 	0x00000000,
 	0x00000000,
 	0x5f433249,
-	0x00000b92,
-	0x00000a35,
+	0x00000b87,
+	0x00000a2a,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -112,8 +112,8 @@
 	0x00000000,
 	0x00000000,
 	0x54534554,
-	0x00000bbb,
-	0x00000b94,
+	0x00000bb0,
+	0x00000b89,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -134,8 +134,8 @@
 	0x00000000,
 	0x00000000,
 	0x454c4449,
-	0x00000bc7,
-	0x00000bc5,
+	0x00000bbc,
+	0x00000bba,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -229,26 +229,26 @@
 /* 0x0370: memx_func_head */
 	0x00000001,
 	0x00000000,
-	0x00000551,
+	0x00000546,
 /* 0x037c: memx_func_next */
 	0x00000002,
 	0x00000000,
-	0x000005db,
+	0x000005d0,
 	0x00000003,
 	0x00000002,
-	0x000006a5,
+	0x0000069a,
 	0x00040004,
 	0x00000000,
-	0x000006c1,
+	0x000006b6,
 	0x00010005,
 	0x00000000,
-	0x000006de,
+	0x000006d3,
 	0x00010006,
 	0x00000000,
-	0x00000663,
+	0x00000658,
 	0x00000007,
 	0x00000000,
-	0x000006e9,
+	0x000006de,
 /* 0x03c4: memx_func_tail */
 /* 0x03c4: memx_ts_start */
 	0x00000000,
@@ -917,7 +917,7 @@
 };
 
 uint32_t gf100_pmu_code[] = {
-	0x039e0ef5,
+	0x03930ef5,
 /* 0x0004: rd32 */
 	0x07a007f1,
 	0xd00604b6,
@@ -987,7 +987,7 @@
 	0xbb9a0a98,
 	0x1cf4029a,
 	0x01d7f00f,
-	0x02dd21f5,
+	0x02d221f5,
 	0x0ef494bd,
 /* 0x00f9: intr_watchdog_next_time */
 	0x9b0a9815,
@@ -1039,7 +1039,7 @@
 	0x48e7f1c0,
 	0x53e3f14f,
 	0x00d7f054,
-	0x034221f5,
+	0x033721f5,
 	0x07f1c0fc,
 	0x04b604c0,
 	0x000cd006,
@@ -1048,760 +1048,758 @@
 	0x04b60688,
 	0x0009d006,
 /* 0x01ca: intr_skip_subintr */
-	0x89c404bd,
-	0x070bf420,
-	0xffbfa4f1,
-/* 0x01d4: intr_skip_pause */
-	0xf44089c4,
-	0xa4f1070b,
-/* 0x01de: intr_skip_user0 */
-	0x07f0ffbf,
-	0x0604b604,
-	0xbd0008d0,
-	0xfe80fc04,
-	0xf0fc0088,
-	0xd0fce0fc,
-	0xb0fcc0fc,
-	0x90fca0fc,
-	0x00fc80fc,
-	0xf80032f4,
-/* 0x0205: ticks_from_ns */
-	0xf9c0f901,
-	0xcbd7f1b0,
-	0x00d3f000,
-	0x041321f5,
-	0x03e8ccec,
-	0xf400b4b0,
-	0xeeec120b,
-	0xd7f103e8,
-	0xd3f000cb,
-	0x1321f500,
-/* 0x022d: ticks_from_ns_quit */
-	0x02ceb904,
-	0xc0fcb0fc,
-/* 0x0236: ticks_from_us */
-	0xc0f900f8,
+	0x97f104bd,
+	0x90bd00e0,
+	0xf00489fd,
+	0x04b60407,
+	0x0008d006,
+	0x80fc04bd,
+	0xfc0088fe,
+	0xfce0fcf0,
+	0xfcc0fcd0,
+	0xfca0fcb0,
+	0xfc80fc90,
+	0x0032f400,
+/* 0x01fa: ticks_from_ns */
+	0xc0f901f8,
 	0xd7f1b0f9,
 	0xd3f000cb,
-	0x1321f500,
-	0x02ceb904,
-	0xf400b4b0,
-	0xe4bd050b,
-/* 0x0250: ticks_from_us_quit */
-	0xc0fcb0fc,
-/* 0x0256: ticks_to_us */
-	0xd7f100f8,
-	0xd3f000cb,
-	0xecedff00,
-/* 0x0262: timer */
-	0x90f900f8,
-	0x32f480f9,
-	0x03f89810,
-	0xf40086b0,
-	0x84bd651c,
-	0xb63807f0,
-	0x08d00604,
-	0xf004bd00,
-	0x84b63487,
-	0x0088cf06,
-	0xbb9a0998,
-	0xe9bb0298,
-	0x03fe8000,
-	0xb60887f0,
-	0x88cf0684,
-	0x0284f000,
-	0xf0261bf4,
-	0x84b63487,
-	0x0088cf06,
-	0xf406e0b8,
-	0xe8b8090b,
-	0x111cf406,
-/* 0x02b8: timer_reset */
-	0xb63407f0,
-	0x0ed00604,
-	0x8004bd00,
-/* 0x02c6: timer_enable */
-	0x87f09a0e,
-	0x3807f001,
+	0x0821f500,
+	0xe8ccec04,
+	0x00b4b003,
+	0xec120bf4,
+	0xf103e8ee,
+	0xf000cbd7,
+	0x21f500d3,
+/* 0x0222: ticks_from_ns_quit */
+	0xceb90408,
+	0xfcb0fc02,
+/* 0x022b: ticks_from_us */
+	0xf900f8c0,
+	0xf1b0f9c0,
+	0xf000cbd7,
+	0x21f500d3,
+	0xceb90408,
+	0x00b4b002,
+	0xbd050bf4,
+/* 0x0245: ticks_from_us_quit */
+	0xfcb0fce4,
+/* 0x024b: ticks_to_us */
+	0xf100f8c0,
+	0xf000cbd7,
+	0xedff00d3,
+/* 0x0257: timer */
+	0xf900f8ec,
+	0xf480f990,
+	0xf8981032,
+	0x0086b003,
+	0xbd651cf4,
+	0x3807f084,
 	0xd00604b6,
 	0x04bd0008,
-/* 0x02d4: timer_done */
-	0xfc1031f4,
-	0xf890fc80,
-/* 0x02dd: send_proc */
-	0xf980f900,
-	0x05e89890,
-	0xf004e998,
-	0x89b80486,
-	0x2a0bf406,
-	0x940398c4,
-	0x80b60488,
-	0x008ebb18,
-	0x8000fa98,
-	0x8d80008a,
-	0x028c8001,
-	0xb6038b80,
-	0x94f00190,
-	0x04e98007,
-/* 0x0317: send_done */
-	0xfc0231f4,
-	0xf880fc90,
-/* 0x031d: find */
-	0xf080f900,
-	0x31f45887,
-/* 0x0325: find_loop */
-	0x008a9801,
-	0xf406aeb8,
-	0x80b6100b,
-	0x6886b158,
-	0xf01bf402,
-/* 0x033b: find_done */
-	0xb90132f4,
-	0x80fc028e,
-/* 0x0342: send */
-	0x21f500f8,
-	0x01f4031d,
-/* 0x034b: recv */
-	0xf900f897,
-	0x9880f990,
-	0xe99805e8,
-	0x0132f404,
-	0xf40689b8,
-	0x89c43d0b,
-	0x0180b603,
-	0x800784f0,
-	0xea9805e8,
-	0xfef0f902,
-	0xf0f9018f,
-	0x9402efb9,
-	0xe9bb0499,
-	0x18e0b600,
-	0x9803eb98,
-	0xed9802ec,
-	0x00ee9801,
-	0xf0fca5f9,
-	0xf400f8fe,
-	0xf0fc0131,
-/* 0x0398: recv_done */
+	0xb63487f0,
+	0x88cf0684,
+	0x9a099800,
+	0xbb0298bb,
+	0xfe8000e9,
+	0x0887f003,
+	0xcf0684b6,
+	0x84f00088,
+	0x261bf402,
+	0xb63487f0,
+	0x88cf0684,
+	0x06e0b800,
+	0xb8090bf4,
+	0x1cf406e8,
+/* 0x02ad: timer_reset */
+	0x3407f011,
+	0xd00604b6,
+	0x04bd000e,
+/* 0x02bb: timer_enable */
+	0xf09a0e80,
+	0x07f00187,
+	0x0604b638,
+	0xbd0008d0,
+/* 0x02c9: timer_done */
+	0x1031f404,
 	0x90fc80fc,
-/* 0x039e: init */
-	0x17f100f8,
-	0x14b60108,
-	0x0011cf06,
-	0x010911e7,
-	0xfe0814b6,
-	0x17f10014,
-	0x13f000e0,
-	0x1c07f000,
-	0xd00604b6,
-	0x04bd0001,
-	0xf0ff17f0,
-	0x04b61407,
-	0x0001d006,
-	0x17f004bd,
-	0x0015f102,
-	0x1007f008,
-	0xd00604b6,
-	0x04bd0001,
-	0x011a17f1,
-	0xfe0013f0,
-	0x31f40010,
-	0x0117f010,
-	0xb63807f0,
+/* 0x02d2: send_proc */
+	0x80f900f8,
+	0xe89890f9,
+	0x04e99805,
+	0xb80486f0,
+	0x0bf40689,
+	0x0398c42a,
+	0xb6048894,
+	0x8ebb1880,
+	0x00fa9800,
+	0x80008a80,
+	0x8c80018d,
+	0x038b8002,
+	0xf00190b6,
+	0xe9800794,
+	0x0231f404,
+/* 0x030c: send_done */
+	0x80fc90fc,
+/* 0x0312: find */
+	0x80f900f8,
+	0xf45887f0,
+/* 0x031a: find_loop */
+	0x8a980131,
+	0x06aeb800,
+	0xb6100bf4,
+	0x86b15880,
+	0x1bf40268,
+	0x0132f4f0,
+/* 0x0330: find_done */
+	0xfc028eb9,
+/* 0x0337: send */
+	0xf500f880,
+	0xf4031221,
+	0x00f89701,
+/* 0x0340: recv */
+	0x80f990f9,
+	0x9805e898,
+	0x32f404e9,
+	0x0689b801,
+	0xc43d0bf4,
+	0x80b60389,
+	0x0784f001,
+	0x9805e880,
+	0xf0f902ea,
+	0xf9018ffe,
+	0x02efb9f0,
+	0xbb049994,
+	0xe0b600e9,
+	0x03eb9818,
+	0x9802ec98,
+	0xee9801ed,
+	0xfca5f900,
+	0x00f8fef0,
+	0xfc0131f4,
+/* 0x038d: recv_done */
+	0xfc80fcf0,
+/* 0x0393: init */
+	0xf100f890,
+	0xb6010817,
+	0x11cf0614,
+	0x0911e700,
+	0x0814b601,
+	0xf10014fe,
+	0xf000e017,
+	0x07f00013,
+	0x0604b61c,
+	0xbd0001d0,
+	0xff17f004,
+	0xb61407f0,
 	0x01d00604,
 	0xf004bd00,
-/* 0x0402: init_proc */
-	0xf19858f7,
-	0x0016b001,
-	0xf9fa0bf4,
-	0x58f0b615,
-/* 0x0413: mulu32_32_64 */
-	0xf9f20ef4,
-	0xf920f910,
-	0x9540f930,
-	0xd29510e1,
-	0xbdc4bd10,
-	0xc0edffb4,
-	0xb9301dff,
-	0x34f10234,
-	0x34b6ffff,
-	0x1045b610,
-	0xbb00c3bb,
-	0xe2ff01b4,
-	0x0234b930,
-	0xffff34f1,
-	0xb61034b6,
-	0xc3bb1045,
-	0x01b4bb00,
-	0xbb3012ff,
-	0x40fc00b3,
-	0x20fc30fc,
-	0x00f810fc,
-/* 0x0464: host_send */
-	0x04b017f1,
-	0xcf0614b6,
-	0x27f10011,
-	0x24b604a0,
-	0x0022cf06,
-	0xf40612b8,
-	0x1ec4320b,
-	0x04ee9407,
-	0x0270e0b7,
-	0x9803eb98,
-	0xed9802ec,
-	0x00ee9801,
-	0x034221f5,
-	0xc40110b6,
-	0x07f10f1e,
-	0x04b604b0,
-	0x000ed006,
-	0x0ef404bd,
-/* 0x04ad: host_send_done */
-/* 0x04af: host_recv */
-	0xf100f8ba,
-	0xf14e4917,
-	0xb8525413,
-	0x0bf406e1,
-/* 0x04bd: host_recv_wait */
-	0xcc17f1aa,
-	0x0614b604,
-	0xf10011cf,
-	0xb604c827,
-	0x22cf0624,
-	0x0816f000,
-	0xf40612b8,
-	0x23c4e60b,
-	0x0434b607,
-	0x02f030b7,
-	0x80033b80,
-	0x3d80023c,
-	0x003e8001,
-	0xf00120b6,
-	0x07f10f24,
-	0x04b604c8,
-	0x0002d006,
-	0x27f004bd,
-	0x0007f040,
-	0xd00604b6,
-	0x04bd0002,
-/* 0x0512: host_init */
-	0x17f100f8,
-	0x14b60080,
-	0x7015f110,
-	0xd007f102,
-	0x0604b604,
+	0x15f10217,
+	0x07f00800,
+	0x0604b610,
 	0xbd0001d0,
-	0x8017f104,
-	0x1014b600,
-	0x02f015f1,
-	0x04dc07f1,
+	0x1a17f104,
+	0x0013f001,
+	0xf40010fe,
+	0x17f01031,
+	0x3807f001,
 	0xd00604b6,
 	0x04bd0001,
-	0xf10117f0,
-	0xb604c407,
-	0x01d00604,
-	0xf804bd00,
-/* 0x0551: memx_func_enter */
-	0x2067f100,
-	0x5d77f116,
-	0xff73f1f5,
+/* 0x03f7: init_proc */
+	0x9858f7f0,
+	0x16b001f1,
+	0xfa0bf400,
+	0xf0b615f9,
+	0xf20ef458,
+/* 0x0408: mulu32_32_64 */
+	0x20f910f9,
+	0x40f930f9,
+	0x9510e195,
+	0xc4bd10d2,
+	0xedffb4bd,
+	0x301dffc0,
+	0xf10234b9,
+	0xb6ffff34,
+	0x45b61034,
+	0x00c3bb10,
+	0xff01b4bb,
+	0x34b930e2,
+	0xff34f102,
+	0x1034b6ff,
+	0xbb1045b6,
+	0xb4bb00c3,
+	0x3012ff01,
+	0xfc00b3bb,
+	0xfc30fc40,
+	0xf810fc20,
+/* 0x0459: host_send */
+	0xb017f100,
+	0x0614b604,
+	0xf10011cf,
+	0xb604a027,
+	0x22cf0624,
+	0x0612b800,
+	0xc4320bf4,
+	0xee94071e,
+	0x70e0b704,
+	0x03eb9802,
+	0x9802ec98,
+	0xee9801ed,
+	0x3721f500,
+	0x0110b603,
+	0xf10f1ec4,
+	0xb604b007,
+	0x0ed00604,
+	0xf404bd00,
+/* 0x04a2: host_send_done */
+	0x00f8ba0e,
+/* 0x04a4: host_recv */
+	0x4e4917f1,
+	0x525413f1,
+	0xf406e1b8,
+/* 0x04b2: host_recv_wait */
+	0x17f1aa0b,
+	0x14b604cc,
+	0x0011cf06,
+	0x04c827f1,
+	0xcf0624b6,
+	0x16f00022,
+	0x0612b808,
+	0xc4e60bf4,
+	0x34b60723,
+	0xf030b704,
+	0x033b8002,
+	0x80023c80,
+	0x3e80013d,
+	0x0120b600,
+	0xf10f24f0,
+	0xb604c807,
+	0x02d00604,
+	0xf004bd00,
+	0x07f04027,
+	0x0604b600,
+	0xbd0002d0,
+/* 0x0507: host_init */
+	0xf100f804,
+	0xb6008017,
+	0x15f11014,
+	0x07f10270,
+	0x04b604d0,
+	0x0001d006,
+	0x17f104bd,
+	0x14b60080,
+	0xf015f110,
+	0xdc07f102,
+	0x0604b604,
+	0xbd0001d0,
+	0x0117f004,
+	0x04c407f1,
+	0xd00604b6,
+	0x04bd0001,
+/* 0x0546: memx_func_enter */
+	0x67f100f8,
+	0x77f11620,
+	0x73f1f55d,
+	0x6eb9ffff,
+	0x0421f402,
+	0xfd02d8b9,
+	0x60f90487,
+	0xd0fc80f9,
+	0x21f4e0fc,
+	0xfe77f13f,
+	0xff73f1ff,
 	0x026eb9ff,
 	0xb90421f4,
 	0x87fd02d8,
 	0xf960f904,
 	0xfcd0fc80,
 	0x3f21f4e0,
-	0xfffe77f1,
-	0xffff73f1,
+	0x26f067f1,
 	0xf4026eb9,
 	0xd8b90421,
 	0x0487fd02,
 	0x80f960f9,
 	0xe0fcd0fc,
-	0xf13f21f4,
-	0xb926f067,
-	0x21f4026e,
-	0x02d8b904,
-	0xf90487fd,
-	0xfc80f960,
-	0xf4e0fcd0,
-	0x67f03f21,
-	0xe007f104,
-	0x0604b607,
-	0xbd0006d0,
-/* 0x05bd: memx_func_enter_wait */
-	0xc067f104,
-	0x0664b607,
-	0xf00066cf,
-	0x0bf40464,
-	0x2c67f0f3,
-	0xcf0664b6,
-	0x06800066,
-/* 0x05db: memx_func_leave */
-	0xf000f8f1,
-	0x64b62c67,
-	0x0066cf06,
-	0xf0f20680,
+	0xf03f21f4,
 	0x07f10467,
-	0x04b607e4,
+	0x04b607e0,
 	0x0006d006,
-/* 0x05f6: memx_func_leave_wait */
+/* 0x05b2: memx_func_enter_wait */
 	0x67f104bd,
 	0x64b607c0,
 	0x0066cf06,
 	0xf40464f0,
-	0x67f1f31b,
-	0x77f126f0,
-	0x73f00001,
-	0x026eb900,
-	0xb90421f4,
-	0x87fd02d8,
-	0xf960f905,
-	0xfcd0fc80,
-	0x3f21f4e0,
-	0x162067f1,
-	0xf4026eb9,
-	0xd8b90421,
-	0x0587fd02,
-	0x80f960f9,
-	0xe0fcd0fc,
-	0xf13f21f4,
-	0xf00aa277,
+	0x67f0f30b,
+	0x0664b62c,
+	0x800066cf,
+	0x00f8f106,
+/* 0x05d0: memx_func_leave */
+	0xb62c67f0,
+	0x66cf0664,
+	0xf2068000,
+	0xf10467f0,
+	0xb607e407,
+	0x06d00604,
+/* 0x05eb: memx_func_leave_wait */
+	0xf104bd00,
+	0xb607c067,
+	0x66cf0664,
+	0x0464f000,
+	0xf1f31bf4,
+	0xf126f067,
+	0xf0000177,
 	0x6eb90073,
 	0x0421f402,
 	0xfd02d8b9,
 	0x60f90587,
 	0xd0fc80f9,
 	0x21f4e0fc,
-/* 0x0663: memx_func_wait_vblank */
-	0x9800f83f,
-	0x66b00016,
-	0x130bf400,
-	0xf40166b0,
-	0x0ef4060b,
-/* 0x0675: memx_func_wait_vblank_head1 */
-	0x2077f12e,
-	0x070ef400,
-/* 0x067c: memx_func_wait_vblank_head0 */
-	0x000877f1,
-/* 0x0680: memx_func_wait_vblank_0 */
-	0x07c467f1,
-	0xcf0664b6,
-	0x67fd0066,
-	0xf31bf404,
-/* 0x0690: memx_func_wait_vblank_1 */
-	0x07c467f1,
-	0xcf0664b6,
-	0x67fd0066,
-	0xf30bf404,
-/* 0x06a0: memx_func_wait_vblank_fini */
-	0xf80410b6,
-/* 0x06a5: memx_func_wr32 */
-	0x00169800,
-	0xb6011598,
-	0x60f90810,
-	0xd0fc50f9,
-	0x21f4e0fc,
-	0x0242b63f,
-	0xf8e91bf4,
-/* 0x06c1: memx_func_wait */
-	0x2c87f000,
-	0xcf0684b6,
-	0x1e980088,
-	0x011d9800,
-	0x98021c98,
-	0x10b6031b,
-	0xa421f410,
-/* 0x06de: memx_func_delay */
-	0x1e9800f8,
+	0x2067f13f,
+	0x026eb916,
+	0xb90421f4,
+	0x87fd02d8,
+	0xf960f905,
+	0xfcd0fc80,
+	0x3f21f4e0,
+	0x0aa277f1,
+	0xb90073f0,
+	0x21f4026e,
+	0x02d8b904,
+	0xf90587fd,
+	0xfc80f960,
+	0xf4e0fcd0,
+	0x00f83f21,
+/* 0x0658: memx_func_wait_vblank */
+	0xb0001698,
+	0x0bf40066,
+	0x0166b013,
+	0xf4060bf4,
+/* 0x066a: memx_func_wait_vblank_head1 */
+	0x77f12e0e,
+	0x0ef40020,
+/* 0x0671: memx_func_wait_vblank_head0 */
+	0x0877f107,
+/* 0x0675: memx_func_wait_vblank_0 */
+	0xc467f100,
+	0x0664b607,
+	0xfd0066cf,
+	0x1bf40467,
+/* 0x0685: memx_func_wait_vblank_1 */
+	0xc467f1f3,
+	0x0664b607,
+	0xfd0066cf,
+	0x0bf40467,
+/* 0x0695: memx_func_wait_vblank_fini */
+	0x0410b6f3,
+/* 0x069a: memx_func_wr32 */
+	0x169800f8,
+	0x01159800,
+	0xf90810b6,
+	0xfc50f960,
+	0xf4e0fcd0,
+	0x42b63f21,
+	0xe91bf402,
+/* 0x06b6: memx_func_wait */
+	0x87f000f8,
+	0x0684b62c,
+	0x980088cf,
+	0x1d98001e,
+	0x021c9801,
+	0xb6031b98,
+	0x21f41010,
+/* 0x06d3: memx_func_delay */
+	0x9800f8a4,
+	0x10b6001e,
+	0x7f21f404,
+/* 0x06de: memx_func_train */
+	0x00f800f8,
+/* 0x06e0: memx_exec */
+	0xd0f9e0f9,
+	0xb902c1b9,
+/* 0x06ea: memx_exec_next */
+	0x139802b2,
 	0x0410b600,
-	0xf87f21f4,
-/* 0x06e9: memx_func_train */
-/* 0x06eb: memx_exec */
-	0xf900f800,
-	0xb9d0f9e0,
-	0xb2b902c1,
-/* 0x06f5: memx_exec_next */
-	0x00139802,
-	0xe70410b6,
-	0xe701f034,
-	0xb601e033,
-	0x30f00132,
-	0xde35980c,
-	0x12b855f9,
-	0xe41ef406,
-	0x98f10b98,
-	0xcbbbf20c,
-	0xc4b7f102,
-	0x06b4b607,
-	0xfc00bbcf,
-	0xf5e0fcd0,
-	0xf8034221,
-/* 0x0731: memx_info */
-	0x01c67000,
-/* 0x0737: memx_info_data */
-	0xf10e0bf4,
-	0xf103ccc7,
-	0xf40800b7,
-/* 0x0742: memx_info_train */
-	0xc7f10b0e,
-	0xb7f10bcc,
-/* 0x074a: memx_info_send */
-	0x21f50100,
-	0x00f80342,
-/* 0x0750: memx_recv */
-	0xf401d6b0,
-	0xd6b0980b,
-	0xd80bf400,
-/* 0x075e: memx_init */
-	0x00f800f8,
-/* 0x0760: perf_recv */
-/* 0x0762: perf_init */
-	0x00f800f8,
-/* 0x0764: i2c_drive_scl */
-	0xf40036b0,
-	0x07f1110b,
-	0x04b607e0,
-	0x0001d006,
-	0x00f804bd,
-/* 0x0778: i2c_drive_scl_lo */
-	0x07e407f1,
-	0xd00604b6,
-	0x04bd0001,
-/* 0x0786: i2c_drive_sda */
-	0x36b000f8,
-	0x110bf400,
-	0x07e007f1,
-	0xd00604b6,
-	0x04bd0002,
-/* 0x079a: i2c_drive_sda_lo */
-	0x07f100f8,
-	0x04b607e4,
-	0x0002d006,
-	0x00f804bd,
-/* 0x07a8: i2c_sense_scl */
-	0xf10132f4,
-	0xb607c437,
-	0x33cf0634,
-	0x0431fd00,
-	0xf4060bf4,
-/* 0x07be: i2c_sense_scl_done */
-	0x00f80131,
-/* 0x07c0: i2c_sense_sda */
-	0xf10132f4,
-	0xb607c437,
-	0x33cf0634,
-	0x0432fd00,
-	0xf4060bf4,
-/* 0x07d6: i2c_sense_sda_done */
-	0x00f80131,
-/* 0x07d8: i2c_raise_scl */
-	0x47f140f9,
-	0x37f00898,
-	0x6421f501,
-/* 0x07e5: i2c_raise_scl_wait */
-	0xe8e7f107,
-	0x7f21f403,
-	0x07a821f5,
-	0xb60901f4,
-	0x1bf40142,
-/* 0x07f9: i2c_raise_scl_done */
-	0xf840fcef,
-/* 0x07fd: i2c_start */
-	0xa821f500,
-	0x0d11f407,
-	0x07c021f5,
-	0xf40611f4,
-/* 0x080e: i2c_start_rep */
-	0x37f0300e,
-	0x6421f500,
-	0x0137f007,
-	0x078621f5,
-	0xb60076bb,
-	0x50f90465,
-	0xbb046594,
-	0x50bd0256,
-	0xfc0475fd,
-	0xd821f550,
-	0x0464b607,
-/* 0x083b: i2c_start_send */
-	0xf01f11f4,
+	0x01f034e7,
+	0x01e033e7,
+	0xf00132b6,
+	0x35980c30,
+	0xb855f9de,
+	0x1ef40612,
+	0xf10b98e4,
+	0xbbf20c98,
+	0xb7f102cb,
+	0xb4b607c4,
+	0x00bbcf06,
+	0xe0fcd0fc,
+	0x033721f5,
+/* 0x0726: memx_info */
+	0xc67000f8,
+	0x0e0bf401,
+/* 0x072c: memx_info_data */
+	0x03ccc7f1,
+	0x0800b7f1,
+/* 0x0737: memx_info_train */
+	0xf10b0ef4,
+	0xf10bccc7,
+/* 0x073f: memx_info_send */
+	0xf50100b7,
+	0xf8033721,
+/* 0x0745: memx_recv */
+	0x01d6b000,
+	0xb0980bf4,
+	0x0bf400d6,
+/* 0x0753: memx_init */
+	0xf800f8d8,
+/* 0x0755: perf_recv */
+/* 0x0757: perf_init */
+	0xf800f800,
+/* 0x0759: i2c_drive_scl */
+	0x0036b000,
+	0xf1110bf4,
+	0xb607e007,
+	0x01d00604,
+	0xf804bd00,
+/* 0x076d: i2c_drive_scl_lo */
+	0xe407f100,
+	0x0604b607,
+	0xbd0001d0,
+/* 0x077b: i2c_drive_sda */
+	0xb000f804,
+	0x0bf40036,
+	0xe007f111,
+	0x0604b607,
+	0xbd0002d0,
+/* 0x078f: i2c_drive_sda_lo */
+	0xf100f804,
+	0xb607e407,
+	0x02d00604,
+	0xf804bd00,
+/* 0x079d: i2c_sense_scl */
+	0x0132f400,
+	0x07c437f1,
+	0xcf0634b6,
+	0x31fd0033,
+	0x060bf404,
+/* 0x07b3: i2c_sense_scl_done */
+	0xf80131f4,
+/* 0x07b5: i2c_sense_sda */
+	0x0132f400,
+	0x07c437f1,
+	0xcf0634b6,
+	0x32fd0033,
+	0x060bf404,
+/* 0x07cb: i2c_sense_sda_done */
+	0xf80131f4,
+/* 0x07cd: i2c_raise_scl */
+	0xf140f900,
+	0xf0089847,
+	0x21f50137,
+/* 0x07da: i2c_raise_scl_wait */
+	0xe7f10759,
+	0x21f403e8,
+	0x9d21f57f,
+	0x0901f407,
+	0xf40142b6,
+/* 0x07ee: i2c_raise_scl_done */
+	0x40fcef1b,
+/* 0x07f2: i2c_start */
+	0x21f500f8,
+	0x11f4079d,
+	0xb521f50d,
+	0x0611f407,
+/* 0x0803: i2c_start_rep */
+	0xf0300ef4,
 	0x21f50037,
-	0xe7f10786,
-	0x21f41388,
-	0x0037f07f,
-	0x076421f5,
-	0x1388e7f1,
-/* 0x0857: i2c_start_out */
-	0xf87f21f4,
-/* 0x0859: i2c_stop */
-	0x0037f000,
-	0x076421f5,
-	0xf50037f0,
-	0xf1078621,
-	0xf403e8e7,
-	0x37f07f21,
-	0x6421f501,
-	0x88e7f107,
-	0x7f21f413,
-	0xf50137f0,
-	0xf1078621,
-	0xf41388e7,
-	0x00f87f21,
-/* 0x088c: i2c_bitw */
-	0x078621f5,
-	0x03e8e7f1,
-	0xbb7f21f4,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x07d821f5,
-	0xf40464b6,
-	0xe7f11811,
-	0x21f41388,
-	0x0037f07f,
-	0x076421f5,
-	0x1388e7f1,
-/* 0x08cb: i2c_bitw_out */
-	0xf87f21f4,
-/* 0x08cd: i2c_bitr */
-	0x0137f000,
-	0x078621f5,
-	0x03e8e7f1,
-	0xbb7f21f4,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x07d821f5,
-	0xf40464b6,
-	0x21f51b11,
-	0x37f007c0,
-	0x6421f500,
-	0x88e7f107,
-	0x7f21f413,
-	0xf4013cf0,
-/* 0x0912: i2c_bitr_done */
-	0x00f80131,
-/* 0x0914: i2c_get_byte */
-	0xf00057f0,
-/* 0x091a: i2c_get_byte_next */
-	0x54b60847,
-	0x0076bb01,
+	0x37f00759,
+	0x7b21f501,
+	0x0076bb07,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b608cd,
-	0x2b11f404,
-	0xb60553fd,
-	0x1bf40142,
-	0x0137f0d8,
-	0xb60076bb,
-	0x50f90465,
-	0xbb046594,
-	0x50bd0256,
-	0xfc0475fd,
-	0x8c21f550,
-	0x0464b608,
-/* 0x0964: i2c_get_byte_done */
-/* 0x0966: i2c_put_byte */
-	0x47f000f8,
-/* 0x0969: i2c_put_byte_next */
-	0x0142b608,
-	0xbb3854ff,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x088c21f5,
-	0xf40464b6,
-	0x46b03411,
-	0xd81bf400,
+	0x64b607cd,
+	0x1f11f404,
+/* 0x0830: i2c_start_send */
+	0xf50037f0,
+	0xf1077b21,
+	0xf41388e7,
+	0x37f07f21,
+	0x5921f500,
+	0x88e7f107,
+	0x7f21f413,
+/* 0x084c: i2c_start_out */
+/* 0x084e: i2c_stop */
+	0x37f000f8,
+	0x5921f500,
+	0x0037f007,
+	0x077b21f5,
+	0x03e8e7f1,
+	0xf07f21f4,
+	0x21f50137,
+	0xe7f10759,
+	0x21f41388,
+	0x0137f07f,
+	0x077b21f5,
+	0x1388e7f1,
+	0xf87f21f4,
+/* 0x0881: i2c_bitw */
+	0x7b21f500,
+	0xe8e7f107,
+	0x7f21f403,
 	0xb60076bb,
 	0x50f90465,
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
 	0xcd21f550,
-	0x0464b608,
-	0xbb0f11f4,
-	0x36b00076,
-	0x061bf401,
-/* 0x09bf: i2c_put_byte_done */
-	0xf80132f4,
-/* 0x09c1: i2c_addr */
-	0x0076bb00,
-	0xf90465b6,
-	0x04659450,
-	0xbd0256bb,
-	0x0475fd50,
-	0x21f550fc,
-	0x64b607fd,
-	0x2911f404,
-	0x012ec3e7,
-	0xfd0134b6,
-	0x76bb0553,
+	0x0464b607,
+	0xf11811f4,
+	0xf41388e7,
+	0x37f07f21,
+	0x5921f500,
+	0x88e7f107,
+	0x7f21f413,
+/* 0x08c0: i2c_bitw_out */
+/* 0x08c2: i2c_bitr */
+	0x37f000f8,
+	0x7b21f501,
+	0xe8e7f107,
+	0x7f21f403,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xcd21f550,
+	0x0464b607,
+	0xf51b11f4,
+	0xf007b521,
+	0x21f50037,
+	0xe7f10759,
+	0x21f41388,
+	0x013cf07f,
+/* 0x0907: i2c_bitr_done */
+	0xf80131f4,
+/* 0x0909: i2c_get_byte */
+	0x0057f000,
+/* 0x090f: i2c_get_byte_next */
+	0xb60847f0,
+	0x76bb0154,
 	0x0465b600,
 	0x659450f9,
 	0x0256bb04,
 	0x75fd50bd,
 	0xf550fc04,
-	0xb6096621,
-/* 0x0a06: i2c_addr_done */
-	0x00f80464,
-/* 0x0a08: i2c_acquire_addr */
-	0xb6f8cec7,
-	0xe0b702e4,
-	0xee980d1c,
-/* 0x0a17: i2c_acquire */
-	0xf500f800,
-	0xf40a0821,
-	0xd9f00421,
-	0x3f21f403,
-/* 0x0a26: i2c_release */
-	0x21f500f8,
-	0x21f40a08,
-	0x03daf004,
-	0xf83f21f4,
-/* 0x0a35: i2c_recv */
-	0x0132f400,
-	0xb6f8c1c7,
-	0x16b00214,
-	0x3a1ff528,
-	0xf413a001,
-	0x0032980c,
-	0x0ccc13a0,
-	0xf4003198,
-	0xd0f90231,
-	0xd0f9e0f9,
-	0x000067f1,
-	0x100063f1,
-	0xbb016792,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x0a1721f5,
-	0xfc0464b6,
-	0x00d6b0d0,
-	0x00b31bf5,
-	0xbb0057f0,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x09c121f5,
-	0xf50464b6,
-	0xc700d011,
-	0x76bbe0c5,
-	0x0465b600,
-	0x659450f9,
-	0x0256bb04,
-	0x75fd50bd,
-	0xf550fc04,
-	0xb6096621,
-	0x11f50464,
-	0x57f000ad,
+	0xb608c221,
+	0x11f40464,
+	0x0553fd2b,
+	0xf40142b6,
+	0x37f0d81b,
 	0x0076bb01,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b609c1,
-	0x8a11f504,
-	0x0076bb00,
+	0x64b60881,
+/* 0x0959: i2c_get_byte_done */
+/* 0x095b: i2c_put_byte */
+	0xf000f804,
+/* 0x095e: i2c_put_byte_next */
+	0x42b60847,
+	0x3854ff01,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x8121f550,
+	0x0464b608,
+	0xb03411f4,
+	0x1bf40046,
+	0x0076bbd8,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b60914,
-	0x6a11f404,
-	0xbbe05bcb,
+	0x64b608c2,
+	0x0f11f404,
+	0xb00076bb,
+	0x1bf40136,
+	0x0132f406,
+/* 0x09b4: i2c_put_byte_done */
+/* 0x09b6: i2c_addr */
+	0x76bb00f8,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb607f221,
+	0x11f40464,
+	0x2ec3e729,
+	0x0134b601,
+	0xbb0553fd,
 	0x65b60076,
 	0x9450f904,
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x085921f5,
-	0xb90464b6,
-	0x74bd025b,
-/* 0x0b3b: i2c_recv_not_rd08 */
-	0xb0430ef4,
-	0x1bf401d6,
-	0x0057f03d,
-	0x09c121f5,
-	0xc73311f4,
-	0x21f5e0c5,
-	0x11f40966,
-	0x0057f029,
-	0x09c121f5,
-	0xc71f11f4,
-	0x21f5e0b5,
-	0x11f40966,
-	0x5921f515,
-	0xc774bd08,
-	0x1bf408c5,
-	0x0232f409,
-/* 0x0b7b: i2c_recv_not_wr08 */
-/* 0x0b7b: i2c_recv_done */
-	0xc7030ef4,
-	0x21f5f8ce,
-	0xe0fc0a26,
-	0x12f4d0fc,
-	0x027cb90a,
-	0x034221f5,
-/* 0x0b90: i2c_recv_exit */
-/* 0x0b92: i2c_init */
+	0x095b21f5,
+/* 0x09fb: i2c_addr_done */
+	0xf80464b6,
+/* 0x09fd: i2c_acquire_addr */
+	0xf8cec700,
+	0xb702e4b6,
+	0x980d1ce0,
+	0x00f800ee,
+/* 0x0a0c: i2c_acquire */
+	0x09fd21f5,
+	0xf00421f4,
+	0x21f403d9,
+/* 0x0a1b: i2c_release */
+	0xf500f83f,
+	0xf409fd21,
+	0xdaf00421,
+	0x3f21f403,
+/* 0x0a2a: i2c_recv */
+	0x32f400f8,
+	0xf8c1c701,
+	0xb00214b6,
+	0x1ff52816,
+	0x13a0013a,
+	0x32980cf4,
+	0xcc13a000,
+	0x0031980c,
+	0xf90231f4,
+	0xf9e0f9d0,
+	0x0067f1d0,
+	0x0063f100,
+	0x01679210,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x0c21f550,
+	0x0464b60a,
+	0xd6b0d0fc,
+	0xb31bf500,
+	0x0057f000,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xb621f550,
+	0x0464b609,
+	0x00d011f5,
+	0xbbe0c5c7,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x095b21f5,
+	0xf50464b6,
+	0xf000ad11,
+	0x76bb0157,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb609b621,
+	0x11f50464,
+	0x76bb008a,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb6090921,
+	0x11f40464,
+	0xe05bcb6a,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x4e21f550,
+	0x0464b608,
+	0xbd025bb9,
+	0x430ef474,
+/* 0x0b30: i2c_recv_not_rd08 */
+	0xf401d6b0,
+	0x57f03d1b,
+	0xb621f500,
+	0x3311f409,
+	0xf5e0c5c7,
+	0xf4095b21,
+	0x57f02911,
+	0xb621f500,
+	0x1f11f409,
+	0xf5e0b5c7,
+	0xf4095b21,
+	0x21f51511,
+	0x74bd084e,
+	0xf408c5c7,
+	0x32f4091b,
+	0x030ef402,
+/* 0x0b70: i2c_recv_not_wr08 */
+/* 0x0b70: i2c_recv_done */
+	0xf5f8cec7,
+	0xfc0a1b21,
+	0xf4d0fce0,
+	0x7cb90a12,
+	0x3721f502,
+/* 0x0b85: i2c_recv_exit */
+/* 0x0b87: i2c_init */
+	0xf800f803,
+/* 0x0b89: test_recv */
+	0xd817f100,
+	0x0614b605,
+	0xb60011cf,
+	0x07f10110,
+	0x04b605d8,
+	0x0001d006,
+	0xe7f104bd,
+	0xe3f1d900,
+	0x21f5134f,
+	0x00f80257,
+/* 0x0bb0: test_init */
+	0x0800e7f1,
+	0x025721f5,
+/* 0x0bba: idle_recv */
 	0x00f800f8,
-/* 0x0b94: test_recv */
-	0x05d817f1,
-	0xcf0614b6,
-	0x10b60011,
-	0xd807f101,
-	0x0604b605,
-	0xbd0001d0,
-	0x00e7f104,
-	0x4fe3f1d9,
-	0x6221f513,
-/* 0x0bbb: test_init */
-	0xf100f802,
-	0xf50800e7,
-	0xf8026221,
-/* 0x0bc5: idle_recv */
-/* 0x0bc7: idle */
-	0xf400f800,
-	0x17f10031,
-	0x14b605d4,
-	0x0011cf06,
-	0xf10110b6,
-	0xb605d407,
-	0x01d00604,
-/* 0x0be3: idle_loop */
-	0xf004bd00,
-	0x32f45817,
-/* 0x0be9: idle_proc */
-/* 0x0be9: idle_proc_exec */
-	0xb910f902,
-	0x21f5021e,
-	0x10fc034b,
-	0xf40911f4,
-	0x0ef40231,
-/* 0x0bfd: idle_proc_next */
-	0x5810b6ef,
-	0xf4061fb8,
-	0x02f4e61b,
-	0x0028f4dd,
-	0x00bb0ef4,
+/* 0x0bbc: idle */
+	0xf10031f4,
+	0xb605d417,
+	0x11cf0614,
+	0x0110b600,
+	0x05d407f1,
+	0xd00604b6,
+	0x04bd0001,
+/* 0x0bd8: idle_loop */
+	0xf45817f0,
+/* 0x0bde: idle_proc */
+/* 0x0bde: idle_proc_exec */
+	0x10f90232,
+	0xf5021eb9,
+	0xfc034021,
+	0x0911f410,
+	0xf40231f4,
+/* 0x0bf2: idle_proc_next */
+	0x10b6ef0e,
+	0x061fb858,
+	0xf4e61bf4,
+	0x28f4dd02,
+	0xbb0ef400,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h
index 31552af..7bf6b39 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h
@@ -24,8 +24,8 @@
 	0x00000000,
 /* 0x0058: proc_list_head */
 	0x54534f48,
-	0x0000049d,
-	0x00000446,
+	0x00000492,
+	0x0000043b,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -46,8 +46,8 @@
 	0x00000000,
 	0x00000000,
 	0x584d454d,
-	0x0000068b,
-	0x0000067d,
+	0x00000680,
+	0x00000672,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -68,8 +68,8 @@
 	0x00000000,
 	0x00000000,
 	0x46524550,
-	0x0000068f,
-	0x0000068d,
+	0x00000684,
+	0x00000682,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -90,8 +90,8 @@
 	0x00000000,
 	0x00000000,
 	0x5f433249,
-	0x00000aaa,
-	0x0000094d,
+	0x00000a9f,
+	0x00000942,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -112,8 +112,8 @@
 	0x00000000,
 	0x00000000,
 	0x54534554,
-	0x00000acd,
-	0x00000aac,
+	0x00000ac2,
+	0x00000aa1,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -134,8 +134,8 @@
 	0x00000000,
 	0x00000000,
 	0x454c4449,
-	0x00000ad9,
-	0x00000ad7,
+	0x00000ace,
+	0x00000acc,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -229,26 +229,26 @@
 /* 0x0370: memx_func_head */
 	0x00000001,
 	0x00000000,
-	0x000004d3,
+	0x000004c8,
 /* 0x037c: memx_func_next */
 	0x00000002,
 	0x00000000,
-	0x00000554,
+	0x00000549,
 	0x00000003,
 	0x00000002,
-	0x000005d8,
+	0x000005cd,
 	0x00040004,
 	0x00000000,
-	0x000005f4,
+	0x000005e9,
 	0x00010005,
 	0x00000000,
-	0x0000060e,
+	0x00000603,
 	0x00010006,
 	0x00000000,
-	0x000005d3,
+	0x000005c8,
 	0x00000007,
 	0x00000000,
-	0x00000619,
+	0x0000060e,
 /* 0x03c4: memx_func_tail */
 /* 0x03c4: memx_ts_start */
 	0x00000000,
@@ -916,7 +916,7 @@
 };
 
 uint32_t gf119_pmu_code[] = {
-	0x034d0ef5,
+	0x03420ef5,
 /* 0x0004: rd32 */
 	0x07a007f1,
 	0xbd000ed0,
@@ -977,7 +977,7 @@
 	0xbb9a0a98,
 	0x1cf4029a,
 	0x01d7f00f,
-	0x028c21f5,
+	0x028121f5,
 	0x0ef494bd,
 /* 0x00d5: intr_watchdog_next_time */
 	0x9b0a9815,
@@ -1025,716 +1025,714 @@
 	0xf14f48e7,
 	0xf05453e3,
 	0x21f500d7,
-	0xc0fc02f1,
+	0xc0fc02e6,
 	0x04c007f1,
 	0xbd000cd0,
 /* 0x0185: intr_subintr_skip_fifo */
 	0x8807f104,
 	0x0009d006,
 /* 0x018e: intr_skip_subintr */
-	0x89c404bd,
-	0x070bf420,
-	0xffbfa4f1,
-/* 0x0198: intr_skip_pause */
-	0xf44089c4,
-	0xa4f1070b,
-/* 0x01a2: intr_skip_user0 */
-	0x07f0ffbf,
-	0x0008d004,
-	0x80fc04bd,
-	0xfc0088fe,
-	0xfce0fcf0,
-	0xfcc0fcd0,
-	0xfca0fcb0,
-	0xfc80fc90,
-	0x0032f400,
-/* 0x01c6: ticks_from_ns */
-	0xc0f901f8,
-	0xd7f1b0f9,
-	0xd3f00144,
-	0xb321f500,
-	0xe8ccec03,
-	0x00b4b003,
-	0xec120bf4,
-	0xf103e8ee,
-	0xf00144d7,
-	0x21f500d3,
-/* 0x01ee: ticks_from_ns_quit */
-	0xceb903b3,
-	0xfcb0fc02,
-/* 0x01f7: ticks_from_us */
-	0xf900f8c0,
+	0x97f104bd,
+	0x90bd00e0,
+	0xf00489fd,
+	0x08d00407,
+	0xfc04bd00,
+	0x0088fe80,
+	0xe0fcf0fc,
+	0xc0fcd0fc,
+	0xa0fcb0fc,
+	0x80fc90fc,
+	0x32f400fc,
+/* 0x01bb: ticks_from_ns */
+	0xf901f800,
 	0xf1b0f9c0,
 	0xf00144d7,
 	0x21f500d3,
-	0xceb903b3,
-	0x00b4b002,
-	0xbd050bf4,
-/* 0x0211: ticks_from_us_quit */
-	0xfcb0fce4,
-/* 0x0217: ticks_to_us */
-	0xf100f8c0,
-	0xf00144d7,
-	0xedff00d3,
-/* 0x0223: timer */
-	0xf900f8ec,
-	0xf480f990,
-	0xf8981032,
-	0x0086b003,
-	0xbd531cf4,
-	0x3807f084,
-	0xbd0008d0,
-	0x3487f004,
-	0x980088cf,
-	0x98bb9a09,
-	0x00e9bb02,
-	0xf003fe80,
-	0x88cf0887,
-	0x0284f000,
-	0xf0201bf4,
-	0x88cf3487,
-	0x06e0b800,
-	0xb8090bf4,
-	0x1cf406e8,
-/* 0x026d: timer_reset */
-	0x3407f00e,
-	0xbd000ed0,
-	0x9a0e8004,
-/* 0x0278: timer_enable */
-	0xf00187f0,
-	0x08d03807,
-/* 0x0283: timer_done */
-	0xf404bd00,
-	0x80fc1031,
-	0x00f890fc,
-/* 0x028c: send_proc */
-	0x90f980f9,
-	0x9805e898,
-	0x86f004e9,
-	0x0689b804,
-	0xc42a0bf4,
-	0x88940398,
-	0x1880b604,
-	0x98008ebb,
-	0x8a8000fa,
-	0x018d8000,
-	0x80028c80,
-	0x90b6038b,
-	0x0794f001,
-	0xf404e980,
-/* 0x02c6: send_done */
-	0x90fc0231,
-	0x00f880fc,
-/* 0x02cc: find */
-	0x87f080f9,
-	0x0131f458,
-/* 0x02d4: find_loop */
-	0xb8008a98,
-	0x0bf406ae,
-	0x5880b610,
-	0x026886b1,
-	0xf4f01bf4,
-/* 0x02ea: find_done */
-	0x8eb90132,
-	0xf880fc02,
-/* 0x02f1: send */
-	0xcc21f500,
-	0x9701f402,
-/* 0x02fa: recv */
-	0x90f900f8,
-	0xe89880f9,
-	0x04e99805,
-	0xb80132f4,
-	0x0bf40689,
-	0x0389c43d,
-	0xf00180b6,
-	0xe8800784,
-	0x02ea9805,
-	0x8ffef0f9,
-	0xb9f0f901,
-	0x999402ef,
-	0x00e9bb04,
-	0x9818e0b6,
+	0xccec03a8,
+	0xb4b003e8,
+	0x120bf400,
+	0x03e8eeec,
+	0x0144d7f1,
+	0xf500d3f0,
+/* 0x01e3: ticks_from_ns_quit */
+	0xb903a821,
+	0xb0fc02ce,
+	0x00f8c0fc,
+/* 0x01ec: ticks_from_us */
+	0xb0f9c0f9,
+	0x0144d7f1,
+	0xf500d3f0,
+	0xb903a821,
+	0xb4b002ce,
+	0x050bf400,
+/* 0x0206: ticks_from_us_quit */
+	0xb0fce4bd,
+	0x00f8c0fc,
+/* 0x020c: ticks_to_us */
+	0x0144d7f1,
+	0xff00d3f0,
+	0x00f8eced,
+/* 0x0218: timer */
+	0x80f990f9,
+	0x981032f4,
+	0x86b003f8,
+	0x531cf400,
+	0x07f084bd,
+	0x0008d038,
+	0x87f004bd,
+	0x0088cf34,
+	0xbb9a0998,
+	0xe9bb0298,
+	0x03fe8000,
+	0xcf0887f0,
+	0x84f00088,
+	0x201bf402,
+	0xcf3487f0,
+	0xe0b80088,
+	0x090bf406,
+	0xf406e8b8,
+/* 0x0262: timer_reset */
+	0x07f00e1c,
+	0x000ed034,
+	0x0e8004bd,
+/* 0x026d: timer_enable */
+	0x0187f09a,
+	0xd03807f0,
+	0x04bd0008,
+/* 0x0278: timer_done */
+	0xfc1031f4,
+	0xf890fc80,
+/* 0x0281: send_proc */
+	0xf980f900,
+	0x05e89890,
+	0xf004e998,
+	0x89b80486,
+	0x2a0bf406,
+	0x940398c4,
+	0x80b60488,
+	0x008ebb18,
+	0x8000fa98,
+	0x8d80008a,
+	0x028c8001,
+	0xb6038b80,
+	0x94f00190,
+	0x04e98007,
+/* 0x02bb: send_done */
+	0xfc0231f4,
+	0xf880fc90,
+/* 0x02c1: find */
+	0xf080f900,
+	0x31f45887,
+/* 0x02c9: find_loop */
+	0x008a9801,
+	0xf406aeb8,
+	0x80b6100b,
+	0x6886b158,
+	0xf01bf402,
+/* 0x02df: find_done */
+	0xb90132f4,
+	0x80fc028e,
+/* 0x02e6: send */
+	0x21f500f8,
+	0x01f402c1,
+/* 0x02ef: recv */
+	0xf900f897,
+	0x9880f990,
+	0xe99805e8,
+	0x0132f404,
+	0xf40689b8,
+	0x89c43d0b,
+	0x0180b603,
+	0x800784f0,
+	0xea9805e8,
+	0xfef0f902,
+	0xf0f9018f,
+	0x9402efb9,
+	0xe9bb0499,
+	0x18e0b600,
+	0x9803eb98,
+	0xed9802ec,
+	0x00ee9801,
+	0xf0fca5f9,
+	0xf400f8fe,
+	0xf0fc0131,
+/* 0x033c: recv_done */
+	0x90fc80fc,
+/* 0x0342: init */
+	0x17f100f8,
+	0x11cf0108,
+	0x0911e700,
+	0x0814b601,
+	0xf10014fe,
+	0xf000e017,
+	0x07f00013,
+	0x0001d01c,
+	0x17f004bd,
+	0x1407f0ff,
+	0xbd0001d0,
+	0x0217f004,
+	0x080015f1,
+	0xd01007f0,
+	0x04bd0001,
+	0x00f617f1,
+	0xfe0013f0,
+	0x31f40010,
+	0x0117f010,
+	0xd03807f0,
+	0x04bd0001,
+/* 0x0397: init_proc */
+	0x9858f7f0,
+	0x16b001f1,
+	0xfa0bf400,
+	0xf0b615f9,
+	0xf20ef458,
+/* 0x03a8: mulu32_32_64 */
+	0x20f910f9,
+	0x40f930f9,
+	0x9510e195,
+	0xc4bd10d2,
+	0xedffb4bd,
+	0x301dffc0,
+	0xf10234b9,
+	0xb6ffff34,
+	0x45b61034,
+	0x00c3bb10,
+	0xff01b4bb,
+	0x34b930e2,
+	0xff34f102,
+	0x1034b6ff,
+	0xbb1045b6,
+	0xb4bb00c3,
+	0x3012ff01,
+	0xfc00b3bb,
+	0xfc30fc40,
+	0xf810fc20,
+/* 0x03f9: host_send */
+	0xb017f100,
+	0x0011cf04,
+	0x04a027f1,
+	0xb80022cf,
+	0x0bf40612,
+	0x071ec42f,
+	0xb704ee94,
+	0x980270e0,
 	0xec9803eb,
 	0x01ed9802,
-	0xf900ee98,
-	0xfef0fca5,
-	0x31f400f8,
-/* 0x0347: recv_done */
-	0xfcf0fc01,
-	0xf890fc80,
-/* 0x034d: init */
-	0x0817f100,
-	0x0011cf01,
-	0x010911e7,
-	0xfe0814b6,
-	0x17f10014,
-	0x13f000e0,
-	0x1c07f000,
-	0xbd0001d0,
-	0xff17f004,
-	0xd01407f0,
-	0x04bd0001,
-	0xf10217f0,
-	0xf0080015,
-	0x01d01007,
-	0xf104bd00,
-	0xf000f617,
-	0x10fe0013,
-	0x1031f400,
-	0xf00117f0,
-	0x01d03807,
-	0xf004bd00,
-/* 0x03a2: init_proc */
-	0xf19858f7,
-	0x0016b001,
-	0xf9fa0bf4,
-	0x58f0b615,
-/* 0x03b3: mulu32_32_64 */
-	0xf9f20ef4,
-	0xf920f910,
-	0x9540f930,
-	0xd29510e1,
-	0xbdc4bd10,
-	0xc0edffb4,
-	0xb9301dff,
-	0x34f10234,
-	0x34b6ffff,
-	0x1045b610,
-	0xbb00c3bb,
-	0xe2ff01b4,
-	0x0234b930,
-	0xffff34f1,
-	0xb61034b6,
-	0xc3bb1045,
-	0x01b4bb00,
-	0xbb3012ff,
-	0x40fc00b3,
-	0x20fc30fc,
-	0x00f810fc,
-/* 0x0404: host_send */
-	0x04b017f1,
-	0xf10011cf,
-	0xcf04a027,
-	0x12b80022,
-	0x2f0bf406,
-	0x94071ec4,
-	0xe0b704ee,
-	0xeb980270,
-	0x02ec9803,
-	0x9801ed98,
-	0x21f500ee,
-	0x10b602f1,
-	0x0f1ec401,
-	0x04b007f1,
-	0xbd000ed0,
-	0xc30ef404,
-/* 0x0444: host_send_done */
-/* 0x0446: host_recv */
-	0x17f100f8,
-	0x13f14e49,
-	0xe1b85254,
-	0xb30bf406,
-/* 0x0454: host_recv_wait */
-	0x04cc17f1,
-	0xf10011cf,
-	0xcf04c827,
-	0x16f00022,
-	0x0612b808,
-	0xc4ec0bf4,
-	0x34b60723,
-	0xf030b704,
-	0x033b8002,
-	0x80023c80,
-	0x3e80013d,
-	0x0120b600,
-	0xf10f24f0,
-	0xd004c807,
+	0xf500ee98,
+	0xb602e621,
+	0x1ec40110,
+	0xb007f10f,
+	0x000ed004,
+	0x0ef404bd,
+/* 0x0439: host_send_done */
+/* 0x043b: host_recv */
+	0xf100f8c3,
+	0xf14e4917,
+	0xb8525413,
+	0x0bf406e1,
+/* 0x0449: host_recv_wait */
+	0xcc17f1b3,
+	0x0011cf04,
+	0x04c827f1,
+	0xf00022cf,
+	0x12b80816,
+	0xec0bf406,
+	0xb60723c4,
+	0x30b70434,
+	0x3b8002f0,
+	0x023c8003,
+	0x80013d80,
+	0x20b6003e,
+	0x0f24f001,
+	0x04c807f1,
+	0xbd0002d0,
+	0x4027f004,
+	0xd00007f0,
 	0x04bd0002,
-	0xf04027f0,
-	0x02d00007,
-	0xf804bd00,
-/* 0x049d: host_init */
-	0x8017f100,
-	0x1014b600,
-	0x027015f1,
-	0x04d007f1,
-	0xbd0001d0,
-	0x8017f104,
-	0x1014b600,
-	0x02f015f1,
-	0x04dc07f1,
-	0xbd0001d0,
-	0x0117f004,
-	0x04c407f1,
-	0xbd0001d0,
-/* 0x04d3: memx_func_enter */
-	0xf100f804,
-	0xf1162067,
-	0xf1f55d77,
+/* 0x0492: host_init */
+	0x17f100f8,
+	0x14b60080,
+	0x7015f110,
+	0xd007f102,
+	0x0001d004,
+	0x17f104bd,
+	0x14b60080,
+	0xf015f110,
+	0xdc07f102,
+	0x0001d004,
+	0x17f004bd,
+	0xc407f101,
+	0x0001d004,
+	0x00f804bd,
+/* 0x04c8: memx_func_enter */
+	0x162067f1,
+	0xf55d77f1,
+	0xffff73f1,
+	0xf4026eb9,
+	0xd8b90421,
+	0x0487fd02,
+	0x80f960f9,
+	0xe0fcd0fc,
+	0xf13321f4,
+	0xf1fffe77,
 	0xb9ffff73,
 	0x21f4026e,
 	0x02d8b904,
 	0xf90487fd,
 	0xfc80f960,
 	0xf4e0fcd0,
-	0x77f13321,
-	0x73f1fffe,
-	0x6eb9ffff,
+	0x67f13321,
+	0x6eb926f0,
 	0x0421f402,
 	0xfd02d8b9,
 	0x60f90487,
 	0xd0fc80f9,
 	0x21f4e0fc,
-	0xf067f133,
-	0x026eb926,
-	0xb90421f4,
-	0x87fd02d8,
-	0xf960f904,
-	0xfcd0fc80,
-	0x3321f4e0,
-	0xf10467f0,
-	0xd007e007,
-	0x04bd0006,
-/* 0x053c: memx_func_enter_wait */
-	0x07c067f1,
-	0xf00066cf,
-	0x0bf40464,
-	0x2c67f0f6,
-	0x800066cf,
-	0x00f8f106,
-/* 0x0554: memx_func_leave */
-	0xcf2c67f0,
-	0x06800066,
-	0x0467f0f2,
-	0x07e407f1,
+	0x0467f033,
+	0x07e007f1,
 	0xbd0006d0,
-/* 0x0569: memx_func_leave_wait */
+/* 0x0531: memx_func_enter_wait */
 	0xc067f104,
 	0x0066cf07,
 	0xf40464f0,
-	0x67f1f61b,
-	0x77f126f0,
-	0x73f00001,
-	0x026eb900,
-	0xb90421f4,
-	0x87fd02d8,
-	0xf960f905,
-	0xfcd0fc80,
-	0x3321f4e0,
-	0x162067f1,
-	0xf4026eb9,
-	0xd8b90421,
-	0x0587fd02,
-	0x80f960f9,
-	0xe0fcd0fc,
-	0xf13321f4,
-	0xf00aa277,
+	0x67f0f60b,
+	0x0066cf2c,
+	0xf8f10680,
+/* 0x0549: memx_func_leave */
+	0x2c67f000,
+	0x800066cf,
+	0x67f0f206,
+	0xe407f104,
+	0x0006d007,
+/* 0x055e: memx_func_leave_wait */
+	0x67f104bd,
+	0x66cf07c0,
+	0x0464f000,
+	0xf1f61bf4,
+	0xf126f067,
+	0xf0000177,
 	0x6eb90073,
 	0x0421f402,
 	0xfd02d8b9,
 	0x60f90587,
 	0xd0fc80f9,
 	0x21f4e0fc,
-/* 0x05d3: memx_func_wait_vblank */
-	0xb600f833,
-	0x00f80410,
-/* 0x05d8: memx_func_wr32 */
-	0x98001698,
-	0x10b60115,
-	0xf960f908,
-	0xfcd0fc50,
+	0x2067f133,
+	0x026eb916,
+	0xb90421f4,
+	0x87fd02d8,
+	0xf960f905,
+	0xfcd0fc80,
 	0x3321f4e0,
-	0xf40242b6,
-	0x00f8e91b,
-/* 0x05f4: memx_func_wait */
-	0xcf2c87f0,
-	0x1e980088,
-	0x011d9800,
-	0x98021c98,
-	0x10b6031b,
-	0x8621f410,
-/* 0x060e: memx_func_delay */
-	0x1e9800f8,
+	0x0aa277f1,
+	0xb90073f0,
+	0x21f4026e,
+	0x02d8b904,
+	0xf90587fd,
+	0xfc80f960,
+	0xf4e0fcd0,
+	0x00f83321,
+/* 0x05c8: memx_func_wait_vblank */
+	0xf80410b6,
+/* 0x05cd: memx_func_wr32 */
+	0x00169800,
+	0xb6011598,
+	0x60f90810,
+	0xd0fc50f9,
+	0x21f4e0fc,
+	0x0242b633,
+	0xf8e91bf4,
+/* 0x05e9: memx_func_wait */
+	0x2c87f000,
+	0x980088cf,
+	0x1d98001e,
+	0x021c9801,
+	0xb6031b98,
+	0x21f41010,
+/* 0x0603: memx_func_delay */
+	0x9800f886,
+	0x10b6001e,
+	0x6721f404,
+/* 0x060e: memx_func_train */
+	0x00f800f8,
+/* 0x0610: memx_exec */
+	0xd0f9e0f9,
+	0xb902c1b9,
+/* 0x061a: memx_exec_next */
+	0x139802b2,
 	0x0410b600,
-	0xf86721f4,
-/* 0x0619: memx_func_train */
-/* 0x061b: memx_exec */
-	0xf900f800,
-	0xb9d0f9e0,
-	0xb2b902c1,
-/* 0x0625: memx_exec_next */
-	0x00139802,
-	0xe70410b6,
-	0xe701f034,
-	0xb601e033,
-	0x30f00132,
-	0xde35980c,
-	0x12b855f9,
-	0xe41ef406,
-	0x98f10b98,
-	0xcbbbf20c,
-	0xc4b7f102,
-	0x00bbcf07,
-	0xe0fcd0fc,
-	0x02f121f5,
-/* 0x065e: memx_info */
-	0xc67000f8,
-	0x0e0bf401,
-/* 0x0664: memx_info_data */
-	0x03ccc7f1,
-	0x0800b7f1,
-/* 0x066f: memx_info_train */
-	0xf10b0ef4,
-	0xf10bccc7,
-/* 0x0677: memx_info_send */
-	0xf50100b7,
-	0xf802f121,
-/* 0x067d: memx_recv */
-	0x01d6b000,
-	0xb09b0bf4,
-	0x0bf400d6,
-/* 0x068b: memx_init */
-	0xf800f8d8,
-/* 0x068d: perf_recv */
-/* 0x068f: perf_init */
-	0xf800f800,
-/* 0x0691: i2c_drive_scl */
-	0x0036b000,
-	0xf10e0bf4,
-	0xd007e007,
+	0x01f034e7,
+	0x01e033e7,
+	0xf00132b6,
+	0x35980c30,
+	0xb855f9de,
+	0x1ef40612,
+	0xf10b98e4,
+	0xbbf20c98,
+	0xb7f102cb,
+	0xbbcf07c4,
+	0xfcd0fc00,
+	0xe621f5e0,
+/* 0x0653: memx_info */
+	0x7000f802,
+	0x0bf401c6,
+/* 0x0659: memx_info_data */
+	0xccc7f10e,
+	0x00b7f103,
+	0x0b0ef408,
+/* 0x0664: memx_info_train */
+	0x0bccc7f1,
+	0x0100b7f1,
+/* 0x066c: memx_info_send */
+	0x02e621f5,
+/* 0x0672: memx_recv */
+	0xd6b000f8,
+	0x9b0bf401,
+	0xf400d6b0,
+	0x00f8d80b,
+/* 0x0680: memx_init */
+/* 0x0682: perf_recv */
+	0x00f800f8,
+/* 0x0684: perf_init */
+/* 0x0686: i2c_drive_scl */
+	0x36b000f8,
+	0x0e0bf400,
+	0x07e007f1,
+	0xbd0001d0,
+/* 0x0697: i2c_drive_scl_lo */
+	0xf100f804,
+	0xd007e407,
 	0x04bd0001,
-/* 0x06a2: i2c_drive_scl_lo */
-	0x07f100f8,
-	0x01d007e4,
-	0xf804bd00,
-/* 0x06ad: i2c_drive_sda */
-	0x0036b000,
-	0xf10e0bf4,
-	0xd007e007,
+/* 0x06a2: i2c_drive_sda */
+	0x36b000f8,
+	0x0e0bf400,
+	0x07e007f1,
+	0xbd0002d0,
+/* 0x06b3: i2c_drive_sda_lo */
+	0xf100f804,
+	0xd007e407,
 	0x04bd0002,
-/* 0x06be: i2c_drive_sda_lo */
-	0x07f100f8,
-	0x02d007e4,
-	0xf804bd00,
-/* 0x06c9: i2c_sense_scl */
-	0x0132f400,
-	0x07c437f1,
-	0xfd0033cf,
-	0x0bf40431,
-	0x0131f406,
-/* 0x06dc: i2c_sense_scl_done */
-/* 0x06de: i2c_sense_sda */
+/* 0x06be: i2c_sense_scl */
 	0x32f400f8,
 	0xc437f101,
 	0x0033cf07,
-	0xf40432fd,
+	0xf40431fd,
 	0x31f4060b,
-/* 0x06f1: i2c_sense_sda_done */
-/* 0x06f3: i2c_raise_scl */
-	0xf900f801,
-	0x9847f140,
-	0x0137f008,
-	0x069121f5,
-/* 0x0700: i2c_raise_scl_wait */
-	0x03e8e7f1,
-	0xf56721f4,
-	0xf406c921,
-	0x42b60901,
-	0xef1bf401,
-/* 0x0714: i2c_raise_scl_done */
-	0x00f840fc,
-/* 0x0718: i2c_start */
-	0x06c921f5,
-	0xf50d11f4,
-	0xf406de21,
-	0x0ef40611,
-/* 0x0729: i2c_start_rep */
-	0x0037f030,
-	0x069121f5,
-	0xf50137f0,
-	0xbb06ad21,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x06f321f5,
-	0xf40464b6,
-/* 0x0756: i2c_start_send */
-	0x37f01f11,
-	0xad21f500,
-	0x88e7f106,
-	0x6721f413,
-	0xf50037f0,
-	0xf1069121,
-	0xf41388e7,
-/* 0x0772: i2c_start_out */
-	0x00f86721,
-/* 0x0774: i2c_stop */
-	0xf50037f0,
-	0xf0069121,
-	0x21f50037,
-	0xe7f106ad,
-	0x21f403e8,
-	0x0137f067,
-	0x069121f5,
-	0x1388e7f1,
-	0xf06721f4,
-	0x21f50137,
-	0xe7f106ad,
-	0x21f41388,
-/* 0x07a7: i2c_bitw */
-	0xf500f867,
-	0xf106ad21,
-	0xf403e8e7,
-	0x76bb6721,
-	0x0465b600,
-	0x659450f9,
-	0x0256bb04,
-	0x75fd50bd,
-	0xf550fc04,
-	0xb606f321,
-	0x11f40464,
-	0x88e7f118,
-	0x6721f413,
-	0xf50037f0,
-	0xf1069121,
-	0xf41388e7,
-/* 0x07e6: i2c_bitw_out */
-	0x00f86721,
-/* 0x07e8: i2c_bitr */
-	0xf50137f0,
-	0xf106ad21,
-	0xf403e8e7,
-	0x76bb6721,
-	0x0465b600,
-	0x659450f9,
-	0x0256bb04,
-	0x75fd50bd,
-	0xf550fc04,
-	0xb606f321,
-	0x11f40464,
-	0xde21f51b,
-	0x0037f006,
-	0x069121f5,
-	0x1388e7f1,
-	0xf06721f4,
-	0x31f4013c,
-/* 0x082d: i2c_bitr_done */
-/* 0x082f: i2c_get_byte */
-	0xf000f801,
-	0x47f00057,
-/* 0x0835: i2c_get_byte_next */
-	0x0154b608,
+/* 0x06d1: i2c_sense_scl_done */
+/* 0x06d3: i2c_sense_sda */
+	0xf400f801,
+	0x37f10132,
+	0x33cf07c4,
+	0x0432fd00,
+	0xf4060bf4,
+/* 0x06e6: i2c_sense_sda_done */
+	0x00f80131,
+/* 0x06e8: i2c_raise_scl */
+	0x47f140f9,
+	0x37f00898,
+	0x8621f501,
+/* 0x06f5: i2c_raise_scl_wait */
+	0xe8e7f106,
+	0x6721f403,
+	0x06be21f5,
+	0xb60901f4,
+	0x1bf40142,
+/* 0x0709: i2c_raise_scl_done */
+	0xf840fcef,
+/* 0x070d: i2c_start */
+	0xbe21f500,
+	0x0d11f406,
+	0x06d321f5,
+	0xf40611f4,
+/* 0x071e: i2c_start_rep */
+	0x37f0300e,
+	0x8621f500,
+	0x0137f006,
+	0x06a221f5,
 	0xb60076bb,
 	0x50f90465,
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
 	0xe821f550,
-	0x0464b607,
-	0xfd2b11f4,
-	0x42b60553,
-	0xd81bf401,
-	0xbb0137f0,
+	0x0464b606,
+/* 0x074b: i2c_start_send */
+	0xf01f11f4,
+	0x21f50037,
+	0xe7f106a2,
+	0x21f41388,
+	0x0037f067,
+	0x068621f5,
+	0x1388e7f1,
+/* 0x0767: i2c_start_out */
+	0xf86721f4,
+/* 0x0769: i2c_stop */
+	0x0037f000,
+	0x068621f5,
+	0xf50037f0,
+	0xf106a221,
+	0xf403e8e7,
+	0x37f06721,
+	0x8621f501,
+	0x88e7f106,
+	0x6721f413,
+	0xf50137f0,
+	0xf106a221,
+	0xf41388e7,
+	0x00f86721,
+/* 0x079c: i2c_bitw */
+	0x06a221f5,
+	0x03e8e7f1,
+	0xbb6721f4,
 	0x65b60076,
 	0x9450f904,
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x07a721f5,
-/* 0x087f: i2c_get_byte_done */
-	0xf80464b6,
-/* 0x0881: i2c_put_byte */
-	0x0847f000,
-/* 0x0884: i2c_put_byte_next */
-	0xff0142b6,
-	0x76bb3854,
-	0x0465b600,
-	0x659450f9,
-	0x0256bb04,
-	0x75fd50bd,
-	0xf550fc04,
-	0xb607a721,
-	0x11f40464,
-	0x0046b034,
-	0xbbd81bf4,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x07e821f5,
+	0x06e821f5,
 	0xf40464b6,
-	0x76bb0f11,
-	0x0136b000,
-	0xf4061bf4,
-/* 0x08da: i2c_put_byte_done */
-	0x00f80132,
-/* 0x08dc: i2c_addr */
-	0xb60076bb,
-	0x50f90465,
-	0xbb046594,
-	0x50bd0256,
-	0xfc0475fd,
-	0x1821f550,
-	0x0464b607,
-	0xe72911f4,
-	0xb6012ec3,
-	0x53fd0134,
-	0x0076bb05,
-	0xf90465b6,
-	0x04659450,
-	0xbd0256bb,
-	0x0475fd50,
-	0x21f550fc,
-	0x64b60881,
-/* 0x0921: i2c_addr_done */
-/* 0x0923: i2c_acquire_addr */
-	0xc700f804,
-	0xe4b6f8ce,
-	0x14e0b705,
-/* 0x092f: i2c_acquire */
-	0xf500f8d0,
-	0xf4092321,
-	0xd9f00421,
-	0x3321f403,
-/* 0x093e: i2c_release */
-	0x21f500f8,
-	0x21f40923,
-	0x03daf004,
-	0xf83321f4,
-/* 0x094d: i2c_recv */
-	0x0132f400,
-	0xb6f8c1c7,
-	0x16b00214,
-	0x3a1ff528,
-	0xf413a001,
-	0x0032980c,
-	0x0ccc13a0,
-	0xf4003198,
-	0xd0f90231,
-	0xd0f9e0f9,
-	0x000067f1,
-	0x100063f1,
-	0xbb016792,
+	0xe7f11811,
+	0x21f41388,
+	0x0037f067,
+	0x068621f5,
+	0x1388e7f1,
+/* 0x07db: i2c_bitw_out */
+	0xf86721f4,
+/* 0x07dd: i2c_bitr */
+	0x0137f000,
+	0x06a221f5,
+	0x03e8e7f1,
+	0xbb6721f4,
 	0x65b60076,
 	0x9450f904,
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x092f21f5,
-	0xfc0464b6,
-	0x00d6b0d0,
-	0x00b31bf5,
-	0xbb0057f0,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x08dc21f5,
-	0xf50464b6,
-	0xc700d011,
-	0x76bbe0c5,
-	0x0465b600,
-	0x659450f9,
-	0x0256bb04,
-	0x75fd50bd,
-	0xf550fc04,
-	0xb6088121,
-	0x11f50464,
-	0x57f000ad,
+	0x06e821f5,
+	0xf40464b6,
+	0x21f51b11,
+	0x37f006d3,
+	0x8621f500,
+	0x88e7f106,
+	0x6721f413,
+	0xf4013cf0,
+/* 0x0822: i2c_bitr_done */
+	0x00f80131,
+/* 0x0824: i2c_get_byte */
+	0xf00057f0,
+/* 0x082a: i2c_get_byte_next */
+	0x54b60847,
 	0x0076bb01,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b608dc,
-	0x8a11f504,
+	0x64b607dd,
+	0x2b11f404,
+	0xb60553fd,
+	0x1bf40142,
+	0x0137f0d8,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x9c21f550,
+	0x0464b607,
+/* 0x0874: i2c_get_byte_done */
+/* 0x0876: i2c_put_byte */
+	0x47f000f8,
+/* 0x0879: i2c_put_byte_next */
+	0x0142b608,
+	0xbb3854ff,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x079c21f5,
+	0xf40464b6,
+	0x46b03411,
+	0xd81bf400,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xdd21f550,
+	0x0464b607,
+	0xbb0f11f4,
+	0x36b00076,
+	0x061bf401,
+/* 0x08cf: i2c_put_byte_done */
+	0xf80132f4,
+/* 0x08d1: i2c_addr */
 	0x0076bb00,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b6082f,
-	0x6a11f404,
-	0xbbe05bcb,
+	0x64b6070d,
+	0x2911f404,
+	0x012ec3e7,
+	0xfd0134b6,
+	0x76bb0553,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb6087621,
+/* 0x0916: i2c_addr_done */
+	0x00f80464,
+/* 0x0918: i2c_acquire_addr */
+	0xb6f8cec7,
+	0xe0b705e4,
+	0x00f8d014,
+/* 0x0924: i2c_acquire */
+	0x091821f5,
+	0xf00421f4,
+	0x21f403d9,
+/* 0x0933: i2c_release */
+	0xf500f833,
+	0xf4091821,
+	0xdaf00421,
+	0x3321f403,
+/* 0x0942: i2c_recv */
+	0x32f400f8,
+	0xf8c1c701,
+	0xb00214b6,
+	0x1ff52816,
+	0x13a0013a,
+	0x32980cf4,
+	0xcc13a000,
+	0x0031980c,
+	0xf90231f4,
+	0xf9e0f9d0,
+	0x0067f1d0,
+	0x0063f100,
+	0x01679210,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x2421f550,
+	0x0464b609,
+	0xd6b0d0fc,
+	0xb31bf500,
+	0x0057f000,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xd121f550,
+	0x0464b608,
+	0x00d011f5,
+	0xbbe0c5c7,
 	0x65b60076,
 	0x9450f904,
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x077421f5,
-	0xb90464b6,
-	0x74bd025b,
-/* 0x0a53: i2c_recv_not_rd08 */
-	0xb0430ef4,
-	0x1bf401d6,
-	0x0057f03d,
-	0x08dc21f5,
-	0xc73311f4,
-	0x21f5e0c5,
-	0x11f40881,
-	0x0057f029,
-	0x08dc21f5,
-	0xc71f11f4,
-	0x21f5e0b5,
-	0x11f40881,
-	0x7421f515,
-	0xc774bd07,
-	0x1bf408c5,
-	0x0232f409,
-/* 0x0a93: i2c_recv_not_wr08 */
-/* 0x0a93: i2c_recv_done */
-	0xc7030ef4,
-	0x21f5f8ce,
-	0xe0fc093e,
-	0x12f4d0fc,
-	0x027cb90a,
-	0x02f121f5,
-/* 0x0aa8: i2c_recv_exit */
-/* 0x0aaa: i2c_init */
-	0x00f800f8,
-/* 0x0aac: test_recv */
-	0x05d817f1,
-	0xb60011cf,
-	0x07f10110,
-	0x01d005d8,
-	0xf104bd00,
-	0xf1d900e7,
-	0xf5134fe3,
-	0xf8022321,
-/* 0x0acd: test_init */
-	0x00e7f100,
-	0x2321f508,
-/* 0x0ad7: idle_recv */
+	0x087621f5,
+	0xf50464b6,
+	0xf000ad11,
+	0x76bb0157,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb608d121,
+	0x11f50464,
+	0x76bb008a,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb6082421,
+	0x11f40464,
+	0xe05bcb6a,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x6921f550,
+	0x0464b607,
+	0xbd025bb9,
+	0x430ef474,
+/* 0x0a48: i2c_recv_not_rd08 */
+	0xf401d6b0,
+	0x57f03d1b,
+	0xd121f500,
+	0x3311f408,
+	0xf5e0c5c7,
+	0xf4087621,
+	0x57f02911,
+	0xd121f500,
+	0x1f11f408,
+	0xf5e0b5c7,
+	0xf4087621,
+	0x21f51511,
+	0x74bd0769,
+	0xf408c5c7,
+	0x32f4091b,
+	0x030ef402,
+/* 0x0a88: i2c_recv_not_wr08 */
+/* 0x0a88: i2c_recv_done */
+	0xf5f8cec7,
+	0xfc093321,
+	0xf4d0fce0,
+	0x7cb90a12,
+	0xe621f502,
+/* 0x0a9d: i2c_recv_exit */
+/* 0x0a9f: i2c_init */
 	0xf800f802,
-/* 0x0ad9: idle */
-	0x0031f400,
-	0x05d417f1,
-	0xb60011cf,
-	0x07f10110,
-	0x01d005d4,
-/* 0x0aef: idle_loop */
-	0xf004bd00,
-	0x32f45817,
-/* 0x0af5: idle_proc */
-/* 0x0af5: idle_proc_exec */
-	0xb910f902,
-	0x21f5021e,
-	0x10fc02fa,
-	0xf40911f4,
-	0x0ef40231,
-/* 0x0b09: idle_proc_next */
-	0x5810b6ef,
-	0xf4061fb8,
-	0x02f4e61b,
-	0x0028f4dd,
-	0x00c10ef4,
+/* 0x0aa1: test_recv */
+	0xd817f100,
+	0x0011cf05,
+	0xf10110b6,
+	0xd005d807,
+	0x04bd0001,
+	0xd900e7f1,
+	0x134fe3f1,
+	0x021821f5,
+/* 0x0ac2: test_init */
+	0xe7f100f8,
+	0x21f50800,
+	0x00f80218,
+/* 0x0acc: idle_recv */
+/* 0x0ace: idle */
+	0x31f400f8,
+	0xd417f100,
+	0x0011cf05,
+	0xf10110b6,
+	0xd005d407,
+	0x04bd0001,
+/* 0x0ae4: idle_loop */
+	0xf45817f0,
+/* 0x0aea: idle_proc */
+/* 0x0aea: idle_proc_exec */
+	0x10f90232,
+	0xf5021eb9,
+	0xfc02ef21,
+	0x0911f410,
+	0xf40231f4,
+/* 0x0afe: idle_proc_next */
+	0x10b6ef0e,
+	0x061fb858,
+	0xf4e61bf4,
+	0x28f4dd02,
+	0xc10ef400,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h
index fe4f63d..8a2b628 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h
@@ -24,8 +24,8 @@
 	0x00000000,
 /* 0x0058: proc_list_head */
 	0x54534f48,
-	0x00000453,
-	0x00000404,
+	0x00000447,
+	0x000003f8,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -46,8 +46,8 @@
 	0x00000000,
 	0x00000000,
 	0x584d454d,
-	0x0000062d,
-	0x0000061f,
+	0x00000621,
+	0x00000613,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -68,8 +68,8 @@
 	0x00000000,
 	0x00000000,
 	0x46524550,
-	0x00000631,
-	0x0000062f,
+	0x00000625,
+	0x00000623,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -90,8 +90,8 @@
 	0x00000000,
 	0x00000000,
 	0x5f433249,
-	0x00000a35,
-	0x000008dc,
+	0x00000a29,
+	0x000008d0,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -112,8 +112,8 @@
 	0x00000000,
 	0x00000000,
 	0x54534554,
-	0x00000a56,
-	0x00000a37,
+	0x00000a4a,
+	0x00000a2b,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -134,8 +134,8 @@
 	0x00000000,
 	0x00000000,
 	0x454c4449,
-	0x00000a61,
-	0x00000a5f,
+	0x00000a55,
+	0x00000a53,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -229,26 +229,26 @@
 /* 0x0370: memx_func_head */
 	0x00000001,
 	0x00000000,
-	0x00000483,
+	0x00000477,
 /* 0x037c: memx_func_next */
 	0x00000002,
 	0x00000000,
-	0x00000500,
+	0x000004f4,
 	0x00000003,
 	0x00000002,
-	0x00000580,
+	0x00000574,
 	0x00040004,
 	0x00000000,
-	0x0000059d,
+	0x00000591,
 	0x00010005,
 	0x00000000,
-	0x000005b7,
+	0x000005ab,
 	0x00010006,
 	0x00000000,
-	0x0000057b,
+	0x0000056f,
 	0x00000007,
 	0x00000000,
-	0x000005c3,
+	0x000005b7,
 /* 0x03c4: memx_func_tail */
 /* 0x03c4: memx_ts_start */
 	0x00000000,
@@ -916,7 +916,7 @@
 };
 
 uint32_t gk208_pmu_code[] = {
-	0x031c0ef5,
+	0x03100ef5,
 /* 0x0004: rd32 */
 	0xf607a040,
 	0x04bd000e,
@@ -972,7 +972,7 @@
 	0x0a98280b,
 	0x029abb9a,
 	0x0d0e1cf4,
-	0x02617e01,
+	0x02557e01,
 	0xf494bd00,
 /* 0x00c2: intr_watchdog_next_time */
 	0x0a98140e,
@@ -1017,21 +1017,16 @@
 	0xc0f900cc,
 	0xf14f484e,
 	0x0d5453e3,
-	0x02c27e00,
+	0x02b67e00,
 	0x40c0fc00,
 	0x0cf604c0,
 /* 0x0167: intr_subintr_skip_fifo */
 	0x4004bd00,
 	0x09f60688,
 /* 0x016f: intr_skip_subintr */
-	0xc404bd00,
-	0x0bf42089,
-	0xbfa4f107,
-/* 0x0179: intr_skip_pause */
-	0x4089c4ff,
-	0xf1070bf4,
-/* 0x0183: intr_skip_user0 */
-	0x00ffbfa4,
+	0x4904bd00,
+	0x90bd00e0,
+	0x000489fd,
 	0x0008f604,
 	0x80fc04bd,
 	0xfc0088fe,
@@ -1040,35 +1035,35 @@
 	0xfca0fcb0,
 	0xfc80fc90,
 	0x0032f400,
-/* 0x01a6: ticks_from_ns */
+/* 0x019a: ticks_from_ns */
 	0xc0f901f8,
 	0xd7f1b0f9,
 	0xd3f00144,
-	0x7721f500,
+	0x6b21f500,
 	0xe8ccec03,
 	0x00b4b003,
 	0xec120bf4,
 	0xf103e8ee,
 	0xf00144d7,
 	0x21f500d3,
-/* 0x01ce: ticks_from_ns_quit */
-	0xceb20377,
+/* 0x01c2: ticks_from_ns_quit */
+	0xceb2036b,
 	0xc0fcb0fc,
-/* 0x01d6: ticks_from_us */
+/* 0x01ca: ticks_from_us */
 	0xc0f900f8,
 	0xd7f1b0f9,
 	0xd3f00144,
-	0x7721f500,
+	0x6b21f500,
 	0xb0ceb203,
 	0x0bf400b4,
-/* 0x01ef: ticks_from_us_quit */
+/* 0x01e3: ticks_from_us_quit */
 	0xfce4bd05,
 	0xf8c0fcb0,
-/* 0x01f5: ticks_to_us */
+/* 0x01e9: ticks_to_us */
 	0x44d7f100,
 	0x00d3f001,
 	0xf8ecedff,
-/* 0x0201: timer */
+/* 0x01f5: timer */
 	0xf990f900,
 	0x1032f480,
 	0xb003f898,
@@ -1086,17 +1081,17 @@
 	0xa60088cf,
 	0x080bf4e0,
 	0x1cf4e8a6,
-/* 0x0245: timer_reset */
+/* 0x0239: timer_reset */
 	0xf634000d,
 	0x04bd000e,
-/* 0x024f: timer_enable */
+/* 0x0243: timer_enable */
 	0x089a0eb5,
 	0xf6380001,
 	0x04bd0008,
-/* 0x0258: timer_done */
+/* 0x024c: timer_done */
 	0xfc1031f4,
 	0xf890fc80,
-/* 0x0261: send_proc */
+/* 0x0255: send_proc */
 	0xf980f900,
 	0x05e89890,
 	0xf004e998,
@@ -1111,24 +1106,24 @@
 	0x90b6038b,
 	0x0794f001,
 	0xf404e9b5,
-/* 0x029a: send_done */
+/* 0x028e: send_done */
 	0x90fc0231,
 	0x00f880fc,
-/* 0x02a0: find */
+/* 0x0294: find */
 	0x580880f9,
-/* 0x02a7: find_loop */
+/* 0x029b: find_loop */
 	0x980131f4,
 	0xaea6008a,
 	0xb6100bf4,
 	0x86b15880,
 	0x1bf40268,
 	0x0132f4f1,
-/* 0x02bc: find_done */
+/* 0x02b0: find_done */
 	0x80fc8eb2,
-/* 0x02c2: send */
-	0xa07e00f8,
+/* 0x02b6: send */
+	0x947e00f8,
 	0x01f40002,
-/* 0x02cb: recv */
+/* 0x02bf: recv */
 	0xf900f89b,
 	0x9880f990,
 	0xe99805e8,
@@ -1148,10 +1143,10 @@
 	0xa5f900ee,
 	0xf8fef0fc,
 	0x0131f400,
-/* 0x0316: recv_done */
+/* 0x030a: recv_done */
 	0x80fcf0fc,
 	0x00f890fc,
-/* 0x031c: init */
+/* 0x0310: init */
 	0xcf010841,
 	0x11e70011,
 	0x14b60109,
@@ -1170,12 +1165,12 @@
 	0x011031f4,
 	0xf6380001,
 	0x04bd0001,
-/* 0x0366: init_proc */
+/* 0x035a: init_proc */
 	0xf198580f,
 	0x0016b001,
 	0xf9fa0bf4,
 	0x58f0b615,
-/* 0x0377: mulu32_32_64 */
+/* 0x036b: mulu32_32_64 */
 	0xf9f20ef4,
 	0xf920f910,
 	0x9540f930,
@@ -1196,7 +1191,7 @@
 	0x00b3bb30,
 	0x30fc40fc,
 	0x10fc20fc,
-/* 0x03c6: host_send */
+/* 0x03ba: host_send */
 	0xb04100f8,
 	0x0011cf04,
 	0xcf04a042,
@@ -1207,18 +1202,18 @@
 	0x03eb9802,
 	0x9802ec98,
 	0xee9801ed,
-	0x02c27e00,
+	0x02b67e00,
 	0x0110b600,
 	0x400f1ec4,
 	0x0ef604b0,
 	0xf404bd00,
-/* 0x0402: host_send_done */
+/* 0x03f6: host_send_done */
 	0x00f8c70e,
-/* 0x0404: host_recv */
+/* 0x03f8: host_recv */
 	0xf14e4941,
 	0xa6525413,
 	0xb90bf4e1,
-/* 0x0410: host_recv_wait */
+/* 0x0404: host_recv_wait */
 	0xcf04cc41,
 	0xc8420011,
 	0x0022cf04,
@@ -1235,7 +1230,7 @@
 	0x04bd0002,
 	0x00004002,
 	0xbd0002f6,
-/* 0x0453: host_init */
+/* 0x0447: host_init */
 	0x4100f804,
 	0x14b60080,
 	0x7015f110,
@@ -1248,7 +1243,7 @@
 	0x0104bd00,
 	0x04c44001,
 	0xbd0001f6,
-/* 0x0483: memx_func_enter */
+/* 0x0477: memx_func_enter */
 	0xf100f804,
 	0xf1162067,
 	0xf1f55d77,
@@ -1275,19 +1270,19 @@
 	0x00002e7e,
 	0xe0400406,
 	0x0006f607,
-/* 0x04ea: memx_func_enter_wait */
+/* 0x04de: memx_func_enter_wait */
 	0xc04604bd,
 	0x0066cf07,
 	0xf40464f0,
 	0x2c06f70b,
 	0xb50066cf,
 	0x00f8f106,
-/* 0x0500: memx_func_leave */
+/* 0x04f4: memx_func_leave */
 	0x66cf2c06,
 	0xf206b500,
 	0xe4400406,
 	0x0006f607,
-/* 0x0512: memx_func_leave_wait */
+/* 0x0506: memx_func_leave_wait */
 	0xc04604bd,
 	0x0066cf07,
 	0xf40464f0,
@@ -1314,10 +1309,10 @@
 	0xf960f905,
 	0xfcd0fc80,
 	0x002e7ee0,
-/* 0x057b: memx_func_wait_vblank */
+/* 0x056f: memx_func_wait_vblank */
 	0xb600f800,
 	0x00f80410,
-/* 0x0580: memx_func_wr32 */
+/* 0x0574: memx_func_wr32 */
 	0x98001698,
 	0x10b60115,
 	0xf960f908,
@@ -1325,23 +1320,23 @@
 	0x002e7ee0,
 	0x0242b600,
 	0xf8e81bf4,
-/* 0x059d: memx_func_wait */
+/* 0x0591: memx_func_wait */
 	0xcf2c0800,
 	0x1e980088,
 	0x011d9800,
 	0x98021c98,
 	0x10b6031b,
 	0x00797e10,
-/* 0x05b7: memx_func_delay */
+/* 0x05ab: memx_func_delay */
 	0x9800f800,
 	0x10b6001e,
 	0x005d7e04,
-/* 0x05c3: memx_func_train */
+/* 0x05b7: memx_func_train */
 	0xf800f800,
-/* 0x05c5: memx_exec */
+/* 0x05b9: memx_exec */
 	0xf9e0f900,
 	0xb2c1b2d0,
-/* 0x05cd: memx_exec_next */
+/* 0x05c1: memx_exec_next */
 	0x001398b2,
 	0xe70410b6,
 	0xe701f034,
@@ -1354,111 +1349,111 @@
 	0x02cbbbf2,
 	0xcf07c44b,
 	0xd0fc00bb,
-	0xc27ee0fc,
+	0xb67ee0fc,
 	0x00f80002,
-/* 0x0604: memx_info */
+/* 0x05f8: memx_info */
 	0xf401c670,
-/* 0x060a: memx_info_data */
+/* 0x05fe: memx_info_data */
 	0xcc4c0c0b,
 	0x08004b03,
-/* 0x0613: memx_info_train */
+/* 0x0607: memx_info_train */
 	0x4c090ef4,
 	0x004b0bcc,
-/* 0x0619: memx_info_send */
-	0x02c27e01,
-/* 0x061f: memx_recv */
+/* 0x060d: memx_info_send */
+	0x02b67e01,
+/* 0x0613: memx_recv */
 	0xb000f800,
 	0x0bf401d6,
 	0x00d6b0a3,
 	0xf8dc0bf4,
-/* 0x062d: memx_init */
-/* 0x062f: perf_recv */
+/* 0x0621: memx_init */
+/* 0x0623: perf_recv */
 	0xf800f800,
-/* 0x0631: perf_init */
-/* 0x0633: i2c_drive_scl */
+/* 0x0625: perf_init */
+/* 0x0627: i2c_drive_scl */
 	0xb000f800,
 	0x0bf40036,
 	0x07e0400d,
 	0xbd0001f6,
-/* 0x0643: i2c_drive_scl_lo */
+/* 0x0637: i2c_drive_scl_lo */
 	0x4000f804,
 	0x01f607e4,
 	0xf804bd00,
-/* 0x064d: i2c_drive_sda */
+/* 0x0641: i2c_drive_sda */
 	0x0036b000,
 	0x400d0bf4,
 	0x02f607e0,
 	0xf804bd00,
-/* 0x065d: i2c_drive_sda_lo */
+/* 0x0651: i2c_drive_sda_lo */
 	0x07e44000,
 	0xbd0002f6,
-/* 0x0667: i2c_sense_scl */
+/* 0x065b: i2c_sense_scl */
 	0xf400f804,
 	0xc4430132,
 	0x0033cf07,
 	0xf40431fd,
 	0x31f4060b,
-/* 0x0679: i2c_sense_scl_done */
-/* 0x067b: i2c_sense_sda */
+/* 0x066d: i2c_sense_scl_done */
+/* 0x066f: i2c_sense_sda */
 	0xf400f801,
 	0xc4430132,
 	0x0033cf07,
 	0xf40432fd,
 	0x31f4060b,
-/* 0x068d: i2c_sense_sda_done */
-/* 0x068f: i2c_raise_scl */
+/* 0x0681: i2c_sense_sda_done */
+/* 0x0683: i2c_raise_scl */
 	0xf900f801,
 	0x08984440,
-	0x337e0103,
-/* 0x069a: i2c_raise_scl_wait */
+	0x277e0103,
+/* 0x068e: i2c_raise_scl_wait */
 	0xe84e0006,
 	0x005d7e03,
-	0x06677e00,
+	0x065b7e00,
 	0x0901f400,
 	0xf40142b6,
-/* 0x06ae: i2c_raise_scl_done */
+/* 0x06a2: i2c_raise_scl_done */
 	0x40fcef1b,
-/* 0x06b2: i2c_start */
-	0x677e00f8,
+/* 0x06a6: i2c_start */
+	0x5b7e00f8,
 	0x11f40006,
-	0x067b7e0d,
+	0x066f7e0d,
 	0x0611f400,
-/* 0x06c3: i2c_start_rep */
+/* 0x06b7: i2c_start_rep */
 	0x032e0ef4,
-	0x06337e00,
+	0x06277e00,
 	0x7e010300,
-	0xbb00064d,
+	0xbb000641,
 	0x65b60076,
 	0x9450f904,
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x00068f7e,
+	0x0006837e,
 	0xf40464b6,
-/* 0x06ee: i2c_start_send */
+/* 0x06e2: i2c_start_send */
 	0x00031d11,
-	0x00064d7e,
+	0x0006417e,
 	0x7e13884e,
 	0x0300005d,
-	0x06337e00,
+	0x06277e00,
 	0x13884e00,
 	0x00005d7e,
-/* 0x0708: i2c_start_out */
-/* 0x070a: i2c_stop */
+/* 0x06fc: i2c_start_out */
+/* 0x06fe: i2c_stop */
 	0x000300f8,
-	0x0006337e,
-	0x4d7e0003,
+	0x0006277e,
+	0x417e0003,
 	0xe84e0006,
 	0x005d7e03,
 	0x7e010300,
-	0x4e000633,
+	0x4e000627,
 	0x5d7e1388,
 	0x01030000,
-	0x00064d7e,
+	0x0006417e,
 	0x7e13884e,
 	0xf800005d,
-/* 0x0739: i2c_bitw */
-	0x064d7e00,
+/* 0x072d: i2c_bitw */
+	0x06417e00,
 	0x03e84e00,
 	0x00005d7e,
 	0xb60076bb,
@@ -1466,18 +1461,18 @@
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x068f7e50,
+	0x06837e50,
 	0x0464b600,
 	0x4e1711f4,
 	0x5d7e1388,
 	0x00030000,
-	0x0006337e,
+	0x0006277e,
 	0x7e13884e,
-/* 0x0777: i2c_bitw_out */
+/* 0x076b: i2c_bitw_out */
 	0xf800005d,
-/* 0x0779: i2c_bitr */
+/* 0x076d: i2c_bitr */
 	0x7e010300,
-	0x4e00064d,
+	0x4e000641,
 	0x5d7e03e8,
 	0x76bb0000,
 	0x0465b600,
@@ -1485,25 +1480,25 @@
 	0x0256bb04,
 	0x75fd50bd,
 	0x7e50fc04,
-	0xb600068f,
+	0xb6000683,
 	0x11f40464,
-	0x067b7e1a,
+	0x066f7e1a,
 	0x7e000300,
-	0x4e000633,
+	0x4e000627,
 	0x5d7e1388,
 	0x3cf00000,
 	0x0131f401,
-/* 0x07bc: i2c_bitr_done */
-/* 0x07be: i2c_get_byte */
+/* 0x07b0: i2c_bitr_done */
+/* 0x07b2: i2c_get_byte */
 	0x000500f8,
-/* 0x07c2: i2c_get_byte_next */
+/* 0x07b6: i2c_get_byte_next */
 	0x54b60804,
 	0x0076bb01,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
-	0x797e50fc,
+	0x6d7e50fc,
 	0x64b60007,
 	0x2a11f404,
 	0xb60553fd,
@@ -1514,11 +1509,11 @@
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x0007397e,
-/* 0x080b: i2c_get_byte_done */
+	0x00072d7e,
+/* 0x07ff: i2c_get_byte_done */
 	0xf80464b6,
-/* 0x080d: i2c_put_byte */
-/* 0x080f: i2c_put_byte_next */
+/* 0x0801: i2c_put_byte */
+/* 0x0803: i2c_put_byte_next */
 	0xb6080400,
 	0x54ff0142,
 	0x0076bb38,
@@ -1526,7 +1521,7 @@
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
-	0x397e50fc,
+	0x2d7e50fc,
 	0x64b60007,
 	0x3411f404,
 	0xf40046b0,
@@ -1536,20 +1531,20 @@
 	0x0256bb04,
 	0x75fd50bd,
 	0x7e50fc04,
-	0xb6000779,
+	0xb600076d,
 	0x11f40464,
 	0x0076bb0f,
 	0xf40136b0,
 	0x32f4061b,
-/* 0x0865: i2c_put_byte_done */
-/* 0x0867: i2c_addr */
+/* 0x0859: i2c_put_byte_done */
+/* 0x085b: i2c_addr */
 	0xbb00f801,
 	0x65b60076,
 	0x9450f904,
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x0006b27e,
+	0x0006a67e,
 	0xf40464b6,
 	0xc3e72911,
 	0x34b6012e,
@@ -1559,25 +1554,25 @@
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x080d7e50,
+	0x08017e50,
 	0x0464b600,
-/* 0x08ac: i2c_addr_done */
-/* 0x08ae: i2c_acquire_addr */
+/* 0x08a0: i2c_addr_done */
+/* 0x08a2: i2c_acquire_addr */
 	0xcec700f8,
 	0x05e4b6f8,
 	0xd014e0b7,
-/* 0x08ba: i2c_acquire */
-	0xae7e00f8,
+/* 0x08ae: i2c_acquire */
+	0xa27e00f8,
 	0x047e0008,
 	0xd9f00000,
 	0x002e7e03,
-/* 0x08cb: i2c_release */
+/* 0x08bf: i2c_release */
 	0x7e00f800,
-	0x7e0008ae,
+	0x7e0008a2,
 	0xf0000004,
 	0x2e7e03da,
 	0x00f80000,
-/* 0x08dc: i2c_recv */
+/* 0x08d0: i2c_recv */
 	0xc70132f4,
 	0x14b6f8c1,
 	0x2816b002,
@@ -1596,7 +1591,7 @@
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x08ba7e50,
+	0x08ae7e50,
 	0x0464b600,
 	0xd6b0d0fc,
 	0xb01bf500,
@@ -1606,7 +1601,7 @@
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x0008677e,
+	0x00085b7e,
 	0xf50464b6,
 	0xc700cc11,
 	0x76bbe0c5,
@@ -1615,7 +1610,7 @@
 	0x0256bb04,
 	0x75fd50bd,
 	0x7e50fc04,
-	0xb600080d,
+	0xb6000801,
 	0x11f50464,
 	0x010500a9,
 	0xb60076bb,
@@ -1623,7 +1618,7 @@
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x08677e50,
+	0x085b7e50,
 	0x0464b600,
 	0x008711f5,
 	0xb60076bb,
@@ -1631,7 +1626,7 @@
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
-	0x07be7e50,
+	0x07b27e50,
 	0x0464b600,
 	0xcb6711f4,
 	0x76bbe05b,
@@ -1640,36 +1635,36 @@
 	0x0256bb04,
 	0x75fd50bd,
 	0x7e50fc04,
-	0xb600070a,
+	0xb60006fe,
 	0x5bb20464,
 	0x0ef474bd,
-/* 0x09e1: i2c_recv_not_rd08 */
+/* 0x09d5: i2c_recv_not_rd08 */
 	0x01d6b041,
 	0x053b1bf4,
-	0x08677e00,
+	0x085b7e00,
 	0x3211f400,
 	0x7ee0c5c7,
-	0xf400080d,
+	0xf4000801,
 	0x00052811,
-	0x0008677e,
+	0x00085b7e,
 	0xc71f11f4,
-	0x0d7ee0b5,
+	0x017ee0b5,
 	0x11f40008,
-	0x070a7e15,
+	0x06fe7e15,
 	0xc774bd00,
 	0x1bf408c5,
 	0x0232f409,
-/* 0x0a1f: i2c_recv_not_wr08 */
-/* 0x0a1f: i2c_recv_done */
+/* 0x0a13: i2c_recv_not_wr08 */
+/* 0x0a13: i2c_recv_done */
 	0xc7030ef4,
-	0xcb7ef8ce,
+	0xbf7ef8ce,
 	0xe0fc0008,
 	0x12f4d0fc,
 	0x7e7cb209,
-/* 0x0a33: i2c_recv_exit */
-	0xf80002c2,
-/* 0x0a35: i2c_init */
-/* 0x0a37: test_recv */
+/* 0x0a27: i2c_recv_exit */
+	0xf80002b6,
+/* 0x0a29: i2c_init */
+/* 0x0a2b: test_recv */
 	0x4100f800,
 	0x11cf0458,
 	0x0110b600,
@@ -1677,28 +1672,28 @@
 	0x04bd0001,
 	0xd900e7f1,
 	0x134fe3f1,
-	0x0002017e,
-/* 0x0a56: test_init */
+	0x0001f57e,
+/* 0x0a4a: test_init */
 	0x004e00f8,
-	0x02017e08,
-/* 0x0a5f: idle_recv */
+	0x01f57e08,
+/* 0x0a53: idle_recv */
 	0xf800f800,
-/* 0x0a61: idle */
+/* 0x0a55: idle */
 	0x0031f400,
 	0xcf045441,
 	0x10b60011,
 	0x04544001,
 	0xbd0001f6,
-/* 0x0a75: idle_loop */
+/* 0x0a69: idle_loop */
 	0xf4580104,
-/* 0x0a7a: idle_proc */
-/* 0x0a7a: idle_proc_exec */
+/* 0x0a6e: idle_proc */
+/* 0x0a6e: idle_proc_exec */
 	0x10f90232,
-	0xcb7e1eb2,
+	0xbf7e1eb2,
 	0x10fc0002,
 	0xf40911f4,
 	0x0ef40231,
-/* 0x0a8d: idle_proc_next */
+/* 0x0a81: idle_proc_next */
 	0x5810b6f0,
 	0x1bf41fa6,
 	0xe002f4e8,
@@ -1728,4 +1723,7 @@
 	0x00000000,
 	0x00000000,
 	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 };
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h
index 2686f8f..5165692 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h
@@ -24,8 +24,8 @@
 	0x00000000,
 /* 0x0058: proc_list_head */
 	0x54534f48,
-	0x00000512,
-	0x000004af,
+	0x00000507,
+	0x000004a4,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -46,8 +46,8 @@
 	0x00000000,
 	0x00000000,
 	0x584d454d,
-	0x00000842,
-	0x00000834,
+	0x00000837,
+	0x00000829,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -68,8 +68,8 @@
 	0x00000000,
 	0x00000000,
 	0x46524550,
-	0x00000846,
-	0x00000844,
+	0x0000083b,
+	0x00000839,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -90,8 +90,8 @@
 	0x00000000,
 	0x00000000,
 	0x5f433249,
-	0x00000c76,
-	0x00000b19,
+	0x00000c6b,
+	0x00000b0e,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -112,8 +112,8 @@
 	0x00000000,
 	0x00000000,
 	0x54534554,
-	0x00000c9f,
-	0x00000c78,
+	0x00000c94,
+	0x00000c6d,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -134,8 +134,8 @@
 	0x00000000,
 	0x00000000,
 	0x454c4449,
-	0x00000cab,
-	0x00000ca9,
+	0x00000ca0,
+	0x00000c9e,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -229,26 +229,26 @@
 /* 0x0370: memx_func_head */
 	0x00000001,
 	0x00000000,
-	0x00000551,
+	0x00000546,
 /* 0x037c: memx_func_next */
 	0x00000002,
 	0x00000000,
-	0x000005a8,
+	0x0000059d,
 	0x00000003,
 	0x00000002,
-	0x0000063a,
+	0x0000062f,
 	0x00040004,
 	0x00000000,
-	0x00000656,
+	0x0000064b,
 	0x00010005,
 	0x00000000,
-	0x00000673,
+	0x00000668,
 	0x00010006,
 	0x00000000,
-	0x000005f8,
+	0x000005ed,
 	0x00000007,
 	0x00000000,
-	0x0000067e,
+	0x00000673,
 /* 0x03c4: memx_func_tail */
 /* 0x03c4: memx_ts_start */
 	0x00000000,
@@ -917,7 +917,7 @@
 };
 
 uint32_t gt215_pmu_code[] = {
-	0x039e0ef5,
+	0x03930ef5,
 /* 0x0004: rd32 */
 	0x07a007f1,
 	0xd00604b6,
@@ -987,7 +987,7 @@
 	0xbb9a0a98,
 	0x1cf4029a,
 	0x01d7f00f,
-	0x02dd21f5,
+	0x02d221f5,
 	0x0ef494bd,
 /* 0x00f9: intr_watchdog_next_time */
 	0x9b0a9815,
@@ -1039,7 +1039,7 @@
 	0x48e7f1c0,
 	0x53e3f14f,
 	0x00d7f054,
-	0x034221f5,
+	0x033721f5,
 	0x07f1c0fc,
 	0x04b604c0,
 	0x000cd006,
@@ -1048,820 +1048,818 @@
 	0x04b60688,
 	0x0009d006,
 /* 0x01ca: intr_skip_subintr */
-	0x89c404bd,
-	0x070bf420,
-	0xffbfa4f1,
-/* 0x01d4: intr_skip_pause */
-	0xf44089c4,
-	0xa4f1070b,
-/* 0x01de: intr_skip_user0 */
-	0x07f0ffbf,
-	0x0604b604,
-	0xbd0008d0,
-	0xfe80fc04,
-	0xf0fc0088,
-	0xd0fce0fc,
-	0xb0fcc0fc,
-	0x90fca0fc,
-	0x00fc80fc,
-	0xf80032f4,
-/* 0x0205: ticks_from_ns */
-	0xf9c0f901,
-	0xcbd7f1b0,
-	0x00d3f000,
-	0x041321f5,
-	0x03e8ccec,
-	0xf400b4b0,
-	0xeeec120b,
-	0xd7f103e8,
-	0xd3f000cb,
-	0x1321f500,
-/* 0x022d: ticks_from_ns_quit */
-	0x02ceb904,
-	0xc0fcb0fc,
-/* 0x0236: ticks_from_us */
-	0xc0f900f8,
+	0x97f104bd,
+	0x90bd00e0,
+	0xf00489fd,
+	0x04b60407,
+	0x0008d006,
+	0x80fc04bd,
+	0xfc0088fe,
+	0xfce0fcf0,
+	0xfcc0fcd0,
+	0xfca0fcb0,
+	0xfc80fc90,
+	0x0032f400,
+/* 0x01fa: ticks_from_ns */
+	0xc0f901f8,
 	0xd7f1b0f9,
 	0xd3f000cb,
-	0x1321f500,
-	0x02ceb904,
-	0xf400b4b0,
-	0xe4bd050b,
-/* 0x0250: ticks_from_us_quit */
-	0xc0fcb0fc,
-/* 0x0256: ticks_to_us */
-	0xd7f100f8,
-	0xd3f000cb,
-	0xecedff00,
-/* 0x0262: timer */
-	0x90f900f8,
-	0x32f480f9,
-	0x03f89810,
-	0xf40086b0,
-	0x84bd651c,
-	0xb63807f0,
-	0x08d00604,
-	0xf004bd00,
-	0x84b63487,
-	0x0088cf06,
-	0xbb9a0998,
-	0xe9bb0298,
-	0x03fe8000,
-	0xb60887f0,
-	0x88cf0684,
-	0x0284f000,
-	0xf0261bf4,
-	0x84b63487,
-	0x0088cf06,
-	0xf406e0b8,
-	0xe8b8090b,
-	0x111cf406,
-/* 0x02b8: timer_reset */
-	0xb63407f0,
-	0x0ed00604,
-	0x8004bd00,
-/* 0x02c6: timer_enable */
-	0x87f09a0e,
-	0x3807f001,
+	0x0821f500,
+	0xe8ccec04,
+	0x00b4b003,
+	0xec120bf4,
+	0xf103e8ee,
+	0xf000cbd7,
+	0x21f500d3,
+/* 0x0222: ticks_from_ns_quit */
+	0xceb90408,
+	0xfcb0fc02,
+/* 0x022b: ticks_from_us */
+	0xf900f8c0,
+	0xf1b0f9c0,
+	0xf000cbd7,
+	0x21f500d3,
+	0xceb90408,
+	0x00b4b002,
+	0xbd050bf4,
+/* 0x0245: ticks_from_us_quit */
+	0xfcb0fce4,
+/* 0x024b: ticks_to_us */
+	0xf100f8c0,
+	0xf000cbd7,
+	0xedff00d3,
+/* 0x0257: timer */
+	0xf900f8ec,
+	0xf480f990,
+	0xf8981032,
+	0x0086b003,
+	0xbd651cf4,
+	0x3807f084,
 	0xd00604b6,
 	0x04bd0008,
-/* 0x02d4: timer_done */
-	0xfc1031f4,
-	0xf890fc80,
-/* 0x02dd: send_proc */
-	0xf980f900,
-	0x05e89890,
-	0xf004e998,
-	0x89b80486,
-	0x2a0bf406,
-	0x940398c4,
-	0x80b60488,
-	0x008ebb18,
-	0x8000fa98,
-	0x8d80008a,
-	0x028c8001,
-	0xb6038b80,
-	0x94f00190,
-	0x04e98007,
-/* 0x0317: send_done */
-	0xfc0231f4,
-	0xf880fc90,
-/* 0x031d: find */
-	0xf080f900,
-	0x31f45887,
-/* 0x0325: find_loop */
-	0x008a9801,
-	0xf406aeb8,
-	0x80b6100b,
-	0x6886b158,
-	0xf01bf402,
-/* 0x033b: find_done */
-	0xb90132f4,
-	0x80fc028e,
-/* 0x0342: send */
-	0x21f500f8,
-	0x01f4031d,
-/* 0x034b: recv */
-	0xf900f897,
-	0x9880f990,
-	0xe99805e8,
-	0x0132f404,
-	0xf40689b8,
-	0x89c43d0b,
-	0x0180b603,
-	0x800784f0,
-	0xea9805e8,
-	0xfef0f902,
-	0xf0f9018f,
-	0x9402efb9,
-	0xe9bb0499,
-	0x18e0b600,
-	0x9803eb98,
-	0xed9802ec,
-	0x00ee9801,
-	0xf0fca5f9,
-	0xf400f8fe,
-	0xf0fc0131,
-/* 0x0398: recv_done */
+	0xb63487f0,
+	0x88cf0684,
+	0x9a099800,
+	0xbb0298bb,
+	0xfe8000e9,
+	0x0887f003,
+	0xcf0684b6,
+	0x84f00088,
+	0x261bf402,
+	0xb63487f0,
+	0x88cf0684,
+	0x06e0b800,
+	0xb8090bf4,
+	0x1cf406e8,
+/* 0x02ad: timer_reset */
+	0x3407f011,
+	0xd00604b6,
+	0x04bd000e,
+/* 0x02bb: timer_enable */
+	0xf09a0e80,
+	0x07f00187,
+	0x0604b638,
+	0xbd0008d0,
+/* 0x02c9: timer_done */
+	0x1031f404,
 	0x90fc80fc,
-/* 0x039e: init */
-	0x17f100f8,
-	0x14b60108,
-	0x0011cf06,
-	0x010911e7,
-	0xfe0814b6,
-	0x17f10014,
-	0x13f000e0,
-	0x1c07f000,
-	0xd00604b6,
-	0x04bd0001,
-	0xf0ff17f0,
-	0x04b61407,
-	0x0001d006,
-	0x17f004bd,
-	0x0015f102,
-	0x1007f008,
-	0xd00604b6,
-	0x04bd0001,
-	0x011a17f1,
-	0xfe0013f0,
-	0x31f40010,
-	0x0117f010,
-	0xb63807f0,
+/* 0x02d2: send_proc */
+	0x80f900f8,
+	0xe89890f9,
+	0x04e99805,
+	0xb80486f0,
+	0x0bf40689,
+	0x0398c42a,
+	0xb6048894,
+	0x8ebb1880,
+	0x00fa9800,
+	0x80008a80,
+	0x8c80018d,
+	0x038b8002,
+	0xf00190b6,
+	0xe9800794,
+	0x0231f404,
+/* 0x030c: send_done */
+	0x80fc90fc,
+/* 0x0312: find */
+	0x80f900f8,
+	0xf45887f0,
+/* 0x031a: find_loop */
+	0x8a980131,
+	0x06aeb800,
+	0xb6100bf4,
+	0x86b15880,
+	0x1bf40268,
+	0x0132f4f0,
+/* 0x0330: find_done */
+	0xfc028eb9,
+/* 0x0337: send */
+	0xf500f880,
+	0xf4031221,
+	0x00f89701,
+/* 0x0340: recv */
+	0x80f990f9,
+	0x9805e898,
+	0x32f404e9,
+	0x0689b801,
+	0xc43d0bf4,
+	0x80b60389,
+	0x0784f001,
+	0x9805e880,
+	0xf0f902ea,
+	0xf9018ffe,
+	0x02efb9f0,
+	0xbb049994,
+	0xe0b600e9,
+	0x03eb9818,
+	0x9802ec98,
+	0xee9801ed,
+	0xfca5f900,
+	0x00f8fef0,
+	0xfc0131f4,
+/* 0x038d: recv_done */
+	0xfc80fcf0,
+/* 0x0393: init */
+	0xf100f890,
+	0xb6010817,
+	0x11cf0614,
+	0x0911e700,
+	0x0814b601,
+	0xf10014fe,
+	0xf000e017,
+	0x07f00013,
+	0x0604b61c,
+	0xbd0001d0,
+	0xff17f004,
+	0xb61407f0,
 	0x01d00604,
 	0xf004bd00,
-/* 0x0402: init_proc */
-	0xf19858f7,
-	0x0016b001,
-	0xf9fa0bf4,
-	0x58f0b615,
-/* 0x0413: mulu32_32_64 */
-	0xf9f20ef4,
-	0xf920f910,
-	0x9540f930,
-	0xd29510e1,
-	0xbdc4bd10,
-	0xc0edffb4,
-	0xb9301dff,
-	0x34f10234,
-	0x34b6ffff,
-	0x1045b610,
-	0xbb00c3bb,
-	0xe2ff01b4,
-	0x0234b930,
-	0xffff34f1,
-	0xb61034b6,
-	0xc3bb1045,
-	0x01b4bb00,
-	0xbb3012ff,
-	0x40fc00b3,
-	0x20fc30fc,
-	0x00f810fc,
-/* 0x0464: host_send */
-	0x04b017f1,
-	0xcf0614b6,
-	0x27f10011,
-	0x24b604a0,
-	0x0022cf06,
-	0xf40612b8,
-	0x1ec4320b,
-	0x04ee9407,
-	0x0270e0b7,
-	0x9803eb98,
-	0xed9802ec,
-	0x00ee9801,
-	0x034221f5,
-	0xc40110b6,
-	0x07f10f1e,
-	0x04b604b0,
-	0x000ed006,
-	0x0ef404bd,
-/* 0x04ad: host_send_done */
-/* 0x04af: host_recv */
-	0xf100f8ba,
-	0xf14e4917,
-	0xb8525413,
-	0x0bf406e1,
-/* 0x04bd: host_recv_wait */
-	0xcc17f1aa,
-	0x0614b604,
-	0xf10011cf,
-	0xb604c827,
-	0x22cf0624,
-	0x0816f000,
-	0xf40612b8,
-	0x23c4e60b,
-	0x0434b607,
-	0x02f030b7,
-	0x80033b80,
-	0x3d80023c,
-	0x003e8001,
-	0xf00120b6,
-	0x07f10f24,
-	0x04b604c8,
-	0x0002d006,
-	0x27f004bd,
-	0x0007f040,
-	0xd00604b6,
-	0x04bd0002,
-/* 0x0512: host_init */
-	0x17f100f8,
-	0x14b60080,
-	0x7015f110,
-	0xd007f102,
-	0x0604b604,
+	0x15f10217,
+	0x07f00800,
+	0x0604b610,
 	0xbd0001d0,
-	0x8017f104,
-	0x1014b600,
-	0x02f015f1,
-	0x04dc07f1,
+	0x1a17f104,
+	0x0013f001,
+	0xf40010fe,
+	0x17f01031,
+	0x3807f001,
 	0xd00604b6,
 	0x04bd0001,
-	0xf10117f0,
-	0xb604c407,
-	0x01d00604,
-	0xf804bd00,
-/* 0x0551: memx_func_enter */
-	0x1087f100,
-	0x028eb916,
-	0xb90421f4,
-	0x67f102d7,
-	0x63f1fffc,
-	0x76fdffff,
-	0x0267f104,
-	0x0576fd00,
-	0x70f980f9,
-	0xe0fcd0fc,
-	0xf03f21f4,
-	0x07f10467,
-	0x04b607e0,
-	0x0006d006,
-/* 0x058a: memx_func_enter_wait */
-	0x67f104bd,
-	0x64b607c0,
-	0x0066cf06,
-	0xf40464f0,
-	0x67f0f30b,
-	0x0664b62c,
-	0x800066cf,
-	0x00f8f106,
-/* 0x05a8: memx_func_leave */
-	0xb62c67f0,
-	0x66cf0664,
-	0xf2068000,
+/* 0x03f7: init_proc */
+	0x9858f7f0,
+	0x16b001f1,
+	0xfa0bf400,
+	0xf0b615f9,
+	0xf20ef458,
+/* 0x0408: mulu32_32_64 */
+	0x20f910f9,
+	0x40f930f9,
+	0x9510e195,
+	0xc4bd10d2,
+	0xedffb4bd,
+	0x301dffc0,
+	0xf10234b9,
+	0xb6ffff34,
+	0x45b61034,
+	0x00c3bb10,
+	0xff01b4bb,
+	0x34b930e2,
+	0xff34f102,
+	0x1034b6ff,
+	0xbb1045b6,
+	0xb4bb00c3,
+	0x3012ff01,
+	0xfc00b3bb,
+	0xfc30fc40,
+	0xf810fc20,
+/* 0x0459: host_send */
+	0xb017f100,
+	0x0614b604,
+	0xf10011cf,
+	0xb604a027,
+	0x22cf0624,
+	0x0612b800,
+	0xc4320bf4,
+	0xee94071e,
+	0x70e0b704,
+	0x03eb9802,
+	0x9802ec98,
+	0xee9801ed,
+	0x3721f500,
+	0x0110b603,
+	0xf10f1ec4,
+	0xb604b007,
+	0x0ed00604,
+	0xf404bd00,
+/* 0x04a2: host_send_done */
+	0x00f8ba0e,
+/* 0x04a4: host_recv */
+	0x4e4917f1,
+	0x525413f1,
+	0xf406e1b8,
+/* 0x04b2: host_recv_wait */
+	0x17f1aa0b,
+	0x14b604cc,
+	0x0011cf06,
+	0x04c827f1,
+	0xcf0624b6,
+	0x16f00022,
+	0x0612b808,
+	0xc4e60bf4,
+	0x34b60723,
+	0xf030b704,
+	0x033b8002,
+	0x80023c80,
+	0x3e80013d,
+	0x0120b600,
+	0xf10f24f0,
+	0xb604c807,
+	0x02d00604,
+	0xf004bd00,
+	0x07f04027,
+	0x0604b600,
+	0xbd0002d0,
+/* 0x0507: host_init */
+	0xf100f804,
+	0xb6008017,
+	0x15f11014,
+	0x07f10270,
+	0x04b604d0,
+	0x0001d006,
+	0x17f104bd,
+	0x14b60080,
+	0xf015f110,
+	0xdc07f102,
+	0x0604b604,
+	0xbd0001d0,
+	0x0117f004,
+	0x04c407f1,
+	0xd00604b6,
+	0x04bd0001,
+/* 0x0546: memx_func_enter */
+	0x87f100f8,
+	0x8eb91610,
+	0x0421f402,
+	0xf102d7b9,
+	0xf1fffc67,
+	0xfdffff63,
+	0x67f10476,
+	0x76fd0002,
+	0xf980f905,
+	0xfcd0fc70,
+	0x3f21f4e0,
 	0xf10467f0,
-	0xb607e407,
+	0xb607e007,
 	0x06d00604,
-/* 0x05c3: memx_func_leave_wait */
+/* 0x057f: memx_func_enter_wait */
 	0xf104bd00,
 	0xb607c067,
 	0x66cf0664,
 	0x0464f000,
-	0xf1f31bf4,
-	0xb9161087,
-	0x21f4028e,
-	0x02d7b904,
-	0xffcc67f1,
-	0xffff63f1,
-	0xf90476fd,
-	0xfc70f980,
-	0xf4e0fcd0,
-	0x00f83f21,
-/* 0x05f8: memx_func_wait_vblank */
-	0xb0001698,
-	0x0bf40066,
-	0x0166b013,
-	0xf4060bf4,
-/* 0x060a: memx_func_wait_vblank_head1 */
-	0x77f12e0e,
-	0x0ef40020,
-/* 0x0611: memx_func_wait_vblank_head0 */
-	0x0877f107,
-/* 0x0615: memx_func_wait_vblank_0 */
-	0xc467f100,
-	0x0664b607,
-	0xfd0066cf,
-	0x1bf40467,
-/* 0x0625: memx_func_wait_vblank_1 */
-	0xc467f1f3,
-	0x0664b607,
-	0xfd0066cf,
-	0x0bf40467,
-/* 0x0635: memx_func_wait_vblank_fini */
-	0x0410b6f3,
-/* 0x063a: memx_func_wr32 */
-	0x169800f8,
-	0x01159800,
-	0xf90810b6,
-	0xfc50f960,
-	0xf4e0fcd0,
-	0x42b63f21,
-	0xe91bf402,
-/* 0x0656: memx_func_wait */
-	0x87f000f8,
-	0x0684b62c,
-	0x980088cf,
-	0x1d98001e,
-	0x021c9801,
-	0xb6031b98,
-	0x21f41010,
-/* 0x0673: memx_func_delay */
-	0x9800f8a4,
-	0x10b6001e,
-	0x7f21f404,
-/* 0x067e: memx_func_train */
-	0x57f100f8,
-	0x77f10003,
-	0x97f10000,
-	0x93f00000,
-	0x029eb970,
-	0xb90421f4,
-	0xe7f102d8,
-	0x21f42710,
-/* 0x069d: memx_func_train_loop_outer */
-	0x0158e07f,
-	0x0083f101,
-	0xe097f102,
-	0x1193f011,
-	0x80f990f9,
-	0xe0fcd0fc,
-	0xf93f21f4,
-	0x0067f150,
-/* 0x06bd: memx_func_train_loop_inner */
-	0x1187f100,
-	0x9068ff11,
-	0xfd109894,
-	0x97f10589,
-	0x93f00720,
-	0xf990f910,
-	0xfcd0fc80,
-	0x3f21f4e0,
-	0x008097f1,
-	0xb91093f0,
-	0x21f4029e,
-	0x02d8b904,
-	0xf92088c5,
-	0xfc80f990,
-	0xf4e0fcd0,
-	0x97f13f21,
-	0x93f0053c,
-	0x0287f110,
-	0x0083f130,
-	0xf990f980,
-	0xfcd0fc80,
-	0x3f21f4e0,
-	0x0560e7f1,
-	0xf110e3f0,
-	0xf10000d7,
-	0x908000d3,
-	0xb7f100dc,
-	0xb3f08480,
-	0xa421f41e,
-	0x000057f1,
-	0xffff97f1,
-	0x830093f1,
-/* 0x073c: memx_func_train_loop_4x */
-	0x0080a7f1,
-	0xb910a3f0,
-	0x21f402ae,
-	0x02d8b904,
-	0xffdfb7f1,
-	0xffffb3f1,
-	0xf9048bfd,
-	0xfc80f9a0,
-	0xf4e0fcd0,
-	0xa7f13f21,
-	0xa3f0053c,
-	0x0287f110,
-	0x0083f130,
-	0xf9a0f980,
-	0xfcd0fc80,
-	0x3f21f4e0,
-	0x0560e7f1,
-	0xf110e3f0,
-	0xf10000d7,
-	0xb98000d3,
-	0xb7f102dc,
-	0xb3f02710,
-	0xa421f400,
-	0xf402eeb9,
-	0xddb90421,
-	0x949dff02,
-	0x700150b6,
-	0x1ef40456,
-	0xcc7aa092,
-	0x00a9800b,
-	0xb60160b6,
-	0x66700470,
-	0x001ef510,
-	0xb650fcff,
-	0x56700150,
-	0xd41ef507,
-/* 0x07cf: memx_exec */
-	0xf900f8fe,
-	0xb9d0f9e0,
-	0xb2b902c1,
-/* 0x07d9: memx_exec_next */
-	0x00139802,
-	0xe70410b6,
-	0xe701f034,
-	0xb601e033,
-	0x30f00132,
-	0xde35980c,
-	0x12b855f9,
-	0xe41ef406,
-	0x98f10b98,
-	0xcbbbf20c,
-	0xc4b7f102,
-	0x06b4b607,
-	0xfc00bbcf,
-	0xf5e0fcd0,
-	0xf8034221,
-/* 0x0815: memx_info */
-	0x01c67000,
-/* 0x081b: memx_info_data */
-	0xf10e0bf4,
-	0xf103ccc7,
-	0xf40800b7,
-/* 0x0826: memx_info_train */
-	0xc7f10b0e,
-	0xb7f10bcc,
-/* 0x082e: memx_info_send */
-	0x21f50100,
-	0x00f80342,
-/* 0x0834: memx_recv */
-	0xf401d6b0,
-	0xd6b0980b,
-	0xd80bf400,
-/* 0x0842: memx_init */
-	0x00f800f8,
-/* 0x0844: perf_recv */
-/* 0x0846: perf_init */
-	0x00f800f8,
-/* 0x0848: i2c_drive_scl */
-	0xf40036b0,
-	0x07f1110b,
-	0x04b607e0,
-	0x0001d006,
-	0x00f804bd,
-/* 0x085c: i2c_drive_scl_lo */
+	0xf0f30bf4,
+	0x64b62c67,
+	0x0066cf06,
+	0xf8f10680,
+/* 0x059d: memx_func_leave */
+	0x2c67f000,
+	0xcf0664b6,
+	0x06800066,
+	0x0467f0f2,
 	0x07e407f1,
 	0xd00604b6,
-	0x04bd0001,
-/* 0x086a: i2c_drive_sda */
-	0x36b000f8,
-	0x110bf400,
-	0x07e007f1,
-	0xd00604b6,
-	0x04bd0002,
-/* 0x087e: i2c_drive_sda_lo */
-	0x07f100f8,
-	0x04b607e4,
-	0x0002d006,
-	0x00f804bd,
-/* 0x088c: i2c_sense_scl */
-	0xf10132f4,
-	0xb607c437,
-	0x33cf0634,
-	0x0431fd00,
-	0xf4060bf4,
-/* 0x08a2: i2c_sense_scl_done */
-	0x00f80131,
-/* 0x08a4: i2c_sense_sda */
-	0xf10132f4,
-	0xb607c437,
-	0x33cf0634,
-	0x0432fd00,
-	0xf4060bf4,
-/* 0x08ba: i2c_sense_sda_done */
-	0x00f80131,
-/* 0x08bc: i2c_raise_scl */
-	0x47f140f9,
-	0x37f00898,
-	0x4821f501,
-/* 0x08c9: i2c_raise_scl_wait */
-	0xe8e7f108,
-	0x7f21f403,
-	0x088c21f5,
-	0xb60901f4,
-	0x1bf40142,
-/* 0x08dd: i2c_raise_scl_done */
-	0xf840fcef,
-/* 0x08e1: i2c_start */
-	0x8c21f500,
-	0x0d11f408,
-	0x08a421f5,
-	0xf40611f4,
-/* 0x08f2: i2c_start_rep */
-	0x37f0300e,
-	0x4821f500,
-	0x0137f008,
-	0x086a21f5,
-	0xb60076bb,
-	0x50f90465,
-	0xbb046594,
-	0x50bd0256,
-	0xfc0475fd,
-	0xbc21f550,
-	0x0464b608,
-/* 0x091f: i2c_start_send */
-	0xf01f11f4,
+	0x04bd0006,
+/* 0x05b8: memx_func_leave_wait */
+	0x07c067f1,
+	0xcf0664b6,
+	0x64f00066,
+	0xf31bf404,
+	0x161087f1,
+	0xf4028eb9,
+	0xd7b90421,
+	0xcc67f102,
+	0xff63f1ff,
+	0x0476fdff,
+	0x70f980f9,
+	0xe0fcd0fc,
+	0xf83f21f4,
+/* 0x05ed: memx_func_wait_vblank */
+	0x00169800,
+	0xf40066b0,
+	0x66b0130b,
+	0x060bf401,
+/* 0x05ff: memx_func_wait_vblank_head1 */
+	0xf12e0ef4,
+	0xf4002077,
+/* 0x0606: memx_func_wait_vblank_head0 */
+	0x77f1070e,
+/* 0x060a: memx_func_wait_vblank_0 */
+	0x67f10008,
+	0x64b607c4,
+	0x0066cf06,
+	0xf40467fd,
+/* 0x061a: memx_func_wait_vblank_1 */
+	0x67f1f31b,
+	0x64b607c4,
+	0x0066cf06,
+	0xf40467fd,
+/* 0x062a: memx_func_wait_vblank_fini */
+	0x10b6f30b,
+/* 0x062f: memx_func_wr32 */
+	0x9800f804,
+	0x15980016,
+	0x0810b601,
+	0x50f960f9,
+	0xe0fcd0fc,
+	0xb63f21f4,
+	0x1bf40242,
+/* 0x064b: memx_func_wait */
+	0xf000f8e9,
+	0x84b62c87,
+	0x0088cf06,
+	0x98001e98,
+	0x1c98011d,
+	0x031b9802,
+	0xf41010b6,
+	0x00f8a421,
+/* 0x0668: memx_func_delay */
+	0xb6001e98,
+	0x21f40410,
+/* 0x0673: memx_func_train */
+	0xf100f87f,
+	0xf1000357,
+	0xf1000077,
+	0xf0000097,
+	0x9eb97093,
+	0x0421f402,
+	0xf102d8b9,
+	0xf42710e7,
+/* 0x0692: memx_func_train_loop_outer */
+	0x58e07f21,
+	0x83f10101,
+	0x97f10200,
+	0x93f011e0,
+	0xf990f911,
+	0xfcd0fc80,
+	0x3f21f4e0,
+	0x67f150f9,
+/* 0x06b2: memx_func_train_loop_inner */
+	0x87f10000,
+	0x68ff1111,
+	0x10989490,
+	0xf10589fd,
+	0xf0072097,
+	0x90f91093,
+	0xd0fc80f9,
+	0x21f4e0fc,
+	0x8097f13f,
+	0x1093f000,
+	0xf4029eb9,
+	0xd8b90421,
+	0x2088c502,
+	0x80f990f9,
+	0xe0fcd0fc,
+	0xf13f21f4,
+	0xf0053c97,
+	0x87f11093,
+	0x83f13002,
+	0x90f98000,
+	0xd0fc80f9,
+	0x21f4e0fc,
+	0x60e7f13f,
+	0x10e3f005,
+	0x0000d7f1,
+	0x8000d3f1,
+	0xf100dc90,
+	0xf08480b7,
+	0x21f41eb3,
+	0x0057f1a4,
+	0xff97f100,
+	0x0093f1ff,
+/* 0x0731: memx_func_train_loop_4x */
+	0x80a7f183,
+	0x10a3f000,
+	0xf402aeb9,
+	0xd8b90421,
+	0xdfb7f102,
+	0xffb3f1ff,
+	0x048bfdff,
+	0x80f9a0f9,
+	0xe0fcd0fc,
+	0xf13f21f4,
+	0xf0053ca7,
+	0x87f110a3,
+	0x83f13002,
+	0xa0f98000,
+	0xd0fc80f9,
+	0x21f4e0fc,
+	0x60e7f13f,
+	0x10e3f005,
+	0x0000d7f1,
+	0x8000d3f1,
+	0xf102dcb9,
+	0xf02710b7,
+	0x21f400b3,
+	0x02eeb9a4,
+	0xb90421f4,
+	0x9dff02dd,
+	0x0150b694,
+	0xf4045670,
+	0x7aa0921e,
+	0xa9800bcc,
+	0x0160b600,
+	0x700470b6,
+	0x1ef51066,
+	0x50fcff00,
+	0x700150b6,
+	0x1ef50756,
+	0x00f8fed4,
+/* 0x07c4: memx_exec */
+	0xd0f9e0f9,
+	0xb902c1b9,
+/* 0x07ce: memx_exec_next */
+	0x139802b2,
+	0x0410b600,
+	0x01f034e7,
+	0x01e033e7,
+	0xf00132b6,
+	0x35980c30,
+	0xb855f9de,
+	0x1ef40612,
+	0xf10b98e4,
+	0xbbf20c98,
+	0xb7f102cb,
+	0xb4b607c4,
+	0x00bbcf06,
+	0xe0fcd0fc,
+	0x033721f5,
+/* 0x080a: memx_info */
+	0xc67000f8,
+	0x0e0bf401,
+/* 0x0810: memx_info_data */
+	0x03ccc7f1,
+	0x0800b7f1,
+/* 0x081b: memx_info_train */
+	0xf10b0ef4,
+	0xf10bccc7,
+/* 0x0823: memx_info_send */
+	0xf50100b7,
+	0xf8033721,
+/* 0x0829: memx_recv */
+	0x01d6b000,
+	0xb0980bf4,
+	0x0bf400d6,
+/* 0x0837: memx_init */
+	0xf800f8d8,
+/* 0x0839: perf_recv */
+/* 0x083b: perf_init */
+	0xf800f800,
+/* 0x083d: i2c_drive_scl */
+	0x0036b000,
+	0xf1110bf4,
+	0xb607e007,
+	0x01d00604,
+	0xf804bd00,
+/* 0x0851: i2c_drive_scl_lo */
+	0xe407f100,
+	0x0604b607,
+	0xbd0001d0,
+/* 0x085f: i2c_drive_sda */
+	0xb000f804,
+	0x0bf40036,
+	0xe007f111,
+	0x0604b607,
+	0xbd0002d0,
+/* 0x0873: i2c_drive_sda_lo */
+	0xf100f804,
+	0xb607e407,
+	0x02d00604,
+	0xf804bd00,
+/* 0x0881: i2c_sense_scl */
+	0x0132f400,
+	0x07c437f1,
+	0xcf0634b6,
+	0x31fd0033,
+	0x060bf404,
+/* 0x0897: i2c_sense_scl_done */
+	0xf80131f4,
+/* 0x0899: i2c_sense_sda */
+	0x0132f400,
+	0x07c437f1,
+	0xcf0634b6,
+	0x32fd0033,
+	0x060bf404,
+/* 0x08af: i2c_sense_sda_done */
+	0xf80131f4,
+/* 0x08b1: i2c_raise_scl */
+	0xf140f900,
+	0xf0089847,
+	0x21f50137,
+/* 0x08be: i2c_raise_scl_wait */
+	0xe7f1083d,
+	0x21f403e8,
+	0x8121f57f,
+	0x0901f408,
+	0xf40142b6,
+/* 0x08d2: i2c_raise_scl_done */
+	0x40fcef1b,
+/* 0x08d6: i2c_start */
+	0x21f500f8,
+	0x11f40881,
+	0x9921f50d,
+	0x0611f408,
+/* 0x08e7: i2c_start_rep */
+	0xf0300ef4,
 	0x21f50037,
-	0xe7f1086a,
-	0x21f41388,
-	0x0037f07f,
-	0x084821f5,
-	0x1388e7f1,
-/* 0x093b: i2c_start_out */
-	0xf87f21f4,
-/* 0x093d: i2c_stop */
-	0x0037f000,
-	0x084821f5,
-	0xf50037f0,
-	0xf1086a21,
-	0xf403e8e7,
-	0x37f07f21,
-	0x4821f501,
-	0x88e7f108,
-	0x7f21f413,
-	0xf50137f0,
-	0xf1086a21,
-	0xf41388e7,
-	0x00f87f21,
-/* 0x0970: i2c_bitw */
-	0x086a21f5,
-	0x03e8e7f1,
-	0xbb7f21f4,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x08bc21f5,
-	0xf40464b6,
-	0xe7f11811,
-	0x21f41388,
-	0x0037f07f,
-	0x084821f5,
-	0x1388e7f1,
-/* 0x09af: i2c_bitw_out */
-	0xf87f21f4,
-/* 0x09b1: i2c_bitr */
-	0x0137f000,
-	0x086a21f5,
-	0x03e8e7f1,
-	0xbb7f21f4,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x08bc21f5,
-	0xf40464b6,
-	0x21f51b11,
-	0x37f008a4,
-	0x4821f500,
-	0x88e7f108,
-	0x7f21f413,
-	0xf4013cf0,
-/* 0x09f6: i2c_bitr_done */
-	0x00f80131,
-/* 0x09f8: i2c_get_byte */
-	0xf00057f0,
-/* 0x09fe: i2c_get_byte_next */
-	0x54b60847,
-	0x0076bb01,
+	0x37f0083d,
+	0x5f21f501,
+	0x0076bb08,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b609b1,
-	0x2b11f404,
-	0xb60553fd,
-	0x1bf40142,
-	0x0137f0d8,
-	0xb60076bb,
-	0x50f90465,
-	0xbb046594,
-	0x50bd0256,
-	0xfc0475fd,
-	0x7021f550,
-	0x0464b609,
-/* 0x0a48: i2c_get_byte_done */
-/* 0x0a4a: i2c_put_byte */
-	0x47f000f8,
-/* 0x0a4d: i2c_put_byte_next */
-	0x0142b608,
-	0xbb3854ff,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x097021f5,
-	0xf40464b6,
-	0x46b03411,
-	0xd81bf400,
+	0x64b608b1,
+	0x1f11f404,
+/* 0x0914: i2c_start_send */
+	0xf50037f0,
+	0xf1085f21,
+	0xf41388e7,
+	0x37f07f21,
+	0x3d21f500,
+	0x88e7f108,
+	0x7f21f413,
+/* 0x0930: i2c_start_out */
+/* 0x0932: i2c_stop */
+	0x37f000f8,
+	0x3d21f500,
+	0x0037f008,
+	0x085f21f5,
+	0x03e8e7f1,
+	0xf07f21f4,
+	0x21f50137,
+	0xe7f1083d,
+	0x21f41388,
+	0x0137f07f,
+	0x085f21f5,
+	0x1388e7f1,
+	0xf87f21f4,
+/* 0x0965: i2c_bitw */
+	0x5f21f500,
+	0xe8e7f108,
+	0x7f21f403,
 	0xb60076bb,
 	0x50f90465,
 	0xbb046594,
 	0x50bd0256,
 	0xfc0475fd,
 	0xb121f550,
-	0x0464b609,
-	0xbb0f11f4,
-	0x36b00076,
-	0x061bf401,
-/* 0x0aa3: i2c_put_byte_done */
-	0xf80132f4,
-/* 0x0aa5: i2c_addr */
-	0x0076bb00,
-	0xf90465b6,
-	0x04659450,
-	0xbd0256bb,
-	0x0475fd50,
-	0x21f550fc,
-	0x64b608e1,
-	0x2911f404,
-	0x012ec3e7,
-	0xfd0134b6,
-	0x76bb0553,
+	0x0464b608,
+	0xf11811f4,
+	0xf41388e7,
+	0x37f07f21,
+	0x3d21f500,
+	0x88e7f108,
+	0x7f21f413,
+/* 0x09a4: i2c_bitw_out */
+/* 0x09a6: i2c_bitr */
+	0x37f000f8,
+	0x5f21f501,
+	0xe8e7f108,
+	0x7f21f403,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xb121f550,
+	0x0464b608,
+	0xf51b11f4,
+	0xf0089921,
+	0x21f50037,
+	0xe7f1083d,
+	0x21f41388,
+	0x013cf07f,
+/* 0x09eb: i2c_bitr_done */
+	0xf80131f4,
+/* 0x09ed: i2c_get_byte */
+	0x0057f000,
+/* 0x09f3: i2c_get_byte_next */
+	0xb60847f0,
+	0x76bb0154,
 	0x0465b600,
 	0x659450f9,
 	0x0256bb04,
 	0x75fd50bd,
 	0xf550fc04,
-	0xb60a4a21,
-/* 0x0aea: i2c_addr_done */
-	0x00f80464,
-/* 0x0aec: i2c_acquire_addr */
-	0xb6f8cec7,
-	0xe0b702e4,
-	0xee980d1c,
-/* 0x0afb: i2c_acquire */
-	0xf500f800,
-	0xf40aec21,
-	0xd9f00421,
-	0x3f21f403,
-/* 0x0b0a: i2c_release */
-	0x21f500f8,
-	0x21f40aec,
-	0x03daf004,
-	0xf83f21f4,
-/* 0x0b19: i2c_recv */
-	0x0132f400,
-	0xb6f8c1c7,
-	0x16b00214,
-	0x3a1ff528,
-	0xf413a001,
-	0x0032980c,
-	0x0ccc13a0,
-	0xf4003198,
-	0xd0f90231,
-	0xd0f9e0f9,
-	0x000067f1,
-	0x100063f1,
-	0xbb016792,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x0afb21f5,
-	0xfc0464b6,
-	0x00d6b0d0,
-	0x00b31bf5,
-	0xbb0057f0,
-	0x65b60076,
-	0x9450f904,
-	0x56bb0465,
-	0xfd50bd02,
-	0x50fc0475,
-	0x0aa521f5,
-	0xf50464b6,
-	0xc700d011,
-	0x76bbe0c5,
-	0x0465b600,
-	0x659450f9,
-	0x0256bb04,
-	0x75fd50bd,
-	0xf550fc04,
-	0xb60a4a21,
-	0x11f50464,
-	0x57f000ad,
+	0xb609a621,
+	0x11f40464,
+	0x0553fd2b,
+	0xf40142b6,
+	0x37f0d81b,
 	0x0076bb01,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b60aa5,
-	0x8a11f504,
-	0x0076bb00,
+	0x64b60965,
+/* 0x0a3d: i2c_get_byte_done */
+/* 0x0a3f: i2c_put_byte */
+	0xf000f804,
+/* 0x0a42: i2c_put_byte_next */
+	0x42b60847,
+	0x3854ff01,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x6521f550,
+	0x0464b609,
+	0xb03411f4,
+	0x1bf40046,
+	0x0076bbd8,
 	0xf90465b6,
 	0x04659450,
 	0xbd0256bb,
 	0x0475fd50,
 	0x21f550fc,
-	0x64b609f8,
-	0x6a11f404,
-	0xbbe05bcb,
+	0x64b609a6,
+	0x0f11f404,
+	0xb00076bb,
+	0x1bf40136,
+	0x0132f406,
+/* 0x0a98: i2c_put_byte_done */
+/* 0x0a9a: i2c_addr */
+	0x76bb00f8,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb608d621,
+	0x11f40464,
+	0x2ec3e729,
+	0x0134b601,
+	0xbb0553fd,
 	0x65b60076,
 	0x9450f904,
 	0x56bb0465,
 	0xfd50bd02,
 	0x50fc0475,
-	0x093d21f5,
-	0xb90464b6,
-	0x74bd025b,
-/* 0x0c1f: i2c_recv_not_rd08 */
-	0xb0430ef4,
-	0x1bf401d6,
-	0x0057f03d,
-	0x0aa521f5,
-	0xc73311f4,
-	0x21f5e0c5,
-	0x11f40a4a,
-	0x0057f029,
-	0x0aa521f5,
-	0xc71f11f4,
-	0x21f5e0b5,
-	0x11f40a4a,
-	0x3d21f515,
-	0xc774bd09,
-	0x1bf408c5,
-	0x0232f409,
-/* 0x0c5f: i2c_recv_not_wr08 */
-/* 0x0c5f: i2c_recv_done */
-	0xc7030ef4,
-	0x21f5f8ce,
-	0xe0fc0b0a,
-	0x12f4d0fc,
-	0x027cb90a,
-	0x034221f5,
-/* 0x0c74: i2c_recv_exit */
-/* 0x0c76: i2c_init */
+	0x0a3f21f5,
+/* 0x0adf: i2c_addr_done */
+	0xf80464b6,
+/* 0x0ae1: i2c_acquire_addr */
+	0xf8cec700,
+	0xb702e4b6,
+	0x980d1ce0,
+	0x00f800ee,
+/* 0x0af0: i2c_acquire */
+	0x0ae121f5,
+	0xf00421f4,
+	0x21f403d9,
+/* 0x0aff: i2c_release */
+	0xf500f83f,
+	0xf40ae121,
+	0xdaf00421,
+	0x3f21f403,
+/* 0x0b0e: i2c_recv */
+	0x32f400f8,
+	0xf8c1c701,
+	0xb00214b6,
+	0x1ff52816,
+	0x13a0013a,
+	0x32980cf4,
+	0xcc13a000,
+	0x0031980c,
+	0xf90231f4,
+	0xf9e0f9d0,
+	0x0067f1d0,
+	0x0063f100,
+	0x01679210,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xf021f550,
+	0x0464b60a,
+	0xd6b0d0fc,
+	0xb31bf500,
+	0x0057f000,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x9a21f550,
+	0x0464b60a,
+	0x00d011f5,
+	0xbbe0c5c7,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x0a3f21f5,
+	0xf50464b6,
+	0xf000ad11,
+	0x76bb0157,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb60a9a21,
+	0x11f50464,
+	0x76bb008a,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb609ed21,
+	0x11f40464,
+	0xe05bcb6a,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x3221f550,
+	0x0464b609,
+	0xbd025bb9,
+	0x430ef474,
+/* 0x0c14: i2c_recv_not_rd08 */
+	0xf401d6b0,
+	0x57f03d1b,
+	0x9a21f500,
+	0x3311f40a,
+	0xf5e0c5c7,
+	0xf40a3f21,
+	0x57f02911,
+	0x9a21f500,
+	0x1f11f40a,
+	0xf5e0b5c7,
+	0xf40a3f21,
+	0x21f51511,
+	0x74bd0932,
+	0xf408c5c7,
+	0x32f4091b,
+	0x030ef402,
+/* 0x0c54: i2c_recv_not_wr08 */
+/* 0x0c54: i2c_recv_done */
+	0xf5f8cec7,
+	0xfc0aff21,
+	0xf4d0fce0,
+	0x7cb90a12,
+	0x3721f502,
+/* 0x0c69: i2c_recv_exit */
+/* 0x0c6b: i2c_init */
+	0xf800f803,
+/* 0x0c6d: test_recv */
+	0xd817f100,
+	0x0614b605,
+	0xb60011cf,
+	0x07f10110,
+	0x04b605d8,
+	0x0001d006,
+	0xe7f104bd,
+	0xe3f1d900,
+	0x21f5134f,
+	0x00f80257,
+/* 0x0c94: test_init */
+	0x0800e7f1,
+	0x025721f5,
+/* 0x0c9e: idle_recv */
 	0x00f800f8,
-/* 0x0c78: test_recv */
-	0x05d817f1,
-	0xcf0614b6,
-	0x10b60011,
-	0xd807f101,
-	0x0604b605,
-	0xbd0001d0,
-	0x00e7f104,
-	0x4fe3f1d9,
-	0x6221f513,
-/* 0x0c9f: test_init */
-	0xf100f802,
-	0xf50800e7,
-	0xf8026221,
-/* 0x0ca9: idle_recv */
-/* 0x0cab: idle */
-	0xf400f800,
-	0x17f10031,
-	0x14b605d4,
-	0x0011cf06,
-	0xf10110b6,
-	0xb605d407,
-	0x01d00604,
-/* 0x0cc7: idle_loop */
-	0xf004bd00,
-	0x32f45817,
-/* 0x0ccd: idle_proc */
-/* 0x0ccd: idle_proc_exec */
-	0xb910f902,
-	0x21f5021e,
-	0x10fc034b,
-	0xf40911f4,
-	0x0ef40231,
-/* 0x0ce1: idle_proc_next */
-	0x5810b6ef,
-	0xf4061fb8,
-	0x02f4e61b,
-	0x0028f4dd,
-	0x00bb0ef4,
+/* 0x0ca0: idle */
+	0xf10031f4,
+	0xb605d417,
+	0x11cf0614,
+	0x0110b600,
+	0x05d407f1,
+	0xd00604b6,
+	0x04bd0001,
+/* 0x0cbc: idle_loop */
+	0xf45817f0,
+/* 0x0cc2: idle_proc */
+/* 0x0cc2: idle_proc_exec */
+	0x10f90232,
+	0xf5021eb9,
+	0xfc034021,
+	0x0911f410,
+	0xf40231f4,
+/* 0x0cd6: idle_proc_next */
+	0x10b6ef0e,
+	0x061fb858,
+	0xf4e61bf4,
+	0x28f4dd02,
+	0xbb0ef400,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/kernel.fuc b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/kernel.fuc
index 5cf5be6..ad35fa5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/kernel.fuc
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/kernel.fuc
@@ -225,17 +225,11 @@
 		nv_iowr(NV_PPWR_SUBINTR, $r9)
 
 	intr_skip_subintr:
-	and $r9 $r8 NV_PPWR_INTR_PAUSE
-	bra z #intr_skip_pause
-		and $r10 0xffbf
-
-	intr_skip_pause:
-	and $r9 $r8 NV_PPWR_INTR_USER0
-	bra z #intr_skip_user0
-		and $r10 0xffbf
-
-	intr_skip_user0:
+	mov $r9 (NV_PPWR_INTR_USER0 | NV_PPWR_INTR_USER1 | NV_PPWR_INTR_PAUSE)
+	not b32 $r9
+	and $r8 $r9
 	nv_iowr(NV_PPWR_INTR_ACK, $r8)
+
 	pop $r8
 	mov $flags $r8
 	pop $r15
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
index d942fa7..86f9f3b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
@@ -81,9 +81,7 @@
 	nvkm_mask(device, 0x000200, 0x00001000, 0x00001000);
 	nvkm_rd32(device, 0x000200);
 
-	if ( nvkm_boolopt(device->cfgopt, "War00C800_0",
-	    device->quirk ? device->quirk->War00C800_0 : false)) {
-		nvkm_info(&pmu->subdev, "hw bug workaround enabled\n");
+	if (nvkm_boolopt(device->cfgopt, "War00C800_0", true)) {
 		switch (device->chipset) {
 		case 0xe4:
 			magic(device, 0x04000000);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c
index 6326fdc..2c92ffb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/nv40.c
@@ -107,7 +107,7 @@
 {
 	struct nvkm_subdev *subdev = &therm->subdev;
 	struct nvkm_device *device = subdev->device;
-	u32 mask = enable ? 0x80000000 : 0x0000000;
+	u32 mask = enable ? 0x80000000 : 0x00000000;
 	if      (line == 2) nvkm_mask(device, 0x0010f0, 0x80000000, mask);
 	else if (line == 9) nvkm_mask(device, 0x0015f4, 0x80000000, mask);
 	else {
diff --git a/drivers/gpu/drm/omapdrm/Makefile b/drivers/gpu/drm/omapdrm/Makefile
index 778372b..368c1ec 100644
--- a/drivers/gpu/drm/omapdrm/Makefile
+++ b/drivers/gpu/drm/omapdrm/Makefile
@@ -12,10 +12,11 @@
 	omap_encoder.o \
 	omap_connector.o \
 	omap_fb.o \
-	omap_fbdev.o \
 	omap_gem.o \
 	omap_gem_dmabuf.o \
 	omap_dmm_tiler.o \
 	tcm-sita.o
 
+omapdrm-$(CONFIG_DRM_FBDEV_EMULATION) += omap_fbdev.o
+
 obj-$(CONFIG_DRM_OMAP)	+= omapdrm.o
diff --git a/drivers/gpu/drm/omapdrm/omap_debugfs.c b/drivers/gpu/drm/omapdrm/omap_debugfs.c
index ee91a25..6f5fc14 100644
--- a/drivers/gpu/drm/omapdrm/omap_debugfs.c
+++ b/drivers/gpu/drm/omapdrm/omap_debugfs.c
@@ -51,6 +51,7 @@
 	return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
 }
 
+#ifdef CONFIG_DRM_FBDEV_EMULATION
 static int fb_show(struct seq_file *m, void *arg)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -73,12 +74,15 @@
 
 	return 0;
 }
+#endif
 
 /* list of debufs files that are applicable to all devices */
 static struct drm_info_list omap_debugfs_list[] = {
 	{"gem", gem_show, 0},
 	{"mm", mm_show, 0},
+#ifdef CONFIG_DRM_FBDEV_EMULATION
 	{"fb", fb_show, 0},
+#endif
 };
 
 /* list of debugfs files that are specific to devices with dmm/tiler */
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
index 7841970..dfebdc4 100644
--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
+++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
@@ -363,6 +363,7 @@
 	u32 min_align = 128;
 	int ret;
 	unsigned long flags;
+	size_t slot_bytes;
 
 	BUG_ON(!validfmt(fmt));
 
@@ -371,13 +372,15 @@
 	h = DIV_ROUND_UP(h, geom[fmt].slot_h);
 
 	/* convert alignment to slots */
-	min_align = max(min_align, (geom[fmt].slot_w * geom[fmt].cpp));
-	align = ALIGN(align, min_align);
-	align /= geom[fmt].slot_w * geom[fmt].cpp;
+	slot_bytes = geom[fmt].slot_w * geom[fmt].cpp;
+	min_align = max(min_align, slot_bytes);
+	align = (align > min_align) ? ALIGN(align, min_align) : min_align;
+	align /= slot_bytes;
 
 	block->fmt = fmt;
 
-	ret = tcm_reserve_2d(containers[fmt], w, h, align, &block->area);
+	ret = tcm_reserve_2d(containers[fmt], w, h, align, -1, slot_bytes,
+			&block->area);
 	if (ret) {
 		kfree(block);
 		return ERR_PTR(-ENOMEM);
@@ -739,8 +742,7 @@
 	   programming during reill operations */
 	for (i = 0; i < omap_dmm->num_lut; i++) {
 		omap_dmm->tcm[i] = sita_init(omap_dmm->container_width,
-						omap_dmm->container_height,
-						NULL);
+						omap_dmm->container_height);
 
 		if (!omap_dmm->tcm[i]) {
 			dev_err(&dev->dev, "failed to allocate container\n");
@@ -1030,4 +1032,3 @@
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Andy Gross <andy.gross@ti.com>");
 MODULE_DESCRIPTION("OMAP DMM/Tiler Driver");
-MODULE_ALIAS("platform:" DMM_DRIVER_NAME);
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 5c6609c..dfafdb6 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -547,14 +547,19 @@
 	return 0;
 }
 
+#define OMAP_BO_USER_MASK	0x00ffffff	/* flags settable by userspace */
+
 static int ioctl_gem_new(struct drm_device *dev, void *data,
 		struct drm_file *file_priv)
 {
 	struct drm_omap_gem_new *args = data;
+	u32 flags = args->flags & OMAP_BO_USER_MASK;
+
 	VERB("%p:%p: size=0x%08x, flags=%08x", dev, file_priv,
-			args->size.bytes, args->flags);
-	return omap_gem_new_handle(dev, file_priv, args->size,
-			args->flags, &args->handle);
+	     args->size.bytes, flags);
+
+	return omap_gem_new_handle(dev, file_priv, args->size, flags,
+				   &args->handle);
 }
 
 static int ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
@@ -692,10 +697,6 @@
 		drm_crtc_vblank_off(priv->crtcs[i]);
 
 	priv->fbdev = omap_fbdev_init(dev);
-	if (!priv->fbdev) {
-		dev_warn(dev->dev, "omap_fbdev_init failed\n");
-		/* well, limp along without an fbdev.. maybe X11 will work? */
-	}
 
 	/* store off drm_device for use in pm ops */
 	dev_set_drvdata(dev->dev, dev);
@@ -831,7 +832,8 @@
 };
 
 static struct drm_driver omap_drm_driver = {
-	.driver_features = DRIVER_MODESET | DRIVER_GEM  | DRIVER_PRIME,
+	.driver_features = DRIVER_MODESET | DRIVER_GEM  | DRIVER_PRIME |
+		DRIVER_ATOMIC,
 	.load = dev_load,
 	.unload = dev_unload,
 	.open = dev_open,
@@ -928,35 +930,23 @@
 	.remove = pdev_remove,
 };
 
+static struct platform_driver * const drivers[] = {
+	&omap_dmm_driver,
+	&pdev,
+};
+
 static int __init omap_drm_init(void)
 {
-	int r;
-
 	DBG("init");
 
-	r = platform_driver_register(&omap_dmm_driver);
-	if (r) {
-		pr_err("DMM driver registration failed\n");
-		return r;
-	}
-
-	r = platform_driver_register(&pdev);
-	if (r) {
-		pr_err("omapdrm driver registration failed\n");
-		platform_driver_unregister(&omap_dmm_driver);
-		return r;
-	}
-
-	return 0;
+	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
 }
 
 static void __exit omap_drm_fini(void)
 {
 	DBG("fini");
 
-	platform_driver_unregister(&pdev);
-
-	platform_driver_unregister(&omap_dmm_driver);
+	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
 }
 
 /* need late_initcall() so we load after dss_driver's are loaded */
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 130fca7..9e00307 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -36,11 +36,7 @@
 
 #define MODULE_NAME     "omapdrm"
 
-/* max # of mapper-id's that can be assigned.. todo, come up with a better
- * (but still inexpensive) way to store/access per-buffer mapper private
- * data..
- */
-#define MAX_MAPPERS 2
+struct omap_drm_usergart;
 
 /* parameters which describe (unrotated) coordinates of scanout within a fb: */
 struct omap_drm_window {
@@ -97,6 +93,7 @@
 	/* list of GEM objects: */
 	struct list_head obj_list;
 
+	struct omap_drm_usergart *usergart;
 	bool has_dmm;
 
 	/* properties: */
@@ -138,8 +135,18 @@
 void omap_drm_irq_uninstall(struct drm_device *dev);
 int omap_drm_irq_install(struct drm_device *dev);
 
+#ifdef CONFIG_DRM_FBDEV_EMULATION
 struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev);
 void omap_fbdev_free(struct drm_device *dev);
+#else
+static inline struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
+{
+	return NULL;
+}
+static inline void omap_fbdev_free(struct drm_device *dev)
+{
+}
+#endif
 
 struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc);
 enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 0c104ad..61714e96 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -110,8 +110,6 @@
 	struct omap_dss_driver *dssdrv = dssdev->driver;
 	int ret;
 
-	dssdev->src->manager = omap_dss_get_overlay_manager(channel);
-
 	if (dssdrv->check_timings) {
 		ret = dssdrv->check_timings(dssdev, timings);
 	} else {
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index b8e4cde..3cb16f0 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
@@ -112,11 +112,8 @@
 	dma_addr_t paddr;
 	int ret;
 
-	/* only doing ARGB32 since this is what is needed to alpha-blend
-	 * with video overlays:
-	 */
 	sizes->surface_bpp = 32;
-	sizes->surface_depth = 32;
+	sizes->surface_depth = 24;
 
 	DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width,
 			sizes->surface_height, sizes->surface_bpp,
@@ -298,6 +295,10 @@
 	drm_fb_helper_fini(helper);
 fail:
 	kfree(fbdev);
+
+	dev_warn(dev->dev, "omap_fbdev_init failed\n");
+	/* well, limp along without an fbdev.. maybe X11 will work? */
+
 	return NULL;
 }
 
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index 7ed08fdc..9844626 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -25,24 +25,15 @@
 #include "omap_drv.h"
 #include "omap_dmm_tiler.h"
 
-/* remove these once drm core helpers are merged */
-struct page **_drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
-void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
-		bool dirty, bool accessed);
-int _drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size);
-
 /*
  * GEM buffer object implementation.
  */
 
-#define to_omap_bo(x) container_of(x, struct omap_gem_object, base)
-
 /* note: we use upper 8 bits of flags for driver-internal flags: */
-#define OMAP_BO_DMA			0x01000000	/* actually is physically contiguous */
+#define OMAP_BO_DMA		0x01000000	/* actually is physically contiguous */
 #define OMAP_BO_EXT_SYNC	0x02000000	/* externally allocated sync object */
 #define OMAP_BO_EXT_MEM		0x04000000	/* externally allocated memory */
 
-
 struct omap_gem_object {
 	struct drm_gem_object base;
 
@@ -119,8 +110,7 @@
 	} *sync;
 };
 
-static int get_pages(struct drm_gem_object *obj, struct page ***pages);
-static uint64_t mmap_offset(struct drm_gem_object *obj);
+#define to_omap_bo(x) container_of(x, struct omap_gem_object, base)
 
 /* To deal with userspace mmap'ings of 2d tiled buffers, which (a) are
  * not necessarily pinned in TILER all the time, and (b) when they are
@@ -134,27 +124,69 @@
  * for later..
  */
 #define NUM_USERGART_ENTRIES 2
-struct usergart_entry {
+struct omap_drm_usergart_entry {
 	struct tiler_block *block;	/* the reserved tiler block */
 	dma_addr_t paddr;
 	struct drm_gem_object *obj;	/* the current pinned obj */
 	pgoff_t obj_pgoff;		/* page offset of obj currently
 					   mapped in */
 };
-static struct {
-	struct usergart_entry entry[NUM_USERGART_ENTRIES];
+
+struct omap_drm_usergart {
+	struct omap_drm_usergart_entry entry[NUM_USERGART_ENTRIES];
 	int height;				/* height in rows */
 	int height_shift;		/* ilog2(height in rows) */
 	int slot_shift;			/* ilog2(width per slot) */
 	int stride_pfn;			/* stride in pages */
 	int last;				/* index of last used entry */
-} *usergart;
+};
+
+/* -----------------------------------------------------------------------------
+ * Helpers
+ */
+
+/** get mmap offset */
+static uint64_t mmap_offset(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	int ret;
+	size_t size;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	/* Make it mmapable */
+	size = omap_gem_mmap_size(obj);
+	ret = drm_gem_create_mmap_offset_size(obj, size);
+	if (ret) {
+		dev_err(dev->dev, "could not allocate mmap offset\n");
+		return 0;
+	}
+
+	return drm_vma_node_offset_addr(&obj->vma_node);
+}
+
+/* GEM objects can either be allocated from contiguous memory (in which
+ * case obj->filp==NULL), or w/ shmem backing (obj->filp!=NULL).  But non
+ * contiguous buffers can be remapped in TILER/DMM if they need to be
+ * contiguous... but we don't do this all the time to reduce pressure
+ * on TILER/DMM space when we know at allocation time that the buffer
+ * will need to be scanned out.
+ */
+static inline bool is_shmem(struct drm_gem_object *obj)
+{
+	return obj->filp != NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * Eviction
+ */
 
 static void evict_entry(struct drm_gem_object *obj,
-		enum tiler_fmt fmt, struct usergart_entry *entry)
+		enum tiler_fmt fmt, struct omap_drm_usergart_entry *entry)
 {
 	struct omap_gem_object *omap_obj = to_omap_bo(obj);
-	int n = usergart[fmt].height;
+	struct omap_drm_private *priv = obj->dev->dev_private;
+	int n = priv->usergart[fmt].height;
 	size_t size = PAGE_SIZE * n;
 	loff_t off = mmap_offset(obj) +
 			(entry->obj_pgoff << PAGE_SHIFT);
@@ -180,46 +212,25 @@
 static void evict(struct drm_gem_object *obj)
 {
 	struct omap_gem_object *omap_obj = to_omap_bo(obj);
+	struct omap_drm_private *priv = obj->dev->dev_private;
 
 	if (omap_obj->flags & OMAP_BO_TILED) {
 		enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
 		int i;
 
-		if (!usergart)
-			return;
-
 		for (i = 0; i < NUM_USERGART_ENTRIES; i++) {
-			struct usergart_entry *entry = &usergart[fmt].entry[i];
+			struct omap_drm_usergart_entry *entry =
+				&priv->usergart[fmt].entry[i];
+
 			if (entry->obj == obj)
 				evict_entry(obj, fmt, entry);
 		}
 	}
 }
 
-/* GEM objects can either be allocated from contiguous memory (in which
- * case obj->filp==NULL), or w/ shmem backing (obj->filp!=NULL).  But non
- * contiguous buffers can be remapped in TILER/DMM if they need to be
- * contiguous... but we don't do this all the time to reduce pressure
- * on TILER/DMM space when we know at allocation time that the buffer
- * will need to be scanned out.
+/* -----------------------------------------------------------------------------
+ * Page Management
  */
-static inline bool is_shmem(struct drm_gem_object *obj)
-{
-	return obj->filp != NULL;
-}
-
-/**
- * shmem buffers that are mapped cached can simulate coherency via using
- * page faulting to keep track of dirty pages
- */
-static inline bool is_cached_coherent(struct drm_gem_object *obj)
-{
-	struct omap_gem_object *omap_obj = to_omap_bo(obj);
-	return is_shmem(obj) &&
-		((omap_obj->flags & OMAP_BO_CACHE_MASK) == OMAP_BO_CACHED);
-}
-
-static DEFINE_SPINLOCK(sync_lock);
 
 /** ensure backing pages are allocated */
 static int omap_gem_attach_pages(struct drm_gem_object *obj)
@@ -272,6 +283,28 @@
 	return ret;
 }
 
+/* acquire pages when needed (for example, for DMA where physically
+ * contiguous buffer is not required
+ */
+static int get_pages(struct drm_gem_object *obj, struct page ***pages)
+{
+	struct omap_gem_object *omap_obj = to_omap_bo(obj);
+	int ret = 0;
+
+	if (is_shmem(obj) && !omap_obj->pages) {
+		ret = omap_gem_attach_pages(obj);
+		if (ret) {
+			dev_err(obj->dev->dev, "could not attach pages\n");
+			return ret;
+		}
+	}
+
+	/* TODO: even phys-contig.. we should have a list of pages? */
+	*pages = omap_obj->pages;
+
+	return 0;
+}
+
 /** release backing pages */
 static void omap_gem_detach_pages(struct drm_gem_object *obj)
 {
@@ -301,26 +334,6 @@
 	return to_omap_bo(obj)->flags;
 }
 
-/** get mmap offset */
-static uint64_t mmap_offset(struct drm_gem_object *obj)
-{
-	struct drm_device *dev = obj->dev;
-	int ret;
-	size_t size;
-
-	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
-	/* Make it mmapable */
-	size = omap_gem_mmap_size(obj);
-	ret = drm_gem_create_mmap_offset_size(obj, size);
-	if (ret) {
-		dev_err(dev->dev, "could not allocate mmap offset\n");
-		return 0;
-	}
-
-	return drm_vma_node_offset_addr(&obj->vma_node);
-}
-
 uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
 {
 	uint64_t offset;
@@ -362,6 +375,10 @@
 	return -EINVAL;
 }
 
+/* -----------------------------------------------------------------------------
+ * Fault Handling
+ */
+
 /* Normal handling for the case of faulting in non-tiled buffers */
 static int fault_1d(struct drm_gem_object *obj,
 		struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -393,7 +410,8 @@
 		struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct omap_gem_object *omap_obj = to_omap_bo(obj);
-	struct usergart_entry *entry;
+	struct omap_drm_private *priv = obj->dev->dev_private;
+	struct omap_drm_usergart_entry *entry;
 	enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
 	struct page *pages[64];  /* XXX is this too much to have on stack? */
 	unsigned long pfn;
@@ -406,8 +424,8 @@
 	 * that need to be mapped in to fill 4kb wide CPU page.  If the slot
 	 * height is 64, then 64 pages fill a 4kb wide by 64 row region.
 	 */
-	const int n = usergart[fmt].height;
-	const int n_shift = usergart[fmt].height_shift;
+	const int n = priv->usergart[fmt].height;
+	const int n_shift = priv->usergart[fmt].height_shift;
 
 	/*
 	 * If buffer width in bytes > PAGE_SIZE then the virtual stride is
@@ -428,11 +446,11 @@
 	base_pgoff = round_down(pgoff, m << n_shift);
 
 	/* figure out buffer width in slots */
-	slots = omap_obj->width >> usergart[fmt].slot_shift;
+	slots = omap_obj->width >> priv->usergart[fmt].slot_shift;
 
 	vaddr = vmf->virtual_address - ((pgoff - base_pgoff) << PAGE_SHIFT);
 
-	entry = &usergart[fmt].entry[usergart[fmt].last];
+	entry = &priv->usergart[fmt].entry[priv->usergart[fmt].last];
 
 	/* evict previous buffer using this usergart entry, if any: */
 	if (entry->obj)
@@ -479,12 +497,13 @@
 
 	for (i = n; i > 0; i--) {
 		vm_insert_mixed(vma, (unsigned long)vaddr, pfn);
-		pfn += usergart[fmt].stride_pfn;
+		pfn += priv->usergart[fmt].stride_pfn;
 		vaddr += PAGE_SIZE * m;
 	}
 
 	/* simple round-robin: */
-	usergart[fmt].last = (usergart[fmt].last + 1) % NUM_USERGART_ENTRIES;
+	priv->usergart[fmt].last = (priv->usergart[fmt].last + 1)
+				 % NUM_USERGART_ENTRIES;
 
 	return 0;
 }
@@ -596,6 +615,9 @@
 	return 0;
 }
 
+/* -----------------------------------------------------------------------------
+ * Dumb Buffers
+ */
 
 /**
  * omap_gem_dumb_create	-	create a dumb buffer
@@ -653,6 +675,7 @@
 	return ret;
 }
 
+#ifdef CONFIG_DRM_FBDEV_EMULATION
 /* Set scrolling position.  This allows us to implement fast scrolling
  * for console.
  *
@@ -689,6 +712,22 @@
 
 	return ret;
 }
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Memory Management & DMA Sync
+ */
+
+/**
+ * shmem buffers that are mapped cached can simulate coherency via using
+ * page faulting to keep track of dirty pages
+ */
+static inline bool is_cached_coherent(struct drm_gem_object *obj)
+{
+	struct omap_gem_object *omap_obj = to_omap_bo(obj);
+	return is_shmem(obj) &&
+		((omap_obj->flags & OMAP_BO_CACHE_MASK) == OMAP_BO_CACHED);
+}
 
 /* Sync the buffer for CPU access.. note pages should already be
  * attached, ie. omap_gem_get_pages()
@@ -865,28 +904,6 @@
 	return ret;
 }
 
-/* acquire pages when needed (for example, for DMA where physically
- * contiguous buffer is not required
- */
-static int get_pages(struct drm_gem_object *obj, struct page ***pages)
-{
-	struct omap_gem_object *omap_obj = to_omap_bo(obj);
-	int ret = 0;
-
-	if (is_shmem(obj) && !omap_obj->pages) {
-		ret = omap_gem_attach_pages(obj);
-		if (ret) {
-			dev_err(obj->dev->dev, "could not attach pages\n");
-			return ret;
-		}
-	}
-
-	/* TODO: even phys-contig.. we should have a list of pages? */
-	*pages = omap_obj->pages;
-
-	return 0;
-}
-
 /* if !remap, and we don't have pages backing, then fail, rather than
  * increasing the pin count (which we don't really do yet anyways,
  * because we don't support swapping pages back out).  And 'remap'
@@ -924,6 +941,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_DRM_FBDEV_EMULATION
 /* Get kernel virtual address for CPU access.. this more or less only
  * exists for omap_fbdev.  This should be called with struct_mutex
  * held.
@@ -942,6 +960,11 @@
 	}
 	return omap_obj->vaddr;
 }
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Power Management
+ */
 
 #ifdef CONFIG_PM
 /* re-pin objects in DMM in resume path: */
@@ -971,6 +994,10 @@
 }
 #endif
 
+/* -----------------------------------------------------------------------------
+ * DebugFS
+ */
+
 #ifdef CONFIG_DEBUG_FS
 void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 {
@@ -1017,9 +1044,12 @@
 }
 #endif
 
-/* Buffer Synchronization:
+/* -----------------------------------------------------------------------------
+ * Buffer Synchronization
  */
 
+static DEFINE_SPINLOCK(sync_lock);
+
 struct omap_gem_sync_waiter {
 	struct list_head list;
 	struct omap_gem_object *omap_obj;
@@ -1265,6 +1295,10 @@
 	return ret;
 }
 
+/* -----------------------------------------------------------------------------
+ * Constructor & Destructor
+ */
+
 /* don't call directly.. called from GEM core when it is time to actually
  * free the object..
  */
@@ -1282,8 +1316,6 @@
 	list_del(&omap_obj->mm_list);
 	spin_unlock(&priv->list_lock);
 
-	drm_gem_free_mmap_offset(obj);
-
 	/* this means the object is still pinned.. which really should
 	 * not happen.  I think..
 	 */
@@ -1308,31 +1340,7 @@
 
 	drm_gem_object_release(obj);
 
-	kfree(obj);
-}
-
-/* convenience method to construct a GEM buffer object, and userspace handle */
-int omap_gem_new_handle(struct drm_device *dev, struct drm_file *file,
-		union omap_gem_size gsize, uint32_t flags, uint32_t *handle)
-{
-	struct drm_gem_object *obj;
-	int ret;
-
-	obj = omap_gem_new(dev, gsize, flags);
-	if (!obj)
-		return -ENOMEM;
-
-	ret = drm_gem_handle_create(file, obj, handle);
-	if (ret) {
-		drm_gem_object_release(obj);
-		kfree(obj); /* TODO isn't there a dtor to call? just copying i915 */
-		return ret;
-	}
-
-	/* drop reference from allocate - handle holds it now */
-	drm_gem_object_unreference_unlocked(obj);
-
-	return 0;
+	kfree(omap_obj);
 }
 
 /* GEM buffer object constructor */
@@ -1341,15 +1349,15 @@
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_gem_object *omap_obj;
-	struct drm_gem_object *obj = NULL;
+	struct drm_gem_object *obj;
 	struct address_space *mapping;
 	size_t size;
 	int ret;
 
 	if (flags & OMAP_BO_TILED) {
-		if (!usergart) {
+		if (!priv->usergart) {
 			dev_err(dev->dev, "Tiled buffers require DMM\n");
-			goto fail;
+			return NULL;
 		}
 
 		/* tiled buffers are always shmem paged backed.. when they are
@@ -1420,16 +1428,42 @@
 	return obj;
 
 fail:
-	if (obj)
-		omap_gem_free_object(obj);
-
+	omap_gem_free_object(obj);
 	return NULL;
 }
 
-/* init/cleanup.. if DMM is used, we need to set some stuff up.. */
+/* convenience method to construct a GEM buffer object, and userspace handle */
+int omap_gem_new_handle(struct drm_device *dev, struct drm_file *file,
+		union omap_gem_size gsize, uint32_t flags, uint32_t *handle)
+{
+	struct drm_gem_object *obj;
+	int ret;
+
+	obj = omap_gem_new(dev, gsize, flags);
+	if (!obj)
+		return -ENOMEM;
+
+	ret = drm_gem_handle_create(file, obj, handle);
+	if (ret) {
+		omap_gem_free_object(obj);
+		return ret;
+	}
+
+	/* drop reference from allocate - handle holds it now */
+	drm_gem_object_unreference_unlocked(obj);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Init & Cleanup
+ */
+
+/* If DMM is used, we need to set some stuff up.. */
 void omap_gem_init(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
+	struct omap_drm_usergart *usergart;
 	const enum tiler_fmt fmts[] = {
 			TILFMT_8BIT, TILFMT_16BIT, TILFMT_32BIT
 	};
@@ -1458,10 +1492,11 @@
 		usergart[i].stride_pfn = tiler_stride(fmts[i], 0) >> PAGE_SHIFT;
 		usergart[i].slot_shift = ilog2((PAGE_SIZE / h) >> i);
 		for (j = 0; j < NUM_USERGART_ENTRIES; j++) {
-			struct usergart_entry *entry = &usergart[i].entry[j];
-			struct tiler_block *block =
-					tiler_reserve_2d(fmts[i], w, h,
-							PAGE_SIZE);
+			struct omap_drm_usergart_entry *entry;
+			struct tiler_block *block;
+
+			entry = &usergart[i].entry[j];
+			block = tiler_reserve_2d(fmts[i], w, h, PAGE_SIZE);
 			if (IS_ERR(block)) {
 				dev_err(dev->dev,
 						"reserve failed: %d, %d, %ld\n",
@@ -1477,13 +1512,16 @@
 		}
 	}
 
+	priv->usergart = usergart;
 	priv->has_dmm = true;
 }
 
 void omap_gem_deinit(struct drm_device *dev)
 {
+	struct omap_drm_private *priv = dev->dev_private;
+
 	/* I believe we can rely on there being no more outstanding GEM
 	 * objects which could depend on usergart/dmm at this point.
 	 */
-	kfree(usergart);
+	kfree(priv->usergart);
 }
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index d5ecabd..d75b197 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -188,33 +188,6 @@
 	.atomic_disable = omap_plane_atomic_disable,
 };
 
-static void omap_plane_reset(struct drm_plane *plane)
-{
-	struct omap_plane *omap_plane = to_omap_plane(plane);
-	struct omap_plane_state *omap_state;
-
-	if (plane->state && plane->state->fb)
-		drm_framebuffer_unreference(plane->state->fb);
-
-	kfree(plane->state);
-	plane->state = NULL;
-
-	omap_state = kzalloc(sizeof(*omap_state), GFP_KERNEL);
-	if (omap_state == NULL)
-		return;
-
-	/*
-	 * Set defaults depending on whether we are a primary or overlay
-	 * plane.
-	 */
-	omap_state->zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
-			   ? 0 : omap_plane->id;
-	omap_state->base.rotation = BIT(DRM_ROTATE_0);
-
-	plane->state = &omap_state->base;
-	plane->state->plane = plane;
-}
-
 static void omap_plane_destroy(struct drm_plane *plane)
 {
 	struct omap_plane *omap_plane = to_omap_plane(plane);
@@ -270,6 +243,32 @@
 	kfree(to_omap_plane_state(state));
 }
 
+static void omap_plane_reset(struct drm_plane *plane)
+{
+	struct omap_plane *omap_plane = to_omap_plane(plane);
+	struct omap_plane_state *omap_state;
+
+	if (plane->state) {
+		omap_plane_atomic_destroy_state(plane, plane->state);
+		plane->state = NULL;
+	}
+
+	omap_state = kzalloc(sizeof(*omap_state), GFP_KERNEL);
+	if (omap_state == NULL)
+		return;
+
+	/*
+	 * Set defaults depending on whether we are a primary or overlay
+	 * plane.
+	 */
+	omap_state->zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
+			   ? 0 : omap_plane->id;
+	omap_state->base.rotation = BIT(DRM_ROTATE_0);
+
+	plane->state = &omap_state->base;
+	plane->state->plane = plane;
+}
+
 static int omap_plane_atomic_set_property(struct drm_plane *plane,
 					  struct drm_plane_state *state,
 					  struct drm_property *property,
diff --git a/drivers/gpu/drm/omapdrm/tcm-sita.c b/drivers/gpu/drm/omapdrm/tcm-sita.c
index 6df1f2a..c10fdfc 100644
--- a/drivers/gpu/drm/omapdrm/tcm-sita.c
+++ b/drivers/gpu/drm/omapdrm/tcm-sita.c
@@ -5,8 +5,9 @@
  *
  * Authors: Ravi Ramachandra <r.ramachandra@ti.com>,
  *          Lajos Molnar <molnar@ti.com>
+ *          Andy Gross <andy.gross@ti.com>
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2012 Texas Instruments, Inc.
  *
  * This package is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -17,79 +18,225 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/bitmap.h>
 #include <linux/slab.h>
-#include <linux/spinlock.h>
+#include "tcm.h"
 
-#include "tcm-sita.h"
+static unsigned long mask[8];
+/*
+ * pos		position in bitmap
+ * w		width in slots
+ * h		height in slots
+ * map		ptr to bitmap
+ * stride		slots in a row
+ */
+static void free_slots(unsigned long pos, uint16_t w, uint16_t h,
+		unsigned long *map, uint16_t stride)
+{
+	int i;
 
-#define ALIGN_DOWN(value, align) ((value) & ~((align) - 1))
+	for (i = 0; i < h; i++, pos += stride)
+		bitmap_clear(map, pos, w);
+}
 
-/* Individual selection criteria for different scan areas */
-static s32 CR_L2R_T2B = CR_BIAS_HORIZONTAL;
-static s32 CR_R2L_T2B = CR_DIAGONAL_BALANCE;
+/*
+ * w		width in slots
+ * pos		ptr to position
+ * map		ptr to bitmap
+ * num_bits	number of bits in bitmap
+ */
+static int r2l_b2t_1d(uint16_t w, unsigned long *pos, unsigned long *map,
+		size_t num_bits)
+{
+	unsigned long search_count = 0;
+	unsigned long bit;
+	bool area_found = false;
 
-/*********************************************
- *	TCM API - Sita Implementation
- *********************************************/
-static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
-			   struct tcm_area *area);
-static s32 sita_reserve_1d(struct tcm *tcm, u32 slots, struct tcm_area *area);
-static s32 sita_free(struct tcm *tcm, struct tcm_area *area);
-static void sita_deinit(struct tcm *tcm);
+	*pos = num_bits - w;
 
-/*********************************************
- *	Main Scanner functions
- *********************************************/
-static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
-				   struct tcm_area *area);
+	while (search_count < num_bits) {
+		bit = find_next_bit(map, num_bits, *pos);
 
-static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
-			struct tcm_area *field, struct tcm_area *area);
+		if (bit - *pos >= w) {
+			/* found a long enough free area */
+			bitmap_set(map, *pos, w);
+			area_found = true;
+			break;
+		}
 
-static s32 scan_r2l_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
-			struct tcm_area *field, struct tcm_area *area);
+		search_count = num_bits - bit + w;
+		*pos = bit - w;
+	}
 
-static s32 scan_r2l_b2t_one_dim(struct tcm *tcm, u32 num_slots,
-			struct tcm_area *field, struct tcm_area *area);
+	return (area_found) ? 0 : -ENOMEM;
+}
 
-/*********************************************
- *	Support Infrastructure Methods
- *********************************************/
-static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h);
+/*
+ * w = width in slots
+ * h = height in slots
+ * a = align in slots	(mask, 2^n-1, 0 is unaligned)
+ * offset = offset in bytes from 4KiB
+ * pos = position in bitmap for buffer
+ * map = bitmap ptr
+ * num_bits = size of bitmap
+ * stride = bits in one row of container
+ */
+static int l2r_t2b(uint16_t w, uint16_t h, uint16_t a, int16_t offset,
+		unsigned long *pos, unsigned long slot_bytes,
+		unsigned long *map, size_t num_bits, size_t slot_stride)
+{
+	int i;
+	unsigned long index;
+	bool area_free;
+	unsigned long slots_per_band = PAGE_SIZE / slot_bytes;
+	unsigned long bit_offset = (offset > 0) ? offset / slot_bytes : 0;
+	unsigned long curr_bit = bit_offset;
 
-static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
-			    struct tcm_area *field, s32 criteria,
-			    struct score *best);
+	/* reset alignment to 1 if we are matching a specific offset */
+	/* adjust alignment - 1 to get to the format expected in bitmaps */
+	a = (offset > 0) ? 0 : a - 1;
 
-static void get_nearness_factor(struct tcm_area *field,
-				struct tcm_area *candidate,
-				struct nearness_factor *nf);
+	/* FIXME Return error if slots_per_band > stride */
 
-static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
-			       struct neighbor_stats *stat);
+	while (curr_bit < num_bits) {
+		*pos = bitmap_find_next_zero_area(map, num_bits, curr_bit, w,
+				a);
 
-static void fill_area(struct tcm *tcm,
-				struct tcm_area *area, struct tcm_area *parent);
+		/* skip forward if we are not at right offset */
+		if (bit_offset > 0 && (*pos % slots_per_band != bit_offset)) {
+			curr_bit = ALIGN(*pos, slots_per_band) + bit_offset;
+			continue;
+		}
 
+		/* skip forward to next row if we overlap end of row */
+		if ((*pos % slot_stride) + w > slot_stride) {
+			curr_bit = ALIGN(*pos, slot_stride) + bit_offset;
+			continue;
+		}
 
-/*********************************************/
+		/* TODO: Handle overlapping 4K boundaries */
 
-/*********************************************
- *	Utility Methods
- *********************************************/
-struct tcm *sita_init(u16 width, u16 height, struct tcm_pt *attr)
+		/* break out of look if we will go past end of container */
+		if ((*pos + slot_stride * h) > num_bits)
+			break;
+
+		/* generate mask that represents out matching pattern */
+		bitmap_clear(mask, 0, slot_stride);
+		bitmap_set(mask, (*pos % BITS_PER_LONG), w);
+
+		/* assume the area is free until we find an overlap */
+		area_free = true;
+
+		/* check subsequent rows to see if complete area is free */
+		for (i = 1; i < h; i++) {
+			index = *pos / BITS_PER_LONG + i * 8;
+			if (bitmap_intersects(&map[index], mask,
+				(*pos % BITS_PER_LONG) + w)) {
+				area_free = false;
+				break;
+			}
+		}
+
+		if (area_free)
+			break;
+
+		/* go forward past this match */
+		if (bit_offset > 0)
+			curr_bit = ALIGN(*pos, slots_per_band) + bit_offset;
+		else
+			curr_bit = *pos + a + 1;
+	}
+
+	if (area_free) {
+		/* set area as in-use. iterate over rows */
+		for (i = 0, index = *pos; i < h; i++, index += slot_stride)
+			bitmap_set(map, index, w);
+	}
+
+	return (area_free) ? 0 : -ENOMEM;
+}
+
+static s32 sita_reserve_1d(struct tcm *tcm, u32 num_slots,
+			   struct tcm_area *area)
+{
+	unsigned long pos;
+	int ret;
+
+	spin_lock(&(tcm->lock));
+	ret = r2l_b2t_1d(num_slots, &pos, tcm->bitmap, tcm->map_size);
+	if (!ret) {
+		area->p0.x = pos % tcm->width;
+		area->p0.y = pos / tcm->width;
+		area->p1.x = (pos + num_slots - 1) % tcm->width;
+		area->p1.y = (pos + num_slots - 1) / tcm->width;
+	}
+	spin_unlock(&(tcm->lock));
+
+	return ret;
+}
+
+static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u16 align,
+				int16_t offset, uint16_t slot_bytes,
+				struct tcm_area *area)
+{
+	unsigned long pos;
+	int ret;
+
+	spin_lock(&(tcm->lock));
+	ret = l2r_t2b(w, h, align, offset, &pos, slot_bytes, tcm->bitmap,
+			tcm->map_size, tcm->width);
+
+	if (!ret) {
+		area->p0.x = pos % tcm->width;
+		area->p0.y = pos / tcm->width;
+		area->p1.x = area->p0.x + w - 1;
+		area->p1.y = area->p0.y + h - 1;
+	}
+	spin_unlock(&(tcm->lock));
+
+	return ret;
+}
+
+static void sita_deinit(struct tcm *tcm)
+{
+	kfree(tcm);
+}
+
+static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
+{
+	unsigned long pos;
+	uint16_t w, h;
+
+	pos = area->p0.x + area->p0.y * tcm->width;
+	if (area->is2d) {
+		w = area->p1.x - area->p0.x + 1;
+		h = area->p1.y - area->p0.y + 1;
+	} else {
+		w = area->p1.x + area->p1.y * tcm->width - pos + 1;
+		h = 1;
+	}
+
+	spin_lock(&(tcm->lock));
+	free_slots(pos, w, h, tcm->bitmap, tcm->width);
+	spin_unlock(&(tcm->lock));
+	return 0;
+}
+
+struct tcm *sita_init(u16 width, u16 height)
 {
 	struct tcm *tcm;
-	struct sita_pvt *pvt;
-	struct tcm_area area = {0};
-	s32 i;
+	size_t map_size = BITS_TO_LONGS(width*height) * sizeof(unsigned long);
 
 	if (width == 0 || height == 0)
 		return NULL;
 
-	tcm = kzalloc(sizeof(*tcm), GFP_KERNEL);
-	pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
-	if (!tcm || !pvt)
+	tcm = kzalloc(sizeof(*tcm) + map_size, GFP_KERNEL);
+	if (!tcm)
 		goto error;
 
 	/* Updating the pointers to SiTA implementation APIs */
@@ -99,602 +246,16 @@
 	tcm->reserve_1d = sita_reserve_1d;
 	tcm->free = sita_free;
 	tcm->deinit = sita_deinit;
-	tcm->pvt = (void *)pvt;
 
-	spin_lock_init(&(pvt->lock));
+	spin_lock_init(&tcm->lock);
+	tcm->bitmap = (unsigned long *)(tcm + 1);
+	bitmap_clear(tcm->bitmap, 0, width*height);
 
-	/* Creating tam map */
-	pvt->map = kmalloc(sizeof(*pvt->map) * tcm->width, GFP_KERNEL);
-	if (!pvt->map)
-		goto error;
+	tcm->map_size = width*height;
 
-	for (i = 0; i < tcm->width; i++) {
-		pvt->map[i] =
-			kmalloc(sizeof(**pvt->map) * tcm->height,
-								GFP_KERNEL);
-		if (pvt->map[i] == NULL) {
-			while (i--)
-				kfree(pvt->map[i]);
-			kfree(pvt->map);
-			goto error;
-		}
-	}
-
-	if (attr && attr->x <= tcm->width && attr->y <= tcm->height) {
-		pvt->div_pt.x = attr->x;
-		pvt->div_pt.y = attr->y;
-
-	} else {
-		/* Defaulting to 3:1 ratio on width for 2D area split */
-		/* Defaulting to 3:1 ratio on height for 2D and 1D split */
-		pvt->div_pt.x = (tcm->width * 3) / 4;
-		pvt->div_pt.y = (tcm->height * 3) / 4;
-	}
-
-	spin_lock(&(pvt->lock));
-	assign(&area, 0, 0, width - 1, height - 1);
-	fill_area(tcm, &area, NULL);
-	spin_unlock(&(pvt->lock));
 	return tcm;
 
 error:
 	kfree(tcm);
-	kfree(pvt);
 	return NULL;
 }
-
-static void sita_deinit(struct tcm *tcm)
-{
-	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-	struct tcm_area area = {0};
-	s32 i;
-
-	area.p1.x = tcm->width - 1;
-	area.p1.y = tcm->height - 1;
-
-	spin_lock(&(pvt->lock));
-	fill_area(tcm, &area, NULL);
-	spin_unlock(&(pvt->lock));
-
-	for (i = 0; i < tcm->height; i++)
-		kfree(pvt->map[i]);
-	kfree(pvt->map);
-	kfree(pvt);
-}
-
-/**
- * Reserve a 1D area in the container
- *
- * @param num_slots	size of 1D area
- * @param area		pointer to the area that will be populated with the
- *			reserved area
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 sita_reserve_1d(struct tcm *tcm, u32 num_slots,
-			   struct tcm_area *area)
-{
-	s32 ret;
-	struct tcm_area field = {0};
-	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-
-	spin_lock(&(pvt->lock));
-
-	/* Scanning entire container */
-	assign(&field, tcm->width - 1, tcm->height - 1, 0, 0);
-
-	ret = scan_r2l_b2t_one_dim(tcm, num_slots, &field, area);
-	if (!ret)
-		/* update map */
-		fill_area(tcm, area, area);
-
-	spin_unlock(&(pvt->lock));
-	return ret;
-}
-
-/**
- * Reserve a 2D area in the container
- *
- * @param w	width
- * @param h	height
- * @param area	pointer to the area that will be populated with the reserved
- *		area
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
-			   struct tcm_area *area)
-{
-	s32 ret;
-	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-
-	/* not supporting more than 64 as alignment */
-	if (align > 64)
-		return -EINVAL;
-
-	/* we prefer 1, 32 and 64 as alignment */
-	align = align <= 1 ? 1 : align <= 32 ? 32 : 64;
-
-	spin_lock(&(pvt->lock));
-	ret = scan_areas_and_find_fit(tcm, w, h, align, area);
-	if (!ret)
-		/* update map */
-		fill_area(tcm, area, area);
-
-	spin_unlock(&(pvt->lock));
-	return ret;
-}
-
-/**
- * Unreserve a previously allocated 2D or 1D area
- * @param area	area to be freed
- * @return 0 - success
- */
-static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
-{
-	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-
-	spin_lock(&(pvt->lock));
-
-	/* check that this is in fact an existing area */
-	WARN_ON(pvt->map[area->p0.x][area->p0.y] != area ||
-		pvt->map[area->p1.x][area->p1.y] != area);
-
-	/* Clear the contents of the associated tiles in the map */
-	fill_area(tcm, area, NULL);
-
-	spin_unlock(&(pvt->lock));
-
-	return 0;
-}
-
-/**
- * Note: In general the cordinates in the scan field area relevant to the can
- * sweep directions. The scan origin (e.g. top-left corner) will always be
- * the p0 member of the field.  Therfore, for a scan from top-left p0.x <= p1.x
- * and p0.y <= p1.y; whereas, for a scan from bottom-right p1.x <= p0.x and p1.y
- * <= p0.y
- */
-
-/**
- * Raster scan horizontally right to left from top to bottom to find a place for
- * a 2D area of given size inside a scan field.
- *
- * @param w	width of desired area
- * @param h	height of desired area
- * @param align	desired area alignment
- * @param area	pointer to the area that will be set to the best position
- * @param field	area to scan (inclusive)
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 scan_r2l_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
-			struct tcm_area *field, struct tcm_area *area)
-{
-	s32 x, y;
-	s16 start_x, end_x, start_y, end_y, found_x = -1;
-	struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
-	struct score best = {{0}, {0}, {0}, 0};
-
-	start_x = field->p0.x;
-	end_x = field->p1.x;
-	start_y = field->p0.y;
-	end_y = field->p1.y;
-
-	/* check scan area co-ordinates */
-	if (field->p0.x < field->p1.x ||
-	    field->p1.y < field->p0.y)
-		return -EINVAL;
-
-	/* check if allocation would fit in scan area */
-	if (w > LEN(start_x, end_x) || h > LEN(end_y, start_y))
-		return -ENOSPC;
-
-	/* adjust start_x and end_y, as allocation would not fit beyond */
-	start_x = ALIGN_DOWN(start_x - w + 1, align); /* - 1 to be inclusive */
-	end_y = end_y - h + 1;
-
-	/* check if allocation would still fit in scan area */
-	if (start_x < end_x)
-		return -ENOSPC;
-
-	/* scan field top-to-bottom, right-to-left */
-	for (y = start_y; y <= end_y; y++) {
-		for (x = start_x; x >= end_x; x -= align) {
-			if (is_area_free(map, x, y, w, h)) {
-				found_x = x;
-
-				/* update best candidate */
-				if (update_candidate(tcm, x, y, w, h, field,
-							CR_R2L_T2B, &best))
-					goto done;
-
-				/* change upper x bound */
-				end_x = x + 1;
-				break;
-			} else if (map[x][y] && map[x][y]->is2d) {
-				/* step over 2D areas */
-				x = ALIGN(map[x][y]->p0.x - w + 1, align);
-			}
-		}
-
-		/* break if you find a free area shouldering the scan field */
-		if (found_x == start_x)
-			break;
-	}
-
-	if (!best.a.tcm)
-		return -ENOSPC;
-done:
-	assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
-	return 0;
-}
-
-/**
- * Raster scan horizontally left to right from top to bottom to find a place for
- * a 2D area of given size inside a scan field.
- *
- * @param w	width of desired area
- * @param h	height of desired area
- * @param align	desired area alignment
- * @param area	pointer to the area that will be set to the best position
- * @param field	area to scan (inclusive)
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
-			struct tcm_area *field, struct tcm_area *area)
-{
-	s32 x, y;
-	s16 start_x, end_x, start_y, end_y, found_x = -1;
-	struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
-	struct score best = {{0}, {0}, {0}, 0};
-
-	start_x = field->p0.x;
-	end_x = field->p1.x;
-	start_y = field->p0.y;
-	end_y = field->p1.y;
-
-	/* check scan area co-ordinates */
-	if (field->p1.x < field->p0.x ||
-	    field->p1.y < field->p0.y)
-		return -EINVAL;
-
-	/* check if allocation would fit in scan area */
-	if (w > LEN(end_x, start_x) || h > LEN(end_y, start_y))
-		return -ENOSPC;
-
-	start_x = ALIGN(start_x, align);
-
-	/* check if allocation would still fit in scan area */
-	if (w > LEN(end_x, start_x))
-		return -ENOSPC;
-
-	/* adjust end_x and end_y, as allocation would not fit beyond */
-	end_x = end_x - w + 1; /* + 1 to be inclusive */
-	end_y = end_y - h + 1;
-
-	/* scan field top-to-bottom, left-to-right */
-	for (y = start_y; y <= end_y; y++) {
-		for (x = start_x; x <= end_x; x += align) {
-			if (is_area_free(map, x, y, w, h)) {
-				found_x = x;
-
-				/* update best candidate */
-				if (update_candidate(tcm, x, y, w, h, field,
-							CR_L2R_T2B, &best))
-					goto done;
-				/* change upper x bound */
-				end_x = x - 1;
-
-				break;
-			} else if (map[x][y] && map[x][y]->is2d) {
-				/* step over 2D areas */
-				x = ALIGN_DOWN(map[x][y]->p1.x, align);
-			}
-		}
-
-		/* break if you find a free area shouldering the scan field */
-		if (found_x == start_x)
-			break;
-	}
-
-	if (!best.a.tcm)
-		return -ENOSPC;
-done:
-	assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
-	return 0;
-}
-
-/**
- * Raster scan horizontally right to left from bottom to top to find a place
- * for a 1D area of given size inside a scan field.
- *
- * @param num_slots	size of desired area
- * @param align		desired area alignment
- * @param area		pointer to the area that will be set to the best
- *			position
- * @param field		area to scan (inclusive)
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 scan_r2l_b2t_one_dim(struct tcm *tcm, u32 num_slots,
-				struct tcm_area *field, struct tcm_area *area)
-{
-	s32 found = 0;
-	s16 x, y;
-	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-	struct tcm_area *p;
-
-	/* check scan area co-ordinates */
-	if (field->p0.y < field->p1.y)
-		return -EINVAL;
-
-	/**
-	 * Currently we only support full width 1D scan field, which makes sense
-	 * since 1D slot-ordering spans the full container width.
-	 */
-	if (tcm->width != field->p0.x - field->p1.x + 1)
-		return -EINVAL;
-
-	/* check if allocation would fit in scan area */
-	if (num_slots > tcm->width * LEN(field->p0.y, field->p1.y))
-		return -ENOSPC;
-
-	x = field->p0.x;
-	y = field->p0.y;
-
-	/* find num_slots consecutive free slots to the left */
-	while (found < num_slots) {
-		if (y < 0)
-			return -ENOSPC;
-
-		/* remember bottom-right corner */
-		if (found == 0) {
-			area->p1.x = x;
-			area->p1.y = y;
-		}
-
-		/* skip busy regions */
-		p = pvt->map[x][y];
-		if (p) {
-			/* move to left of 2D areas, top left of 1D */
-			x = p->p0.x;
-			if (!p->is2d)
-				y = p->p0.y;
-
-			/* start over */
-			found = 0;
-		} else {
-			/* count consecutive free slots */
-			found++;
-			if (found == num_slots)
-				break;
-		}
-
-		/* move to the left */
-		if (x == 0)
-			y--;
-		x = (x ? : tcm->width) - 1;
-
-	}
-
-	/* set top-left corner */
-	area->p0.x = x;
-	area->p0.y = y;
-	return 0;
-}
-
-/**
- * Find a place for a 2D area of given size inside a scan field based on its
- * alignment needs.
- *
- * @param w	width of desired area
- * @param h	height of desired area
- * @param align	desired area alignment
- * @param area	pointer to the area that will be set to the best position
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
-				   struct tcm_area *area)
-{
-	s32 ret = 0;
-	struct tcm_area field = {0};
-	u16 boundary_x, boundary_y;
-	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-
-	if (align > 1) {
-		/* prefer top-left corner */
-		boundary_x = pvt->div_pt.x - 1;
-		boundary_y = pvt->div_pt.y - 1;
-
-		/* expand width and height if needed */
-		if (w > pvt->div_pt.x)
-			boundary_x = tcm->width - 1;
-		if (h > pvt->div_pt.y)
-			boundary_y = tcm->height - 1;
-
-		assign(&field, 0, 0, boundary_x, boundary_y);
-		ret = scan_l2r_t2b(tcm, w, h, align, &field, area);
-
-		/* scan whole container if failed, but do not scan 2x */
-		if (ret != 0 && (boundary_x != tcm->width - 1 ||
-				 boundary_y != tcm->height - 1)) {
-			/* scan the entire container if nothing found */
-			assign(&field, 0, 0, tcm->width - 1, tcm->height - 1);
-			ret = scan_l2r_t2b(tcm, w, h, align, &field, area);
-		}
-	} else if (align == 1) {
-		/* prefer top-right corner */
-		boundary_x = pvt->div_pt.x;
-		boundary_y = pvt->div_pt.y - 1;
-
-		/* expand width and height if needed */
-		if (w > (tcm->width - pvt->div_pt.x))
-			boundary_x = 0;
-		if (h > pvt->div_pt.y)
-			boundary_y = tcm->height - 1;
-
-		assign(&field, tcm->width - 1, 0, boundary_x, boundary_y);
-		ret = scan_r2l_t2b(tcm, w, h, align, &field, area);
-
-		/* scan whole container if failed, but do not scan 2x */
-		if (ret != 0 && (boundary_x != 0 ||
-				 boundary_y != tcm->height - 1)) {
-			/* scan the entire container if nothing found */
-			assign(&field, tcm->width - 1, 0, 0, tcm->height - 1);
-			ret = scan_r2l_t2b(tcm, w, h, align, &field,
-					   area);
-		}
-	}
-
-	return ret;
-}
-
-/* check if an entire area is free */
-static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h)
-{
-	u16 x = 0, y = 0;
-	for (y = y0; y < y0 + h; y++) {
-		for (x = x0; x < x0 + w; x++) {
-			if (map[x][y])
-				return false;
-		}
-	}
-	return true;
-}
-
-/* fills an area with a parent tcm_area */
-static void fill_area(struct tcm *tcm, struct tcm_area *area,
-			struct tcm_area *parent)
-{
-	s32 x, y;
-	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-	struct tcm_area a, a_;
-
-	/* set area's tcm; otherwise, enumerator considers it invalid */
-	area->tcm = tcm;
-
-	tcm_for_each_slice(a, *area, a_) {
-		for (x = a.p0.x; x <= a.p1.x; ++x)
-			for (y = a.p0.y; y <= a.p1.y; ++y)
-				pvt->map[x][y] = parent;
-
-	}
-}
-
-/**
- * Compares a candidate area to the current best area, and if it is a better
- * fit, it updates the best to this one.
- *
- * @param x0, y0, w, h		top, left, width, height of candidate area
- * @param field			scan field
- * @param criteria		scan criteria
- * @param best			best candidate and its scores
- *
- * @return 1 (true) if the candidate area is known to be the final best, so no
- * more searching should be performed
- */
-static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
-			    struct tcm_area *field, s32 criteria,
-			    struct score *best)
-{
-	struct score me;	/* score for area */
-
-	/*
-	 * NOTE: For horizontal bias we always give the first found, because our
-	 * scan is horizontal-raster-based and the first candidate will always
-	 * have the horizontal bias.
-	 */
-	bool first = criteria & CR_BIAS_HORIZONTAL;
-
-	assign(&me.a, x0, y0, x0 + w - 1, y0 + h - 1);
-
-	/* calculate score for current candidate */
-	if (!first) {
-		get_neighbor_stats(tcm, &me.a, &me.n);
-		me.neighs = me.n.edge + me.n.busy;
-		get_nearness_factor(field, &me.a, &me.f);
-	}
-
-	/* the 1st candidate is always the best */
-	if (!best->a.tcm)
-		goto better;
-
-	BUG_ON(first);
-
-	/* diagonal balance check */
-	if ((criteria & CR_DIAGONAL_BALANCE) &&
-		best->neighs <= me.neighs &&
-		(best->neighs < me.neighs ||
-		 /* this implies that neighs and occupied match */
-		 best->n.busy < me.n.busy ||
-		 (best->n.busy == me.n.busy &&
-		  /* check the nearness factor */
-		  best->f.x + best->f.y > me.f.x + me.f.y)))
-		goto better;
-
-	/* not better, keep going */
-	return 0;
-
-better:
-	/* save current area as best */
-	memcpy(best, &me, sizeof(me));
-	best->a.tcm = tcm;
-	return first;
-}
-
-/**
- * Calculate the nearness factor of an area in a search field.  The nearness
- * factor is smaller if the area is closer to the search origin.
- */
-static void get_nearness_factor(struct tcm_area *field, struct tcm_area *area,
-				struct nearness_factor *nf)
-{
-	/**
-	 * Using signed math as field coordinates may be reversed if
-	 * search direction is right-to-left or bottom-to-top.
-	 */
-	nf->x = (s32)(area->p0.x - field->p0.x) * 1000 /
-		(field->p1.x - field->p0.x);
-	nf->y = (s32)(area->p0.y - field->p0.y) * 1000 /
-		(field->p1.y - field->p0.y);
-}
-
-/* get neighbor statistics */
-static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
-			 struct neighbor_stats *stat)
-{
-	s16 x = 0, y = 0;
-	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-
-	/* Clearing any exisiting values */
-	memset(stat, 0, sizeof(*stat));
-
-	/* process top & bottom edges */
-	for (x = area->p0.x; x <= area->p1.x; x++) {
-		if (area->p0.y == 0)
-			stat->edge++;
-		else if (pvt->map[x][area->p0.y - 1])
-			stat->busy++;
-
-		if (area->p1.y == tcm->height - 1)
-			stat->edge++;
-		else if (pvt->map[x][area->p1.y + 1])
-			stat->busy++;
-	}
-
-	/* process left & right edges */
-	for (y = area->p0.y; y <= area->p1.y; ++y) {
-		if (area->p0.x == 0)
-			stat->edge++;
-		else if (pvt->map[area->p0.x - 1][y])
-			stat->busy++;
-
-		if (area->p1.x == tcm->width - 1)
-			stat->edge++;
-		else if (pvt->map[area->p1.x + 1][y])
-			stat->busy++;
-	}
-}
diff --git a/drivers/gpu/drm/omapdrm/tcm.h b/drivers/gpu/drm/omapdrm/tcm.h
index a8d5ce4..ef7df7d 100644
--- a/drivers/gpu/drm/omapdrm/tcm.h
+++ b/drivers/gpu/drm/omapdrm/tcm.h
@@ -61,18 +61,17 @@
 
 	unsigned int y_offset;	/* offset to use for y coordinates */
 
-	/* 'pvt' structure shall contain any tcm details (attr) along with
-	linked list of allocated areas and mutex for mutually exclusive access
-	to the list.  It may also contain copies of width and height to notice
-	any changes to the publicly available width and height fields. */
-	void *pvt;
+	spinlock_t lock;
+	unsigned long *bitmap;
+	size_t map_size;
 
 	/* function table */
-	s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u8 align,
+	s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u16 align,
+			  int16_t offset, uint16_t slot_bytes,
 			  struct tcm_area *area);
 	s32 (*reserve_1d)(struct tcm *tcm, u32 slots, struct tcm_area *area);
-	s32 (*free)      (struct tcm *tcm, struct tcm_area *area);
-	void (*deinit)   (struct tcm *tcm);
+	s32 (*free)(struct tcm *tcm, struct tcm_area *area);
+	void (*deinit)(struct tcm *tcm);
 };
 
 /*=============================================================================
@@ -91,7 +90,7 @@
  *
  */
 
-struct tcm *sita_init(u16 width, u16 height, struct tcm_pt *attr);
+struct tcm *sita_init(u16 width, u16 height);
 
 
 /**
@@ -120,6 +119,9 @@
  *			all values may be supported by the container manager,
  *			but it must support 0 (1), 32 and 64.
  *			0 value is equivalent to 1.
+ * @param offset	Offset requirement, in bytes.  This is the offset
+ *			from a 4KiB aligned virtual address.
+ * @param slot_bytes	Width of slot in bytes
  * @param area		Pointer to where the reserved area should be stored.
  *
  * @return 0 on success.  Non-0 error code on failure.  Also,
@@ -129,7 +131,8 @@
  *	    allocation.
  */
 static inline s32 tcm_reserve_2d(struct tcm *tcm, u16 width, u16 height,
-				 u16 align, struct tcm_area *area)
+				u16 align, int16_t offset, uint16_t slot_bytes,
+				struct tcm_area *area)
 {
 	/* perform rudimentary error checking */
 	s32 res = tcm  == NULL ? -ENODEV :
@@ -140,7 +143,8 @@
 
 	if (!res) {
 		area->is2d = true;
-		res = tcm->reserve_2d(tcm, height, width, align, area);
+		res = tcm->reserve_2d(tcm, height, width, align, offset,
+					slot_bytes, area);
 		area->tcm = res ? NULL : tcm;
 	}
 
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 7d4704b..1500ab9 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -31,6 +31,16 @@
 	  Say Y here if you want to enable support for LG4573 RGB panel.
 	  To compile this driver as a module, choose M here.
 
+config DRM_PANEL_PANASONIC_VVX10F034N00
+	tristate "Panasonic VVX10F034N00 1920x1200 video mode panel"
+	depends on OF
+	depends on DRM_MIPI_DSI
+	depends on BACKLIGHT_CLASS_DEVICE
+	help
+	  Say Y here if you want to enable support for Panasonic VVX10F034N00
+	  WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some
+	  Xperia Z2 tablets
+
 config DRM_PANEL_SAMSUNG_S6E8AA0
 	tristate "Samsung S6E8AA0 DSI video mode panel"
 	depends on OF
@@ -51,4 +61,13 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called panel-sharp-lq101r1sx01.
 
+config DRM_PANEL_SHARP_LS043T1LE01
+	tristate "Sharp LS043T1LE01 qHD video mode panel"
+	depends on OF
+	depends on DRM_MIPI_DSI
+	depends on BACKLIGHT_CLASS_DEVICE
+	help
+	  Say Y here if you want to enable support for Sharp LS043T1LE01 qHD
+	  (540x960) DSI panel as found on the Qualcomm APQ8074 Dragonboard
+
 endmenu
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index d0f016d..f277eed 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,5 +1,7 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
+obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
 obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
+obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o
diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
new file mode 100644
index 0000000..7f915f7
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2015 Red Hat
+ * Copyright (C) 2015 Sony Mobile Communications Inc.
+ * Author: Werner Johansson <werner.johansson@sonymobile.com>
+ *
+ * Based on AUO panel driver by 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 <linux/backlight.h>
+#include <linux/module.h>
+#include <linux/of.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>
+
+#include <video/mipi_display.h>
+
+/*
+ * When power is turned off to this panel a minimum off time of 500ms has to be
+ * observed before powering back on as there's no external reset pin. Keep
+ * track of earliest wakeup time and delay subsequent prepare call accordingly
+ */
+#define MIN_POFF_MS (500)
+
+struct wuxga_nt_panel {
+	struct drm_panel base;
+	struct mipi_dsi_device *dsi;
+
+	struct backlight_device *backlight;
+	struct regulator *supply;
+
+	bool prepared;
+	bool enabled;
+
+	ktime_t earliest_wake;
+
+	const struct drm_display_mode *mode;
+};
+
+static inline struct wuxga_nt_panel *to_wuxga_nt_panel(struct drm_panel *panel)
+{
+	return container_of(panel, struct wuxga_nt_panel, base);
+}
+
+static int wuxga_nt_panel_on(struct wuxga_nt_panel *wuxga_nt)
+{
+	struct mipi_dsi_device *dsi = wuxga_nt->dsi;
+	int ret;
+
+	ret = mipi_dsi_turn_on_peripheral(dsi);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int wuxga_nt_panel_disable(struct drm_panel *panel)
+{
+	struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
+
+	if (!wuxga_nt->enabled)
+		return 0;
+
+	mipi_dsi_shutdown_peripheral(wuxga_nt->dsi);
+
+	if (wuxga_nt->backlight) {
+		wuxga_nt->backlight->props.power = FB_BLANK_POWERDOWN;
+		wuxga_nt->backlight->props.state |= BL_CORE_FBBLANK;
+		backlight_update_status(wuxga_nt->backlight);
+	}
+
+	wuxga_nt->enabled = false;
+
+	return 0;
+}
+
+static int wuxga_nt_panel_unprepare(struct drm_panel *panel)
+{
+	struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
+
+	if (!wuxga_nt->prepared)
+		return 0;
+
+	regulator_disable(wuxga_nt->supply);
+	wuxga_nt->earliest_wake = ktime_add_ms(ktime_get_real(), MIN_POFF_MS);
+	wuxga_nt->prepared = false;
+
+	return 0;
+}
+
+static int wuxga_nt_panel_prepare(struct drm_panel *panel)
+{
+	struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
+	int ret;
+	s64 enablewait;
+
+	if (wuxga_nt->prepared)
+		return 0;
+
+	/*
+	 * If the user re-enabled the panel before the required off-time then
+	 * we need to wait the remaining period before re-enabling regulator
+	 */
+	enablewait = ktime_ms_delta(wuxga_nt->earliest_wake, ktime_get_real());
+
+	/* Sanity check, this should never happen */
+	if (enablewait > MIN_POFF_MS)
+		enablewait = MIN_POFF_MS;
+
+	if (enablewait > 0)
+		msleep(enablewait);
+
+	ret = regulator_enable(wuxga_nt->supply);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * A minimum delay of 250ms is required after power-up until commands
+	 * can be sent
+	 */
+	msleep(250);
+
+	ret = wuxga_nt_panel_on(wuxga_nt);
+	if (ret < 0) {
+		dev_err(panel->dev, "failed to set panel on: %d\n", ret);
+		goto poweroff;
+	}
+
+	wuxga_nt->prepared = true;
+
+	return 0;
+
+poweroff:
+	regulator_disable(wuxga_nt->supply);
+
+	return ret;
+}
+
+static int wuxga_nt_panel_enable(struct drm_panel *panel)
+{
+	struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
+
+	if (wuxga_nt->enabled)
+		return 0;
+
+	if (wuxga_nt->backlight) {
+		wuxga_nt->backlight->props.power = FB_BLANK_UNBLANK;
+		wuxga_nt->backlight->props.state &= ~BL_CORE_FBBLANK;
+		backlight_update_status(wuxga_nt->backlight);
+	}
+
+	wuxga_nt->enabled = true;
+
+	return 0;
+}
+
+static const struct drm_display_mode default_mode = {
+	.clock = 164402,
+	.hdisplay = 1920,
+	.hsync_start = 1920 + 152,
+	.hsync_end = 1920 + 152 + 52,
+	.htotal = 1920 + 152 + 52 + 20,
+	.vdisplay = 1200,
+	.vsync_start = 1200 + 24,
+	.vsync_end = 1200 + 24 + 6,
+	.vtotal = 1200 + 24 + 6 + 48,
+	.vrefresh = 60,
+};
+
+static int wuxga_nt_panel_get_modes(struct drm_panel *panel)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(panel->drm, &default_mode);
+	if (!mode) {
+		dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
+				default_mode.hdisplay, default_mode.vdisplay,
+				default_mode.vrefresh);
+		return -ENOMEM;
+	}
+
+	drm_mode_set_name(mode);
+
+	drm_mode_probed_add(panel->connector, mode);
+
+	panel->connector->display_info.width_mm = 217;
+	panel->connector->display_info.height_mm = 136;
+
+	return 1;
+}
+
+static const struct drm_panel_funcs wuxga_nt_panel_funcs = {
+	.disable = wuxga_nt_panel_disable,
+	.unprepare = wuxga_nt_panel_unprepare,
+	.prepare = wuxga_nt_panel_prepare,
+	.enable = wuxga_nt_panel_enable,
+	.get_modes = wuxga_nt_panel_get_modes,
+};
+
+static const struct of_device_id wuxga_nt_of_match[] = {
+	{ .compatible = "panasonic,vvx10f034n00", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wuxga_nt_of_match);
+
+static int wuxga_nt_panel_add(struct wuxga_nt_panel *wuxga_nt)
+{
+	struct device *dev = &wuxga_nt->dsi->dev;
+	struct device_node *np;
+	int ret;
+
+	wuxga_nt->mode = &default_mode;
+
+	wuxga_nt->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(wuxga_nt->supply))
+		return PTR_ERR(wuxga_nt->supply);
+
+	np = of_parse_phandle(dev->of_node, "backlight", 0);
+	if (np) {
+		wuxga_nt->backlight = of_find_backlight_by_node(np);
+		of_node_put(np);
+
+		if (!wuxga_nt->backlight)
+			return -EPROBE_DEFER;
+	}
+
+	drm_panel_init(&wuxga_nt->base);
+	wuxga_nt->base.funcs = &wuxga_nt_panel_funcs;
+	wuxga_nt->base.dev = &wuxga_nt->dsi->dev;
+
+	ret = drm_panel_add(&wuxga_nt->base);
+	if (ret < 0)
+		goto put_backlight;
+
+	return 0;
+
+put_backlight:
+	if (wuxga_nt->backlight)
+		put_device(&wuxga_nt->backlight->dev);
+
+	return ret;
+}
+
+static void wuxga_nt_panel_del(struct wuxga_nt_panel *wuxga_nt)
+{
+	if (wuxga_nt->base.dev)
+		drm_panel_remove(&wuxga_nt->base);
+
+	if (wuxga_nt->backlight)
+		put_device(&wuxga_nt->backlight->dev);
+}
+
+static int wuxga_nt_panel_probe(struct mipi_dsi_device *dsi)
+{
+	struct wuxga_nt_panel *wuxga_nt;
+	int ret;
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
+			MIPI_DSI_MODE_VIDEO_HSE |
+			MIPI_DSI_CLOCK_NON_CONTINUOUS |
+			MIPI_DSI_MODE_LPM;
+
+	wuxga_nt = devm_kzalloc(&dsi->dev, sizeof(*wuxga_nt), GFP_KERNEL);
+	if (!wuxga_nt)
+		return -ENOMEM;
+
+	mipi_dsi_set_drvdata(dsi, wuxga_nt);
+
+	wuxga_nt->dsi = dsi;
+
+	ret = wuxga_nt_panel_add(wuxga_nt);
+	if (ret < 0)
+		return ret;
+
+	return mipi_dsi_attach(dsi);
+}
+
+static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi)
+{
+	struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = wuxga_nt_panel_disable(&wuxga_nt->base);
+	if (ret < 0)
+		dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_detach(&wuxga_nt->base);
+	wuxga_nt_panel_del(wuxga_nt);
+
+	return 0;
+}
+
+static void wuxga_nt_panel_shutdown(struct mipi_dsi_device *dsi)
+{
+	struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
+
+	wuxga_nt_panel_disable(&wuxga_nt->base);
+}
+
+static struct mipi_dsi_driver wuxga_nt_panel_driver = {
+	.driver = {
+		.name = "panel-panasonic-vvx10f034n00",
+		.of_match_table = wuxga_nt_of_match,
+	},
+	.probe = wuxga_nt_panel_probe,
+	.remove = wuxga_nt_panel_remove,
+	.shutdown = wuxga_nt_panel_shutdown,
+};
+module_mipi_dsi_driver(wuxga_nt_panel_driver);
+
+MODULE_AUTHOR("Werner Johansson <werner.johansson@sonymobile.com>");
+MODULE_DESCRIPTION("Panasonic VVX10F034N00 Novatek NT1397-based WUXGA (1920x1200) video mode panel driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
new file mode 100644
index 0000000..3aeb0bd
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2015 Red Hat
+ * Copyright (C) 2015 Sony Mobile Communications Inc.
+ * Author: Werner Johansson <werner.johansson@sonymobile.com>
+ *
+ * Based on AUO panel driver by 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 <linux/backlight.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.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>
+
+#include <video/mipi_display.h>
+
+struct sharp_nt_panel {
+	struct drm_panel base;
+	struct mipi_dsi_device *dsi;
+
+	struct backlight_device *backlight;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+
+	bool prepared;
+	bool enabled;
+
+	const struct drm_display_mode *mode;
+};
+
+static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel)
+{
+	return container_of(panel, struct sharp_nt_panel, base);
+}
+
+static int sharp_nt_panel_init(struct sharp_nt_panel *sharp_nt)
+{
+	struct mipi_dsi_device *dsi = sharp_nt->dsi;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0)
+		return ret;
+
+	msleep(120);
+
+	/* Novatek two-lane operation */
+	ret = mipi_dsi_dcs_write(dsi, 0xae, (u8[]){ 0x03 }, 1);
+	if (ret < 0)
+		return ret;
+
+	/* Set both MCU and RGB I/F to 24bpp */
+	ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT |
+					(MIPI_DCS_PIXEL_FMT_24BIT << 4));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int sharp_nt_panel_on(struct sharp_nt_panel *sharp_nt)
+{
+	struct mipi_dsi_device *dsi = sharp_nt->dsi;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int sharp_nt_panel_off(struct sharp_nt_panel *sharp_nt)
+{
+	struct mipi_dsi_device *dsi = sharp_nt->dsi;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0)
+		return ret;
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+
+static int sharp_nt_panel_disable(struct drm_panel *panel)
+{
+	struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
+
+	if (!sharp_nt->enabled)
+		return 0;
+
+	if (sharp_nt->backlight) {
+		sharp_nt->backlight->props.power = FB_BLANK_POWERDOWN;
+		backlight_update_status(sharp_nt->backlight);
+	}
+
+	sharp_nt->enabled = false;
+
+	return 0;
+}
+
+static int sharp_nt_panel_unprepare(struct drm_panel *panel)
+{
+	struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
+	int ret;
+
+	if (!sharp_nt->prepared)
+		return 0;
+
+	ret = sharp_nt_panel_off(sharp_nt);
+	if (ret < 0) {
+		dev_err(panel->dev, "failed to set panel off: %d\n", ret);
+		return ret;
+	}
+
+	regulator_disable(sharp_nt->supply);
+	if (sharp_nt->reset_gpio)
+		gpiod_set_value(sharp_nt->reset_gpio, 0);
+
+	sharp_nt->prepared = false;
+
+	return 0;
+}
+
+static int sharp_nt_panel_prepare(struct drm_panel *panel)
+{
+	struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
+	int ret;
+
+	if (sharp_nt->prepared)
+		return 0;
+
+	ret = regulator_enable(sharp_nt->supply);
+	if (ret < 0)
+		return ret;
+
+	msleep(20);
+
+	if (sharp_nt->reset_gpio) {
+		gpiod_set_value(sharp_nt->reset_gpio, 1);
+		msleep(1);
+		gpiod_set_value(sharp_nt->reset_gpio, 0);
+		msleep(1);
+		gpiod_set_value(sharp_nt->reset_gpio, 1);
+		msleep(10);
+	}
+
+	ret = sharp_nt_panel_init(sharp_nt);
+	if (ret < 0) {
+		dev_err(panel->dev, "failed to init panel: %d\n", ret);
+		goto poweroff;
+	}
+
+	ret = sharp_nt_panel_on(sharp_nt);
+	if (ret < 0) {
+		dev_err(panel->dev, "failed to set panel on: %d\n", ret);
+		goto poweroff;
+	}
+
+	sharp_nt->prepared = true;
+
+	return 0;
+
+poweroff:
+	regulator_disable(sharp_nt->supply);
+	if (sharp_nt->reset_gpio)
+		gpiod_set_value(sharp_nt->reset_gpio, 0);
+	return ret;
+}
+
+static int sharp_nt_panel_enable(struct drm_panel *panel)
+{
+	struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
+
+	if (sharp_nt->enabled)
+		return 0;
+
+	if (sharp_nt->backlight) {
+		sharp_nt->backlight->props.power = FB_BLANK_UNBLANK;
+		backlight_update_status(sharp_nt->backlight);
+	}
+
+	sharp_nt->enabled = true;
+
+	return 0;
+}
+
+static const struct drm_display_mode default_mode = {
+	.clock = 41118,
+	.hdisplay = 540,
+	.hsync_start = 540 + 48,
+	.hsync_end = 540 + 48 + 80,
+	.htotal = 540 + 48 + 80 + 32,
+	.vdisplay = 960,
+	.vsync_start = 960 + 3,
+	.vsync_end = 960 + 3 + 15,
+	.vtotal = 960 + 3 + 15 + 1,
+	.vrefresh = 60,
+};
+
+static int sharp_nt_panel_get_modes(struct drm_panel *panel)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(panel->drm, &default_mode);
+	if (!mode) {
+		dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
+				default_mode.hdisplay, default_mode.vdisplay,
+				default_mode.vrefresh);
+		return -ENOMEM;
+	}
+
+	drm_mode_set_name(mode);
+
+	drm_mode_probed_add(panel->connector, mode);
+
+	panel->connector->display_info.width_mm = 54;
+	panel->connector->display_info.height_mm = 95;
+
+	return 1;
+}
+
+static const struct drm_panel_funcs sharp_nt_panel_funcs = {
+	.disable = sharp_nt_panel_disable,
+	.unprepare = sharp_nt_panel_unprepare,
+	.prepare = sharp_nt_panel_prepare,
+	.enable = sharp_nt_panel_enable,
+	.get_modes = sharp_nt_panel_get_modes,
+};
+
+static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt)
+{
+	struct device *dev = &sharp_nt->dsi->dev;
+	struct device_node *np;
+	int ret;
+
+	sharp_nt->mode = &default_mode;
+
+	sharp_nt->supply = devm_regulator_get(dev, "avdd");
+	if (IS_ERR(sharp_nt->supply))
+		return PTR_ERR(sharp_nt->supply);
+
+	sharp_nt->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(sharp_nt->reset_gpio)) {
+		dev_err(dev, "cannot get reset-gpios %ld\n",
+			PTR_ERR(sharp_nt->reset_gpio));
+		sharp_nt->reset_gpio = NULL;
+	} else {
+		gpiod_set_value(sharp_nt->reset_gpio, 0);
+	}
+
+	np = of_parse_phandle(dev->of_node, "backlight", 0);
+	if (np) {
+		sharp_nt->backlight = of_find_backlight_by_node(np);
+		of_node_put(np);
+
+		if (!sharp_nt->backlight)
+			return -EPROBE_DEFER;
+	}
+
+	drm_panel_init(&sharp_nt->base);
+	sharp_nt->base.funcs = &sharp_nt_panel_funcs;
+	sharp_nt->base.dev = &sharp_nt->dsi->dev;
+
+	ret = drm_panel_add(&sharp_nt->base);
+	if (ret < 0)
+		goto put_backlight;
+
+	return 0;
+
+put_backlight:
+	if (sharp_nt->backlight)
+		put_device(&sharp_nt->backlight->dev);
+
+	return ret;
+}
+
+static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt)
+{
+	if (sharp_nt->base.dev)
+		drm_panel_remove(&sharp_nt->base);
+
+	if (sharp_nt->backlight)
+		put_device(&sharp_nt->backlight->dev);
+}
+
+static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi)
+{
+	struct sharp_nt_panel *sharp_nt;
+	int ret;
+
+	dsi->lanes = 2;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
+			MIPI_DSI_MODE_VIDEO_HSE |
+			MIPI_DSI_CLOCK_NON_CONTINUOUS |
+			MIPI_DSI_MODE_EOT_PACKET;
+
+	sharp_nt = devm_kzalloc(&dsi->dev, sizeof(*sharp_nt), GFP_KERNEL);
+	if (!sharp_nt)
+		return -ENOMEM;
+
+	mipi_dsi_set_drvdata(dsi, sharp_nt);
+
+	sharp_nt->dsi = dsi;
+
+	ret = sharp_nt_panel_add(sharp_nt);
+	if (ret < 0)
+		return ret;
+
+	return mipi_dsi_attach(dsi);
+}
+
+static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
+{
+	struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = sharp_nt_panel_disable(&sharp_nt->base);
+	if (ret < 0)
+		dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_detach(&sharp_nt->base);
+	sharp_nt_panel_del(sharp_nt);
+
+	return 0;
+}
+
+static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi)
+{
+	struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
+
+	sharp_nt_panel_disable(&sharp_nt->base);
+}
+
+static const struct of_device_id sharp_nt_of_match[] = {
+	{ .compatible = "sharp,ls043t1le01-qhd", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sharp_nt_of_match);
+
+static struct mipi_dsi_driver sharp_nt_panel_driver = {
+	.driver = {
+		.name = "panel-sharp-ls043t1le01-qhd",
+		.of_match_table = sharp_nt_of_match,
+	},
+	.probe = sharp_nt_panel_probe,
+	.remove = sharp_nt_panel_remove,
+	.shutdown = sharp_nt_panel_shutdown,
+};
+module_mipi_dsi_driver(sharp_nt_panel_driver);
+
+MODULE_AUTHOR("Werner Johansson <werner.johansson@sonymobile.com>");
+MODULE_DESCRIPTION("Sharp LS043T1LE01 NT35565-based qHD (540x960) video mode panel driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index f97b73e..f88a631 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -44,6 +44,10 @@
 
 	unsigned int bpc;
 
+	/**
+	 * @width: width (in millimeters) of the panel's active display area
+	 * @height: height (in millimeters) of the panel's active display area
+	 */
 	struct {
 		unsigned int width;
 		unsigned int height;
@@ -832,6 +836,34 @@
 	},
 };
 
+static const struct drm_display_mode innolux_g121x1_l03_mode = {
+	.clock = 65000,
+	.hdisplay = 1024,
+	.hsync_start = 1024 + 0,
+	.hsync_end = 1024 + 1,
+	.htotal = 1024 + 0 + 1 + 320,
+	.vdisplay = 768,
+	.vsync_start = 768 + 38,
+	.vsync_end = 768 + 38 + 1,
+	.vtotal = 768 + 38 + 1 + 0,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc innolux_g121x1_l03 = {
+	.modes = &innolux_g121x1_l03_mode,
+	.num_modes = 1,
+	.bpc = 6,
+	.size = {
+		.width = 246,
+		.height = 185,
+	},
+	.delay = {
+		.enable = 200,
+		.unprepare = 200,
+		.disable = 400,
+	},
+};
+
 static const struct drm_display_mode innolux_n116bge_mode = {
 	.clock = 76420,
 	.hdisplay = 1366,
@@ -902,6 +934,30 @@
 	},
 };
 
+static const struct display_timing kyo_tcg121xglp_timing = {
+	.pixelclock = { 52000000, 65000000, 71000000 },
+	.hactive = { 1024, 1024, 1024 },
+	.hfront_porch = { 2, 2, 2 },
+	.hback_porch = { 2, 2, 2 },
+	.hsync_len = { 86, 124, 244 },
+	.vactive = { 768, 768, 768 },
+	.vfront_porch = { 2, 2, 2 },
+	.vback_porch = { 2, 2, 2 },
+	.vsync_len = { 6, 34, 73 },
+	.flags = DISPLAY_FLAGS_DE_HIGH,
+};
+
+static const struct panel_desc kyo_tcg121xglp = {
+	.timings = &kyo_tcg121xglp_timing,
+	.num_timings = 1,
+	.bpc = 8,
+	.size = {
+		.width = 246,
+		.height = 184,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+};
+
 static const struct drm_display_mode lg_lb070wv8_mode = {
 	.clock = 33246,
 	.hdisplay = 800,
@@ -1027,6 +1083,30 @@
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
 };
 
+static const struct drm_display_mode qd43003c0_40_mode = {
+	.clock = 9000,
+	.hdisplay = 480,
+	.hsync_start = 480 + 8,
+	.hsync_end = 480 + 8 + 4,
+	.htotal = 480 + 8 + 4 + 39,
+	.vdisplay = 272,
+	.vsync_start = 272 + 4,
+	.vsync_end = 272 + 4 + 10,
+	.vtotal = 272 + 4 + 10 + 2,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc qd43003c0_40 = {
+	.modes = &qd43003c0_40_mode,
+	.num_modes = 1,
+	.bpc = 8,
+	.size = {
+		.width = 95,
+		.height = 53,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+};
+
 static const struct drm_display_mode samsung_ltn101nt05_mode = {
 	.clock = 54030,
 	.hdisplay = 1024,
@@ -1158,6 +1238,9 @@
 		.compatible ="innolux,g121i1-l01",
 		.data = &innolux_g121i1_l01
 	}, {
+		.compatible = "innolux,g121x1-l03",
+		.data = &innolux_g121x1_l03,
+	}, {
 		.compatible = "innolux,n116bge",
 		.data = &innolux_n116bge,
 	}, {
@@ -1167,6 +1250,9 @@
 		.compatible = "innolux,zj070na-01p",
 		.data = &innolux_zj070na_01p,
 	}, {
+		.compatible = "kyo,tcg121xglp",
+		.data = &kyo_tcg121xglp,
+	}, {
 		.compatible = "lg,lb070wv8",
 		.data = &lg_lb070wv8,
 	}, {
@@ -1182,6 +1268,9 @@
 		.compatible = "ortustech,com43h4m85ulc",
 		.data = &ortustech_com43h4m85ulc,
 	}, {
+		.compatible = "qiaodian,qd43003c0-40",
+		.data = &qd43003c0_40,
+	}, {
 		.compatible = "samsung,ltn101nt05",
 		.data = &samsung_ltn101nt05,
 	}, {
@@ -1263,6 +1352,36 @@
 	.lanes = 4,
 };
 
+static const struct drm_display_mode boe_tv080wum_nl0_mode = {
+	.clock = 160000,
+	.hdisplay = 1200,
+	.hsync_start = 1200 + 120,
+	.hsync_end = 1200 + 120 + 20,
+	.htotal = 1200 + 120 + 20 + 21,
+	.vdisplay = 1920,
+	.vsync_start = 1920 + 21,
+	.vsync_end = 1920 + 21 + 3,
+	.vtotal = 1920 + 21 + 3 + 18,
+	.vrefresh = 60,
+	.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static const struct panel_desc_dsi boe_tv080wum_nl0 = {
+	.desc = {
+		.modes = &boe_tv080wum_nl0_mode,
+		.num_modes = 1,
+		.size = {
+			.width = 107,
+			.height = 172,
+		},
+	},
+	.flags = MIPI_DSI_MODE_VIDEO |
+		 MIPI_DSI_MODE_VIDEO_BURST |
+		 MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
+	.format = MIPI_DSI_FMT_RGB888,
+	.lanes = 4,
+};
+
 static const struct drm_display_mode lg_ld070wx3_sl01_mode = {
 	.clock = 71000,
 	.hdisplay = 800,
@@ -1348,11 +1467,15 @@
 	.lanes = 4,
 };
 
+
 static const struct of_device_id dsi_of_match[] = {
 	{
 		.compatible = "auo,b080uan01",
 		.data = &auo_b080uan01
 	}, {
+		.compatible = "boe,tv080wum-nl0",
+		.data = &boe_tv080wum_nl0
+	}, {
 		.compatible = "lg,ld070wx3-sl01",
 		.data = &lg_ld070wx3_sl01
 	}, {
diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
index 421ae13..9909f5c 100644
--- a/drivers/gpu/drm/radeon/Kconfig
+++ b/drivers/gpu/drm/radeon/Kconfig
@@ -5,12 +5,3 @@
 	help
 	  This option selects CONFIG_MMU_NOTIFIER if it isn't already
 	  selected to enabled full userptr support.
-
-config DRM_RADEON_UMS
-	bool "Enable userspace modesetting on radeon (DEPRECATED)"
-	depends on DRM_RADEON
-	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.
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index dea53e3..08bd17d 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -58,10 +58,6 @@
 
 radeon-y := radeon_drv.o
 
-# add UMS driver
-radeon-$(CONFIG_DRM_RADEON_UMS)+= radeon_cp.o radeon_state.o radeon_mem.o \
-	radeon_irq.o r300_cmdbuf.o r600_cp.o r600_blit.o drm_buffer.o
-
 # add KMS driver
 radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
 	radeon_atombios.o radeon_agp.o atombios_crtc.o radeon_combios.o \
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index bd73b40..44ee72e 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -302,77 +302,31 @@
 		return bpc * 3;
 }
 
-/* get the max pix clock supported by the link rate and lane num */
-static int dp_get_max_dp_pix_clock(int link_rate,
-				   int lane_num,
-				   int bpp)
-{
-	return (link_rate * lane_num * 8) / bpp;
-}
-
 /***** radeon specific DP functions *****/
 
-int radeon_dp_get_max_link_rate(struct drm_connector *connector,
-				const u8 dpcd[DP_DPCD_SIZE])
-{
-	int max_link_rate;
-
-	if (radeon_connector_is_dp12_capable(connector))
-		max_link_rate = min(drm_dp_max_link_rate(dpcd), 540000);
-	else
-		max_link_rate = min(drm_dp_max_link_rate(dpcd), 270000);
-
-	return max_link_rate;
-}
-
-/* First get the min lane# when low rate is used according to pixel clock
- * (prefer low rate), second check max lane# supported by DP panel,
- * if the max lane# < low rate lane# then use max lane# instead.
- */
-static int radeon_dp_get_dp_lane_number(struct drm_connector *connector,
-					const u8 dpcd[DP_DPCD_SIZE],
-					int pix_clock)
+int radeon_dp_get_dp_link_config(struct drm_connector *connector,
+				 const u8 dpcd[DP_DPCD_SIZE],
+				 unsigned pix_clock,
+				 unsigned *dp_lanes, unsigned *dp_rate)
 {
 	int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
-	int max_link_rate = radeon_dp_get_max_link_rate(connector, dpcd);
-	int max_lane_num = drm_dp_max_lane_count(dpcd);
-	int lane_num;
-	int max_dp_pix_clock;
+	static const unsigned link_rates[3] = { 162000, 270000, 540000 };
+	unsigned max_link_rate = drm_dp_max_link_rate(dpcd);
+	unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
+	unsigned lane_num, i, max_pix_clock;
 
-	for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) {
-		max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp);
-		if (pix_clock <= max_dp_pix_clock)
-			break;
+	for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
+		for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
+			max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
+			if (max_pix_clock >= pix_clock) {
+				*dp_lanes = lane_num;
+				*dp_rate = link_rates[i];
+				return 0;
+			}
+		}
 	}
 
-	return lane_num;
-}
-
-static int radeon_dp_get_dp_link_clock(struct drm_connector *connector,
-				       const u8 dpcd[DP_DPCD_SIZE],
-				       int pix_clock)
-{
-	int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
-	int lane_num, max_pix_clock;
-
-	if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
-	    ENCODER_OBJECT_ID_NUTMEG)
-		return 270000;
-
-	lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock);
-	max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp);
-	if (pix_clock <= max_pix_clock)
-		return 162000;
-	max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp);
-	if (pix_clock <= max_pix_clock)
-		return 270000;
-	if (radeon_connector_is_dp12_capable(connector)) {
-		max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp);
-		if (pix_clock <= max_pix_clock)
-			return 540000;
-	}
-
-	return radeon_dp_get_max_link_rate(connector, dpcd);
+	return -EINVAL;
 }
 
 static u8 radeon_dp_encoder_service(struct radeon_device *rdev,
@@ -491,6 +445,7 @@
 {
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct radeon_connector_atom_dig *dig_connector;
+	int ret;
 
 	if (!radeon_connector->con_priv)
 		return;
@@ -498,10 +453,14 @@
 
 	if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
 	    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
-		dig_connector->dp_clock =
-			radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
-		dig_connector->dp_lane_count =
-			radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock);
+		ret = radeon_dp_get_dp_link_config(connector, dig_connector->dpcd,
+						   mode->clock,
+						   &dig_connector->dp_lane_count,
+						   &dig_connector->dp_clock);
+		if (ret) {
+			dig_connector->dp_clock = 0;
+			dig_connector->dp_lane_count = 0;
+		}
 	}
 }
 
@@ -510,7 +469,8 @@
 {
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct radeon_connector_atom_dig *dig_connector;
-	int dp_clock;
+	unsigned dp_clock, dp_lanes;
+	int ret;
 
 	if ((mode->clock > 340000) &&
 	    (!radeon_connector_is_dp12_capable(connector)))
@@ -520,8 +480,12 @@
 		return MODE_CLOCK_HIGH;
 	dig_connector = radeon_connector->con_priv;
 
-	dp_clock =
-		radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock);
+	ret = radeon_dp_get_dp_link_config(connector, dig_connector->dpcd,
+					   mode->clock,
+					   &dp_lanes,
+					   &dp_clock);
+	if (ret)
+		return MODE_CLOCK_HIGH;
 
 	if ((dp_clock == 540000) &&
 	    (!radeon_connector_is_dp12_capable(connector)))
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 0154db4..4c30d8c 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -4132,10 +4132,10 @@
  * @rdev: radeon_device pointer
  * @ib: radeon indirect buffer object
  *
- * Emits an DE (drawing engine) or CE (constant engine) IB
+ * Emits a DE (drawing engine) or CE (constant engine) IB
  * on the gfx ring.  IBs are usually generated by userspace
  * acceleration drivers and submitted to the kernel for
- * sheduling on the ring.  This function schedules the IB
+ * scheduling on the ring.  This function schedules the IB
  * on the gfx ring for execution by the GPU.
  */
 void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
@@ -4173,11 +4173,7 @@
 	control |= ib->length_dw | (vm_id << 24);
 
 	radeon_ring_write(ring, header);
-	radeon_ring_write(ring,
-#ifdef __BIG_ENDIAN
-			  (2 << 0) |
-#endif
-			  (ib->gpu_addr & 0xFFFFFFFC));
+	radeon_ring_write(ring, (ib->gpu_addr & 0xFFFFFFFC));
 	radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF);
 	radeon_ring_write(ring, control);
 }
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c
index 7520727..6bfc463 100644
--- a/drivers/gpu/drm/radeon/dce6_afmt.c
+++ b/drivers/gpu/drm/radeon/dce6_afmt.c
@@ -301,6 +301,22 @@
 	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
 	 */
 	if (ASIC_IS_DCE8(rdev)) {
+		unsigned int div = (RREG32(DENTIST_DISPCLK_CNTL) &
+			DENTIST_DPREFCLK_WDIVIDER_MASK) >>
+			DENTIST_DPREFCLK_WDIVIDER_SHIFT;
+
+		if (div < 128 && div >= 96)
+			div -= 64;
+		else if (div >= 64)
+			div = div / 2 - 16;
+		else if (div >= 8)
+			div /= 4;
+		else
+			div = 0;
+
+		if (div)
+			clock = rdev->clock.gpupll_outputfreq * 10 / div;
+
 		WREG32(DCE8_DCCG_AUDIO_DTO1_PHASE, 24000);
 		WREG32(DCE8_DCCG_AUDIO_DTO1_MODULE, clock);
 	} else {
diff --git a/drivers/gpu/drm/radeon/drm_buffer.c b/drivers/gpu/drm/radeon/drm_buffer.c
deleted file mode 100644
index f4e0f3a..0000000
--- a/drivers/gpu/drm/radeon/drm_buffer.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2010 Pauli Nieminen.
- * 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.
- *
- *
- **************************************************************************/
-/*
- * Multipart buffer for coping data which is larger than the page size.
- *
- * Authors:
- * Pauli Nieminen <suokkos-at-gmail-dot-com>
- */
-
-#include <linux/export.h>
-#include "drm_buffer.h"
-
-/**
- * Allocate the drm buffer object.
- *
- *   buf: Pointer to a pointer where the object is stored.
- *   size: The number of bytes to allocate.
- */
-int drm_buffer_alloc(struct drm_buffer **buf, int size)
-{
-	int nr_pages = size / PAGE_SIZE + 1;
-	int idx;
-
-	/* Allocating pointer table to end of structure makes drm_buffer
-	 * variable sized */
-	*buf = kzalloc(sizeof(struct drm_buffer) + nr_pages*sizeof(char *),
-			GFP_KERNEL);
-
-	if (*buf == NULL) {
-		DRM_ERROR("Failed to allocate drm buffer object to hold"
-				" %d bytes in %d pages.\n",
-				size, nr_pages);
-		return -ENOMEM;
-	}
-
-	(*buf)->size = size;
-
-	for (idx = 0; idx < nr_pages; ++idx) {
-
-		(*buf)->data[idx] =
-			kmalloc(min(PAGE_SIZE, size - idx * PAGE_SIZE),
-				GFP_KERNEL);
-
-
-		if ((*buf)->data[idx] == NULL) {
-			DRM_ERROR("Failed to allocate %dth page for drm"
-					" buffer with %d bytes and %d pages.\n",
-					idx + 1, size, nr_pages);
-			goto error_out;
-		}
-
-	}
-
-	return 0;
-
-error_out:
-
-	for (; idx >= 0; --idx)
-		kfree((*buf)->data[idx]);
-
-	kfree(*buf);
-	return -ENOMEM;
-}
-
-/**
- * Copy the user data to the begin of the buffer and reset the processing
- * iterator.
- *
- *   user_data: A pointer the data that is copied to the buffer.
- *   size: The Number of bytes to copy.
- */
-int drm_buffer_copy_from_user(struct drm_buffer *buf,
-			      void __user *user_data, int size)
-{
-	int nr_pages = size / PAGE_SIZE + 1;
-	int idx;
-
-	if (size > buf->size) {
-		DRM_ERROR("Requesting to copy %d bytes to a drm buffer with"
-				" %d bytes space\n",
-				size, buf->size);
-		return -EFAULT;
-	}
-
-	for (idx = 0; idx < nr_pages; ++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"
-					" (%p) %dth page.\n",
-					user_data, buf, idx);
-			return -EFAULT;
-
-		}
-	}
-	buf->iterator = 0;
-	return 0;
-}
-
-/**
- * Free the drm buffer object
- */
-void drm_buffer_free(struct drm_buffer *buf)
-{
-
-	if (buf != NULL) {
-
-		int nr_pages = buf->size / PAGE_SIZE + 1;
-		int idx;
-		for (idx = 0; idx < nr_pages; ++idx)
-			kfree(buf->data[idx]);
-
-		kfree(buf);
-	}
-}
-
-/**
- * Read an object from buffer that may be split to multiple parts. If object
- * is not split function just returns the pointer to object in buffer. But in
- * case of split object data is copied to given stack object that is suplied
- * by caller.
- *
- * The processing location of the buffer is also advanced to the next byte
- * after the object.
- *
- *   objsize: The size of the objet in bytes.
- *   stack_obj: A pointer to a memory location where object can be copied.
- */
-void *drm_buffer_read_object(struct drm_buffer *buf,
-		int objsize, void *stack_obj)
-{
-	int idx = drm_buffer_index(buf);
-	int page = drm_buffer_page(buf);
-	void *obj = NULL;
-
-	if (idx + objsize <= PAGE_SIZE) {
-		obj = &buf->data[page][idx];
-	} else {
-		/* The object is split which forces copy to temporary object.*/
-		int beginsz = PAGE_SIZE - idx;
-		memcpy(stack_obj, &buf->data[page][idx], beginsz);
-
-		memcpy(stack_obj + beginsz, &buf->data[page + 1][0],
-				objsize - beginsz);
-
-		obj = stack_obj;
-	}
-
-	drm_buffer_advance(buf, objsize);
-	return obj;
-}
diff --git a/drivers/gpu/drm/radeon/drm_buffer.h b/drivers/gpu/drm/radeon/drm_buffer.h
deleted file mode 100644
index c80d3a3..0000000
--- a/drivers/gpu/drm/radeon/drm_buffer.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2010 Pauli Nieminen.
- * 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.
- *
- *
- **************************************************************************/
-/*
- * Multipart buffer for coping data which is larger than the page size.
- *
- * Authors:
- * Pauli Nieminen <suokkos-at-gmail-dot-com>
- */
-
-#ifndef _DRM_BUFFER_H_
-#define _DRM_BUFFER_H_
-
-#include <drm/drmP.h>
-
-struct drm_buffer {
-	int iterator;
-	int size;
-	char *data[];
-};
-
-
-/**
- * Return the index of page that buffer is currently pointing at.
- */
-static inline int drm_buffer_page(struct drm_buffer *buf)
-{
-	return buf->iterator / PAGE_SIZE;
-}
-/**
- * Return the index of the current byte in the page
- */
-static inline int drm_buffer_index(struct drm_buffer *buf)
-{
-	return buf->iterator & (PAGE_SIZE - 1);
-}
-/**
- * Return number of bytes that is left to process
- */
-static inline int drm_buffer_unprocessed(struct drm_buffer *buf)
-{
-	return buf->size - buf->iterator;
-}
-
-/**
- * Advance the buffer iterator number of bytes that is given.
- */
-static inline void drm_buffer_advance(struct drm_buffer *buf, int bytes)
-{
-	buf->iterator += bytes;
-}
-
-/**
- * Allocate the drm buffer object.
- *
- *   buf: A pointer to a pointer where the object is stored.
- *   size: The number of bytes to allocate.
- */
-extern int drm_buffer_alloc(struct drm_buffer **buf, int size);
-
-/**
- * Copy the user data to the begin of the buffer and reset the processing
- * iterator.
- *
- *   user_data: A pointer the data that is copied to the buffer.
- *   size: The Number of bytes to copy.
- */
-extern int drm_buffer_copy_from_user(struct drm_buffer *buf,
-		void __user *user_data, int size);
-
-/**
- * Free the drm buffer object
- */
-extern void drm_buffer_free(struct drm_buffer *buf);
-
-/**
- * Read an object from buffer that may be split to multiple parts. If object
- * is not split function just returns the pointer to object in buffer. But in
- * case of split object data is copied to given stack object that is suplied
- * by caller.
- *
- * The processing location of the buffer is also advanced to the next byte
- * after the object.
- *
- *   objsize: The size of the objet in bytes.
- *   stack_obj: A pointer to a memory location where object can be copied.
- */
-extern void *drm_buffer_read_object(struct drm_buffer *buf,
-		int objsize, void *stack_obj);
-
-/**
- * Returns the pointer to the dword which is offset number of elements from the
- * current processing location.
- *
- * Caller must make sure that dword is not split in the buffer. This
- * requirement is easily met if all the sizes of objects in buffer are
- * multiples of dword and PAGE_SIZE is multiple dword.
- *
- * Call to this function doesn't change the processing location.
- *
- *   offset: The index of the dword relative to the internat iterator.
- */
-static inline void *drm_buffer_pointer_to_dword(struct drm_buffer *buffer,
-		int offset)
-{
-	int iter = buffer->iterator + offset * 4;
-	return &buffer->data[iter / PAGE_SIZE][iter & (PAGE_SIZE - 1)];
-}
-/**
- * Returns the pointer to the dword which is offset number of elements from
- * the current processing location.
- *
- * Call to this function doesn't change the processing location.
- *
- *   offset: The index of the byte relative to the internat iterator.
- */
-static inline void *drm_buffer_pointer_to_byte(struct drm_buffer *buffer,
-		int offset)
-{
-	int iter = buffer->iterator + offset;
-	return &buffer->data[iter / PAGE_SIZE][iter & (PAGE_SIZE - 1)];
-}
-
-#endif
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 9e7e2bf..5eae0a8 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -3150,7 +3150,8 @@
 {
 	fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff;
 	fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff;
-	fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff;
+	fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff;
+	fixed20_12 crit_point_ff = {0};
 	uint32_t temp, data, mem_trcd, mem_trp, mem_tras;
 	fixed20_12 memtcas_ff[8] = {
 		dfixed_init(1),
@@ -3204,7 +3205,7 @@
 	fixed20_12 min_mem_eff;
 	fixed20_12 mc_latency_sclk, mc_latency_mclk, k1;
 	fixed20_12 cur_latency_mclk, cur_latency_sclk;
-	fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate,
+	fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate = {0},
 		disp_drain_rate2, read_return_rate;
 	fixed20_12 time_disp1_drop_priority;
 	int c;
diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c
deleted file mode 100644
index 9418e38..0000000
--- a/drivers/gpu/drm/radeon/r300_cmdbuf.c
+++ /dev/null
@@ -1,1186 +0,0 @@
-/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*-
- *
- * Copyright (C) The Weather Channel, Inc.  2002.
- * Copyright (C) 2004 Nicolai Haehnle.
- * All Rights Reserved.
- *
- * The Weather Channel (TM) funded Tungsten Graphics to develop the
- * initial release of the Radeon 8500 driver under the XFree86 license.
- * This notice must be preserved.
- *
- * 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
- * PRECISION INSIGHT 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.
- *
- * Authors:
- *    Nicolai Haehnle <prefect_@gmx.net>
- *
- * ------------------------ This file is DEPRECATED! -------------------------
- */
-
-#include <drm/drmP.h>
-#include <drm/radeon_drm.h>
-#include "radeon_drv.h"
-#include "r300_reg.h"
-#include "drm_buffer.h"
-
-#include <asm/unaligned.h>
-
-#define R300_SIMULTANEOUS_CLIPRECTS		4
-
-/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
- */
-static const int r300_cliprect_cntl[4] = {
-	0xAAAA,
-	0xEEEE,
-	0xFEFE,
-	0xFFFE
-};
-
-/**
- * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
- * buffer, starting with index n.
- */
-static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
-			       drm_radeon_kcmd_buffer_t *cmdbuf, int n)
-{
-	struct drm_clip_rect box;
-	int nr;
-	int i;
-	RING_LOCALS;
-
-	nr = cmdbuf->nbox - n;
-	if (nr > R300_SIMULTANEOUS_CLIPRECTS)
-		nr = R300_SIMULTANEOUS_CLIPRECTS;
-
-	DRM_DEBUG("%i cliprects\n", nr);
-
-	if (nr) {
-		BEGIN_RING(6 + nr * 2);
-		OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
-
-		for (i = 0; i < nr; ++i) {
-			if (copy_from_user
-			    (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
-				DRM_ERROR("copy cliprect faulted\n");
-				return -EFAULT;
-			}
-
-			box.x2--; /* Hardware expects inclusive bottom-right corner */
-			box.y2--;
-
-			if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
-				box.x1 = (box.x1) &
-					R300_CLIPRECT_MASK;
-				box.y1 = (box.y1) &
-					R300_CLIPRECT_MASK;
-				box.x2 = (box.x2) &
-					R300_CLIPRECT_MASK;
-				box.y2 = (box.y2) &
-					R300_CLIPRECT_MASK;
-			} else {
-				box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) &
-					R300_CLIPRECT_MASK;
-				box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) &
-					R300_CLIPRECT_MASK;
-				box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) &
-					R300_CLIPRECT_MASK;
-				box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
-					R300_CLIPRECT_MASK;
-			}
-
-			OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
-				 (box.y1 << R300_CLIPRECT_Y_SHIFT));
-			OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
-				 (box.y2 << R300_CLIPRECT_Y_SHIFT));
-
-		}
-
-		OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
-
-		/* TODO/SECURITY: Force scissors to a safe value, otherwise the
-		 * client might be able to trample over memory.
-		 * The impact should be very limited, but I'd rather be safe than
-		 * sorry.
-		 */
-		OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1));
-		OUT_RING(0);
-		OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK);
-		ADVANCE_RING();
-	} else {
-		/* Why we allow zero cliprect rendering:
-		 * There are some commands in a command buffer that must be submitted
-		 * even when there are no cliprects, e.g. DMA buffer discard
-		 * or state setting (though state setting could be avoided by
-		 * simulating a loss of context).
-		 *
-		 * Now since the cmdbuf interface is so chaotic right now (and is
-		 * bound to remain that way for a bit until things settle down),
-		 * it is basically impossible to filter out the commands that are
-		 * necessary and those that aren't.
-		 *
-		 * So I choose the safe way and don't do any filtering at all;
-		 * instead, I simply set up the engine so that all rendering
-		 * can't produce any fragments.
-		 */
-		BEGIN_RING(2);
-		OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0);
-		ADVANCE_RING();
-	}
-
-	/* flus cache and wait idle clean after cliprect change */
-	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
-	OUT_RING(R300_RB3D_DC_FLUSH);
-	ADVANCE_RING();
-	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
-	ADVANCE_RING();
-	/* set flush flag */
-	dev_priv->track_flush |= RADEON_FLUSH_EMITED;
-
-	return 0;
-}
-
-static u8 r300_reg_flags[0x10000 >> 2];
-
-void r300_init_reg_flags(struct drm_device *dev)
-{
-	int i;
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	memset(r300_reg_flags, 0, 0x10000 >> 2);
-#define ADD_RANGE_MARK(reg, count,mark) \
-		for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
-			r300_reg_flags[i]|=(mark);
-
-#define MARK_SAFE		1
-#define MARK_CHECK_OFFSET	2
-
-#define ADD_RANGE(reg, count)	ADD_RANGE_MARK(reg, count, MARK_SAFE)
-
-	/* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
-	ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
-	ADD_RANGE(R300_VAP_CNTL, 1);
-	ADD_RANGE(R300_SE_VTE_CNTL, 2);
-	ADD_RANGE(0x2134, 2);
-	ADD_RANGE(R300_VAP_CNTL_STATUS, 1);
-	ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
-	ADD_RANGE(0x21DC, 1);
-	ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
-	ADD_RANGE(R300_VAP_CLIP_X_0, 4);
-	ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1);
-	ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
-	ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
-	ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
-	ADD_RANGE(R300_GB_ENABLE, 1);
-	ADD_RANGE(R300_GB_MSPOS0, 5);
-	ADD_RANGE(R300_TX_INVALTAGS, 1);
-	ADD_RANGE(R300_TX_ENABLE, 1);
-	ADD_RANGE(0x4200, 4);
-	ADD_RANGE(0x4214, 1);
-	ADD_RANGE(R300_RE_POINTSIZE, 1);
-	ADD_RANGE(0x4230, 3);
-	ADD_RANGE(R300_RE_LINE_CNT, 1);
-	ADD_RANGE(R300_RE_UNK4238, 1);
-	ADD_RANGE(0x4260, 3);
-	ADD_RANGE(R300_RE_SHADE, 4);
-	ADD_RANGE(R300_RE_POLYGON_MODE, 5);
-	ADD_RANGE(R300_RE_ZBIAS_CNTL, 1);
-	ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
-	ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1);
-	ADD_RANGE(R300_RE_CULL_CNTL, 1);
-	ADD_RANGE(0x42C0, 2);
-	ADD_RANGE(R300_RS_CNTL_0, 2);
-
-	ADD_RANGE(R300_SU_REG_DEST, 1);
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530)
-		ADD_RANGE(RV530_FG_ZBREG_DEST, 1);
-
-	ADD_RANGE(R300_SC_HYPERZ, 2);
-	ADD_RANGE(0x43E8, 1);
-
-	ADD_RANGE(0x46A4, 5);
-
-	ADD_RANGE(R300_RE_FOG_STATE, 1);
-	ADD_RANGE(R300_FOG_COLOR_R, 3);
-	ADD_RANGE(R300_PP_ALPHA_TEST, 2);
-	ADD_RANGE(0x4BD8, 1);
-	ADD_RANGE(R300_PFS_PARAM_0_X, 64);
-	ADD_RANGE(0x4E00, 1);
-	ADD_RANGE(R300_RB3D_CBLEND, 2);
-	ADD_RANGE(R300_RB3D_COLORMASK, 1);
-	ADD_RANGE(R300_RB3D_BLEND_COLOR, 3);
-	ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET);	/* check offset */
-	ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
-	ADD_RANGE(0x4E50, 9);
-	ADD_RANGE(0x4E88, 1);
-	ADD_RANGE(0x4EA0, 2);
-	ADD_RANGE(R300_ZB_CNTL, 3);
-	ADD_RANGE(R300_ZB_FORMAT, 4);
-	ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);	/* check offset */
-	ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
-	ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
-	ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
-	ADD_RANGE(R300_ZB_ZPASS_DATA, 2); /* ZB_ZPASS_DATA, ZB_ZPASS_ADDR */
-
-	ADD_RANGE(R300_TX_FILTER_0, 16);
-	ADD_RANGE(R300_TX_FILTER1_0, 16);
-	ADD_RANGE(R300_TX_SIZE_0, 16);
-	ADD_RANGE(R300_TX_FORMAT_0, 16);
-	ADD_RANGE(R300_TX_PITCH_0, 16);
-	/* Texture offset is dangerous and needs more checking */
-	ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
-	ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
-	ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
-
-	/* Sporadic registers used as primitives are emitted */
-	ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1);
-	ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
-	ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
-	ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
-		ADD_RANGE(R500_VAP_INDEX_OFFSET, 1);
-		ADD_RANGE(R500_US_CONFIG, 2);
-		ADD_RANGE(R500_US_CODE_ADDR, 3);
-		ADD_RANGE(R500_US_FC_CTRL, 1);
-		ADD_RANGE(R500_RS_IP_0, 16);
-		ADD_RANGE(R500_RS_INST_0, 16);
-		ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
-		ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
-		ADD_RANGE(R500_ZB_FIFO_SIZE, 2);
-	} else {
-		ADD_RANGE(R300_PFS_CNTL_0, 3);
-		ADD_RANGE(R300_PFS_NODE_0, 4);
-		ADD_RANGE(R300_PFS_TEXI_0, 64);
-		ADD_RANGE(R300_PFS_INSTR0_0, 64);
-		ADD_RANGE(R300_PFS_INSTR1_0, 64);
-		ADD_RANGE(R300_PFS_INSTR2_0, 64);
-		ADD_RANGE(R300_PFS_INSTR3_0, 64);
-		ADD_RANGE(R300_RS_INTERP_0, 8);
-		ADD_RANGE(R300_RS_ROUTE_0, 8);
-
-	}
-}
-
-static __inline__ int r300_check_range(unsigned reg, int count)
-{
-	int i;
-	if (reg & ~0xffff)
-		return -1;
-	for (i = (reg >> 2); i < (reg >> 2) + count; i++)
-		if (r300_reg_flags[i] != MARK_SAFE)
-			return 1;
-	return 0;
-}
-
-static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
-							  dev_priv,
-							  drm_radeon_kcmd_buffer_t
-							  * cmdbuf,
-							  drm_r300_cmd_header_t
-							  header)
-{
-	int reg;
-	int sz;
-	int i;
-	u32 *value;
-	RING_LOCALS;
-
-	sz = header.packet0.count;
-	reg = (header.packet0.reghi << 8) | header.packet0.reglo;
-
-	if ((sz > 64) || (sz < 0)) {
-		DRM_ERROR("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
-			 reg, sz);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < sz; i++) {
-		switch (r300_reg_flags[(reg >> 2) + i]) {
-		case MARK_SAFE:
-			break;
-		case MARK_CHECK_OFFSET:
-			value = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
-			if (!radeon_check_offset(dev_priv, *value)) {
-				DRM_ERROR("Offset failed range check (reg=%04x sz=%d)\n",
-					 reg, sz);
-				return -EINVAL;
-			}
-			break;
-		default:
-			DRM_ERROR("Register %04x failed check as flag=%02x\n",
-				reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
-			return -EINVAL;
-		}
-	}
-
-	BEGIN_RING(1 + sz);
-	OUT_RING(CP_PACKET0(reg, sz - 1));
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
-	ADVANCE_RING();
-
-	return 0;
-}
-
-/**
- * Emits a packet0 setting arbitrary registers.
- * Called by r300_do_cp_cmdbuf.
- *
- * Note that checks are performed on contents and addresses of the registers
- */
-static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
-					drm_radeon_kcmd_buffer_t *cmdbuf,
-					drm_r300_cmd_header_t header)
-{
-	int reg;
-	int sz;
-	RING_LOCALS;
-
-	sz = header.packet0.count;
-	reg = (header.packet0.reghi << 8) | header.packet0.reglo;
-
-	if (!sz)
-		return 0;
-
-	if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
-		return -EINVAL;
-
-	if (reg + sz * 4 >= 0x10000) {
-		DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
-			  sz);
-		return -EINVAL;
-	}
-
-	if (r300_check_range(reg, sz)) {
-		/* go and check everything */
-		return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf,
-							   header);
-	}
-	/* the rest of the data is safe to emit, whatever the values the user passed */
-
-	BEGIN_RING(1 + sz);
-	OUT_RING(CP_PACKET0(reg, sz - 1));
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
-	ADVANCE_RING();
-
-	return 0;
-}
-
-/**
- * Uploads user-supplied vertex program instructions or parameters onto
- * the graphics card.
- * Called by r300_do_cp_cmdbuf.
- */
-static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
-				    drm_radeon_kcmd_buffer_t *cmdbuf,
-				    drm_r300_cmd_header_t header)
-{
-	int sz;
-	int addr;
-	RING_LOCALS;
-
-	sz = header.vpu.count;
-	addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;
-
-	if (!sz)
-		return 0;
-	if (sz * 16 > drm_buffer_unprocessed(cmdbuf->buffer))
-		return -EINVAL;
-
-	/* VAP is very sensitive so we purge cache before we program it
-	 * and we also flush its state before & after */
-	BEGIN_RING(6);
-	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
-	OUT_RING(R300_RB3D_DC_FLUSH);
-	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
-	OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
-	OUT_RING(0);
-	ADVANCE_RING();
-	/* set flush flag */
-	dev_priv->track_flush |= RADEON_FLUSH_EMITED;
-
-	BEGIN_RING(3 + sz * 4);
-	OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
-	OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * 4);
-	ADVANCE_RING();
-
-	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
-	OUT_RING(0);
-	ADVANCE_RING();
-
-	return 0;
-}
-
-/**
- * Emit a clear packet from userspace.
- * Called by r300_emit_packet3.
- */
-static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
-				      drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	RING_LOCALS;
-
-	if (8 * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
-		return -EINVAL;
-
-	BEGIN_RING(10);
-	OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
-	OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
-		 (1 << R300_PRIM_NUM_VERTICES_SHIFT));
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, 8);
-	ADVANCE_RING();
-
-	BEGIN_RING(4);
-	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
-	OUT_RING(R300_RB3D_DC_FLUSH);
-	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
-	ADVANCE_RING();
-	/* set flush flag */
-	dev_priv->track_flush |= RADEON_FLUSH_EMITED;
-
-	return 0;
-}
-
-static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
-					       drm_radeon_kcmd_buffer_t *cmdbuf,
-					       u32 header)
-{
-	int count, i, k;
-#define MAX_ARRAY_PACKET  64
-	u32 *data;
-	u32 narrays;
-	RING_LOCALS;
-
-	count = (header & RADEON_CP_PACKET_COUNT_MASK) >> 16;
-
-	if ((count + 1) > MAX_ARRAY_PACKET) {
-		DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
-			  count);
-		return -EINVAL;
-	}
-	/* carefully check packet contents */
-
-	/* We have already read the header so advance the buffer. */
-	drm_buffer_advance(cmdbuf->buffer, 4);
-
-	narrays = *(u32 *)drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
-	k = 0;
-	i = 1;
-	while ((k < narrays) && (i < (count + 1))) {
-		i++;		/* skip attribute field */
-		data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
-		if (!radeon_check_offset(dev_priv, *data)) {
-			DRM_ERROR
-			    ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
-			     k, i);
-			return -EINVAL;
-		}
-		k++;
-		i++;
-		if (k == narrays)
-			break;
-		/* have one more to process, they come in pairs */
-		data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
-		if (!radeon_check_offset(dev_priv, *data)) {
-			DRM_ERROR
-			    ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
-			     k, i);
-			return -EINVAL;
-		}
-		k++;
-		i++;
-	}
-	/* do the counts match what we expect ? */
-	if ((k != narrays) || (i != (count + 1))) {
-		DRM_ERROR
-		    ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
-		     k, i, narrays, count + 1);
-		return -EINVAL;
-	}
-
-	/* all clear, output packet */
-
-	BEGIN_RING(count + 2);
-	OUT_RING(header);
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 1);
-	ADVANCE_RING();
-
-	return 0;
-}
-
-static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
-					     drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
-	int count, ret;
-	RING_LOCALS;
-
-
-	count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16;
-
-	if (*cmd & 0x8000) {
-		u32 offset;
-		u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
-		if (*cmd1 & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
-			      | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-
-			u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
-			offset = *cmd2 << 10;
-			ret = !radeon_check_offset(dev_priv, offset);
-			if (ret) {
-				DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
-				return -EINVAL;
-			}
-		}
-
-		if ((*cmd1 & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
-		    (*cmd1 & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-			u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
-			offset = *cmd3 << 10;
-			ret = !radeon_check_offset(dev_priv, offset);
-			if (ret) {
-				DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
-				return -EINVAL;
-			}
-
-		}
-	}
-
-	BEGIN_RING(count+2);
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
-	ADVANCE_RING();
-
-	return 0;
-}
-
-static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
-					    drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
-	u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
-	int count;
-	int expected_count;
-	RING_LOCALS;
-
-	count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16;
-
-	expected_count = *cmd1 >> 16;
-	if (!(*cmd1 & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
-		expected_count = (expected_count+1)/2;
-
-	if (count && count != expected_count) {
-		DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n",
-			count, expected_count);
-		return -EINVAL;
-	}
-
-	BEGIN_RING(count+2);
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
-	ADVANCE_RING();
-
-	if (!count) {
-		drm_r300_cmd_header_t stack_header, *header;
-		u32 *cmd1, *cmd2, *cmd3;
-
-		if (drm_buffer_unprocessed(cmdbuf->buffer)
-				< 4*4 + sizeof(stack_header)) {
-			DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n");
-			return -EINVAL;
-		}
-
-		header = drm_buffer_read_object(cmdbuf->buffer,
-				sizeof(stack_header), &stack_header);
-
-		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
-		cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
-		cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
-		cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
-
-		if (header->header.cmd_type != R300_CMD_PACKET3 ||
-		    header->packet3.packet != R300_CMD_PACKET3_RAW ||
-		    *cmd != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
-			DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n");
-			return -EINVAL;
-		}
-
-		if ((*cmd1 & 0x8000ffff) != 0x80000810) {
-			DRM_ERROR("Invalid indx_buffer reg address %08X\n",
-					*cmd1);
-			return -EINVAL;
-		}
-		if (!radeon_check_offset(dev_priv, *cmd2)) {
-			DRM_ERROR("Invalid indx_buffer offset is %08X\n",
-					*cmd2);
-			return -EINVAL;
-		}
-		if (*cmd3 != expected_count) {
-			DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n",
-				*cmd3, expected_count);
-			return -EINVAL;
-		}
-
-		BEGIN_RING(4);
-		OUT_RING_DRM_BUFFER(cmdbuf->buffer, 4);
-		ADVANCE_RING();
-	}
-
-	return 0;
-}
-
-static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
-					    drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	u32 *header;
-	int count;
-	RING_LOCALS;
-
-	if (4 > drm_buffer_unprocessed(cmdbuf->buffer))
-		return -EINVAL;
-
-	/* Fixme !! This simply emits a packet without much checking.
-	   We need to be smarter. */
-
-	/* obtain first word - actual packet3 header */
-	header = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
-
-	/* Is it packet 3 ? */
-	if ((*header >> 30) != 0x3) {
-		DRM_ERROR("Not a packet3 header (0x%08x)\n", *header);
-		return -EINVAL;
-	}
-
-	count = (*header >> 16) & 0x3fff;
-
-	/* Check again now that we know how much data to expect */
-	if ((count + 2) * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) {
-		DRM_ERROR
-		    ("Expected packet3 of length %d but have only %d bytes left\n",
-		     (count + 2) * 4, drm_buffer_unprocessed(cmdbuf->buffer));
-		return -EINVAL;
-	}
-
-	/* Is it a packet type we know about ? */
-	switch (*header & 0xff00) {
-	case RADEON_3D_LOAD_VBPNTR:	/* load vertex array pointers */
-		return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, *header);
-
-	case RADEON_CNTL_BITBLT_MULTI:
-		return r300_emit_bitblt_multi(dev_priv, cmdbuf);
-
-	case RADEON_CP_INDX_BUFFER:
-		DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n");
-		return -EINVAL;
-	case RADEON_CP_3D_DRAW_IMMD_2:
-		/* triggers drawing using in-packet vertex data */
-	case RADEON_CP_3D_DRAW_VBUF_2:
-		/* triggers drawing of vertex buffers setup elsewhere */
-		dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
-					   RADEON_PURGE_EMITED);
-		break;
-	case RADEON_CP_3D_DRAW_INDX_2:
-		/* triggers drawing using indices to vertex buffer */
-		/* whenever we send vertex we clear flush & purge */
-		dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
-					   RADEON_PURGE_EMITED);
-		return r300_emit_draw_indx_2(dev_priv, cmdbuf);
-	case RADEON_WAIT_FOR_IDLE:
-	case RADEON_CP_NOP:
-		/* these packets are safe */
-		break;
-	default:
-		DRM_ERROR("Unknown packet3 header (0x%08x)\n", *header);
-		return -EINVAL;
-	}
-
-	BEGIN_RING(count + 2);
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
-	ADVANCE_RING();
-
-	return 0;
-}
-
-/**
- * Emit a rendering packet3 from userspace.
- * Called by r300_do_cp_cmdbuf.
- */
-static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
-					drm_radeon_kcmd_buffer_t *cmdbuf,
-					drm_r300_cmd_header_t header)
-{
-	int n;
-	int ret;
-	int orig_iter = cmdbuf->buffer->iterator;
-
-	/* This is a do-while-loop so that we run the interior at least once,
-	 * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
-	 */
-	n = 0;
-	do {
-		if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) {
-			ret = r300_emit_cliprects(dev_priv, cmdbuf, n);
-			if (ret)
-				return ret;
-
-			cmdbuf->buffer->iterator = orig_iter;
-		}
-
-		switch (header.packet3.packet) {
-		case R300_CMD_PACKET3_CLEAR:
-			DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
-			ret = r300_emit_clear(dev_priv, cmdbuf);
-			if (ret) {
-				DRM_ERROR("r300_emit_clear failed\n");
-				return ret;
-			}
-			break;
-
-		case R300_CMD_PACKET3_RAW:
-			DRM_DEBUG("R300_CMD_PACKET3_RAW\n");
-			ret = r300_emit_raw_packet3(dev_priv, cmdbuf);
-			if (ret) {
-				DRM_ERROR("r300_emit_raw_packet3 failed\n");
-				return ret;
-			}
-			break;
-
-		default:
-			DRM_ERROR("bad packet3 type %i at byte %d\n",
-				  header.packet3.packet,
-				  cmdbuf->buffer->iterator - (int)sizeof(header));
-			return -EINVAL;
-		}
-
-		n += R300_SIMULTANEOUS_CLIPRECTS;
-	} while (n < cmdbuf->nbox);
-
-	return 0;
-}
-
-/* Some of the R300 chips seem to be extremely touchy about the two registers
- * that are configured in r300_pacify.
- * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace
- * sends a command buffer that contains only state setting commands and a
- * vertex program/parameter upload sequence, this will eventually lead to a
- * lockup, unless the sequence is bracketed by calls to r300_pacify.
- * So we should take great care to *always* call r300_pacify before
- * *anything* 3D related, and again afterwards. This is what the
- * call bracket in r300_do_cp_cmdbuf is for.
- */
-
-/**
- * Emit the sequence to pacify R300.
- */
-static void r300_pacify(drm_radeon_private_t *dev_priv)
-{
-	uint32_t cache_z, cache_3d, cache_2d;
-	RING_LOCALS;
-
-	cache_z = R300_ZC_FLUSH;
-	cache_2d = R300_RB2D_DC_FLUSH;
-	cache_3d = R300_RB3D_DC_FLUSH;
-	if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) {
-		/* we can purge, primitive where draw since last purge */
-		cache_z |= R300_ZC_FREE;
-		cache_2d |= R300_RB2D_DC_FREE;
-		cache_3d |= R300_RB3D_DC_FREE;
-	}
-
-	/* flush & purge zbuffer */
-	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
-	OUT_RING(cache_z);
-	ADVANCE_RING();
-	/* flush & purge 3d */
-	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
-	OUT_RING(cache_3d);
-	ADVANCE_RING();
-	/* flush & purge texture */
-	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0));
-	OUT_RING(0);
-	ADVANCE_RING();
-	/* FIXME: is this one really needed ? */
-	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0));
-	OUT_RING(0);
-	ADVANCE_RING();
-	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
-	ADVANCE_RING();
-	/* flush & purge 2d through E2 as RB2D will trigger lockup */
-	BEGIN_RING(4);
-	OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0));
-	OUT_RING(cache_2d);
-	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-	OUT_RING(RADEON_WAIT_2D_IDLECLEAN |
-		 RADEON_WAIT_HOST_IDLECLEAN);
-	ADVANCE_RING();
-	/* set flush & purge flags */
-	dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
-}
-
-/**
- * Called by r300_do_cp_cmdbuf to update the internal buffer age and state.
- * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
- * be careful about how this function is called.
- */
-static void r300_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf)
-{
-	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
-	struct drm_radeon_master_private *master_priv = master->driver_priv;
-
-	buf_priv->age = ++master_priv->sarea_priv->last_dispatch;
-	buf->pending = 1;
-	buf->used = 0;
-}
-
-static void r300_cmd_wait(drm_radeon_private_t * dev_priv,
-			  drm_r300_cmd_header_t header)
-{
-	u32 wait_until;
-	RING_LOCALS;
-
-	if (!header.wait.flags)
-		return;
-
-	wait_until = 0;
-
-	switch(header.wait.flags) {
-	case R300_WAIT_2D:
-		wait_until = RADEON_WAIT_2D_IDLE;
-		break;
-	case R300_WAIT_3D:
-		wait_until = RADEON_WAIT_3D_IDLE;
-		break;
-	case R300_NEW_WAIT_2D_3D:
-		wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE;
-		break;
-	case R300_NEW_WAIT_2D_2D_CLEAN:
-		wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
-		break;
-	case R300_NEW_WAIT_3D_3D_CLEAN:
-		wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
-		break;
-	case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN:
-		wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
-		wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
-		break;
-	default:
-		return;
-	}
-
-	BEGIN_RING(2);
-	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-	OUT_RING(wait_until);
-	ADVANCE_RING();
-}
-
-static int r300_scratch(drm_radeon_private_t *dev_priv,
-			drm_radeon_kcmd_buffer_t *cmdbuf,
-			drm_r300_cmd_header_t header)
-{
-	u32 *ref_age_base;
-	u32 i, *buf_idx, h_pending;
-	u64 *ptr_addr;
-	u64 stack_ptr_addr;
-	RING_LOCALS;
-
-	if (drm_buffer_unprocessed(cmdbuf->buffer) <
-	    (sizeof(u64) + header.scratch.n_bufs * sizeof(*buf_idx))) {
-		return -EINVAL;
-	}
-
-	if (header.scratch.reg >= 5) {
-		return -EINVAL;
-	}
-
-	dev_priv->scratch_ages[header.scratch.reg]++;
-
-	ptr_addr = drm_buffer_read_object(cmdbuf->buffer,
-			sizeof(stack_ptr_addr), &stack_ptr_addr);
-	ref_age_base = (u32 *)(unsigned long)get_unaligned(ptr_addr);
-
-	for (i=0; i < header.scratch.n_bufs; i++) {
-		buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
-		*buf_idx *= 2; /* 8 bytes per buf */
-
-		if (copy_to_user(ref_age_base + *buf_idx,
-				&dev_priv->scratch_ages[header.scratch.reg],
-				sizeof(u32)))
-			return -EINVAL;
-
-		if (copy_from_user(&h_pending,
-				ref_age_base + *buf_idx + 1,
-				sizeof(u32)))
-			return -EINVAL;
-
-		if (h_pending == 0)
-			return -EINVAL;
-
-		h_pending--;
-
-		if (copy_to_user(ref_age_base + *buf_idx + 1,
-					&h_pending,
-					sizeof(u32)))
-			return -EINVAL;
-
-		drm_buffer_advance(cmdbuf->buffer, sizeof(*buf_idx));
-	}
-
-	BEGIN_RING(2);
-	OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
-	OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
-	ADVANCE_RING();
-
-	return 0;
-}
-
-/**
- * Uploads user-supplied vertex program instructions or parameters onto
- * the graphics card.
- * Called by r300_do_cp_cmdbuf.
- */
-static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
-				       drm_radeon_kcmd_buffer_t *cmdbuf,
-				       drm_r300_cmd_header_t header)
-{
-	int sz;
-	int addr;
-	int type;
-	int isclamp;
-	int stride;
-	RING_LOCALS;
-
-	sz = header.r500fp.count;
-	/* address is 9 bits 0 - 8, bit 1 of flags is part of address */
-	addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo;
-
-	type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
-	isclamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
-
-	addr |= (type << 16);
-	addr |= (isclamp << 17);
-
-	stride = type ? 4 : 6;
-
-	DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type);
-	if (!sz)
-		return 0;
-	if (sz * stride * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
-		return -EINVAL;
-
-	BEGIN_RING(3 + sz * stride);
-	OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr);
-	OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1));
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * stride);
-
-	ADVANCE_RING();
-
-	return 0;
-}
-
-
-/**
- * Parses and validates a user-supplied command buffer and emits appropriate
- * commands on the DMA ring buffer.
- * Called by the ioctl handler function radeon_cp_cmdbuf.
- */
-int r300_do_cp_cmdbuf(struct drm_device *dev,
-		      struct drm_file *file_priv,
-		      drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
-	struct drm_device_dma *dma = dev->dma;
-	struct drm_buf *buf = NULL;
-	int emit_dispatch_age = 0;
-	int ret = 0;
-
-	DRM_DEBUG("\n");
-
-	/* pacify */
-	r300_pacify(dev_priv);
-
-	if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
-		ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
-		if (ret)
-			goto cleanup;
-	}
-
-	while (drm_buffer_unprocessed(cmdbuf->buffer)
-			>= sizeof(drm_r300_cmd_header_t)) {
-		int idx;
-		drm_r300_cmd_header_t *header, stack_header;
-
-		header = drm_buffer_read_object(cmdbuf->buffer,
-				sizeof(stack_header), &stack_header);
-
-		switch (header->header.cmd_type) {
-		case R300_CMD_PACKET0:
-			DRM_DEBUG("R300_CMD_PACKET0\n");
-			ret = r300_emit_packet0(dev_priv, cmdbuf, *header);
-			if (ret) {
-				DRM_ERROR("r300_emit_packet0 failed\n");
-				goto cleanup;
-			}
-			break;
-
-		case R300_CMD_VPU:
-			DRM_DEBUG("R300_CMD_VPU\n");
-			ret = r300_emit_vpu(dev_priv, cmdbuf, *header);
-			if (ret) {
-				DRM_ERROR("r300_emit_vpu failed\n");
-				goto cleanup;
-			}
-			break;
-
-		case R300_CMD_PACKET3:
-			DRM_DEBUG("R300_CMD_PACKET3\n");
-			ret = r300_emit_packet3(dev_priv, cmdbuf, *header);
-			if (ret) {
-				DRM_ERROR("r300_emit_packet3 failed\n");
-				goto cleanup;
-			}
-			break;
-
-		case R300_CMD_END3D:
-			DRM_DEBUG("R300_CMD_END3D\n");
-			/* TODO:
-			   Ideally userspace driver should not need to issue this call,
-			   i.e. the drm driver should issue it automatically and prevent
-			   lockups.
-
-			   In practice, we do not understand why this call is needed and what
-			   it does (except for some vague guesses that it has to do with cache
-			   coherence) and so the user space driver does it.
-
-			   Once we are sure which uses prevent lockups the code could be moved
-			   into the kernel and the userspace driver will not
-			   need to use this command.
-
-			   Note that issuing this command does not hurt anything
-			   except, possibly, performance */
-			r300_pacify(dev_priv);
-			break;
-
-		case R300_CMD_CP_DELAY:
-			/* simple enough, we can do it here */
-			DRM_DEBUG("R300_CMD_CP_DELAY\n");
-			{
-				int i;
-				RING_LOCALS;
-
-				BEGIN_RING(header->delay.count);
-				for (i = 0; i < header->delay.count; i++)
-					OUT_RING(RADEON_CP_PACKET2);
-				ADVANCE_RING();
-			}
-			break;
-
-		case R300_CMD_DMA_DISCARD:
-			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
-			idx = header->dma.buf_idx;
-			if (idx < 0 || idx >= dma->buf_count) {
-				DRM_ERROR("buffer index %d (of %d max)\n",
-					  idx, dma->buf_count - 1);
-				ret = -EINVAL;
-				goto cleanup;
-			}
-
-			buf = dma->buflist[idx];
-			if (buf->file_priv != file_priv || buf->pending) {
-				DRM_ERROR("bad buffer %p %p %d\n",
-					  buf->file_priv, file_priv,
-					  buf->pending);
-				ret = -EINVAL;
-				goto cleanup;
-			}
-
-			emit_dispatch_age = 1;
-			r300_discard_buffer(dev, file_priv->master, buf);
-			break;
-
-		case R300_CMD_WAIT:
-			DRM_DEBUG("R300_CMD_WAIT\n");
-			r300_cmd_wait(dev_priv, *header);
-			break;
-
-		case R300_CMD_SCRATCH:
-			DRM_DEBUG("R300_CMD_SCRATCH\n");
-			ret = r300_scratch(dev_priv, cmdbuf, *header);
-			if (ret) {
-				DRM_ERROR("r300_scratch failed\n");
-				goto cleanup;
-			}
-			break;
-
-		case R300_CMD_R500FP:
-			if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
-				DRM_ERROR("Calling r500 command on r300 card\n");
-				ret = -EINVAL;
-				goto cleanup;
-			}
-			DRM_DEBUG("R300_CMD_R500FP\n");
-			ret = r300_emit_r500fp(dev_priv, cmdbuf, *header);
-			if (ret) {
-				DRM_ERROR("r300_emit_r500fp failed\n");
-				goto cleanup;
-			}
-			break;
-		default:
-			DRM_ERROR("bad cmd_type %i at byte %d\n",
-				  header->header.cmd_type,
-				  cmdbuf->buffer->iterator - (int)sizeof(*header));
-			ret = -EINVAL;
-			goto cleanup;
-		}
-	}
-
-	DRM_DEBUG("END\n");
-
-      cleanup:
-	r300_pacify(dev_priv);
-
-	/* We emit the vertex buffer age here, outside the pacifier "brackets"
-	 * for two reasons:
-	 *  (1) This may coalesce multiple age emissions into a single one and
-	 *  (2) more importantly, some chips lock up hard when scratch registers
-	 *      are written inside the pacifier bracket.
-	 */
-	if (emit_dispatch_age) {
-		RING_LOCALS;
-
-		/* Emit the vertex buffer age */
-		BEGIN_RING(2);
-		RADEON_DISPATCH_AGE(master_priv->sarea_priv->last_dispatch);
-		ADVANCE_RING();
-	}
-
-	COMMIT_RING();
-
-	return ret;
-}
diff --git a/drivers/gpu/drm/radeon/r600_blit.c b/drivers/gpu/drm/radeon/r600_blit.c
deleted file mode 100644
index daf7572..0000000
--- a/drivers/gpu/drm/radeon/r600_blit.c
+++ /dev/null
@@ -1,874 +0,0 @@
-/*
- * Copyright 2009 Advanced Micro Devices, 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 (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 HOLDER(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.
- *
- * Authors:
- *     Alex Deucher <alexander.deucher@amd.com>
- *
- * ------------------------ This file is DEPRECATED! -------------------------
- */
-#include <drm/drmP.h>
-#include <drm/radeon_drm.h>
-#include "radeon_drv.h"
-
-#include "r600_blit_shaders.h"
-
-/* 23 bits of float fractional data */
-#define I2F_FRAC_BITS  23
-#define I2F_MASK ((1 << I2F_FRAC_BITS) - 1)
-
-/*
- * Converts unsigned integer into 32-bit IEEE floating point representation.
- * Will be exact from 0 to 2^24.  Above that, we round towards zero
- * as the fractional bits will not fit in a float.  (It would be better to
- * round towards even as the fpu does, but that is slower.)
- */
-static __pure uint32_t int2float(uint32_t x)
-{
-	uint32_t msb, exponent, fraction;
-
-	/* Zero is special */
-	if (!x) return 0;
-
-	/* Get location of the most significant bit */
-	msb = __fls(x);
-
-	/*
-	 * Use a rotate instead of a shift because that works both leftwards
-	 * and rightwards due to the mod(32) behaviour.  This means we don't
-	 * need to check to see if we are above 2^24 or not.
-	 */
-	fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK;
-	exponent = (127 + msb) << I2F_FRAC_BITS;
-
-	return fraction + exponent;
-}
-
-#define DI_PT_RECTLIST        0x11
-#define DI_INDEX_SIZE_16_BIT  0x0
-#define DI_SRC_SEL_AUTO_INDEX 0x2
-
-#define FMT_8                 0x1
-#define FMT_5_6_5             0x8
-#define FMT_8_8_8_8           0x1a
-#define COLOR_8               0x1
-#define COLOR_5_6_5           0x8
-#define COLOR_8_8_8_8         0x1a
-
-static void
-set_render_target(drm_radeon_private_t *dev_priv, int format, int w, int h, u64 gpu_addr)
-{
-	u32 cb_color_info;
-	int pitch, slice;
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	h = ALIGN(h, 8);
-	if (h < 8)
-		h = 8;
-
-	cb_color_info = ((format << 2) | (1 << 27));
-	pitch = (w / 8) - 1;
-	slice = ((w * h) / 64) - 1;
-
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_R600) &&
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV770)) {
-		BEGIN_RING(21 + 2);
-		OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-		OUT_RING((R600_CB_COLOR0_BASE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-		OUT_RING(gpu_addr >> 8);
-		OUT_RING(CP_PACKET3(R600_IT_SURFACE_BASE_UPDATE, 0));
-		OUT_RING(2 << 0);
-	} else {
-		BEGIN_RING(21);
-		OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-		OUT_RING((R600_CB_COLOR0_BASE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-		OUT_RING(gpu_addr >> 8);
-	}
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_CB_COLOR0_SIZE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING((pitch << 0) | (slice << 10));
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_CB_COLOR0_VIEW - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(0);
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_CB_COLOR0_INFO - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(cb_color_info);
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_CB_COLOR0_TILE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(0);
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_CB_COLOR0_FRAG - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(0);
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_CB_COLOR0_MASK - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(0);
-
-	ADVANCE_RING();
-}
-
-static void
-cp_set_surface_sync(drm_radeon_private_t *dev_priv,
-		    u32 sync_type, u32 size, u64 mc_addr)
-{
-	u32 cp_coher_size;
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	if (size == 0xffffffff)
-		cp_coher_size = 0xffffffff;
-	else
-		cp_coher_size = ((size + 255) >> 8);
-
-	BEGIN_RING(5);
-	OUT_RING(CP_PACKET3(R600_IT_SURFACE_SYNC, 3));
-	OUT_RING(sync_type);
-	OUT_RING(cp_coher_size);
-	OUT_RING((mc_addr >> 8));
-	OUT_RING(10); /* poll interval */
-	ADVANCE_RING();
-}
-
-static void
-set_shaders(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	u64 gpu_addr;
-	int i;
-	u32 *vs, *ps;
-	uint32_t sq_pgm_resources;
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	/* load shaders */
-	vs = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset);
-	ps = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset + 256);
-
-	for (i = 0; i < r6xx_vs_size; i++)
-		vs[i] = cpu_to_le32(r6xx_vs[i]);
-	for (i = 0; i < r6xx_ps_size; i++)
-		ps[i] = cpu_to_le32(r6xx_ps[i]);
-
-	dev_priv->blit_vb->used = 512;
-
-	gpu_addr = dev_priv->gart_buffers_offset + dev_priv->blit_vb->offset;
-
-	/* setup shader regs */
-	sq_pgm_resources = (1 << 0);
-
-	BEGIN_RING(9 + 12);
-	/* VS */
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_SQ_PGM_START_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(gpu_addr >> 8);
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_SQ_PGM_RESOURCES_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(sq_pgm_resources);
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_SQ_PGM_CF_OFFSET_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(0);
-
-	/* PS */
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_SQ_PGM_START_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING((gpu_addr + 256) >> 8);
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_SQ_PGM_RESOURCES_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(sq_pgm_resources | (1 << 28));
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_SQ_PGM_EXPORTS_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(2);
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
-	OUT_RING((R600_SQ_PGM_CF_OFFSET_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING(0);
-	ADVANCE_RING();
-
-	cp_set_surface_sync(dev_priv,
-			    R600_SH_ACTION_ENA, 512, gpu_addr);
-}
-
-static void
-set_vtx_resource(drm_radeon_private_t *dev_priv, u64 gpu_addr)
-{
-	uint32_t sq_vtx_constant_word2;
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	sq_vtx_constant_word2 = (((gpu_addr >> 32) & 0xff) | (16 << 8));
-#ifdef __BIG_ENDIAN
-	sq_vtx_constant_word2 |= (2 << 30);
-#endif
-
-	BEGIN_RING(9);
-	OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7));
-	OUT_RING(0x460);
-	OUT_RING(gpu_addr & 0xffffffff);
-	OUT_RING(48 - 1);
-	OUT_RING(sq_vtx_constant_word2);
-	OUT_RING(1 << 0);
-	OUT_RING(0);
-	OUT_RING(0);
-	OUT_RING(R600_SQ_TEX_VTX_VALID_BUFFER << 30);
-	ADVANCE_RING();
-
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710))
-		cp_set_surface_sync(dev_priv,
-				    R600_TC_ACTION_ENA, 48, gpu_addr);
-	else
-		cp_set_surface_sync(dev_priv,
-				    R600_VC_ACTION_ENA, 48, gpu_addr);
-}
-
-static void
-set_tex_resource(drm_radeon_private_t *dev_priv,
-		 int format, int w, int h, int pitch, u64 gpu_addr)
-{
-	uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	if (h < 1)
-		h = 1;
-
-	sq_tex_resource_word0 = (1 << 0);
-	sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 8) |
-				  ((w - 1) << 19));
-
-	sq_tex_resource_word1 = (format << 26);
-	sq_tex_resource_word1 |= ((h - 1) << 0);
-
-	sq_tex_resource_word4 = ((1 << 14) |
-				 (0 << 16) |
-				 (1 << 19) |
-				 (2 << 22) |
-				 (3 << 25));
-
-	BEGIN_RING(9);
-	OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7));
-	OUT_RING(0);
-	OUT_RING(sq_tex_resource_word0);
-	OUT_RING(sq_tex_resource_word1);
-	OUT_RING(gpu_addr >> 8);
-	OUT_RING(gpu_addr >> 8);
-	OUT_RING(sq_tex_resource_word4);
-	OUT_RING(0);
-	OUT_RING(R600_SQ_TEX_VTX_VALID_TEXTURE << 30);
-	ADVANCE_RING();
-
-}
-
-static void
-set_scissors(drm_radeon_private_t *dev_priv, int x1, int y1, int x2, int y2)
-{
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	BEGIN_RING(12);
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2));
-	OUT_RING((R600_PA_SC_SCREEN_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING((x1 << 0) | (y1 << 16));
-	OUT_RING((x2 << 0) | (y2 << 16));
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2));
-	OUT_RING((R600_PA_SC_GENERIC_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING((x1 << 0) | (y1 << 16) | (1 << 31));
-	OUT_RING((x2 << 0) | (y2 << 16));
-
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2));
-	OUT_RING((R600_PA_SC_WINDOW_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2);
-	OUT_RING((x1 << 0) | (y1 << 16) | (1 << 31));
-	OUT_RING((x2 << 0) | (y2 << 16));
-	ADVANCE_RING();
-}
-
-static void
-draw_auto(drm_radeon_private_t *dev_priv)
-{
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	BEGIN_RING(10);
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
-	OUT_RING((R600_VGT_PRIMITIVE_TYPE - R600_SET_CONFIG_REG_OFFSET) >> 2);
-	OUT_RING(DI_PT_RECTLIST);
-
-	OUT_RING(CP_PACKET3(R600_IT_INDEX_TYPE, 0));
-#ifdef __BIG_ENDIAN
-	OUT_RING((2 << 2) | DI_INDEX_SIZE_16_BIT);
-#else
-	OUT_RING(DI_INDEX_SIZE_16_BIT);
-#endif
-
-	OUT_RING(CP_PACKET3(R600_IT_NUM_INSTANCES, 0));
-	OUT_RING(1);
-
-	OUT_RING(CP_PACKET3(R600_IT_DRAW_INDEX_AUTO, 1));
-	OUT_RING(3);
-	OUT_RING(DI_SRC_SEL_AUTO_INDEX);
-
-	ADVANCE_RING();
-	COMMIT_RING();
-}
-
-static void
-set_default_state(drm_radeon_private_t *dev_priv)
-{
-	int i;
-	u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2;
-	u32 sq_thread_resource_mgmt, sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2;
-	int num_ps_gprs, num_vs_gprs, num_temp_gprs, num_gs_gprs, num_es_gprs;
-	int num_ps_threads, num_vs_threads, num_gs_threads, num_es_threads;
-	int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries;
-	RING_LOCALS;
-
-	switch ((dev_priv->flags & RADEON_FAMILY_MASK)) {
-	case CHIP_R600:
-		num_ps_gprs = 192;
-		num_vs_gprs = 56;
-		num_temp_gprs = 4;
-		num_gs_gprs = 0;
-		num_es_gprs = 0;
-		num_ps_threads = 136;
-		num_vs_threads = 48;
-		num_gs_threads = 4;
-		num_es_threads = 4;
-		num_ps_stack_entries = 128;
-		num_vs_stack_entries = 128;
-		num_gs_stack_entries = 0;
-		num_es_stack_entries = 0;
-		break;
-	case CHIP_RV630:
-	case CHIP_RV635:
-		num_ps_gprs = 84;
-		num_vs_gprs = 36;
-		num_temp_gprs = 4;
-		num_gs_gprs = 0;
-		num_es_gprs = 0;
-		num_ps_threads = 144;
-		num_vs_threads = 40;
-		num_gs_threads = 4;
-		num_es_threads = 4;
-		num_ps_stack_entries = 40;
-		num_vs_stack_entries = 40;
-		num_gs_stack_entries = 32;
-		num_es_stack_entries = 16;
-		break;
-	case CHIP_RV610:
-	case CHIP_RV620:
-	case CHIP_RS780:
-	case CHIP_RS880:
-	default:
-		num_ps_gprs = 84;
-		num_vs_gprs = 36;
-		num_temp_gprs = 4;
-		num_gs_gprs = 0;
-		num_es_gprs = 0;
-		num_ps_threads = 136;
-		num_vs_threads = 48;
-		num_gs_threads = 4;
-		num_es_threads = 4;
-		num_ps_stack_entries = 40;
-		num_vs_stack_entries = 40;
-		num_gs_stack_entries = 32;
-		num_es_stack_entries = 16;
-		break;
-	case CHIP_RV670:
-		num_ps_gprs = 144;
-		num_vs_gprs = 40;
-		num_temp_gprs = 4;
-		num_gs_gprs = 0;
-		num_es_gprs = 0;
-		num_ps_threads = 136;
-		num_vs_threads = 48;
-		num_gs_threads = 4;
-		num_es_threads = 4;
-		num_ps_stack_entries = 40;
-		num_vs_stack_entries = 40;
-		num_gs_stack_entries = 32;
-		num_es_stack_entries = 16;
-		break;
-	case CHIP_RV770:
-		num_ps_gprs = 192;
-		num_vs_gprs = 56;
-		num_temp_gprs = 4;
-		num_gs_gprs = 0;
-		num_es_gprs = 0;
-		num_ps_threads = 188;
-		num_vs_threads = 60;
-		num_gs_threads = 0;
-		num_es_threads = 0;
-		num_ps_stack_entries = 256;
-		num_vs_stack_entries = 256;
-		num_gs_stack_entries = 0;
-		num_es_stack_entries = 0;
-		break;
-	case CHIP_RV730:
-	case CHIP_RV740:
-		num_ps_gprs = 84;
-		num_vs_gprs = 36;
-		num_temp_gprs = 4;
-		num_gs_gprs = 0;
-		num_es_gprs = 0;
-		num_ps_threads = 188;
-		num_vs_threads = 60;
-		num_gs_threads = 0;
-		num_es_threads = 0;
-		num_ps_stack_entries = 128;
-		num_vs_stack_entries = 128;
-		num_gs_stack_entries = 0;
-		num_es_stack_entries = 0;
-		break;
-	case CHIP_RV710:
-		num_ps_gprs = 192;
-		num_vs_gprs = 56;
-		num_temp_gprs = 4;
-		num_gs_gprs = 0;
-		num_es_gprs = 0;
-		num_ps_threads = 144;
-		num_vs_threads = 48;
-		num_gs_threads = 0;
-		num_es_threads = 0;
-		num_ps_stack_entries = 128;
-		num_vs_stack_entries = 128;
-		num_gs_stack_entries = 0;
-		num_es_stack_entries = 0;
-		break;
-	}
-
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710))
-		sq_config = 0;
-	else
-		sq_config = R600_VC_ENABLE;
-
-	sq_config |= (R600_DX9_CONSTS |
-		      R600_ALU_INST_PREFER_VECTOR |
-		      R600_PS_PRIO(0) |
-		      R600_VS_PRIO(1) |
-		      R600_GS_PRIO(2) |
-		      R600_ES_PRIO(3));
-
-	sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(num_ps_gprs) |
-				  R600_NUM_VS_GPRS(num_vs_gprs) |
-				  R600_NUM_CLAUSE_TEMP_GPRS(num_temp_gprs));
-	sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(num_gs_gprs) |
-				  R600_NUM_ES_GPRS(num_es_gprs));
-	sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(num_ps_threads) |
-				   R600_NUM_VS_THREADS(num_vs_threads) |
-				   R600_NUM_GS_THREADS(num_gs_threads) |
-				   R600_NUM_ES_THREADS(num_es_threads));
-	sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(num_ps_stack_entries) |
-				    R600_NUM_VS_STACK_ENTRIES(num_vs_stack_entries));
-	sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(num_gs_stack_entries) |
-				    R600_NUM_ES_STACK_ENTRIES(num_es_stack_entries));
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) {
-		BEGIN_RING(r7xx_default_size + 10);
-		for (i = 0; i < r7xx_default_size; i++)
-			OUT_RING(r7xx_default_state[i]);
-	} else {
-		BEGIN_RING(r6xx_default_size + 10);
-		for (i = 0; i < r6xx_default_size; i++)
-			OUT_RING(r6xx_default_state[i]);
-	}
-	OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0));
-	OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT);
-	/* SQ config */
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 6));
-	OUT_RING((R600_SQ_CONFIG - R600_SET_CONFIG_REG_OFFSET) >> 2);
-	OUT_RING(sq_config);
-	OUT_RING(sq_gpr_resource_mgmt_1);
-	OUT_RING(sq_gpr_resource_mgmt_2);
-	OUT_RING(sq_thread_resource_mgmt);
-	OUT_RING(sq_stack_resource_mgmt_1);
-	OUT_RING(sq_stack_resource_mgmt_2);
-	ADVANCE_RING();
-}
-
-static int r600_nomm_get_vb(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	dev_priv->blit_vb = radeon_freelist_get(dev);
-	if (!dev_priv->blit_vb) {
-		DRM_ERROR("Unable to allocate vertex buffer for blit\n");
-		return -EAGAIN;
-	}
-	return 0;
-}
-
-static void r600_nomm_put_vb(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	dev_priv->blit_vb->used = 0;
-	radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->master, dev_priv->blit_vb);
-}
-
-static void *r600_nomm_get_vb_ptr(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	return (((char *)dev->agp_buffer_map->handle +
-		 dev_priv->blit_vb->offset + dev_priv->blit_vb->used));
-}
-
-int
-r600_prepare_blit_copy(struct drm_device *dev, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	int ret;
-	DRM_DEBUG("\n");
-
-	ret = r600_nomm_get_vb(dev);
-	if (ret)
-		return ret;
-
-	dev_priv->blit_vb->file_priv = file_priv;
-
-	set_default_state(dev_priv);
-	set_shaders(dev);
-
-	return 0;
-}
-
-
-void
-r600_done_blit_copy(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	BEGIN_RING(5);
-	OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0));
-	OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT);
-	/* wait for 3D idle clean */
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
-	OUT_RING((R600_WAIT_UNTIL - R600_SET_CONFIG_REG_OFFSET) >> 2);
-	OUT_RING(RADEON_WAIT_3D_IDLE | RADEON_WAIT_3D_IDLECLEAN);
-
-	ADVANCE_RING();
-	COMMIT_RING();
-
-	r600_nomm_put_vb(dev);
-}
-
-void
-r600_blit_copy(struct drm_device *dev,
-	       uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
-	       int size_bytes)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	int max_bytes;
-	u64 vb_addr;
-	u32 *vb;
-
-	vb = r600_nomm_get_vb_ptr(dev);
-
-	if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
-		max_bytes = 8192;
-
-		while (size_bytes) {
-			int cur_size = size_bytes;
-			int src_x = src_gpu_addr & 255;
-			int dst_x = dst_gpu_addr & 255;
-			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255;
-			dst_gpu_addr = dst_gpu_addr & ~255;
-
-			if (!src_x && !dst_x) {
-				h = (cur_size / max_bytes);
-				if (h > 8192)
-					h = 8192;
-				if (h == 0)
-					h = 1;
-				else
-					cur_size = max_bytes;
-			} else {
-				if (cur_size > max_bytes)
-					cur_size = max_bytes;
-				if (cur_size > (max_bytes - dst_x))
-					cur_size = (max_bytes - dst_x);
-				if (cur_size > (max_bytes - src_x))
-					cur_size = (max_bytes - src_x);
-			}
-
-			if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) {
-
-				r600_nomm_put_vb(dev);
-				r600_nomm_get_vb(dev);
-				if (!dev_priv->blit_vb)
-					return;
-				set_shaders(dev);
-				vb = r600_nomm_get_vb_ptr(dev);
-			}
-
-			vb[0] = int2float(dst_x);
-			vb[1] = 0;
-			vb[2] = int2float(src_x);
-			vb[3] = 0;
-
-			vb[4] = int2float(dst_x);
-			vb[5] = int2float(h);
-			vb[6] = int2float(src_x);
-			vb[7] = int2float(h);
-
-			vb[8] = int2float(dst_x + cur_size);
-			vb[9] = int2float(h);
-			vb[10] = int2float(src_x + cur_size);
-			vb[11] = int2float(h);
-
-			/* src */
-			set_tex_resource(dev_priv, FMT_8,
-					 src_x + cur_size, h, src_x + cur_size,
-					 src_gpu_addr);
-
-			cp_set_surface_sync(dev_priv,
-					    R600_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
-			/* dst */
-			set_render_target(dev_priv, COLOR_8,
-					  dst_x + cur_size, h,
-					  dst_gpu_addr);
-
-			/* scissors */
-			set_scissors(dev_priv, dst_x, 0, dst_x + cur_size, h);
-
-			/* Vertex buffer setup */
-			vb_addr = dev_priv->gart_buffers_offset +
-				dev_priv->blit_vb->offset +
-				dev_priv->blit_vb->used;
-			set_vtx_resource(dev_priv, vb_addr);
-
-			/* draw */
-			draw_auto(dev_priv);
-
-			cp_set_surface_sync(dev_priv,
-					    R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA,
-					    cur_size * h, dst_gpu_addr);
-
-			vb += 12;
-			dev_priv->blit_vb->used += 12 * 4;
-
-			src_gpu_addr += cur_size * h;
-			dst_gpu_addr += cur_size * h;
-			size_bytes -= cur_size * h;
-		}
-	} else {
-		max_bytes = 8192 * 4;
-
-		while (size_bytes) {
-			int cur_size = size_bytes;
-			int src_x = (src_gpu_addr & 255);
-			int dst_x = (dst_gpu_addr & 255);
-			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255;
-			dst_gpu_addr = dst_gpu_addr & ~255;
-
-			if (!src_x && !dst_x) {
-				h = (cur_size / max_bytes);
-				if (h > 8192)
-					h = 8192;
-				if (h == 0)
-					h = 1;
-				else
-					cur_size = max_bytes;
-			} else {
-				if (cur_size > max_bytes)
-					cur_size = max_bytes;
-				if (cur_size > (max_bytes - dst_x))
-					cur_size = (max_bytes - dst_x);
-				if (cur_size > (max_bytes - src_x))
-					cur_size = (max_bytes - src_x);
-			}
-
-			if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) {
-				r600_nomm_put_vb(dev);
-				r600_nomm_get_vb(dev);
-				if (!dev_priv->blit_vb)
-					return;
-
-				set_shaders(dev);
-				vb = r600_nomm_get_vb_ptr(dev);
-			}
-
-			vb[0] = int2float(dst_x / 4);
-			vb[1] = 0;
-			vb[2] = int2float(src_x / 4);
-			vb[3] = 0;
-
-			vb[4] = int2float(dst_x / 4);
-			vb[5] = int2float(h);
-			vb[6] = int2float(src_x / 4);
-			vb[7] = int2float(h);
-
-			vb[8] = int2float((dst_x + cur_size) / 4);
-			vb[9] = int2float(h);
-			vb[10] = int2float((src_x + cur_size) / 4);
-			vb[11] = int2float(h);
-
-			/* src */
-			set_tex_resource(dev_priv, FMT_8_8_8_8,
-					 (src_x + cur_size) / 4,
-					 h, (src_x + cur_size) / 4,
-					 src_gpu_addr);
-
-			cp_set_surface_sync(dev_priv,
-					    R600_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
-
-			/* dst */
-			set_render_target(dev_priv, COLOR_8_8_8_8,
-					  (dst_x + cur_size) / 4, h,
-					  dst_gpu_addr);
-
-			/* scissors */
-			set_scissors(dev_priv, (dst_x / 4), 0, (dst_x + cur_size / 4), h);
-
-			/* Vertex buffer setup */
-			vb_addr = dev_priv->gart_buffers_offset +
-				dev_priv->blit_vb->offset +
-				dev_priv->blit_vb->used;
-			set_vtx_resource(dev_priv, vb_addr);
-
-			/* draw */
-			draw_auto(dev_priv);
-
-			cp_set_surface_sync(dev_priv,
-					    R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA,
-					    cur_size * h, dst_gpu_addr);
-
-			vb += 12;
-			dev_priv->blit_vb->used += 12 * 4;
-
-			src_gpu_addr += cur_size * h;
-			dst_gpu_addr += cur_size * h;
-			size_bytes -= cur_size * h;
-		}
-	}
-}
-
-void
-r600_blit_swap(struct drm_device *dev,
-	       uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
-	       int sx, int sy, int dx, int dy,
-	       int w, int h, int src_pitch, int dst_pitch, int cpp)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	int cb_format, tex_format;
-	int sx2, sy2, dx2, dy2;
-	u64 vb_addr;
-	u32 *vb;
-
-	if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) {
-
-		r600_nomm_put_vb(dev);
-		r600_nomm_get_vb(dev);
-		if (!dev_priv->blit_vb)
-			return;
-
-		set_shaders(dev);
-	}
-	vb = r600_nomm_get_vb_ptr(dev);
-
-	sx2 = sx + w;
-	sy2 = sy + h;
-	dx2 = dx + w;
-	dy2 = dy + h;
-
-	vb[0] = int2float(dx);
-	vb[1] = int2float(dy);
-	vb[2] = int2float(sx);
-	vb[3] = int2float(sy);
-
-	vb[4] = int2float(dx);
-	vb[5] = int2float(dy2);
-	vb[6] = int2float(sx);
-	vb[7] = int2float(sy2);
-
-	vb[8] = int2float(dx2);
-	vb[9] = int2float(dy2);
-	vb[10] = int2float(sx2);
-	vb[11] = int2float(sy2);
-
-	switch(cpp) {
-	case 4:
-		cb_format = COLOR_8_8_8_8;
-		tex_format = FMT_8_8_8_8;
-		break;
-	case 2:
-		cb_format = COLOR_5_6_5;
-		tex_format = FMT_5_6_5;
-		break;
-	default:
-		cb_format = COLOR_8;
-		tex_format = FMT_8;
-		break;
-	}
-
-	/* src */
-	set_tex_resource(dev_priv, tex_format,
-			 src_pitch / cpp,
-			 sy2, src_pitch / cpp,
-			 src_gpu_addr);
-
-	cp_set_surface_sync(dev_priv,
-			    R600_TC_ACTION_ENA, src_pitch * sy2, src_gpu_addr);
-
-	/* dst */
-	set_render_target(dev_priv, cb_format,
-			  dst_pitch / cpp, dy2,
-			  dst_gpu_addr);
-
-	/* scissors */
-	set_scissors(dev_priv, dx, dy, dx2, dy2);
-
-	/* Vertex buffer setup */
-	vb_addr = dev_priv->gart_buffers_offset +
-		dev_priv->blit_vb->offset +
-		dev_priv->blit_vb->used;
-	set_vtx_resource(dev_priv, vb_addr);
-
-	/* draw */
-	draw_auto(dev_priv);
-
-	cp_set_surface_sync(dev_priv,
-			    R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA,
-			    dst_pitch * dy2, dst_gpu_addr);
-
-	dev_priv->blit_vb->used += 12 * 4;
-}
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
deleted file mode 100644
index e231eea..0000000
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ /dev/null
@@ -1,2660 +0,0 @@
-/*
- * Copyright 2008-2009 Advanced Micro Devices, Inc.
- * Copyright 2008 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 (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 HOLDER(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.
- *
- * Authors:
- *     Dave Airlie <airlied@redhat.com>
- *     Alex Deucher <alexander.deucher@amd.com>
- *
- * ------------------------ This file is DEPRECATED! -------------------------
- */
-
-#include <linux/module.h>
-
-#include <drm/drmP.h>
-#include <drm/radeon_drm.h>
-#include "radeon_drv.h"
-
-#define PFP_UCODE_SIZE 576
-#define PM4_UCODE_SIZE 1792
-#define R700_PFP_UCODE_SIZE 848
-#define R700_PM4_UCODE_SIZE 1360
-
-/* Firmware Names */
-MODULE_FIRMWARE("radeon/R600_pfp.bin");
-MODULE_FIRMWARE("radeon/R600_me.bin");
-MODULE_FIRMWARE("radeon/RV610_pfp.bin");
-MODULE_FIRMWARE("radeon/RV610_me.bin");
-MODULE_FIRMWARE("radeon/RV630_pfp.bin");
-MODULE_FIRMWARE("radeon/RV630_me.bin");
-MODULE_FIRMWARE("radeon/RV620_pfp.bin");
-MODULE_FIRMWARE("radeon/RV620_me.bin");
-MODULE_FIRMWARE("radeon/RV635_pfp.bin");
-MODULE_FIRMWARE("radeon/RV635_me.bin");
-MODULE_FIRMWARE("radeon/RV670_pfp.bin");
-MODULE_FIRMWARE("radeon/RV670_me.bin");
-MODULE_FIRMWARE("radeon/RS780_pfp.bin");
-MODULE_FIRMWARE("radeon/RS780_me.bin");
-MODULE_FIRMWARE("radeon/RV770_pfp.bin");
-MODULE_FIRMWARE("radeon/RV770_me.bin");
-MODULE_FIRMWARE("radeon/RV730_pfp.bin");
-MODULE_FIRMWARE("radeon/RV730_me.bin");
-MODULE_FIRMWARE("radeon/RV710_pfp.bin");
-MODULE_FIRMWARE("radeon/RV710_me.bin");
-
-
-int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
-			unsigned family, u32 *ib, int *l);
-void r600_cs_legacy_init(void);
-
-
-# define ATI_PCIGART_PAGE_SIZE		4096	/**< PCI GART page size */
-# define ATI_PCIGART_PAGE_MASK		(~(ATI_PCIGART_PAGE_SIZE-1))
-
-#define R600_PTE_VALID     (1 << 0)
-#define R600_PTE_SYSTEM    (1 << 1)
-#define R600_PTE_SNOOPED   (1 << 2)
-#define R600_PTE_READABLE  (1 << 5)
-#define R600_PTE_WRITEABLE (1 << 6)
-
-/* MAX values used for gfx init */
-#define R6XX_MAX_SH_GPRS           256
-#define R6XX_MAX_TEMP_GPRS         16
-#define R6XX_MAX_SH_THREADS        256
-#define R6XX_MAX_SH_STACK_ENTRIES  4096
-#define R6XX_MAX_BACKENDS          8
-#define R6XX_MAX_BACKENDS_MASK     0xff
-#define R6XX_MAX_SIMDS             8
-#define R6XX_MAX_SIMDS_MASK        0xff
-#define R6XX_MAX_PIPES             8
-#define R6XX_MAX_PIPES_MASK        0xff
-
-#define R7XX_MAX_SH_GPRS           256
-#define R7XX_MAX_TEMP_GPRS         16
-#define R7XX_MAX_SH_THREADS        256
-#define R7XX_MAX_SH_STACK_ENTRIES  4096
-#define R7XX_MAX_BACKENDS          8
-#define R7XX_MAX_BACKENDS_MASK     0xff
-#define R7XX_MAX_SIMDS             16
-#define R7XX_MAX_SIMDS_MASK        0xffff
-#define R7XX_MAX_PIPES             8
-#define R7XX_MAX_PIPES_MASK        0xff
-
-static int r600_do_wait_for_fifo(drm_radeon_private_t *dev_priv, int entries)
-{
-	int i;
-
-	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-	for (i = 0; i < dev_priv->usec_timeout; i++) {
-		int slots;
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
-			slots = (RADEON_READ(R600_GRBM_STATUS)
-				 & R700_CMDFIFO_AVAIL_MASK);
-		else
-			slots = (RADEON_READ(R600_GRBM_STATUS)
-				 & R600_CMDFIFO_AVAIL_MASK);
-		if (slots >= entries)
-			return 0;
-		DRM_UDELAY(1);
-	}
-	DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n",
-		 RADEON_READ(R600_GRBM_STATUS),
-		 RADEON_READ(R600_GRBM_STATUS2));
-
-	return -EBUSY;
-}
-
-static int r600_do_wait_for_idle(drm_radeon_private_t *dev_priv)
-{
-	int i, ret;
-
-	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
-		ret = r600_do_wait_for_fifo(dev_priv, 8);
-	else
-		ret = r600_do_wait_for_fifo(dev_priv, 16);
-	if (ret)
-		return ret;
-	for (i = 0; i < dev_priv->usec_timeout; i++) {
-		if (!(RADEON_READ(R600_GRBM_STATUS) & R600_GUI_ACTIVE))
-			return 0;
-		DRM_UDELAY(1);
-	}
-	DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n",
-		 RADEON_READ(R600_GRBM_STATUS),
-		 RADEON_READ(R600_GRBM_STATUS2));
-
-	return -EBUSY;
-}
-
-void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
-{
-	struct drm_sg_mem *entry = dev->sg;
-	int max_pages;
-	int pages;
-	int i;
-
-	if (!entry)
-		return;
-
-	if (gart_info->bus_addr) {
-		max_pages = (gart_info->table_size / sizeof(u64));
-		pages = (entry->pages <= max_pages)
-		  ? entry->pages : max_pages;
-
-		for (i = 0; i < pages; i++) {
-			if (!entry->busaddr[i])
-				break;
-			pci_unmap_page(dev->pdev, entry->busaddr[i],
-				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-		}
-		if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
-			gart_info->bus_addr = 0;
-	}
-}
-
-/* R600 has page table setup */
-int r600_page_table_init(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info;
-	struct drm_local_map *map = &gart_info->mapping;
-	struct drm_sg_mem *entry = dev->sg;
-	int ret = 0;
-	int i, j;
-	int pages;
-	u64 page_base;
-	dma_addr_t entry_addr;
-	int max_ati_pages, max_real_pages, gart_idx;
-
-	/* okay page table is available - lets rock */
-	max_ati_pages = (gart_info->table_size / sizeof(u64));
-	max_real_pages = max_ati_pages / (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE);
-
-	pages = (entry->pages <= max_real_pages) ?
-		entry->pages : max_real_pages;
-
-	memset_io((void __iomem *)map->handle, 0, max_ati_pages * sizeof(u64));
-
-	gart_idx = 0;
-	for (i = 0; i < pages; i++) {
-		entry->busaddr[i] = pci_map_page(dev->pdev,
-						 entry->pagelist[i], 0,
-						 PAGE_SIZE,
-						 PCI_DMA_BIDIRECTIONAL);
-		if (pci_dma_mapping_error(dev->pdev, entry->busaddr[i])) {
-			DRM_ERROR("unable to map PCIGART pages!\n");
-			r600_page_table_cleanup(dev, gart_info);
-			goto done;
-		}
-		entry_addr = entry->busaddr[i];
-		for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
-			page_base = (u64) entry_addr & ATI_PCIGART_PAGE_MASK;
-			page_base |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED;
-			page_base |= R600_PTE_READABLE | R600_PTE_WRITEABLE;
-
-			DRM_WRITE64(map, gart_idx * sizeof(u64), page_base);
-
-			gart_idx++;
-
-			if ((i % 128) == 0)
-				DRM_DEBUG("page entry %d: 0x%016llx\n",
-				    i, (unsigned long long)page_base);
-			entry_addr += ATI_PCIGART_PAGE_SIZE;
-		}
-	}
-	ret = 1;
-done:
-	return ret;
-}
-
-static void r600_vm_flush_gart_range(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	u32 resp, countdown = 1000;
-	RADEON_WRITE(R600_VM_CONTEXT0_INVALIDATION_LOW_ADDR, dev_priv->gart_vm_start >> 12);
-	RADEON_WRITE(R600_VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
-	RADEON_WRITE(R600_VM_CONTEXT0_REQUEST_RESPONSE, 2);
-
-	do {
-		resp = RADEON_READ(R600_VM_CONTEXT0_REQUEST_RESPONSE);
-		countdown--;
-		DRM_UDELAY(1);
-	} while (((resp & 0xf0) == 0) && countdown);
-}
-
-static void r600_vm_init(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	/* initialise the VM to use the page table we constructed up there */
-	u32 vm_c0, i;
-	u32 mc_rd_a;
-	u32 vm_l2_cntl, vm_l2_cntl3;
-	/* okay set up the PCIE aperture type thingo */
-	RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR, dev_priv->gart_vm_start >> 12);
-	RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
-	RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
-
-	/* setup MC RD a */
-	mc_rd_a = R600_MCD_L1_TLB | R600_MCD_L1_FRAG_PROC | R600_MCD_SYSTEM_ACCESS_MODE_IN_SYS |
-		R600_MCD_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | R600_MCD_EFFECTIVE_L1_TLB_SIZE(5) |
-		R600_MCD_EFFECTIVE_L1_QUEUE_SIZE(5) | R600_MCD_WAIT_L2_QUERY;
-
-	RADEON_WRITE(R600_MCD_RD_A_CNTL, mc_rd_a);
-	RADEON_WRITE(R600_MCD_RD_B_CNTL, mc_rd_a);
-
-	RADEON_WRITE(R600_MCD_WR_A_CNTL, mc_rd_a);
-	RADEON_WRITE(R600_MCD_WR_B_CNTL, mc_rd_a);
-
-	RADEON_WRITE(R600_MCD_RD_GFX_CNTL, mc_rd_a);
-	RADEON_WRITE(R600_MCD_WR_GFX_CNTL, mc_rd_a);
-
-	RADEON_WRITE(R600_MCD_RD_SYS_CNTL, mc_rd_a);
-	RADEON_WRITE(R600_MCD_WR_SYS_CNTL, mc_rd_a);
-
-	RADEON_WRITE(R600_MCD_RD_HDP_CNTL, mc_rd_a | R600_MCD_L1_STRICT_ORDERING);
-	RADEON_WRITE(R600_MCD_WR_HDP_CNTL, mc_rd_a /*| R600_MCD_L1_STRICT_ORDERING*/);
-
-	RADEON_WRITE(R600_MCD_RD_PDMA_CNTL, mc_rd_a);
-	RADEON_WRITE(R600_MCD_WR_PDMA_CNTL, mc_rd_a);
-
-	RADEON_WRITE(R600_MCD_RD_SEM_CNTL, mc_rd_a | R600_MCD_SEMAPHORE_MODE);
-	RADEON_WRITE(R600_MCD_WR_SEM_CNTL, mc_rd_a);
-
-	vm_l2_cntl = R600_VM_L2_CACHE_EN | R600_VM_L2_FRAG_PROC | R600_VM_ENABLE_PTE_CACHE_LRU_W;
-	vm_l2_cntl |= R600_VM_L2_CNTL_QUEUE_SIZE(7);
-	RADEON_WRITE(R600_VM_L2_CNTL, vm_l2_cntl);
-
-	RADEON_WRITE(R600_VM_L2_CNTL2, 0);
-	vm_l2_cntl3 = (R600_VM_L2_CNTL3_BANK_SELECT_0(0) |
-		       R600_VM_L2_CNTL3_BANK_SELECT_1(1) |
-		       R600_VM_L2_CNTL3_CACHE_UPDATE_MODE(2));
-	RADEON_WRITE(R600_VM_L2_CNTL3, vm_l2_cntl3);
-
-	vm_c0 = R600_VM_ENABLE_CONTEXT | R600_VM_PAGE_TABLE_DEPTH_FLAT;
-
-	RADEON_WRITE(R600_VM_CONTEXT0_CNTL, vm_c0);
-
-	vm_c0 &= ~R600_VM_ENABLE_CONTEXT;
-
-	/* disable all other contexts */
-	for (i = 1; i < 8; i++)
-		RADEON_WRITE(R600_VM_CONTEXT0_CNTL + (i * 4), vm_c0);
-
-	RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, dev_priv->gart_info.bus_addr >> 12);
-	RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_START_ADDR, dev_priv->gart_vm_start >> 12);
-	RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_END_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
-
-	r600_vm_flush_gart_range(dev);
-}
-
-static int r600_cp_init_microcode(drm_radeon_private_t *dev_priv)
-{
-	struct platform_device *pdev;
-	const char *chip_name;
-	size_t pfp_req_size, me_req_size;
-	char fw_name[30];
-	int err;
-
-	pdev = platform_device_register_simple("r600_cp", 0, NULL, 0);
-	err = IS_ERR(pdev);
-	if (err) {
-		printk(KERN_ERR "r600_cp: Failed to register firmware\n");
-		return -EINVAL;
-	}
-
-	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
-	case CHIP_R600:  chip_name = "R600";  break;
-	case CHIP_RV610: chip_name = "RV610"; break;
-	case CHIP_RV630: chip_name = "RV630"; break;
-	case CHIP_RV620: chip_name = "RV620"; break;
-	case CHIP_RV635: chip_name = "RV635"; break;
-	case CHIP_RV670: chip_name = "RV670"; break;
-	case CHIP_RS780:
-	case CHIP_RS880: chip_name = "RS780"; break;
-	case CHIP_RV770: chip_name = "RV770"; break;
-	case CHIP_RV730:
-	case CHIP_RV740: chip_name = "RV730"; break;
-	case CHIP_RV710: chip_name = "RV710"; break;
-	default:         BUG();
-	}
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) {
-		pfp_req_size = R700_PFP_UCODE_SIZE * 4;
-		me_req_size = R700_PM4_UCODE_SIZE * 4;
-	} else {
-		pfp_req_size = PFP_UCODE_SIZE * 4;
-		me_req_size = PM4_UCODE_SIZE * 12;
-	}
-
-	DRM_INFO("Loading %s CP Microcode\n", chip_name);
-
-	snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
-	err = request_firmware(&dev_priv->pfp_fw, fw_name, &pdev->dev);
-	if (err)
-		goto out;
-	if (dev_priv->pfp_fw->size != pfp_req_size) {
-		printk(KERN_ERR
-		       "r600_cp: Bogus length %zu in firmware \"%s\"\n",
-		       dev_priv->pfp_fw->size, fw_name);
-		err = -EINVAL;
-		goto out;
-	}
-
-	snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
-	err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev);
-	if (err)
-		goto out;
-	if (dev_priv->me_fw->size != me_req_size) {
-		printk(KERN_ERR
-		       "r600_cp: Bogus length %zu in firmware \"%s\"\n",
-		       dev_priv->me_fw->size, fw_name);
-		err = -EINVAL;
-	}
-out:
-	platform_device_unregister(pdev);
-
-	if (err) {
-		if (err != -EINVAL)
-			printk(KERN_ERR
-			       "r600_cp: Failed to load firmware \"%s\"\n",
-			       fw_name);
-		release_firmware(dev_priv->pfp_fw);
-		dev_priv->pfp_fw = NULL;
-		release_firmware(dev_priv->me_fw);
-		dev_priv->me_fw = NULL;
-	}
-	return err;
-}
-
-static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
-{
-	const __be32 *fw_data;
-	int i;
-
-	if (!dev_priv->me_fw || !dev_priv->pfp_fw)
-		return;
-
-	r600_do_cp_stop(dev_priv);
-
-	RADEON_WRITE(R600_CP_RB_CNTL,
-#ifdef __BIG_ENDIAN
-		     R600_BUF_SWAP_32BIT |
-#endif
-		     R600_RB_NO_UPDATE |
-		     R600_RB_BLKSZ(15) |
-		     R600_RB_BUFSZ(3));
-
-	RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
-	RADEON_READ(R600_GRBM_SOFT_RESET);
-	mdelay(15);
-	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
-
-	fw_data = (const __be32 *)dev_priv->me_fw->data;
-	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-	for (i = 0; i < PM4_UCODE_SIZE * 3; i++)
-		RADEON_WRITE(R600_CP_ME_RAM_DATA,
-			     be32_to_cpup(fw_data++));
-
-	fw_data = (const __be32 *)dev_priv->pfp_fw->data;
-	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-	for (i = 0; i < PFP_UCODE_SIZE; i++)
-		RADEON_WRITE(R600_CP_PFP_UCODE_DATA,
-			     be32_to_cpup(fw_data++));
-
-	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-	RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
-
-}
-
-static void r700_vm_init(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	/* initialise the VM to use the page table we constructed up there */
-	u32 vm_c0, i;
-	u32 mc_vm_md_l1;
-	u32 vm_l2_cntl, vm_l2_cntl3;
-	/* okay set up the PCIE aperture type thingo */
-	RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR, dev_priv->gart_vm_start >> 12);
-	RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
-	RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
-
-	mc_vm_md_l1 = R700_ENABLE_L1_TLB |
-	    R700_ENABLE_L1_FRAGMENT_PROCESSING |
-	    R700_SYSTEM_ACCESS_MODE_IN_SYS |
-	    R700_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
-	    R700_EFFECTIVE_L1_TLB_SIZE(5) |
-	    R700_EFFECTIVE_L1_QUEUE_SIZE(5);
-
-	RADEON_WRITE(R700_MC_VM_MD_L1_TLB0_CNTL, mc_vm_md_l1);
-	RADEON_WRITE(R700_MC_VM_MD_L1_TLB1_CNTL, mc_vm_md_l1);
-	RADEON_WRITE(R700_MC_VM_MD_L1_TLB2_CNTL, mc_vm_md_l1);
-	RADEON_WRITE(R700_MC_VM_MB_L1_TLB0_CNTL, mc_vm_md_l1);
-	RADEON_WRITE(R700_MC_VM_MB_L1_TLB1_CNTL, mc_vm_md_l1);
-	RADEON_WRITE(R700_MC_VM_MB_L1_TLB2_CNTL, mc_vm_md_l1);
-	RADEON_WRITE(R700_MC_VM_MB_L1_TLB3_CNTL, mc_vm_md_l1);
-
-	vm_l2_cntl = R600_VM_L2_CACHE_EN | R600_VM_L2_FRAG_PROC | R600_VM_ENABLE_PTE_CACHE_LRU_W;
-	vm_l2_cntl |= R700_VM_L2_CNTL_QUEUE_SIZE(7);
-	RADEON_WRITE(R600_VM_L2_CNTL, vm_l2_cntl);
-
-	RADEON_WRITE(R600_VM_L2_CNTL2, 0);
-	vm_l2_cntl3 = R700_VM_L2_CNTL3_BANK_SELECT(0) | R700_VM_L2_CNTL3_CACHE_UPDATE_MODE(2);
-	RADEON_WRITE(R600_VM_L2_CNTL3, vm_l2_cntl3);
-
-	vm_c0 = R600_VM_ENABLE_CONTEXT | R600_VM_PAGE_TABLE_DEPTH_FLAT;
-
-	RADEON_WRITE(R600_VM_CONTEXT0_CNTL, vm_c0);
-
-	vm_c0 &= ~R600_VM_ENABLE_CONTEXT;
-
-	/* disable all other contexts */
-	for (i = 1; i < 8; i++)
-		RADEON_WRITE(R600_VM_CONTEXT0_CNTL + (i * 4), vm_c0);
-
-	RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, dev_priv->gart_info.bus_addr >> 12);
-	RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_START_ADDR, dev_priv->gart_vm_start >> 12);
-	RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_END_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
-
-	r600_vm_flush_gart_range(dev);
-}
-
-static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
-{
-	const __be32 *fw_data;
-	int i;
-
-	if (!dev_priv->me_fw || !dev_priv->pfp_fw)
-		return;
-
-	r600_do_cp_stop(dev_priv);
-
-	RADEON_WRITE(R600_CP_RB_CNTL,
-#ifdef __BIG_ENDIAN
-		     R600_BUF_SWAP_32BIT |
-#endif
-		     R600_RB_NO_UPDATE |
-		     R600_RB_BLKSZ(15) |
-		     R600_RB_BUFSZ(3));
-
-	RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
-	RADEON_READ(R600_GRBM_SOFT_RESET);
-	mdelay(15);
-	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
-
-	fw_data = (const __be32 *)dev_priv->pfp_fw->data;
-	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-	for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
-		RADEON_WRITE(R600_CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
-	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-
-	fw_data = (const __be32 *)dev_priv->me_fw->data;
-	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-	for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
-		RADEON_WRITE(R600_CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
-	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-
-	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-	RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
-
-}
-
-static void r600_test_writeback(drm_radeon_private_t *dev_priv)
-{
-	u32 tmp;
-
-	/* Start with assuming that writeback doesn't work */
-	dev_priv->writeback_works = 0;
-
-	/* Writeback doesn't seem to work everywhere, test it here and possibly
-	 * enable it if it appears to work
-	 */
-	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0);
-
-	RADEON_WRITE(R600_SCRATCH_REG1, 0xdeadbeef);
-
-	for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
-		u32 val;
-
-		val = radeon_read_ring_rptr(dev_priv, R600_SCRATCHOFF(1));
-		if (val == 0xdeadbeef)
-			break;
-		DRM_UDELAY(1);
-	}
-
-	if (tmp < dev_priv->usec_timeout) {
-		dev_priv->writeback_works = 1;
-		DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
-	} else {
-		dev_priv->writeback_works = 0;
-		DRM_INFO("writeback test failed\n");
-	}
-	if (radeon_no_wb == 1) {
-		dev_priv->writeback_works = 0;
-		DRM_INFO("writeback forced off\n");
-	}
-
-	if (!dev_priv->writeback_works) {
-		/* Disable writeback to avoid unnecessary bus master transfer */
-		RADEON_WRITE(R600_CP_RB_CNTL,
-#ifdef __BIG_ENDIAN
-			     R600_BUF_SWAP_32BIT |
-#endif
-			     RADEON_READ(R600_CP_RB_CNTL) |
-			     R600_RB_NO_UPDATE);
-		RADEON_WRITE(R600_SCRATCH_UMSK, 0);
-	}
-}
-
-int r600_do_engine_reset(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	u32 cp_ptr, cp_me_cntl, cp_rb_cntl;
-
-	DRM_INFO("Resetting GPU\n");
-
-	cp_ptr = RADEON_READ(R600_CP_RB_WPTR);
-	cp_me_cntl = RADEON_READ(R600_CP_ME_CNTL);
-	RADEON_WRITE(R600_CP_ME_CNTL, R600_CP_ME_HALT);
-
-	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0x7fff);
-	RADEON_READ(R600_GRBM_SOFT_RESET);
-	DRM_UDELAY(50);
-	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
-	RADEON_READ(R600_GRBM_SOFT_RESET);
-
-	RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0);
-	cp_rb_cntl = RADEON_READ(R600_CP_RB_CNTL);
-	RADEON_WRITE(R600_CP_RB_CNTL,
-#ifdef __BIG_ENDIAN
-		     R600_BUF_SWAP_32BIT |
-#endif
-		     R600_RB_RPTR_WR_ENA);
-
-	RADEON_WRITE(R600_CP_RB_RPTR_WR, cp_ptr);
-	RADEON_WRITE(R600_CP_RB_WPTR, cp_ptr);
-	RADEON_WRITE(R600_CP_RB_CNTL, cp_rb_cntl);
-	RADEON_WRITE(R600_CP_ME_CNTL, cp_me_cntl);
-
-	/* Reset the CP ring */
-	r600_do_cp_reset(dev_priv);
-
-	/* The CP is no longer running after an engine reset */
-	dev_priv->cp_running = 0;
-
-	/* Reset any pending vertex, indirect buffers */
-	radeon_freelist_reset(dev);
-
-	return 0;
-
-}
-
-static u32 r600_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
-					     u32 num_backends,
-					     u32 backend_disable_mask)
-{
-	u32 backend_map = 0;
-	u32 enabled_backends_mask;
-	u32 enabled_backends_count;
-	u32 cur_pipe;
-	u32 swizzle_pipe[R6XX_MAX_PIPES];
-	u32 cur_backend;
-	u32 i;
-
-	if (num_tile_pipes > R6XX_MAX_PIPES)
-		num_tile_pipes = R6XX_MAX_PIPES;
-	if (num_tile_pipes < 1)
-		num_tile_pipes = 1;
-	if (num_backends > R6XX_MAX_BACKENDS)
-		num_backends = R6XX_MAX_BACKENDS;
-	if (num_backends < 1)
-		num_backends = 1;
-
-	enabled_backends_mask = 0;
-	enabled_backends_count = 0;
-	for (i = 0; i < R6XX_MAX_BACKENDS; ++i) {
-		if (((backend_disable_mask >> i) & 1) == 0) {
-			enabled_backends_mask |= (1 << i);
-			++enabled_backends_count;
-		}
-		if (enabled_backends_count == num_backends)
-			break;
-	}
-
-	if (enabled_backends_count == 0) {
-		enabled_backends_mask = 1;
-		enabled_backends_count = 1;
-	}
-
-	if (enabled_backends_count != num_backends)
-		num_backends = enabled_backends_count;
-
-	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R6XX_MAX_PIPES);
-	switch (num_tile_pipes) {
-	case 1:
-		swizzle_pipe[0] = 0;
-		break;
-	case 2:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 1;
-		break;
-	case 3:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 1;
-		swizzle_pipe[2] = 2;
-		break;
-	case 4:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 1;
-		swizzle_pipe[2] = 2;
-		swizzle_pipe[3] = 3;
-		break;
-	case 5:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 1;
-		swizzle_pipe[2] = 2;
-		swizzle_pipe[3] = 3;
-		swizzle_pipe[4] = 4;
-		break;
-	case 6:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 5;
-		swizzle_pipe[4] = 1;
-		swizzle_pipe[5] = 3;
-		break;
-	case 7:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 6;
-		swizzle_pipe[4] = 1;
-		swizzle_pipe[5] = 3;
-		swizzle_pipe[6] = 5;
-		break;
-	case 8:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 6;
-		swizzle_pipe[4] = 1;
-		swizzle_pipe[5] = 3;
-		swizzle_pipe[6] = 5;
-		swizzle_pipe[7] = 7;
-		break;
-	}
-
-	cur_backend = 0;
-	for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) {
-		while (((1 << cur_backend) & enabled_backends_mask) == 0)
-			cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS;
-
-		backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2)));
-
-		cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS;
-	}
-
-	return backend_map;
-}
-
-static int r600_count_pipe_bits(uint32_t val)
-{
-	return hweight32(val);
-}
-
-static void r600_gfx_init(struct drm_device *dev,
-			  drm_radeon_private_t *dev_priv)
-{
-	int i, j, num_qd_pipes;
-	u32 sx_debug_1;
-	u32 tc_cntl;
-	u32 arb_pop;
-	u32 num_gs_verts_per_thread;
-	u32 vgt_gs_per_es;
-	u32 gs_prim_buffer_depth = 0;
-	u32 sq_ms_fifo_sizes;
-	u32 sq_config;
-	u32 sq_gpr_resource_mgmt_1 = 0;
-	u32 sq_gpr_resource_mgmt_2 = 0;
-	u32 sq_thread_resource_mgmt = 0;
-	u32 sq_stack_resource_mgmt_1 = 0;
-	u32 sq_stack_resource_mgmt_2 = 0;
-	u32 hdp_host_path_cntl;
-	u32 backend_map;
-	u32 gb_tiling_config = 0;
-	u32 cc_rb_backend_disable;
-	u32 cc_gc_shader_pipe_config;
-	u32 ramcfg;
-
-	/* setup chip specs */
-	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
-	case CHIP_R600:
-		dev_priv->r600_max_pipes = 4;
-		dev_priv->r600_max_tile_pipes = 8;
-		dev_priv->r600_max_simds = 4;
-		dev_priv->r600_max_backends = 4;
-		dev_priv->r600_max_gprs = 256;
-		dev_priv->r600_max_threads = 192;
-		dev_priv->r600_max_stack_entries = 256;
-		dev_priv->r600_max_hw_contexts = 8;
-		dev_priv->r600_max_gs_threads = 16;
-		dev_priv->r600_sx_max_export_size = 128;
-		dev_priv->r600_sx_max_export_pos_size = 16;
-		dev_priv->r600_sx_max_export_smx_size = 128;
-		dev_priv->r600_sq_num_cf_insts = 2;
-		break;
-	case CHIP_RV630:
-	case CHIP_RV635:
-		dev_priv->r600_max_pipes = 2;
-		dev_priv->r600_max_tile_pipes = 2;
-		dev_priv->r600_max_simds = 3;
-		dev_priv->r600_max_backends = 1;
-		dev_priv->r600_max_gprs = 128;
-		dev_priv->r600_max_threads = 192;
-		dev_priv->r600_max_stack_entries = 128;
-		dev_priv->r600_max_hw_contexts = 8;
-		dev_priv->r600_max_gs_threads = 4;
-		dev_priv->r600_sx_max_export_size = 128;
-		dev_priv->r600_sx_max_export_pos_size = 16;
-		dev_priv->r600_sx_max_export_smx_size = 128;
-		dev_priv->r600_sq_num_cf_insts = 2;
-		break;
-	case CHIP_RV610:
-	case CHIP_RS780:
-	case CHIP_RS880:
-	case CHIP_RV620:
-		dev_priv->r600_max_pipes = 1;
-		dev_priv->r600_max_tile_pipes = 1;
-		dev_priv->r600_max_simds = 2;
-		dev_priv->r600_max_backends = 1;
-		dev_priv->r600_max_gprs = 128;
-		dev_priv->r600_max_threads = 192;
-		dev_priv->r600_max_stack_entries = 128;
-		dev_priv->r600_max_hw_contexts = 4;
-		dev_priv->r600_max_gs_threads = 4;
-		dev_priv->r600_sx_max_export_size = 128;
-		dev_priv->r600_sx_max_export_pos_size = 16;
-		dev_priv->r600_sx_max_export_smx_size = 128;
-		dev_priv->r600_sq_num_cf_insts = 1;
-		break;
-	case CHIP_RV670:
-		dev_priv->r600_max_pipes = 4;
-		dev_priv->r600_max_tile_pipes = 4;
-		dev_priv->r600_max_simds = 4;
-		dev_priv->r600_max_backends = 4;
-		dev_priv->r600_max_gprs = 192;
-		dev_priv->r600_max_threads = 192;
-		dev_priv->r600_max_stack_entries = 256;
-		dev_priv->r600_max_hw_contexts = 8;
-		dev_priv->r600_max_gs_threads = 16;
-		dev_priv->r600_sx_max_export_size = 128;
-		dev_priv->r600_sx_max_export_pos_size = 16;
-		dev_priv->r600_sx_max_export_smx_size = 128;
-		dev_priv->r600_sq_num_cf_insts = 2;
-		break;
-	default:
-		break;
-	}
-
-	/* Initialize HDP */
-	j = 0;
-	for (i = 0; i < 32; i++) {
-		RADEON_WRITE((0x2c14 + j), 0x00000000);
-		RADEON_WRITE((0x2c18 + j), 0x00000000);
-		RADEON_WRITE((0x2c1c + j), 0x00000000);
-		RADEON_WRITE((0x2c20 + j), 0x00000000);
-		RADEON_WRITE((0x2c24 + j), 0x00000000);
-		j += 0x18;
-	}
-
-	RADEON_WRITE(R600_GRBM_CNTL, R600_GRBM_READ_TIMEOUT(0xff));
-
-	/* setup tiling, simd, pipe config */
-	ramcfg = RADEON_READ(R600_RAMCFG);
-
-	switch (dev_priv->r600_max_tile_pipes) {
-	case 1:
-		gb_tiling_config |= R600_PIPE_TILING(0);
-		break;
-	case 2:
-		gb_tiling_config |= R600_PIPE_TILING(1);
-		break;
-	case 4:
-		gb_tiling_config |= R600_PIPE_TILING(2);
-		break;
-	case 8:
-		gb_tiling_config |= R600_PIPE_TILING(3);
-		break;
-	default:
-		break;
-	}
-
-	gb_tiling_config |= R600_BANK_TILING((ramcfg >> R600_NOOFBANK_SHIFT) & R600_NOOFBANK_MASK);
-
-	gb_tiling_config |= R600_GROUP_SIZE(0);
-
-	if (((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK) > 3) {
-		gb_tiling_config |= R600_ROW_TILING(3);
-		gb_tiling_config |= R600_SAMPLE_SPLIT(3);
-	} else {
-		gb_tiling_config |=
-			R600_ROW_TILING(((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK));
-		gb_tiling_config |=
-			R600_SAMPLE_SPLIT(((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK));
-	}
-
-	gb_tiling_config |= R600_BANK_SWAPS(1);
-
-	cc_rb_backend_disable = RADEON_READ(R600_CC_RB_BACKEND_DISABLE) & 0x00ff0000;
-	cc_rb_backend_disable |=
-		R600_BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R6XX_MAX_BACKENDS_MASK);
-
-	cc_gc_shader_pipe_config = RADEON_READ(R600_CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
-	cc_gc_shader_pipe_config |=
-		R600_INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R6XX_MAX_PIPES_MASK);
-	cc_gc_shader_pipe_config |=
-		R600_INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R6XX_MAX_SIMDS_MASK);
-
-	backend_map = r600_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
-							(R6XX_MAX_BACKENDS -
-							 r600_count_pipe_bits((cc_rb_backend_disable &
-									       R6XX_MAX_BACKENDS_MASK) >> 16)),
-							(cc_rb_backend_disable >> 16));
-	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
-
-	RADEON_WRITE(R600_GB_TILING_CONFIG,      gb_tiling_config);
-	RADEON_WRITE(R600_DCP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
-	RADEON_WRITE(R600_HDP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
-	if (gb_tiling_config & 0xc0) {
-		dev_priv->r600_group_size = 512;
-	} else {
-		dev_priv->r600_group_size = 256;
-	}
-	dev_priv->r600_npipes = 1 << ((gb_tiling_config >> 1) & 0x7);
-	if (gb_tiling_config & 0x30) {
-		dev_priv->r600_nbanks = 8;
-	} else {
-		dev_priv->r600_nbanks = 4;
-	}
-
-	RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
-	RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
-	RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
-
-	num_qd_pipes =
-		R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8);
-	RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK);
-	RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK);
-
-	/* set HW defaults for 3D engine */
-	RADEON_WRITE(R600_CP_QUEUE_THRESHOLDS, (R600_ROQ_IB1_START(0x16) |
-						R600_ROQ_IB2_START(0x2b)));
-
-	RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, (R600_MEQ_END(0x40) |
-					      R600_ROQ_END(0x40)));
-
-	RADEON_WRITE(R600_TA_CNTL_AUX, (R600_DISABLE_CUBE_ANISO |
-					R600_SYNC_GRADIENT |
-					R600_SYNC_WALKER |
-					R600_SYNC_ALIGNER));
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670)
-		RADEON_WRITE(R600_ARB_GDEC_RD_CNTL, 0x00000021);
-
-	sx_debug_1 = RADEON_READ(R600_SX_DEBUG_1);
-	sx_debug_1 |= R600_SMX_EVENT_RELEASE;
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_R600))
-		sx_debug_1 |= R600_ENABLE_NEW_SMX_ADDRESS;
-	RADEON_WRITE(R600_SX_DEBUG_1, sx_debug_1);
-
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
-		RADEON_WRITE(R600_DB_DEBUG, R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE);
-	else
-		RADEON_WRITE(R600_DB_DEBUG, 0);
-
-	RADEON_WRITE(R600_DB_WATERMARKS, (R600_DEPTH_FREE(4) |
-					  R600_DEPTH_FLUSH(16) |
-					  R600_DEPTH_PENDING_FREE(4) |
-					  R600_DEPTH_CACHELINE_FREE(16)));
-	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
-	RADEON_WRITE(R600_VGT_NUM_INSTANCES, 0);
-
-	RADEON_WRITE(R600_SPI_CONFIG_CNTL, R600_GPR_WRITE_PRIORITY(0));
-	RADEON_WRITE(R600_SPI_CONFIG_CNTL_1, R600_VTX_DONE_DELAY(0));
-
-	sq_ms_fifo_sizes = RADEON_READ(R600_SQ_MS_FIFO_SIZES);
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
-		sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(0xa) |
-				    R600_FETCH_FIFO_HIWATER(0xa) |
-				    R600_DONE_FIFO_HIWATER(0xe0) |
-				    R600_ALU_UPDATE_FIFO_HIWATER(0x8));
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) {
-		sq_ms_fifo_sizes &= ~R600_DONE_FIFO_HIWATER(0xff);
-		sq_ms_fifo_sizes |= R600_DONE_FIFO_HIWATER(0x4);
-	}
-	RADEON_WRITE(R600_SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes);
-
-	/* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT
-	 * should be adjusted as needed by the 2D/3D drivers.  This just sets default values
-	 */
-	sq_config = RADEON_READ(R600_SQ_CONFIG);
-	sq_config &= ~(R600_PS_PRIO(3) |
-		       R600_VS_PRIO(3) |
-		       R600_GS_PRIO(3) |
-		       R600_ES_PRIO(3));
-	sq_config |= (R600_DX9_CONSTS |
-		      R600_VC_ENABLE |
-		      R600_PS_PRIO(0) |
-		      R600_VS_PRIO(1) |
-		      R600_GS_PRIO(2) |
-		      R600_ES_PRIO(3));
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) {
-		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(124) |
-					  R600_NUM_VS_GPRS(124) |
-					  R600_NUM_CLAUSE_TEMP_GPRS(4));
-		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(0) |
-					  R600_NUM_ES_GPRS(0));
-		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(136) |
-					   R600_NUM_VS_THREADS(48) |
-					   R600_NUM_GS_THREADS(4) |
-					   R600_NUM_ES_THREADS(4));
-		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(128) |
-					    R600_NUM_VS_STACK_ENTRIES(128));
-		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(0) |
-					    R600_NUM_ES_STACK_ENTRIES(0));
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
-		/* no vertex cache */
-		sq_config &= ~R600_VC_ENABLE;
-
-		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) |
-					  R600_NUM_VS_GPRS(44) |
-					  R600_NUM_CLAUSE_TEMP_GPRS(2));
-		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(17) |
-					  R600_NUM_ES_GPRS(17));
-		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) |
-					   R600_NUM_VS_THREADS(78) |
-					   R600_NUM_GS_THREADS(4) |
-					   R600_NUM_ES_THREADS(31));
-		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(40) |
-					    R600_NUM_VS_STACK_ENTRIES(40));
-		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(32) |
-					    R600_NUM_ES_STACK_ENTRIES(16));
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) {
-		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) |
-					  R600_NUM_VS_GPRS(44) |
-					  R600_NUM_CLAUSE_TEMP_GPRS(2));
-		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(18) |
-					  R600_NUM_ES_GPRS(18));
-		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) |
-					   R600_NUM_VS_THREADS(78) |
-					   R600_NUM_GS_THREADS(4) |
-					   R600_NUM_ES_THREADS(31));
-		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(40) |
-					    R600_NUM_VS_STACK_ENTRIES(40));
-		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(32) |
-					    R600_NUM_ES_STACK_ENTRIES(16));
-	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670) {
-		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) |
-					  R600_NUM_VS_GPRS(44) |
-					  R600_NUM_CLAUSE_TEMP_GPRS(2));
-		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(17) |
-					  R600_NUM_ES_GPRS(17));
-		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) |
-					   R600_NUM_VS_THREADS(78) |
-					   R600_NUM_GS_THREADS(4) |
-					   R600_NUM_ES_THREADS(31));
-		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(64) |
-					    R600_NUM_VS_STACK_ENTRIES(64));
-		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(64) |
-					    R600_NUM_ES_STACK_ENTRIES(64));
-	}
-
-	RADEON_WRITE(R600_SQ_CONFIG, sq_config);
-	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_1,  sq_gpr_resource_mgmt_1);
-	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_2,  sq_gpr_resource_mgmt_2);
-	RADEON_WRITE(R600_SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt);
-	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_1, sq_stack_resource_mgmt_1);
-	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_2, sq_stack_resource_mgmt_2);
-
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
-		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_TC_ONLY));
-	else
-		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_VC_AND_TC));
-
-	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_2S, (R600_S0_X(0xc) |
-						    R600_S0_Y(0x4) |
-						    R600_S1_X(0x4) |
-						    R600_S1_Y(0xc)));
-	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_4S, (R600_S0_X(0xe) |
-						    R600_S0_Y(0xe) |
-						    R600_S1_X(0x2) |
-						    R600_S1_Y(0x2) |
-						    R600_S2_X(0xa) |
-						    R600_S2_Y(0x6) |
-						    R600_S3_X(0x6) |
-						    R600_S3_Y(0xa)));
-	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_8S_WD0, (R600_S0_X(0xe) |
-							R600_S0_Y(0xb) |
-							R600_S1_X(0x4) |
-							R600_S1_Y(0xc) |
-							R600_S2_X(0x1) |
-							R600_S2_Y(0x6) |
-							R600_S3_X(0xa) |
-							R600_S3_Y(0xe)));
-	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_8S_WD1, (R600_S4_X(0x6) |
-							R600_S4_Y(0x1) |
-							R600_S5_X(0x0) |
-							R600_S5_Y(0x0) |
-							R600_S6_X(0xb) |
-							R600_S6_Y(0x4) |
-							R600_S7_X(0x7) |
-							R600_S7_Y(0x8)));
-
-
-	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
-	case CHIP_R600:
-	case CHIP_RV630:
-	case CHIP_RV635:
-		gs_prim_buffer_depth = 0;
-		break;
-	case CHIP_RV610:
-	case CHIP_RS780:
-	case CHIP_RS880:
-	case CHIP_RV620:
-		gs_prim_buffer_depth = 32;
-		break;
-	case CHIP_RV670:
-		gs_prim_buffer_depth = 128;
-		break;
-	default:
-		break;
-	}
-
-	num_gs_verts_per_thread = dev_priv->r600_max_pipes * 16;
-	vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread;
-	/* Max value for this is 256 */
-	if (vgt_gs_per_es > 256)
-		vgt_gs_per_es = 256;
-
-	RADEON_WRITE(R600_VGT_ES_PER_GS, 128);
-	RADEON_WRITE(R600_VGT_GS_PER_ES, vgt_gs_per_es);
-	RADEON_WRITE(R600_VGT_GS_PER_VS, 2);
-	RADEON_WRITE(R600_VGT_GS_VERTEX_REUSE, 16);
-
-	/* more default values. 2D/3D driver should adjust as needed */
-	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE_STATE, 0);
-	RADEON_WRITE(R600_VGT_STRMOUT_EN, 0);
-	RADEON_WRITE(R600_SX_MISC, 0);
-	RADEON_WRITE(R600_PA_SC_MODE_CNTL, 0);
-	RADEON_WRITE(R600_PA_SC_AA_CONFIG, 0);
-	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE, 0);
-	RADEON_WRITE(R600_SPI_INPUT_Z, 0);
-	RADEON_WRITE(R600_SPI_PS_IN_CONTROL_0, R600_NUM_INTERP(2));
-	RADEON_WRITE(R600_CB_COLOR7_FRAG, 0);
-
-	/* clear render buffer base addresses */
-	RADEON_WRITE(R600_CB_COLOR0_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR1_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR2_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR3_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR4_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR5_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR6_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR7_BASE, 0);
-
-	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
-	case CHIP_RV610:
-	case CHIP_RS780:
-	case CHIP_RS880:
-	case CHIP_RV620:
-		tc_cntl = R600_TC_L2_SIZE(8);
-		break;
-	case CHIP_RV630:
-	case CHIP_RV635:
-		tc_cntl = R600_TC_L2_SIZE(4);
-		break;
-	case CHIP_R600:
-		tc_cntl = R600_TC_L2_SIZE(0) | R600_L2_DISABLE_LATE_HIT;
-		break;
-	default:
-		tc_cntl = R600_TC_L2_SIZE(0);
-		break;
-	}
-
-	RADEON_WRITE(R600_TC_CNTL, tc_cntl);
-
-	hdp_host_path_cntl = RADEON_READ(R600_HDP_HOST_PATH_CNTL);
-	RADEON_WRITE(R600_HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
-
-	arb_pop = RADEON_READ(R600_ARB_POP);
-	arb_pop |= R600_ENABLE_TC128;
-	RADEON_WRITE(R600_ARB_POP, arb_pop);
-
-	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
-	RADEON_WRITE(R600_PA_CL_ENHANCE, (R600_CLIP_VTX_REORDER_ENA |
-					  R600_NUM_CLIP_SEQ(3)));
-	RADEON_WRITE(R600_PA_SC_ENHANCE, R600_FORCE_EOV_MAX_CLK_CNT(4095));
-
-}
-
-static u32 r700_get_tile_pipe_to_backend_map(drm_radeon_private_t *dev_priv,
-					     u32 num_tile_pipes,
-					     u32 num_backends,
-					     u32 backend_disable_mask)
-{
-	u32 backend_map = 0;
-	u32 enabled_backends_mask;
-	u32 enabled_backends_count;
-	u32 cur_pipe;
-	u32 swizzle_pipe[R7XX_MAX_PIPES];
-	u32 cur_backend;
-	u32 i;
-	bool force_no_swizzle;
-
-	if (num_tile_pipes > R7XX_MAX_PIPES)
-		num_tile_pipes = R7XX_MAX_PIPES;
-	if (num_tile_pipes < 1)
-		num_tile_pipes = 1;
-	if (num_backends > R7XX_MAX_BACKENDS)
-		num_backends = R7XX_MAX_BACKENDS;
-	if (num_backends < 1)
-		num_backends = 1;
-
-	enabled_backends_mask = 0;
-	enabled_backends_count = 0;
-	for (i = 0; i < R7XX_MAX_BACKENDS; ++i) {
-		if (((backend_disable_mask >> i) & 1) == 0) {
-			enabled_backends_mask |= (1 << i);
-			++enabled_backends_count;
-		}
-		if (enabled_backends_count == num_backends)
-			break;
-	}
-
-	if (enabled_backends_count == 0) {
-		enabled_backends_mask = 1;
-		enabled_backends_count = 1;
-	}
-
-	if (enabled_backends_count != num_backends)
-		num_backends = enabled_backends_count;
-
-	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
-	case CHIP_RV770:
-	case CHIP_RV730:
-		force_no_swizzle = false;
-		break;
-	case CHIP_RV710:
-	case CHIP_RV740:
-	default:
-		force_no_swizzle = true;
-		break;
-	}
-
-	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES);
-	switch (num_tile_pipes) {
-	case 1:
-		swizzle_pipe[0] = 0;
-		break;
-	case 2:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 1;
-		break;
-	case 3:
-		if (force_no_swizzle) {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 1;
-			swizzle_pipe[2] = 2;
-		} else {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 2;
-			swizzle_pipe[2] = 1;
-		}
-		break;
-	case 4:
-		if (force_no_swizzle) {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 1;
-			swizzle_pipe[2] = 2;
-			swizzle_pipe[3] = 3;
-		} else {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 2;
-			swizzle_pipe[2] = 3;
-			swizzle_pipe[3] = 1;
-		}
-		break;
-	case 5:
-		if (force_no_swizzle) {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 1;
-			swizzle_pipe[2] = 2;
-			swizzle_pipe[3] = 3;
-			swizzle_pipe[4] = 4;
-		} else {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 2;
-			swizzle_pipe[2] = 4;
-			swizzle_pipe[3] = 1;
-			swizzle_pipe[4] = 3;
-		}
-		break;
-	case 6:
-		if (force_no_swizzle) {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 1;
-			swizzle_pipe[2] = 2;
-			swizzle_pipe[3] = 3;
-			swizzle_pipe[4] = 4;
-			swizzle_pipe[5] = 5;
-		} else {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 2;
-			swizzle_pipe[2] = 4;
-			swizzle_pipe[3] = 5;
-			swizzle_pipe[4] = 3;
-			swizzle_pipe[5] = 1;
-		}
-		break;
-	case 7:
-		if (force_no_swizzle) {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 1;
-			swizzle_pipe[2] = 2;
-			swizzle_pipe[3] = 3;
-			swizzle_pipe[4] = 4;
-			swizzle_pipe[5] = 5;
-			swizzle_pipe[6] = 6;
-		} else {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 2;
-			swizzle_pipe[2] = 4;
-			swizzle_pipe[3] = 6;
-			swizzle_pipe[4] = 3;
-			swizzle_pipe[5] = 1;
-			swizzle_pipe[6] = 5;
-		}
-		break;
-	case 8:
-		if (force_no_swizzle) {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 1;
-			swizzle_pipe[2] = 2;
-			swizzle_pipe[3] = 3;
-			swizzle_pipe[4] = 4;
-			swizzle_pipe[5] = 5;
-			swizzle_pipe[6] = 6;
-			swizzle_pipe[7] = 7;
-		} else {
-			swizzle_pipe[0] = 0;
-			swizzle_pipe[1] = 2;
-			swizzle_pipe[2] = 4;
-			swizzle_pipe[3] = 6;
-			swizzle_pipe[4] = 3;
-			swizzle_pipe[5] = 1;
-			swizzle_pipe[6] = 7;
-			swizzle_pipe[7] = 5;
-		}
-		break;
-	}
-
-	cur_backend = 0;
-	for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) {
-		while (((1 << cur_backend) & enabled_backends_mask) == 0)
-			cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS;
-
-		backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2)));
-
-		cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS;
-	}
-
-	return backend_map;
-}
-
-static void r700_gfx_init(struct drm_device *dev,
-			  drm_radeon_private_t *dev_priv)
-{
-	int i, j, num_qd_pipes;
-	u32 ta_aux_cntl;
-	u32 sx_debug_1;
-	u32 smx_dc_ctl0;
-	u32 db_debug3;
-	u32 num_gs_verts_per_thread;
-	u32 vgt_gs_per_es;
-	u32 gs_prim_buffer_depth = 0;
-	u32 sq_ms_fifo_sizes;
-	u32 sq_config;
-	u32 sq_thread_resource_mgmt;
-	u32 hdp_host_path_cntl;
-	u32 sq_dyn_gpr_size_simd_ab_0;
-	u32 backend_map;
-	u32 gb_tiling_config = 0;
-	u32 cc_rb_backend_disable;
-	u32 cc_gc_shader_pipe_config;
-	u32 mc_arb_ramcfg;
-	u32 db_debug4;
-
-	/* setup chip specs */
-	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
-	case CHIP_RV770:
-		dev_priv->r600_max_pipes = 4;
-		dev_priv->r600_max_tile_pipes = 8;
-		dev_priv->r600_max_simds = 10;
-		dev_priv->r600_max_backends = 4;
-		dev_priv->r600_max_gprs = 256;
-		dev_priv->r600_max_threads = 248;
-		dev_priv->r600_max_stack_entries = 512;
-		dev_priv->r600_max_hw_contexts = 8;
-		dev_priv->r600_max_gs_threads = 16 * 2;
-		dev_priv->r600_sx_max_export_size = 128;
-		dev_priv->r600_sx_max_export_pos_size = 16;
-		dev_priv->r600_sx_max_export_smx_size = 112;
-		dev_priv->r600_sq_num_cf_insts = 2;
-
-		dev_priv->r700_sx_num_of_sets = 7;
-		dev_priv->r700_sc_prim_fifo_size = 0xF9;
-		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
-		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
-		break;
-	case CHIP_RV730:
-		dev_priv->r600_max_pipes = 2;
-		dev_priv->r600_max_tile_pipes = 4;
-		dev_priv->r600_max_simds = 8;
-		dev_priv->r600_max_backends = 2;
-		dev_priv->r600_max_gprs = 128;
-		dev_priv->r600_max_threads = 248;
-		dev_priv->r600_max_stack_entries = 256;
-		dev_priv->r600_max_hw_contexts = 8;
-		dev_priv->r600_max_gs_threads = 16 * 2;
-		dev_priv->r600_sx_max_export_size = 256;
-		dev_priv->r600_sx_max_export_pos_size = 32;
-		dev_priv->r600_sx_max_export_smx_size = 224;
-		dev_priv->r600_sq_num_cf_insts = 2;
-
-		dev_priv->r700_sx_num_of_sets = 7;
-		dev_priv->r700_sc_prim_fifo_size = 0xf9;
-		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
-		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
-		if (dev_priv->r600_sx_max_export_pos_size > 16) {
-			dev_priv->r600_sx_max_export_pos_size -= 16;
-			dev_priv->r600_sx_max_export_smx_size += 16;
-		}
-		break;
-	case CHIP_RV710:
-		dev_priv->r600_max_pipes = 2;
-		dev_priv->r600_max_tile_pipes = 2;
-		dev_priv->r600_max_simds = 2;
-		dev_priv->r600_max_backends = 1;
-		dev_priv->r600_max_gprs = 256;
-		dev_priv->r600_max_threads = 192;
-		dev_priv->r600_max_stack_entries = 256;
-		dev_priv->r600_max_hw_contexts = 4;
-		dev_priv->r600_max_gs_threads = 8 * 2;
-		dev_priv->r600_sx_max_export_size = 128;
-		dev_priv->r600_sx_max_export_pos_size = 16;
-		dev_priv->r600_sx_max_export_smx_size = 112;
-		dev_priv->r600_sq_num_cf_insts = 1;
-
-		dev_priv->r700_sx_num_of_sets = 7;
-		dev_priv->r700_sc_prim_fifo_size = 0x40;
-		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
-		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
-		break;
-	case CHIP_RV740:
-		dev_priv->r600_max_pipes = 4;
-		dev_priv->r600_max_tile_pipes = 4;
-		dev_priv->r600_max_simds = 8;
-		dev_priv->r600_max_backends = 4;
-		dev_priv->r600_max_gprs = 256;
-		dev_priv->r600_max_threads = 248;
-		dev_priv->r600_max_stack_entries = 512;
-		dev_priv->r600_max_hw_contexts = 8;
-		dev_priv->r600_max_gs_threads = 16 * 2;
-		dev_priv->r600_sx_max_export_size = 256;
-		dev_priv->r600_sx_max_export_pos_size = 32;
-		dev_priv->r600_sx_max_export_smx_size = 224;
-		dev_priv->r600_sq_num_cf_insts = 2;
-
-		dev_priv->r700_sx_num_of_sets = 7;
-		dev_priv->r700_sc_prim_fifo_size = 0x100;
-		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
-		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
-
-		if (dev_priv->r600_sx_max_export_pos_size > 16) {
-			dev_priv->r600_sx_max_export_pos_size -= 16;
-			dev_priv->r600_sx_max_export_smx_size += 16;
-		}
-		break;
-	default:
-		break;
-	}
-
-	/* Initialize HDP */
-	j = 0;
-	for (i = 0; i < 32; i++) {
-		RADEON_WRITE((0x2c14 + j), 0x00000000);
-		RADEON_WRITE((0x2c18 + j), 0x00000000);
-		RADEON_WRITE((0x2c1c + j), 0x00000000);
-		RADEON_WRITE((0x2c20 + j), 0x00000000);
-		RADEON_WRITE((0x2c24 + j), 0x00000000);
-		j += 0x18;
-	}
-
-	RADEON_WRITE(R600_GRBM_CNTL, R600_GRBM_READ_TIMEOUT(0xff));
-
-	/* setup tiling, simd, pipe config */
-	mc_arb_ramcfg = RADEON_READ(R700_MC_ARB_RAMCFG);
-
-	switch (dev_priv->r600_max_tile_pipes) {
-	case 1:
-		gb_tiling_config |= R600_PIPE_TILING(0);
-		break;
-	case 2:
-		gb_tiling_config |= R600_PIPE_TILING(1);
-		break;
-	case 4:
-		gb_tiling_config |= R600_PIPE_TILING(2);
-		break;
-	case 8:
-		gb_tiling_config |= R600_PIPE_TILING(3);
-		break;
-	default:
-		break;
-	}
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)
-		gb_tiling_config |= R600_BANK_TILING(1);
-	else
-		gb_tiling_config |= R600_BANK_TILING((mc_arb_ramcfg >> R700_NOOFBANK_SHIFT) & R700_NOOFBANK_MASK);
-
-	gb_tiling_config |= R600_GROUP_SIZE(0);
-
-	if (((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK) > 3) {
-		gb_tiling_config |= R600_ROW_TILING(3);
-		gb_tiling_config |= R600_SAMPLE_SPLIT(3);
-	} else {
-		gb_tiling_config |=
-			R600_ROW_TILING(((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK));
-		gb_tiling_config |=
-			R600_SAMPLE_SPLIT(((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK));
-	}
-
-	gb_tiling_config |= R600_BANK_SWAPS(1);
-
-	cc_rb_backend_disable = RADEON_READ(R600_CC_RB_BACKEND_DISABLE) & 0x00ff0000;
-	cc_rb_backend_disable |=
-		R600_BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R7XX_MAX_BACKENDS_MASK);
-
-	cc_gc_shader_pipe_config = RADEON_READ(R600_CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
-	cc_gc_shader_pipe_config |=
-		R600_INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R7XX_MAX_PIPES_MASK);
-	cc_gc_shader_pipe_config |=
-		R600_INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R7XX_MAX_SIMDS_MASK);
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740)
-		backend_map = 0x28;
-	else
-		backend_map = r700_get_tile_pipe_to_backend_map(dev_priv,
-								dev_priv->r600_max_tile_pipes,
-								(R7XX_MAX_BACKENDS -
-								 r600_count_pipe_bits((cc_rb_backend_disable &
-										       R7XX_MAX_BACKENDS_MASK) >> 16)),
-								(cc_rb_backend_disable >> 16));
-	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
-
-	RADEON_WRITE(R600_GB_TILING_CONFIG,      gb_tiling_config);
-	RADEON_WRITE(R600_DCP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
-	RADEON_WRITE(R600_HDP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
-	if (gb_tiling_config & 0xc0) {
-		dev_priv->r600_group_size = 512;
-	} else {
-		dev_priv->r600_group_size = 256;
-	}
-	dev_priv->r600_npipes = 1 << ((gb_tiling_config >> 1) & 0x7);
-	if (gb_tiling_config & 0x30) {
-		dev_priv->r600_nbanks = 8;
-	} else {
-		dev_priv->r600_nbanks = 4;
-	}
-
-	RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
-	RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
-	RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
-
-	RADEON_WRITE(R700_CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
-	RADEON_WRITE(R700_CGTS_SYS_TCC_DISABLE, 0);
-	RADEON_WRITE(R700_CGTS_TCC_DISABLE, 0);
-	RADEON_WRITE(R700_CGTS_USER_SYS_TCC_DISABLE, 0);
-	RADEON_WRITE(R700_CGTS_USER_TCC_DISABLE, 0);
-
-	num_qd_pipes =
-		R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8);
-	RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK);
-	RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK);
-
-	/* set HW defaults for 3D engine */
-	RADEON_WRITE(R600_CP_QUEUE_THRESHOLDS, (R600_ROQ_IB1_START(0x16) |
-						R600_ROQ_IB2_START(0x2b)));
-
-	RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, R700_STQ_SPLIT(0x30));
-
-	ta_aux_cntl = RADEON_READ(R600_TA_CNTL_AUX);
-	RADEON_WRITE(R600_TA_CNTL_AUX, ta_aux_cntl | R600_DISABLE_CUBE_ANISO);
-
-	sx_debug_1 = RADEON_READ(R700_SX_DEBUG_1);
-	sx_debug_1 |= R700_ENABLE_NEW_SMX_ADDRESS;
-	RADEON_WRITE(R700_SX_DEBUG_1, sx_debug_1);
-
-	smx_dc_ctl0 = RADEON_READ(R600_SMX_DC_CTL0);
-	smx_dc_ctl0 &= ~R700_CACHE_DEPTH(0x1ff);
-	smx_dc_ctl0 |= R700_CACHE_DEPTH((dev_priv->r700_sx_num_of_sets * 64) - 1);
-	RADEON_WRITE(R600_SMX_DC_CTL0, smx_dc_ctl0);
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) != CHIP_RV740)
-		RADEON_WRITE(R700_SMX_EVENT_CTL, (R700_ES_FLUSH_CTL(4) |
-						  R700_GS_FLUSH_CTL(4) |
-						  R700_ACK_FLUSH_CTL(3) |
-						  R700_SYNC_FLUSH_CTL));
-
-	db_debug3 = RADEON_READ(R700_DB_DEBUG3);
-	db_debug3 &= ~R700_DB_CLK_OFF_DELAY(0x1f);
-	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
-	case CHIP_RV770:
-	case CHIP_RV740:
-		db_debug3 |= R700_DB_CLK_OFF_DELAY(0x1f);
-		break;
-	case CHIP_RV710:
-	case CHIP_RV730:
-	default:
-		db_debug3 |= R700_DB_CLK_OFF_DELAY(2);
-		break;
-	}
-	RADEON_WRITE(R700_DB_DEBUG3, db_debug3);
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) != CHIP_RV770) {
-		db_debug4 = RADEON_READ(RV700_DB_DEBUG4);
-		db_debug4 |= RV700_DISABLE_TILE_COVERED_FOR_PS_ITER;
-		RADEON_WRITE(RV700_DB_DEBUG4, db_debug4);
-	}
-
-	RADEON_WRITE(R600_SX_EXPORT_BUFFER_SIZES, (R600_COLOR_BUFFER_SIZE((dev_priv->r600_sx_max_export_size / 4) - 1) |
-						   R600_POSITION_BUFFER_SIZE((dev_priv->r600_sx_max_export_pos_size / 4) - 1) |
-						   R600_SMX_BUFFER_SIZE((dev_priv->r600_sx_max_export_smx_size / 4) - 1)));
-
-	RADEON_WRITE(R700_PA_SC_FIFO_SIZE_R7XX, (R700_SC_PRIM_FIFO_SIZE(dev_priv->r700_sc_prim_fifo_size) |
-						 R700_SC_HIZ_TILE_FIFO_SIZE(dev_priv->r700_sc_hiz_tile_fifo_size) |
-						 R700_SC_EARLYZ_TILE_FIFO_SIZE(dev_priv->r700_sc_earlyz_tile_fifo_fize)));
-
-	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
-
-	RADEON_WRITE(R600_VGT_NUM_INSTANCES, 1);
-
-	RADEON_WRITE(R600_SPI_CONFIG_CNTL, R600_GPR_WRITE_PRIORITY(0));
-
-	RADEON_WRITE(R600_SPI_CONFIG_CNTL_1, R600_VTX_DONE_DELAY(4));
-
-	RADEON_WRITE(R600_CP_PERFMON_CNTL, 0);
-
-	sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(16 * dev_priv->r600_sq_num_cf_insts) |
-			    R600_DONE_FIFO_HIWATER(0xe0) |
-			    R600_ALU_UPDATE_FIFO_HIWATER(0x8));
-	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
-	case CHIP_RV770:
-	case CHIP_RV730:
-	case CHIP_RV710:
-		sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x1);
-		break;
-	case CHIP_RV740:
-	default:
-		sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4);
-		break;
-	}
-	RADEON_WRITE(R600_SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes);
-
-	/* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT
-	 * should be adjusted as needed by the 2D/3D drivers.  This just sets default values
-	 */
-	sq_config = RADEON_READ(R600_SQ_CONFIG);
-	sq_config &= ~(R600_PS_PRIO(3) |
-		       R600_VS_PRIO(3) |
-		       R600_GS_PRIO(3) |
-		       R600_ES_PRIO(3));
-	sq_config |= (R600_DX9_CONSTS |
-		      R600_VC_ENABLE |
-		      R600_EXPORT_SRC_C |
-		      R600_PS_PRIO(0) |
-		      R600_VS_PRIO(1) |
-		      R600_GS_PRIO(2) |
-		      R600_ES_PRIO(3));
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)
-		/* no vertex cache */
-		sq_config &= ~R600_VC_ENABLE;
-
-	RADEON_WRITE(R600_SQ_CONFIG, sq_config);
-
-	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_1,  (R600_NUM_PS_GPRS((dev_priv->r600_max_gprs * 24)/64) |
-						    R600_NUM_VS_GPRS((dev_priv->r600_max_gprs * 24)/64) |
-						    R600_NUM_CLAUSE_TEMP_GPRS(((dev_priv->r600_max_gprs * 24)/64)/2)));
-
-	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_2,  (R600_NUM_GS_GPRS((dev_priv->r600_max_gprs * 7)/64) |
-						    R600_NUM_ES_GPRS((dev_priv->r600_max_gprs * 7)/64)));
-
-	sq_thread_resource_mgmt = (R600_NUM_PS_THREADS((dev_priv->r600_max_threads * 4)/8) |
-				   R600_NUM_VS_THREADS((dev_priv->r600_max_threads * 2)/8) |
-				   R600_NUM_ES_THREADS((dev_priv->r600_max_threads * 1)/8));
-	if (((dev_priv->r600_max_threads * 1) / 8) > dev_priv->r600_max_gs_threads)
-		sq_thread_resource_mgmt |= R600_NUM_GS_THREADS(dev_priv->r600_max_gs_threads);
-	else
-		sq_thread_resource_mgmt |= R600_NUM_GS_THREADS((dev_priv->r600_max_gs_threads * 1)/8);
-	RADEON_WRITE(R600_SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt);
-
-	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_1, (R600_NUM_PS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4) |
-						     R600_NUM_VS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4)));
-
-	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_2, (R600_NUM_GS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4) |
-						     R600_NUM_ES_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4)));
-
-	sq_dyn_gpr_size_simd_ab_0 = (R700_SIMDA_RING0((dev_priv->r600_max_gprs * 38)/64) |
-				     R700_SIMDA_RING1((dev_priv->r600_max_gprs * 38)/64) |
-				     R700_SIMDB_RING0((dev_priv->r600_max_gprs * 38)/64) |
-				     R700_SIMDB_RING1((dev_priv->r600_max_gprs * 38)/64));
-
-	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_0, sq_dyn_gpr_size_simd_ab_0);
-	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_1, sq_dyn_gpr_size_simd_ab_0);
-	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_2, sq_dyn_gpr_size_simd_ab_0);
-	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_3, sq_dyn_gpr_size_simd_ab_0);
-	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_4, sq_dyn_gpr_size_simd_ab_0);
-	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_5, sq_dyn_gpr_size_simd_ab_0);
-	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_6, sq_dyn_gpr_size_simd_ab_0);
-	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_7, sq_dyn_gpr_size_simd_ab_0);
-
-	RADEON_WRITE(R700_PA_SC_FORCE_EOV_MAX_CNTS, (R700_FORCE_EOV_MAX_CLK_CNT(4095) |
-						     R700_FORCE_EOV_MAX_REZ_CNT(255)));
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)
-		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, (R600_CACHE_INVALIDATION(R600_TC_ONLY) |
-							   R700_AUTO_INVLD_EN(R700_ES_AND_GS_AUTO)));
-	else
-		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, (R600_CACHE_INVALIDATION(R600_VC_AND_TC) |
-							   R700_AUTO_INVLD_EN(R700_ES_AND_GS_AUTO)));
-
-	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
-	case CHIP_RV770:
-	case CHIP_RV730:
-	case CHIP_RV740:
-		gs_prim_buffer_depth = 384;
-		break;
-	case CHIP_RV710:
-		gs_prim_buffer_depth = 128;
-		break;
-	default:
-		break;
-	}
-
-	num_gs_verts_per_thread = dev_priv->r600_max_pipes * 16;
-	vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread;
-	/* Max value for this is 256 */
-	if (vgt_gs_per_es > 256)
-		vgt_gs_per_es = 256;
-
-	RADEON_WRITE(R600_VGT_ES_PER_GS, 128);
-	RADEON_WRITE(R600_VGT_GS_PER_ES, vgt_gs_per_es);
-	RADEON_WRITE(R600_VGT_GS_PER_VS, 2);
-
-	/* more default values. 2D/3D driver should adjust as needed */
-	RADEON_WRITE(R600_VGT_GS_VERTEX_REUSE, 16);
-	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE_STATE, 0);
-	RADEON_WRITE(R600_VGT_STRMOUT_EN, 0);
-	RADEON_WRITE(R600_SX_MISC, 0);
-	RADEON_WRITE(R600_PA_SC_MODE_CNTL, 0);
-	RADEON_WRITE(R700_PA_SC_EDGERULE, 0xaaaaaaaa);
-	RADEON_WRITE(R600_PA_SC_AA_CONFIG, 0);
-	RADEON_WRITE(R600_PA_SC_CLIPRECT_RULE, 0xffff);
-	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE, 0);
-	RADEON_WRITE(R600_SPI_INPUT_Z, 0);
-	RADEON_WRITE(R600_SPI_PS_IN_CONTROL_0, R600_NUM_INTERP(2));
-	RADEON_WRITE(R600_CB_COLOR7_FRAG, 0);
-
-	/* clear render buffer base addresses */
-	RADEON_WRITE(R600_CB_COLOR0_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR1_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR2_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR3_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR4_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR5_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR6_BASE, 0);
-	RADEON_WRITE(R600_CB_COLOR7_BASE, 0);
-
-	RADEON_WRITE(R700_TCP_CNTL, 0);
-
-	hdp_host_path_cntl = RADEON_READ(R600_HDP_HOST_PATH_CNTL);
-	RADEON_WRITE(R600_HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
-
-	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
-
-	RADEON_WRITE(R600_PA_CL_ENHANCE, (R600_CLIP_VTX_REORDER_ENA |
-					  R600_NUM_CLIP_SEQ(3)));
-
-}
-
-static void r600_cp_init_ring_buffer(struct drm_device *dev,
-				       drm_radeon_private_t *dev_priv,
-				       struct drm_file *file_priv)
-{
-	struct drm_radeon_master_private *master_priv;
-	u32 ring_start;
-	u64 rptr_addr;
-
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
-		r700_gfx_init(dev, dev_priv);
-	else
-		r600_gfx_init(dev, dev_priv);
-
-	RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
-	RADEON_READ(R600_GRBM_SOFT_RESET);
-	mdelay(15);
-	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
-
-
-	/* Set ring buffer size */
-#ifdef __BIG_ENDIAN
-	RADEON_WRITE(R600_CP_RB_CNTL,
-		     R600_BUF_SWAP_32BIT |
-		     R600_RB_NO_UPDATE |
-		     (dev_priv->ring.rptr_update_l2qw << 8) |
-		     dev_priv->ring.size_l2qw);
-#else
-	RADEON_WRITE(R600_CP_RB_CNTL,
-		     RADEON_RB_NO_UPDATE |
-		     (dev_priv->ring.rptr_update_l2qw << 8) |
-		     dev_priv->ring.size_l2qw);
-#endif
-
-	RADEON_WRITE(R600_CP_SEM_WAIT_TIMER, 0x0);
-
-	/* Set the write pointer delay */
-	RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0);
-
-#ifdef __BIG_ENDIAN
-	RADEON_WRITE(R600_CP_RB_CNTL,
-		     R600_BUF_SWAP_32BIT |
-		     R600_RB_NO_UPDATE |
-		     R600_RB_RPTR_WR_ENA |
-		     (dev_priv->ring.rptr_update_l2qw << 8) |
-		     dev_priv->ring.size_l2qw);
-#else
-	RADEON_WRITE(R600_CP_RB_CNTL,
-		     R600_RB_NO_UPDATE |
-		     R600_RB_RPTR_WR_ENA |
-		     (dev_priv->ring.rptr_update_l2qw << 8) |
-		     dev_priv->ring.size_l2qw);
-#endif
-
-	/* Initialize the ring buffer's read and write pointers */
-	RADEON_WRITE(R600_CP_RB_RPTR_WR, 0);
-	RADEON_WRITE(R600_CP_RB_WPTR, 0);
-	SET_RING_HEAD(dev_priv, 0);
-	dev_priv->ring.tail = 0;
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		rptr_addr = dev_priv->ring_rptr->offset
-			- dev->agp->base +
-			dev_priv->gart_vm_start;
-	} else
-#endif
-	{
-		rptr_addr = dev_priv->ring_rptr->offset
-			- ((unsigned long) dev->sg->virtual)
-			+ dev_priv->gart_vm_start;
-	}
-	RADEON_WRITE(R600_CP_RB_RPTR_ADDR, (rptr_addr & 0xfffffffc));
-	RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI, upper_32_bits(rptr_addr));
-
-#ifdef __BIG_ENDIAN
-	RADEON_WRITE(R600_CP_RB_CNTL,
-		     RADEON_BUF_SWAP_32BIT |
-		     (dev_priv->ring.rptr_update_l2qw << 8) |
-		     dev_priv->ring.size_l2qw);
-#else
-	RADEON_WRITE(R600_CP_RB_CNTL,
-		     (dev_priv->ring.rptr_update_l2qw << 8) |
-		     dev_priv->ring.size_l2qw);
-#endif
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		/* XXX */
-		radeon_write_agp_base(dev_priv, dev->agp->base);
-
-		/* XXX */
-		radeon_write_agp_location(dev_priv,
-			     (((dev_priv->gart_vm_start - 1 +
-				dev_priv->gart_size) & 0xffff0000) |
-			      (dev_priv->gart_vm_start >> 16)));
-
-		ring_start = (dev_priv->cp_ring->offset
-			      - dev->agp->base
-			      + dev_priv->gart_vm_start);
-	} else
-#endif
-		ring_start = (dev_priv->cp_ring->offset
-			      - (unsigned long)dev->sg->virtual
-			      + dev_priv->gart_vm_start);
-
-	RADEON_WRITE(R600_CP_RB_BASE, ring_start >> 8);
-
-	RADEON_WRITE(R600_CP_ME_CNTL, 0xff);
-
-	RADEON_WRITE(R600_CP_DEBUG, (1 << 27) | (1 << 28));
-
-	/* Initialize the scratch register pointer.  This will cause
-	 * the scratch register values to be written out to memory
-	 * whenever they are updated.
-	 *
-	 * We simply put this behind the ring read pointer, this works
-	 * with PCI GART as well as (whatever kind of) AGP GART
-	 */
-	{
-		u64 scratch_addr;
-
-		scratch_addr = RADEON_READ(R600_CP_RB_RPTR_ADDR) & 0xFFFFFFFC;
-		scratch_addr |= ((u64)RADEON_READ(R600_CP_RB_RPTR_ADDR_HI)) << 32;
-		scratch_addr += R600_SCRATCH_REG_OFFSET;
-		scratch_addr >>= 8;
-		scratch_addr &= 0xffffffff;
-
-		RADEON_WRITE(R600_SCRATCH_ADDR, (uint32_t)scratch_addr);
-	}
-
-	RADEON_WRITE(R600_SCRATCH_UMSK, 0x7);
-
-	/* Turn on bus mastering */
-	radeon_enable_bm(dev_priv);
-
-	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(0), 0);
-	RADEON_WRITE(R600_LAST_FRAME_REG, 0);
-
-	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0);
-	RADEON_WRITE(R600_LAST_DISPATCH_REG, 0);
-
-	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(2), 0);
-	RADEON_WRITE(R600_LAST_CLEAR_REG, 0);
-
-	/* reset sarea copies of these */
-	master_priv = file_priv->master->driver_priv;
-	if (master_priv->sarea_priv) {
-		master_priv->sarea_priv->last_frame = 0;
-		master_priv->sarea_priv->last_dispatch = 0;
-		master_priv->sarea_priv->last_clear = 0;
-	}
-
-	r600_do_wait_for_idle(dev_priv);
-
-}
-
-int r600_do_cleanup_cp(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG("\n");
-
-	/* Make sure interrupts are disabled here because the uninstall ioctl
-	 * may not have been called from userspace and after dev_private
-	 * is freed, it's too late.
-	 */
-	if (dev->irq_enabled)
-		drm_irq_uninstall(dev);
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		if (dev_priv->cp_ring != NULL) {
-			drm_legacy_ioremapfree(dev_priv->cp_ring, dev);
-			dev_priv->cp_ring = NULL;
-		}
-		if (dev_priv->ring_rptr != NULL) {
-			drm_legacy_ioremapfree(dev_priv->ring_rptr, dev);
-			dev_priv->ring_rptr = NULL;
-		}
-		if (dev->agp_buffer_map != NULL) {
-			drm_legacy_ioremapfree(dev->agp_buffer_map, dev);
-			dev->agp_buffer_map = NULL;
-		}
-	} else
-#endif
-	{
-
-		if (dev_priv->gart_info.bus_addr)
-			r600_page_table_cleanup(dev, &dev_priv->gart_info);
-
-		if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) {
-			drm_legacy_ioremapfree(&dev_priv->gart_info.mapping, dev);
-			dev_priv->gart_info.addr = NULL;
-		}
-	}
-	/* only clear to the start of flags */
-	memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
-
-	return 0;
-}
-
-int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
-		    struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
-
-	DRM_DEBUG("\n");
-
-	mutex_init(&dev_priv->cs_mutex);
-	r600_cs_legacy_init();
-	/* if we require new memory map but we don't have it fail */
-	if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
-		DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
-		r600_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
-		DRM_DEBUG("Forcing AGP card to PCI mode\n");
-		dev_priv->flags &= ~RADEON_IS_AGP;
-		/* The writeback test succeeds, but when writeback is enabled,
-		 * the ring buffer read ptr update fails after first 128 bytes.
-		 */
-		radeon_no_wb = 1;
-	} else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
-		 && !init->is_pci) {
-		DRM_DEBUG("Restoring AGP flag\n");
-		dev_priv->flags |= RADEON_IS_AGP;
-	}
-
-	dev_priv->usec_timeout = init->usec_timeout;
-	if (dev_priv->usec_timeout < 1 ||
-	    dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
-		DRM_DEBUG("TIMEOUT problem!\n");
-		r600_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	/* Enable vblank on CRTC1 for older X servers
-	 */
-	dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
-	dev_priv->do_boxes = 0;
-	dev_priv->cp_mode = init->cp_mode;
-
-	/* We don't support anything other than bus-mastering ring mode,
-	 * but the ring can be in either AGP or PCI space for the ring
-	 * read pointer.
-	 */
-	if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
-	    (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
-		DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
-		r600_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	switch (init->fb_bpp) {
-	case 16:
-		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
-		break;
-	case 32:
-	default:
-		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
-		break;
-	}
-	dev_priv->front_offset = init->front_offset;
-	dev_priv->front_pitch = init->front_pitch;
-	dev_priv->back_offset = init->back_offset;
-	dev_priv->back_pitch = init->back_pitch;
-
-	dev_priv->ring_offset = init->ring_offset;
-	dev_priv->ring_rptr_offset = init->ring_rptr_offset;
-	dev_priv->buffers_offset = init->buffers_offset;
-	dev_priv->gart_textures_offset = init->gart_textures_offset;
-
-	master_priv->sarea = drm_legacy_getsarea(dev);
-	if (!master_priv->sarea) {
-		DRM_ERROR("could not find sarea!\n");
-		r600_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	dev_priv->cp_ring = drm_legacy_findmap(dev, init->ring_offset);
-	if (!dev_priv->cp_ring) {
-		DRM_ERROR("could not find cp ring region!\n");
-		r600_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-	dev_priv->ring_rptr = drm_legacy_findmap(dev, init->ring_rptr_offset);
-	if (!dev_priv->ring_rptr) {
-		DRM_ERROR("could not find ring read pointer!\n");
-		r600_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-	dev->agp_buffer_token = init->buffers_offset;
-	dev->agp_buffer_map = drm_legacy_findmap(dev, init->buffers_offset);
-	if (!dev->agp_buffer_map) {
-		DRM_ERROR("could not find dma buffer region!\n");
-		r600_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	if (init->gart_textures_offset) {
-		dev_priv->gart_textures =
-		    drm_legacy_findmap(dev, init->gart_textures_offset);
-		if (!dev_priv->gart_textures) {
-			DRM_ERROR("could not find GART texture region!\n");
-			r600_do_cleanup_cp(dev);
-			return -EINVAL;
-		}
-	}
-
-#if IS_ENABLED(CONFIG_AGP)
-	/* XXX */
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		drm_legacy_ioremap_wc(dev_priv->cp_ring, dev);
-		drm_legacy_ioremap_wc(dev_priv->ring_rptr, dev);
-		drm_legacy_ioremap_wc(dev->agp_buffer_map, dev);
-		if (!dev_priv->cp_ring->handle ||
-		    !dev_priv->ring_rptr->handle ||
-		    !dev->agp_buffer_map->handle) {
-			DRM_ERROR("could not find ioremap agp regions!\n");
-			r600_do_cleanup_cp(dev);
-			return -EINVAL;
-		}
-	} else
-#endif
-	{
-		dev_priv->cp_ring->handle = (void *)(unsigned long)dev_priv->cp_ring->offset;
-		dev_priv->ring_rptr->handle =
-			(void *)(unsigned long)dev_priv->ring_rptr->offset;
-		dev->agp_buffer_map->handle =
-			(void *)(unsigned long)dev->agp_buffer_map->offset;
-
-		DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
-			  dev_priv->cp_ring->handle);
-		DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
-			  dev_priv->ring_rptr->handle);
-		DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
-			  dev->agp_buffer_map->handle);
-	}
-
-	dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 24;
-	dev_priv->fb_size =
-		(((radeon_read_fb_location(dev_priv) & 0xffff0000u) << 8) + 0x1000000)
-		- dev_priv->fb_location;
-
-	dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
-					((dev_priv->front_offset
-					  + dev_priv->fb_location) >> 10));
-
-	dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
-				       ((dev_priv->back_offset
-					 + dev_priv->fb_location) >> 10));
-
-	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
-					((dev_priv->depth_offset
-					  + dev_priv->fb_location) >> 10));
-
-	dev_priv->gart_size = init->gart_size;
-
-	/* New let's set the memory map ... */
-	if (dev_priv->new_memmap) {
-		u32 base = 0;
-
-		DRM_INFO("Setting GART location based on new memory map\n");
-
-		/* If using AGP, try to locate the AGP aperture at the same
-		 * location in the card and on the bus, though we have to
-		 * align it down.
-		 */
-#if IS_ENABLED(CONFIG_AGP)
-		/* XXX */
-		if (dev_priv->flags & RADEON_IS_AGP) {
-			base = dev->agp->base;
-			/* Check if valid */
-			if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
-			    base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
-				DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
-					 dev->agp->base);
-				base = 0;
-			}
-		}
-#endif
-		/* If not or if AGP is at 0 (Macs), try to put it elsewhere */
-		if (base == 0) {
-			base = dev_priv->fb_location + dev_priv->fb_size;
-			if (base < dev_priv->fb_location ||
-			    ((base + dev_priv->gart_size) & 0xfffffffful) < base)
-				base = dev_priv->fb_location
-					- dev_priv->gart_size;
-		}
-		dev_priv->gart_vm_start = base & 0xffc00000u;
-		if (dev_priv->gart_vm_start != base)
-			DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
-				 base, dev_priv->gart_vm_start);
-	}
-
-#if IS_ENABLED(CONFIG_AGP)
-	/* XXX */
-	if (dev_priv->flags & RADEON_IS_AGP)
-		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
-						 - dev->agp->base
-						 + dev_priv->gart_vm_start);
-	else
-#endif
-		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
-						 - (unsigned long)dev->sg->virtual
-						 + dev_priv->gart_vm_start);
-
-	DRM_DEBUG("fb 0x%08x size %d\n",
-		  (unsigned int) dev_priv->fb_location,
-		  (unsigned int) dev_priv->fb_size);
-	DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
-	DRM_DEBUG("dev_priv->gart_vm_start 0x%08x\n",
-		  (unsigned int) dev_priv->gart_vm_start);
-	DRM_DEBUG("dev_priv->gart_buffers_offset 0x%08lx\n",
-		  dev_priv->gart_buffers_offset);
-
-	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
-	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
-			      + init->ring_size / sizeof(u32));
-	dev_priv->ring.size = init->ring_size;
-	dev_priv->ring.size_l2qw = order_base_2(init->ring_size / 8);
-
-	dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
-	dev_priv->ring.rptr_update_l2qw = order_base_2(/* init->rptr_update */ 4096 / 8);
-
-	dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
-	dev_priv->ring.fetch_size_l2ow = order_base_2(/* init->fetch_size */ 32 / 16);
-
-	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
-
-	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		/* XXX turn off pcie gart */
-	} else
-#endif
-	{
-		dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
-		/* if we have an offset set from userspace */
-		if (!dev_priv->pcigart_offset_set) {
-			DRM_ERROR("Need gart offset from userspace\n");
-			r600_do_cleanup_cp(dev);
-			return -EINVAL;
-		}
-
-		DRM_DEBUG("Using gart offset 0x%08lx\n", dev_priv->pcigart_offset);
-
-		dev_priv->gart_info.bus_addr =
-			dev_priv->pcigart_offset + dev_priv->fb_location;
-		dev_priv->gart_info.mapping.offset =
-			dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
-		dev_priv->gart_info.mapping.size =
-			dev_priv->gart_info.table_size;
-
-		drm_legacy_ioremap_wc(&dev_priv->gart_info.mapping, dev);
-		if (!dev_priv->gart_info.mapping.handle) {
-			DRM_ERROR("ioremap failed.\n");
-			r600_do_cleanup_cp(dev);
-			return -EINVAL;
-		}
-
-		dev_priv->gart_info.addr =
-			dev_priv->gart_info.mapping.handle;
-
-		DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
-			  dev_priv->gart_info.addr,
-			  dev_priv->pcigart_offset);
-
-		if (!r600_page_table_init(dev)) {
-			DRM_ERROR("Failed to init GART table\n");
-			r600_do_cleanup_cp(dev);
-			return -EINVAL;
-		}
-
-		if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
-			r700_vm_init(dev);
-		else
-			r600_vm_init(dev);
-	}
-
-	if (!dev_priv->me_fw || !dev_priv->pfp_fw) {
-		int err = r600_cp_init_microcode(dev_priv);
-		if (err) {
-			DRM_ERROR("Failed to load firmware!\n");
-			r600_do_cleanup_cp(dev);
-			return err;
-		}
-	}
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
-		r700_cp_load_microcode(dev_priv);
-	else
-		r600_cp_load_microcode(dev_priv);
-
-	r600_cp_init_ring_buffer(dev, dev_priv, file_priv);
-
-	dev_priv->last_buf = 0;
-
-	r600_do_engine_reset(dev);
-	r600_test_writeback(dev_priv);
-
-	return 0;
-}
-
-int r600_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	DRM_DEBUG("\n");
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) {
-		r700_vm_init(dev);
-		r700_cp_load_microcode(dev_priv);
-	} else {
-		r600_vm_init(dev);
-		r600_cp_load_microcode(dev_priv);
-	}
-	r600_cp_init_ring_buffer(dev, dev_priv, file_priv);
-	r600_do_engine_reset(dev);
-
-	return 0;
-}
-
-/* Wait for the CP to go idle.
- */
-int r600_do_cp_idle(drm_radeon_private_t *dev_priv)
-{
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	BEGIN_RING(5);
-	OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0));
-	OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT);
-	/* wait for 3D idle clean */
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
-	OUT_RING((R600_WAIT_UNTIL - R600_SET_CONFIG_REG_OFFSET) >> 2);
-	OUT_RING(RADEON_WAIT_3D_IDLE | RADEON_WAIT_3D_IDLECLEAN);
-
-	ADVANCE_RING();
-	COMMIT_RING();
-
-	return r600_do_wait_for_idle(dev_priv);
-}
-
-/* Start the Command Processor.
- */
-void r600_do_cp_start(drm_radeon_private_t *dev_priv)
-{
-	u32 cp_me;
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	BEGIN_RING(7);
-	OUT_RING(CP_PACKET3(R600_IT_ME_INITIALIZE, 5));
-	OUT_RING(0x00000001);
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV770))
-		OUT_RING(0x00000003);
-	else
-		OUT_RING(0x00000000);
-	OUT_RING((dev_priv->r600_max_hw_contexts - 1));
-	OUT_RING(R600_ME_INITIALIZE_DEVICE_ID(1));
-	OUT_RING(0x00000000);
-	OUT_RING(0x00000000);
-	ADVANCE_RING();
-	COMMIT_RING();
-
-	/* set the mux and reset the halt bit */
-	cp_me = 0xff;
-	RADEON_WRITE(R600_CP_ME_CNTL, cp_me);
-
-	dev_priv->cp_running = 1;
-
-}
-
-void r600_do_cp_reset(drm_radeon_private_t *dev_priv)
-{
-	u32 cur_read_ptr;
-	DRM_DEBUG("\n");
-
-	cur_read_ptr = RADEON_READ(R600_CP_RB_RPTR);
-	RADEON_WRITE(R600_CP_RB_WPTR, cur_read_ptr);
-	SET_RING_HEAD(dev_priv, cur_read_ptr);
-	dev_priv->ring.tail = cur_read_ptr;
-}
-
-void r600_do_cp_stop(drm_radeon_private_t *dev_priv)
-{
-	uint32_t cp_me;
-
-	DRM_DEBUG("\n");
-
-	cp_me = 0xff | R600_CP_ME_HALT;
-
-	RADEON_WRITE(R600_CP_ME_CNTL, cp_me);
-
-	dev_priv->cp_running = 0;
-}
-
-int r600_cp_dispatch_indirect(struct drm_device *dev,
-			      struct drm_buf *buf, int start, int end)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-
-	if (start != end) {
-		unsigned long offset = (dev_priv->gart_buffers_offset
-					+ buf->offset + start);
-		int dwords = (end - start + 3) / sizeof(u32);
-
-		DRM_DEBUG("dwords:%d\n", dwords);
-		DRM_DEBUG("offset 0x%lx\n", offset);
-
-
-		/* Indirect buffer data must be a multiple of 16 dwords.
-		 * pad the data with a Type-2 CP packet.
-		 */
-		while (dwords & 0xf) {
-			u32 *data = (u32 *)
-			    ((char *)dev->agp_buffer_map->handle
-			     + buf->offset + start);
-			data[dwords++] = RADEON_CP_PACKET2;
-		}
-
-		/* Fire off the indirect buffer */
-		BEGIN_RING(4);
-		OUT_RING(CP_PACKET3(R600_IT_INDIRECT_BUFFER, 2));
-		OUT_RING((offset & 0xfffffffc));
-		OUT_RING((upper_32_bits(offset) & 0xff));
-		OUT_RING(dwords);
-		ADVANCE_RING();
-	}
-
-	return 0;
-}
-
-void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_master *master = file_priv->master;
-	struct drm_radeon_master_private *master_priv = master->driver_priv;
-	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
-	int nbox = sarea_priv->nbox;
-	struct drm_clip_rect *pbox = sarea_priv->boxes;
-	int i, cpp, src_pitch, dst_pitch;
-	uint64_t src, dst;
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	if (dev_priv->color_fmt == RADEON_COLOR_FORMAT_ARGB8888)
-		cpp = 4;
-	else
-		cpp = 2;
-
-	if (sarea_priv->pfCurrentPage == 0) {
-		src_pitch = dev_priv->back_pitch;
-		dst_pitch = dev_priv->front_pitch;
-		src = dev_priv->back_offset + dev_priv->fb_location;
-		dst = dev_priv->front_offset + dev_priv->fb_location;
-	} else {
-		src_pitch = dev_priv->front_pitch;
-		dst_pitch = dev_priv->back_pitch;
-		src = dev_priv->front_offset + dev_priv->fb_location;
-		dst = dev_priv->back_offset + dev_priv->fb_location;
-	}
-
-	if (r600_prepare_blit_copy(dev, file_priv)) {
-		DRM_ERROR("unable to allocate vertex buffer for swap buffer\n");
-		return;
-	}
-	for (i = 0; i < nbox; i++) {
-		int x = pbox[i].x1;
-		int y = pbox[i].y1;
-		int w = pbox[i].x2 - x;
-		int h = pbox[i].y2 - y;
-
-		DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h);
-
-		r600_blit_swap(dev,
-			       src, dst,
-			       x, y, x, y, w, h,
-			       src_pitch, dst_pitch, cpp);
-	}
-	r600_done_blit_copy(dev);
-
-	/* Increment the frame counter.  The client-side 3D driver must
-	 * throttle the framerate by waiting for this value before
-	 * performing the swapbuffer ioctl.
-	 */
-	sarea_priv->last_frame++;
-
-	BEGIN_RING(3);
-	R600_FRAME_AGE(sarea_priv->last_frame);
-	ADVANCE_RING();
-}
-
-int r600_cp_dispatch_texture(struct drm_device *dev,
-			     struct drm_file *file_priv,
-			     drm_radeon_texture_t *tex,
-			     drm_radeon_tex_image_t *image)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_buf *buf;
-	u32 *buffer;
-	const u8 __user *data;
-	unsigned int size, pass_size;
-	u64 src_offset, dst_offset;
-
-	if (!radeon_check_offset(dev_priv, tex->offset)) {
-		DRM_ERROR("Invalid destination offset\n");
-		return -EINVAL;
-	}
-
-	/* this might fail for zero-sized uploads - are those illegal? */
-	if (!radeon_check_offset(dev_priv, tex->offset + tex->height * tex->pitch - 1)) {
-		DRM_ERROR("Invalid final destination offset\n");
-		return -EINVAL;
-	}
-
-	size = tex->height * tex->pitch;
-
-	if (size == 0)
-		return 0;
-
-	dst_offset = tex->offset;
-
-	if (r600_prepare_blit_copy(dev, file_priv)) {
-		DRM_ERROR("unable to allocate vertex buffer for swap buffer\n");
-		return -EAGAIN;
-	}
-	do {
-		data = (const u8 __user *)image->data;
-		pass_size = size;
-
-		buf = radeon_freelist_get(dev);
-		if (!buf) {
-			DRM_DEBUG("EAGAIN\n");
-			if (copy_to_user(tex->image, image, sizeof(*image)))
-				return -EFAULT;
-			return -EAGAIN;
-		}
-
-		if (pass_size > buf->total)
-			pass_size = buf->total;
-
-		/* Dispatch the indirect buffer.
-		 */
-		buffer =
-		    (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
-
-		if (copy_from_user(buffer, data, pass_size)) {
-			DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size);
-			return -EFAULT;
-		}
-
-		buf->file_priv = file_priv;
-		buf->used = pass_size;
-		src_offset = dev_priv->gart_buffers_offset + buf->offset;
-
-		r600_blit_copy(dev, src_offset, dst_offset, pass_size);
-
-		radeon_cp_discard_buffer(dev, file_priv->master, buf);
-
-		/* Update the input parameters for next time */
-		image->data = (const u8 __user *)image->data + pass_size;
-		dst_offset += pass_size;
-		size -= pass_size;
-	} while (size > 0);
-	r600_done_blit_copy(dev);
-
-	return 0;
-}
-
-/*
- * Legacy cs ioctl
- */
-static u32 radeon_cs_id_get(struct drm_radeon_private *radeon)
-{
-	/* FIXME: check if wrap affect last reported wrap & sequence */
-	radeon->cs_id_scnt = (radeon->cs_id_scnt + 1) & 0x00FFFFFF;
-	if (!radeon->cs_id_scnt) {
-		/* increment wrap counter */
-		radeon->cs_id_wcnt += 0x01000000;
-		/* valid sequence counter start at 1 */
-		radeon->cs_id_scnt = 1;
-	}
-	return (radeon->cs_id_scnt | radeon->cs_id_wcnt);
-}
-
-static void r600_cs_id_emit(drm_radeon_private_t *dev_priv, u32 *id)
-{
-	RING_LOCALS;
-
-	*id = radeon_cs_id_get(dev_priv);
-
-	/* SCRATCH 2 */
-	BEGIN_RING(3);
-	R600_CLEAR_AGE(*id);
-	ADVANCE_RING();
-	COMMIT_RING();
-}
-
-static int r600_ib_get(struct drm_device *dev,
-			struct drm_file *fpriv,
-			struct drm_buf **buffer)
-{
-	struct drm_buf *buf;
-
-	*buffer = NULL;
-	buf = radeon_freelist_get(dev);
-	if (!buf) {
-		return -EBUSY;
-	}
-	buf->file_priv = fpriv;
-	*buffer = buf;
-	return 0;
-}
-
-static void r600_ib_free(struct drm_device *dev, struct drm_buf *buf,
-			struct drm_file *fpriv, int l, int r)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	if (buf) {
-		if (!r)
-			r600_cp_dispatch_indirect(dev, buf, 0, l * 4);
-		radeon_cp_discard_buffer(dev, fpriv->master, buf);
-		COMMIT_RING();
-	}
-}
-
-int r600_cs_legacy_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
-{
-	struct drm_radeon_private *dev_priv = dev->dev_private;
-	struct drm_radeon_cs *cs = data;
-	struct drm_buf *buf;
-	unsigned family;
-	int l, r = 0;
-	u32 *ib, cs_id = 0;
-
-	if (dev_priv == NULL) {
-		DRM_ERROR("called with no initialization\n");
-		return -EINVAL;
-	}
-	family = dev_priv->flags & RADEON_FAMILY_MASK;
-	if (family < CHIP_R600) {
-		DRM_ERROR("cs ioctl valid only for R6XX & R7XX in legacy mode\n");
-		return -EINVAL;
-	}
-	mutex_lock(&dev_priv->cs_mutex);
-	/* get ib */
-	r = r600_ib_get(dev, fpriv, &buf);
-	if (r) {
-		DRM_ERROR("ib_get failed\n");
-		goto out;
-	}
-	ib = dev->agp_buffer_map->handle + buf->offset;
-	/* now parse command stream */
-	r = r600_cs_legacy(dev, data,  fpriv, family, ib, &l);
-	if (r) {
-		goto out;
-	}
-
-out:
-	r600_ib_free(dev, buf, fpriv, l, r);
-	/* emit cs id sequence */
-	r600_cs_id_emit(dev_priv, &cs_id);
-	cs->cs_id = cs_id;
-	mutex_unlock(&dev_priv->cs_mutex);
-	return r;
-}
-
-void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size)
-{
-	struct drm_radeon_private *dev_priv = dev->dev_private;
-
-	*npipes = dev_priv->r600_npipes;
-	*nbanks = dev_priv->r600_nbanks;
-	*group_size = dev_priv->r600_group_size;
-}
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index acc1f99..2f36fa15 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -2328,101 +2328,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_DRM_RADEON_UMS
-
-/**
- * cs_parser_fini() - clean parser states
- * @parser:	parser structure holding parsing context.
- * @error:	error number
- *
- * If error is set than unvalidate buffer, otherwise just free memory
- * used by parsing context.
- **/
-static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error)
-{
-	unsigned i;
-
-	kfree(parser->relocs);
-	for (i = 0; i < parser->nchunks; i++)
-		drm_free_large(parser->chunks[i].kdata);
-	kfree(parser->chunks);
-	kfree(parser->chunks_array);
-}
-
-static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
-{
-	if (p->chunk_relocs == NULL) {
-		return 0;
-	}
-	p->relocs = kzalloc(sizeof(struct radeon_bo_list), GFP_KERNEL);
-	if (p->relocs == NULL) {
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
-			unsigned family, u32 *ib, int *l)
-{
-	struct radeon_cs_parser parser;
-	struct radeon_cs_chunk *ib_chunk;
-	struct r600_cs_track *track;
-	int r;
-
-	/* initialize tracker */
-	track = kzalloc(sizeof(*track), GFP_KERNEL);
-	if (track == NULL)
-		return -ENOMEM;
-	r600_cs_track_init(track);
-	r600_cs_legacy_get_tiling_conf(dev, &track->npipes, &track->nbanks, &track->group_size);
-	/* initialize parser */
-	memset(&parser, 0, sizeof(struct radeon_cs_parser));
-	parser.filp = filp;
-	parser.dev = &dev->pdev->dev;
-	parser.rdev = NULL;
-	parser.family = family;
-	parser.track = track;
-	parser.ib.ptr = ib;
-	r = radeon_cs_parser_init(&parser, data);
-	if (r) {
-		DRM_ERROR("Failed to initialize parser !\n");
-		r600_cs_parser_fini(&parser, r);
-		return r;
-	}
-	r = r600_cs_parser_relocs_legacy(&parser);
-	if (r) {
-		DRM_ERROR("Failed to parse relocation !\n");
-		r600_cs_parser_fini(&parser, r);
-		return r;
-	}
-	/* Copy the packet into the IB, the parser will read from the
-	 * input memory (cached) and write to the IB (which can be
-	 * uncached). */
-	ib_chunk = parser.chunk_ib;
-	parser.ib.length_dw = ib_chunk->length_dw;
-	*l = parser.ib.length_dw;
-	if (copy_from_user(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) {
-		r = -EFAULT;
-		r600_cs_parser_fini(&parser, r);
-		return r;
-	}
-	r = r600_cs_parse(&parser);
-	if (r) {
-		DRM_ERROR("Invalid command stream !\n");
-		r600_cs_parser_fini(&parser, r);
-		return r;
-	}
-	r600_cs_parser_fini(&parser, r);
-	return r;
-}
-
-void r600_cs_legacy_init(void)
-{
-	r600_nomm = 1;
-}
-
-#endif
-
 /*
  *  DMA
  */
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 87db649..5ae6db9 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -268,6 +268,7 @@
 	uint32_t current_dispclk;
 	uint32_t dp_extclk;
 	uint32_t max_pixel_clock;
+	uint32_t gpupll_outputfreq;
 };
 
 /*
@@ -1889,7 +1890,7 @@
 		void (*pad_ib)(struct radeon_ib *ib);
 	} vm;
 	/* ring specific callbacks */
-	struct radeon_asic_ring *ring[RADEON_NUM_RINGS];
+	const struct radeon_asic_ring *ring[RADEON_NUM_RINGS];
 	/* irqs */
 	struct {
 		int (*set)(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 1d4d452..7d5a36d 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -179,7 +179,7 @@
  * ASIC
  */
 
-static struct radeon_asic_ring r100_gfx_ring = {
+static const struct radeon_asic_ring r100_gfx_ring = {
 	.ib_execute = &r100_ring_ib_execute,
 	.emit_fence = &r100_fence_ring_emit,
 	.emit_semaphore = &r100_semaphore_ring_emit,
@@ -329,7 +329,7 @@
 	},
 };
 
-static struct radeon_asic_ring r300_gfx_ring = {
+static const struct radeon_asic_ring r300_gfx_ring = {
 	.ib_execute = &r100_ring_ib_execute,
 	.emit_fence = &r300_fence_ring_emit,
 	.emit_semaphore = &r100_semaphore_ring_emit,
@@ -343,7 +343,7 @@
 	.set_wptr = &r100_gfx_set_wptr,
 };
 
-static struct radeon_asic_ring rv515_gfx_ring = {
+static const struct radeon_asic_ring rv515_gfx_ring = {
 	.ib_execute = &r100_ring_ib_execute,
 	.emit_fence = &r300_fence_ring_emit,
 	.emit_semaphore = &r100_semaphore_ring_emit,
@@ -901,7 +901,7 @@
 	},
 };
 
-static struct radeon_asic_ring r600_gfx_ring = {
+static const struct radeon_asic_ring r600_gfx_ring = {
 	.ib_execute = &r600_ring_ib_execute,
 	.emit_fence = &r600_fence_ring_emit,
 	.emit_semaphore = &r600_semaphore_ring_emit,
@@ -914,7 +914,7 @@
 	.set_wptr = &r600_gfx_set_wptr,
 };
 
-static struct radeon_asic_ring r600_dma_ring = {
+static const struct radeon_asic_ring r600_dma_ring = {
 	.ib_execute = &r600_dma_ring_ib_execute,
 	.emit_fence = &r600_dma_fence_ring_emit,
 	.emit_semaphore = &r600_dma_semaphore_ring_emit,
@@ -999,7 +999,7 @@
 	},
 };
 
-static struct radeon_asic_ring rv6xx_uvd_ring = {
+static const struct radeon_asic_ring rv6xx_uvd_ring = {
 	.ib_execute = &uvd_v1_0_ib_execute,
 	.emit_fence = &uvd_v1_0_fence_emit,
 	.emit_semaphore = &uvd_v1_0_semaphore_emit,
@@ -1198,7 +1198,7 @@
 	},
 };
 
-static struct radeon_asic_ring rv770_uvd_ring = {
+static const struct radeon_asic_ring rv770_uvd_ring = {
 	.ib_execute = &uvd_v1_0_ib_execute,
 	.emit_fence = &uvd_v2_2_fence_emit,
 	.emit_semaphore = &uvd_v2_2_semaphore_emit,
@@ -1305,7 +1305,7 @@
 	},
 };
 
-static struct radeon_asic_ring evergreen_gfx_ring = {
+static const struct radeon_asic_ring evergreen_gfx_ring = {
 	.ib_execute = &evergreen_ring_ib_execute,
 	.emit_fence = &r600_fence_ring_emit,
 	.emit_semaphore = &r600_semaphore_ring_emit,
@@ -1318,7 +1318,7 @@
 	.set_wptr = &r600_gfx_set_wptr,
 };
 
-static struct radeon_asic_ring evergreen_dma_ring = {
+static const struct radeon_asic_ring evergreen_dma_ring = {
 	.ib_execute = &evergreen_dma_ring_ib_execute,
 	.emit_fence = &evergreen_dma_fence_ring_emit,
 	.emit_semaphore = &r600_dma_semaphore_ring_emit,
@@ -1612,7 +1612,7 @@
 	},
 };
 
-static struct radeon_asic_ring cayman_gfx_ring = {
+static const struct radeon_asic_ring cayman_gfx_ring = {
 	.ib_execute = &cayman_ring_ib_execute,
 	.ib_parse = &evergreen_ib_parse,
 	.emit_fence = &cayman_fence_ring_emit,
@@ -1627,7 +1627,7 @@
 	.set_wptr = &cayman_gfx_set_wptr,
 };
 
-static struct radeon_asic_ring cayman_dma_ring = {
+static const struct radeon_asic_ring cayman_dma_ring = {
 	.ib_execute = &cayman_dma_ring_ib_execute,
 	.ib_parse = &evergreen_dma_ib_parse,
 	.emit_fence = &evergreen_dma_fence_ring_emit,
@@ -1642,7 +1642,7 @@
 	.set_wptr = &cayman_dma_set_wptr
 };
 
-static struct radeon_asic_ring cayman_uvd_ring = {
+static const struct radeon_asic_ring cayman_uvd_ring = {
 	.ib_execute = &uvd_v1_0_ib_execute,
 	.emit_fence = &uvd_v2_2_fence_emit,
 	.emit_semaphore = &uvd_v3_1_semaphore_emit,
@@ -1760,7 +1760,7 @@
 	},
 };
 
-static struct radeon_asic_ring trinity_vce_ring = {
+static const struct radeon_asic_ring trinity_vce_ring = {
 	.ib_execute = &radeon_vce_ib_execute,
 	.emit_fence = &radeon_vce_fence_emit,
 	.emit_semaphore = &radeon_vce_semaphore_emit,
@@ -1881,7 +1881,7 @@
 	},
 };
 
-static struct radeon_asic_ring si_gfx_ring = {
+static const struct radeon_asic_ring si_gfx_ring = {
 	.ib_execute = &si_ring_ib_execute,
 	.ib_parse = &si_ib_parse,
 	.emit_fence = &si_fence_ring_emit,
@@ -1896,7 +1896,7 @@
 	.set_wptr = &cayman_gfx_set_wptr,
 };
 
-static struct radeon_asic_ring si_dma_ring = {
+static const struct radeon_asic_ring si_dma_ring = {
 	.ib_execute = &cayman_dma_ring_ib_execute,
 	.ib_parse = &evergreen_dma_ib_parse,
 	.emit_fence = &evergreen_dma_fence_ring_emit,
@@ -2023,7 +2023,7 @@
 	},
 };
 
-static struct radeon_asic_ring ci_gfx_ring = {
+static const struct radeon_asic_ring ci_gfx_ring = {
 	.ib_execute = &cik_ring_ib_execute,
 	.ib_parse = &cik_ib_parse,
 	.emit_fence = &cik_fence_gfx_ring_emit,
@@ -2038,7 +2038,7 @@
 	.set_wptr = &cik_gfx_set_wptr,
 };
 
-static struct radeon_asic_ring ci_cp_ring = {
+static const struct radeon_asic_ring ci_cp_ring = {
 	.ib_execute = &cik_ring_ib_execute,
 	.ib_parse = &cik_ib_parse,
 	.emit_fence = &cik_fence_compute_ring_emit,
@@ -2053,7 +2053,7 @@
 	.set_wptr = &cik_compute_set_wptr,
 };
 
-static struct radeon_asic_ring ci_dma_ring = {
+static const struct radeon_asic_ring ci_dma_ring = {
 	.ib_execute = &cik_sdma_ring_ib_execute,
 	.ib_parse = &cik_ib_parse,
 	.emit_fence = &cik_sdma_fence_ring_emit,
@@ -2068,7 +2068,7 @@
 	.set_wptr = &cik_sdma_set_wptr,
 };
 
-static struct radeon_asic_ring ci_vce_ring = {
+static const struct radeon_asic_ring ci_vce_ring = {
 	.ib_execute = &radeon_vce_ib_execute,
 	.emit_fence = &radeon_vce_fence_emit,
 	.emit_semaphore = &radeon_vce_semaphore_emit,
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 8f28524..08fc1b5 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -437,7 +437,9 @@
 	}
 
 	/* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
-	if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) &&
+	if (((dev->pdev->device == 0x9802) ||
+	     (dev->pdev->device == 0x9805) ||
+	     (dev->pdev->device == 0x9806)) &&
 	    (dev->pdev->subsystem_vendor == 0x1734) &&
 	    (dev->pdev->subsystem_device == 0x11bd)) {
 		if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
@@ -448,14 +450,6 @@
 		}
 	}
 
-	/* Fujitsu D3003-S2 board lists DVI-I as DVI-I and VGA */
-	if ((dev->pdev->device == 0x9805) &&
-	    (dev->pdev->subsystem_vendor == 0x1734) &&
-	    (dev->pdev->subsystem_device == 0x11bd)) {
-		if (*connector_type == DRM_MODE_CONNECTOR_VGA)
-			return false;
-	}
-
 	return true;
 }
 
@@ -1263,6 +1257,13 @@
 		rdev->mode_info.firmware_flags =
 			le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess);
 
+		if (ASIC_IS_DCE8(rdev)) {
+			rdev->clock.gpupll_outputfreq =
+				le32_to_cpu(firmware_info->info_22.ulGPUPLL_OutputFreq);
+			if (rdev->clock.gpupll_outputfreq == 0)
+				rdev->clock.gpupll_outputfreq = 360000;	/* 3.6 GHz */
+		}
+
 		return true;
 	}
 
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
deleted file mode 100644
index 500287e..0000000
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ /dev/null
@@ -1,2243 +0,0 @@
-/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */
-/*
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
- * Copyright 2007 Advanced Micro Devices, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT 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.
- *
- * Authors:
- *    Kevin E. Martin <martin@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- *
- * ------------------------ This file is DEPRECATED! -------------------------
- */
-
-#include <linux/module.h>
-
-#include <drm/drmP.h>
-#include <drm/radeon_drm.h>
-#include "radeon_drv.h"
-#include "r300_reg.h"
-
-#define RADEON_FIFO_DEBUG	0
-
-/* Firmware Names */
-#define FIRMWARE_R100		"radeon/R100_cp.bin"
-#define FIRMWARE_R200		"radeon/R200_cp.bin"
-#define FIRMWARE_R300		"radeon/R300_cp.bin"
-#define FIRMWARE_R420		"radeon/R420_cp.bin"
-#define FIRMWARE_RS690		"radeon/RS690_cp.bin"
-#define FIRMWARE_RS600		"radeon/RS600_cp.bin"
-#define FIRMWARE_R520		"radeon/R520_cp.bin"
-
-MODULE_FIRMWARE(FIRMWARE_R100);
-MODULE_FIRMWARE(FIRMWARE_R200);
-MODULE_FIRMWARE(FIRMWARE_R300);
-MODULE_FIRMWARE(FIRMWARE_R420);
-MODULE_FIRMWARE(FIRMWARE_RS690);
-MODULE_FIRMWARE(FIRMWARE_RS600);
-MODULE_FIRMWARE(FIRMWARE_R520);
-
-static int radeon_do_cleanup_cp(struct drm_device * dev);
-static void radeon_do_cp_start(drm_radeon_private_t * dev_priv);
-
-u32 radeon_read_ring_rptr(drm_radeon_private_t *dev_priv, u32 off)
-{
-	u32 val;
-
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		val = DRM_READ32(dev_priv->ring_rptr, off);
-	} else {
-		val = *(((volatile u32 *)
-			 dev_priv->ring_rptr->handle) +
-			(off / sizeof(u32)));
-		val = le32_to_cpu(val);
-	}
-	return val;
-}
-
-u32 radeon_get_ring_head(drm_radeon_private_t *dev_priv)
-{
-	if (dev_priv->writeback_works)
-		return radeon_read_ring_rptr(dev_priv, 0);
-	else {
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-			return RADEON_READ(R600_CP_RB_RPTR);
-		else
-			return RADEON_READ(RADEON_CP_RB_RPTR);
-	}
-}
-
-void radeon_write_ring_rptr(drm_radeon_private_t *dev_priv, u32 off, u32 val)
-{
-	if (dev_priv->flags & RADEON_IS_AGP)
-		DRM_WRITE32(dev_priv->ring_rptr, off, val);
-	else
-		*(((volatile u32 *) dev_priv->ring_rptr->handle) +
-		  (off / sizeof(u32))) = cpu_to_le32(val);
-}
-
-void radeon_set_ring_head(drm_radeon_private_t *dev_priv, u32 val)
-{
-	radeon_write_ring_rptr(dev_priv, 0, val);
-}
-
-u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index)
-{
-	if (dev_priv->writeback_works) {
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-			return radeon_read_ring_rptr(dev_priv,
-						     R600_SCRATCHOFF(index));
-		else
-			return radeon_read_ring_rptr(dev_priv,
-						     RADEON_SCRATCHOFF(index));
-	} else {
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-			return RADEON_READ(R600_SCRATCH_REG0 + 4*index);
-		else
-			return RADEON_READ(RADEON_SCRATCH_REG0 + 4*index);
-	}
-}
-
-static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
-{
-	u32 ret;
-	RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff));
-	ret = RADEON_READ(R520_MC_IND_DATA);
-	RADEON_WRITE(R520_MC_IND_INDEX, 0);
-	return ret;
-}
-
-static u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
-{
-	u32 ret;
-	RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff);
-	ret = RADEON_READ(RS480_NB_MC_DATA);
-	RADEON_WRITE(RS480_NB_MC_INDEX, 0xff);
-	return ret;
-}
-
-static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
-{
-	u32 ret;
-	RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK));
-	ret = RADEON_READ(RS690_MC_DATA);
-	RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK);
-	return ret;
-}
-
-static u32 RS600_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
-{
-	u32 ret;
-	RADEON_WRITE(RS600_MC_INDEX, ((addr & RS600_MC_ADDR_MASK) |
-				      RS600_MC_IND_CITF_ARB0));
-	ret = RADEON_READ(RS600_MC_DATA);
-	return ret;
-}
-
-static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
-{
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
-		return RS690_READ_MCIND(dev_priv, addr);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
-		return RS600_READ_MCIND(dev_priv, addr);
-	else
-		return RS480_READ_MCIND(dev_priv, addr);
-}
-
-u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv)
-{
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
-		return RADEON_READ(R700_MC_VM_FB_LOCATION);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return RADEON_READ(R600_MC_VM_FB_LOCATION);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-		return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
-	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
-		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
-		return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
-		return RS600_READ_MCIND(dev_priv, RS600_MC_FB_LOCATION);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-		return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
-	else
-		return RADEON_READ(RADEON_MC_FB_LOCATION);
-}
-
-static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc)
-{
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
-		RADEON_WRITE(R700_MC_VM_FB_LOCATION, fb_loc);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		RADEON_WRITE(R600_MC_VM_FB_LOCATION, fb_loc);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-		R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
-	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
-		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
-		RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
-		RS600_WRITE_MCIND(RS600_MC_FB_LOCATION, fb_loc);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-		R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
-	else
-		RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc);
-}
-
-void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc)
-{
-	/*R6xx/R7xx: AGP_TOP and BOT are actually 18 bits each */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) {
-		RADEON_WRITE(R700_MC_VM_AGP_BOT, agp_loc & 0xffff); /* FIX ME */
-		RADEON_WRITE(R700_MC_VM_AGP_TOP, (agp_loc >> 16) & 0xffff);
-	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
-		RADEON_WRITE(R600_MC_VM_AGP_BOT, agp_loc & 0xffff); /* FIX ME */
-		RADEON_WRITE(R600_MC_VM_AGP_TOP, (agp_loc >> 16) & 0xffff);
-	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-		R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
-	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
-		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
-		RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
-		RS600_WRITE_MCIND(RS600_MC_AGP_LOCATION, agp_loc);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-		R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
-	else
-		RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc);
-}
-
-void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base)
-{
-	u32 agp_base_hi = upper_32_bits(agp_base);
-	u32 agp_base_lo = agp_base & 0xffffffff;
-	u32 r6xx_agp_base = (agp_base >> 22) & 0x3ffff;
-
-	/* R6xx/R7xx must be aligned to a 4MB boundary */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
-		RADEON_WRITE(R700_MC_VM_AGP_BASE, r6xx_agp_base);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		RADEON_WRITE(R600_MC_VM_AGP_BASE, r6xx_agp_base);
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) {
-		R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo);
-		R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi);
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
-		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
-		RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo);
-		RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi);
-	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) {
-		RS600_WRITE_MCIND(RS600_AGP_BASE, agp_base_lo);
-		RS600_WRITE_MCIND(RS600_AGP_BASE_2, agp_base_hi);
-	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) {
-		R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo);
-		R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi);
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
-		RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
-		RADEON_WRITE(RS480_AGP_BASE_2, agp_base_hi);
-	} else {
-		RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200)
-			RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi);
-	}
-}
-
-void radeon_enable_bm(struct drm_radeon_private *dev_priv)
-{
-	u32 tmp;
-	/* Turn on bus mastering */
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
-		/* rs600/rs690/rs740 */
-		tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
-		RADEON_WRITE(RADEON_BUS_CNTL, tmp);
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV350) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
-		/* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */
-		tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
-		RADEON_WRITE(RADEON_BUS_CNTL, tmp);
-	} /* PCIE cards appears to not need this */
-}
-
-static int RADEON_READ_PLL(struct drm_device * dev, int addr)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
-	return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
-}
-
-static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
-{
-	RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
-	return RADEON_READ(RADEON_PCIE_DATA);
-}
-
-#if RADEON_FIFO_DEBUG
-static void radeon_status(drm_radeon_private_t * dev_priv)
-{
-	printk("%s:\n", __func__);
-	printk("RBBM_STATUS = 0x%08x\n",
-	       (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
-	printk("CP_RB_RTPR = 0x%08x\n",
-	       (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR));
-	printk("CP_RB_WTPR = 0x%08x\n",
-	       (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR));
-	printk("AIC_CNTL = 0x%08x\n",
-	       (unsigned int)RADEON_READ(RADEON_AIC_CNTL));
-	printk("AIC_STAT = 0x%08x\n",
-	       (unsigned int)RADEON_READ(RADEON_AIC_STAT));
-	printk("AIC_PT_BASE = 0x%08x\n",
-	       (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE));
-	printk("TLB_ADDR = 0x%08x\n",
-	       (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR));
-	printk("TLB_DATA = 0x%08x\n",
-	       (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA));
-}
-#endif
-
-/* ================================================================
- * Engine, FIFO control
- */
-
-static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
-{
-	u32 tmp;
-	int i;
-
-	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {
-		tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
-		tmp |= RADEON_RB3D_DC_FLUSH_ALL;
-		RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
-
-		for (i = 0; i < dev_priv->usec_timeout; i++) {
-			if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
-			      & RADEON_RB3D_DC_BUSY)) {
-				return 0;
-			}
-			DRM_UDELAY(1);
-		}
-	} else {
-		/* don't flush or purge cache here or lockup */
-		return 0;
-	}
-
-#if RADEON_FIFO_DEBUG
-	DRM_ERROR("failed!\n");
-	radeon_status(dev_priv);
-#endif
-	return -EBUSY;
-}
-
-static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
-{
-	int i;
-
-	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-	for (i = 0; i < dev_priv->usec_timeout; i++) {
-		int slots = (RADEON_READ(RADEON_RBBM_STATUS)
-			     & RADEON_RBBM_FIFOCNT_MASK);
-		if (slots >= entries)
-			return 0;
-		DRM_UDELAY(1);
-	}
-	DRM_DEBUG("wait for fifo failed status : 0x%08X 0x%08X\n",
-		 RADEON_READ(RADEON_RBBM_STATUS),
-		 RADEON_READ(R300_VAP_CNTL_STATUS));
-
-#if RADEON_FIFO_DEBUG
-	DRM_ERROR("failed!\n");
-	radeon_status(dev_priv);
-#endif
-	return -EBUSY;
-}
-
-static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
-{
-	int i, ret;
-
-	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-	ret = radeon_do_wait_for_fifo(dev_priv, 64);
-	if (ret)
-		return ret;
-
-	for (i = 0; i < dev_priv->usec_timeout; i++) {
-		if (!(RADEON_READ(RADEON_RBBM_STATUS)
-		      & RADEON_RBBM_ACTIVE)) {
-			radeon_do_pixcache_flush(dev_priv);
-			return 0;
-		}
-		DRM_UDELAY(1);
-	}
-	DRM_DEBUG("wait idle failed status : 0x%08X 0x%08X\n",
-		 RADEON_READ(RADEON_RBBM_STATUS),
-		 RADEON_READ(R300_VAP_CNTL_STATUS));
-
-#if RADEON_FIFO_DEBUG
-	DRM_ERROR("failed!\n");
-	radeon_status(dev_priv);
-#endif
-	return -EBUSY;
-}
-
-static void radeon_init_pipes(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	uint32_t gb_tile_config, gb_pipe_sel = 0;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) {
-		uint32_t z_pipe_sel = RADEON_READ(RV530_GB_PIPE_SELECT2);
-		if ((z_pipe_sel & 3) == 3)
-			dev_priv->num_z_pipes = 2;
-		else
-			dev_priv->num_z_pipes = 1;
-	} else
-		dev_priv->num_z_pipes = 1;
-
-	/* RS4xx/RS6xx/R4xx/R5xx */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
-		gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
-		dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
-		/* SE cards have 1 pipe */
-		if ((dev->pdev->device == 0x5e4c) ||
-		    (dev->pdev->device == 0x5e4f))
-			dev_priv->num_gb_pipes = 1;
-	} else {
-		/* R3xx */
-		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300 &&
-		     dev->pdev->device != 0x4144) ||
-		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350 &&
-		     dev->pdev->device != 0x4148)) {
-			dev_priv->num_gb_pipes = 2;
-		} else {
-			/* RV3xx/R300 AD/R350 AH */
-			dev_priv->num_gb_pipes = 1;
-		}
-	}
-	DRM_INFO("Num pipes: %d\n", dev_priv->num_gb_pipes);
-
-	gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/);
-
-	switch (dev_priv->num_gb_pipes) {
-	case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
-	case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
-	case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
-	default:
-	case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
-	}
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
-		RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
-		RADEON_WRITE(R300_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
-	}
-	RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config);
-	radeon_do_wait_for_idle(dev_priv);
-	RADEON_WRITE(R300_DST_PIPE_CONFIG, RADEON_READ(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
-	RADEON_WRITE(R300_RB2D_DSTCACHE_MODE, (RADEON_READ(R300_RB2D_DSTCACHE_MODE) |
-					       R300_DC_AUTOFLUSH_ENABLE |
-					       R300_DC_DC_DISABLE_IGNORE_PE));
-
-
-}
-
-/* ================================================================
- * CP control, initialization
- */
-
-/* Load the microcode for the CP */
-static int radeon_cp_init_microcode(drm_radeon_private_t *dev_priv)
-{
-	struct platform_device *pdev;
-	const char *fw_name = NULL;
-	int err;
-
-	DRM_DEBUG("\n");
-
-	pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0);
-	err = IS_ERR(pdev);
-	if (err) {
-		printk(KERN_ERR "radeon_cp: Failed to register firmware\n");
-		return -EINVAL;
-	}
-
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) {
-		DRM_INFO("Loading R100 Microcode\n");
-		fw_name = FIRMWARE_R100;
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) {
-		DRM_INFO("Loading R200 Microcode\n");
-		fw_name = FIRMWARE_R200;
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
-		DRM_INFO("Loading R300 Microcode\n");
-		fw_name = FIRMWARE_R300;
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
-		DRM_INFO("Loading R400 Microcode\n");
-		fw_name = FIRMWARE_R420;
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
-		DRM_INFO("Loading RS690/RS740 Microcode\n");
-		fw_name = FIRMWARE_RS690;
-	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) {
-		DRM_INFO("Loading RS600 Microcode\n");
-		fw_name = FIRMWARE_RS600;
-	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
-		DRM_INFO("Loading R500 Microcode\n");
-		fw_name = FIRMWARE_R520;
-	}
-
-	err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev);
-	platform_device_unregister(pdev);
-	if (err) {
-		printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n",
-		       fw_name);
-	} else if (dev_priv->me_fw->size % 8) {
-		printk(KERN_ERR
-		       "radeon_cp: Bogus length %zu in firmware \"%s\"\n",
-		       dev_priv->me_fw->size, fw_name);
-		err = -EINVAL;
-		release_firmware(dev_priv->me_fw);
-		dev_priv->me_fw = NULL;
-	}
-	return err;
-}
-
-static void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv)
-{
-	const __be32 *fw_data;
-	int i, size;
-
-	radeon_do_wait_for_idle(dev_priv);
-
-	if (dev_priv->me_fw) {
-		size = dev_priv->me_fw->size / 4;
-		fw_data = (const __be32 *)&dev_priv->me_fw->data[0];
-		RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
-		for (i = 0; i < size; i += 2) {
-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-				     be32_to_cpup(&fw_data[i]));
-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-				     be32_to_cpup(&fw_data[i + 1]));
-		}
-	}
-}
-
-/* Flush any pending commands to the CP.  This should only be used just
- * prior to a wait for idle, as it informs the engine that the command
- * stream is ending.
- */
-static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv)
-{
-	DRM_DEBUG("\n");
-#if 0
-	u32 tmp;
-
-	tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31);
-	RADEON_WRITE(RADEON_CP_RB_WPTR, tmp);
-#endif
-}
-
-/* Wait for the CP to go idle.
- */
-int radeon_do_cp_idle(drm_radeon_private_t * dev_priv)
-{
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	BEGIN_RING(6);
-
-	RADEON_PURGE_CACHE();
-	RADEON_PURGE_ZCACHE();
-	RADEON_WAIT_UNTIL_IDLE();
-
-	ADVANCE_RING();
-	COMMIT_RING();
-
-	return radeon_do_wait_for_idle(dev_priv);
-}
-
-/* Start the Command Processor.
- */
-static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
-{
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	radeon_do_wait_for_idle(dev_priv);
-
-	RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode);
-
-	dev_priv->cp_running = 1;
-
-	/* on r420, any DMA from CP to system memory while 2D is active
-	 * can cause a hang.  workaround is to queue a CP RESYNC token
-	 */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
-		BEGIN_RING(3);
-		OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1));
-		OUT_RING(5); /* scratch reg 5 */
-		OUT_RING(0xdeadbeef);
-		ADVANCE_RING();
-		COMMIT_RING();
-	}
-
-	BEGIN_RING(8);
-	/* isync can only be written through cp on r5xx write it here */
-	OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0));
-	OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D |
-		 RADEON_ISYNC_ANY3D_IDLE2D |
-		 RADEON_ISYNC_WAIT_IDLEGUI |
-		 RADEON_ISYNC_CPSCRATCH_IDLEGUI);
-	RADEON_PURGE_CACHE();
-	RADEON_PURGE_ZCACHE();
-	RADEON_WAIT_UNTIL_IDLE();
-	ADVANCE_RING();
-	COMMIT_RING();
-
-	dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
-}
-
-/* Reset the Command Processor.  This will not flush any pending
- * commands, so you must wait for the CP command stream to complete
- * before calling this routine.
- */
-static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv)
-{
-	u32 cur_read_ptr;
-	DRM_DEBUG("\n");
-
-	cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
-	RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
-	SET_RING_HEAD(dev_priv, cur_read_ptr);
-	dev_priv->ring.tail = cur_read_ptr;
-}
-
-/* Stop the Command Processor.  This will not flush any pending
- * commands, so you must flush the command stream and wait for the CP
- * to go idle before calling this routine.
- */
-static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
-{
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	/* finish the pending CP_RESYNC token */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
-		BEGIN_RING(2);
-		OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
-		OUT_RING(R300_RB3D_DC_FINISH);
-		ADVANCE_RING();
-		COMMIT_RING();
-		radeon_do_wait_for_idle(dev_priv);
-	}
-
-	RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
-
-	dev_priv->cp_running = 0;
-}
-
-/* Reset the engine.  This will stop the CP if it is running.
- */
-static int radeon_do_engine_reset(struct drm_device * dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	u32 clock_cntl_index = 0, mclk_cntl = 0, rbbm_soft_reset;
-	DRM_DEBUG("\n");
-
-	radeon_do_pixcache_flush(dev_priv);
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
-		/* may need something similar for newer chips */
-		clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
-		mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
-
-		RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
-						    RADEON_FORCEON_MCLKA |
-						    RADEON_FORCEON_MCLKB |
-						    RADEON_FORCEON_YCLKA |
-						    RADEON_FORCEON_YCLKB |
-						    RADEON_FORCEON_MC |
-						    RADEON_FORCEON_AIC));
-	}
-
-	rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
-
-	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
-					      RADEON_SOFT_RESET_CP |
-					      RADEON_SOFT_RESET_HI |
-					      RADEON_SOFT_RESET_SE |
-					      RADEON_SOFT_RESET_RE |
-					      RADEON_SOFT_RESET_PP |
-					      RADEON_SOFT_RESET_E2 |
-					      RADEON_SOFT_RESET_RB));
-	RADEON_READ(RADEON_RBBM_SOFT_RESET);
-	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
-					      ~(RADEON_SOFT_RESET_CP |
-						RADEON_SOFT_RESET_HI |
-						RADEON_SOFT_RESET_SE |
-						RADEON_SOFT_RESET_RE |
-						RADEON_SOFT_RESET_PP |
-						RADEON_SOFT_RESET_E2 |
-						RADEON_SOFT_RESET_RB)));
-	RADEON_READ(RADEON_RBBM_SOFT_RESET);
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
-		RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
-		RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
-		RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
-	}
-
-	/* setup the raster pipes */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300)
-	    radeon_init_pipes(dev);
-
-	/* Reset the CP ring */
-	radeon_do_cp_reset(dev_priv);
-
-	/* The CP is no longer running after an engine reset */
-	dev_priv->cp_running = 0;
-
-	/* Reset any pending vertex, indirect buffers */
-	radeon_freelist_reset(dev);
-
-	return 0;
-}
-
-static void radeon_cp_init_ring_buffer(struct drm_device * dev,
-				       drm_radeon_private_t *dev_priv,
-				       struct drm_file *file_priv)
-{
-	struct drm_radeon_master_private *master_priv;
-	u32 ring_start, cur_read_ptr;
-
-	/* Initialize the memory controller. With new memory map, the fb location
-	 * is not changed, it should have been properly initialized already. Part
-	 * of the problem is that the code below is bogus, assuming the GART is
-	 * always appended to the fb which is not necessarily the case
-	 */
-	if (!dev_priv->new_memmap)
-		radeon_write_fb_location(dev_priv,
-			     ((dev_priv->gart_vm_start - 1) & 0xffff0000)
-			     | (dev_priv->fb_location >> 16));
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		radeon_write_agp_base(dev_priv, dev->agp->base);
-
-		radeon_write_agp_location(dev_priv,
-			     (((dev_priv->gart_vm_start - 1 +
-				dev_priv->gart_size) & 0xffff0000) |
-			      (dev_priv->gart_vm_start >> 16)));
-
-		ring_start = (dev_priv->cp_ring->offset
-			      - dev->agp->base
-			      + dev_priv->gart_vm_start);
-	} else
-#endif
-		ring_start = (dev_priv->cp_ring->offset
-			      - (unsigned long)dev->sg->virtual
-			      + dev_priv->gart_vm_start);
-
-	RADEON_WRITE(RADEON_CP_RB_BASE, ring_start);
-
-	/* Set the write pointer delay */
-	RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0);
-
-	/* Initialize the ring buffer's read and write pointers */
-	cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
-	RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
-	SET_RING_HEAD(dev_priv, cur_read_ptr);
-	dev_priv->ring.tail = cur_read_ptr;
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
-			     dev_priv->ring_rptr->offset
-			     - dev->agp->base + dev_priv->gart_vm_start);
-	} else
-#endif
-	{
-		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
-			     dev_priv->ring_rptr->offset
-			     - ((unsigned long) dev->sg->virtual)
-			     + dev_priv->gart_vm_start);
-	}
-
-	/* Set ring buffer size */
-#ifdef __BIG_ENDIAN
-	RADEON_WRITE(RADEON_CP_RB_CNTL,
-		     RADEON_BUF_SWAP_32BIT |
-		     (dev_priv->ring.fetch_size_l2ow << 18) |
-		     (dev_priv->ring.rptr_update_l2qw << 8) |
-		     dev_priv->ring.size_l2qw);
-#else
-	RADEON_WRITE(RADEON_CP_RB_CNTL,
-		     (dev_priv->ring.fetch_size_l2ow << 18) |
-		     (dev_priv->ring.rptr_update_l2qw << 8) |
-		     dev_priv->ring.size_l2qw);
-#endif
-
-
-	/* Initialize the scratch register pointer.  This will cause
-	 * the scratch register values to be written out to memory
-	 * whenever they are updated.
-	 *
-	 * We simply put this behind the ring read pointer, this works
-	 * with PCI GART as well as (whatever kind of) AGP GART
-	 */
-	RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
-		     + RADEON_SCRATCH_REG_OFFSET);
-
-	RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
-
-	radeon_enable_bm(dev_priv);
-
-	radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(0), 0);
-	RADEON_WRITE(RADEON_LAST_FRAME_REG, 0);
-
-	radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1), 0);
-	RADEON_WRITE(RADEON_LAST_DISPATCH_REG, 0);
-
-	radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(2), 0);
-	RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
-
-	/* reset sarea copies of these */
-	master_priv = file_priv->master->driver_priv;
-	if (master_priv->sarea_priv) {
-		master_priv->sarea_priv->last_frame = 0;
-		master_priv->sarea_priv->last_dispatch = 0;
-		master_priv->sarea_priv->last_clear = 0;
-	}
-
-	radeon_do_wait_for_idle(dev_priv);
-
-	/* Sync everything up */
-	RADEON_WRITE(RADEON_ISYNC_CNTL,
-		     (RADEON_ISYNC_ANY2D_IDLE3D |
-		      RADEON_ISYNC_ANY3D_IDLE2D |
-		      RADEON_ISYNC_WAIT_IDLEGUI |
-		      RADEON_ISYNC_CPSCRATCH_IDLEGUI));
-
-}
-
-static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
-{
-	u32 tmp;
-
-	/* Start with assuming that writeback doesn't work */
-	dev_priv->writeback_works = 0;
-
-	/* Writeback doesn't seem to work everywhere, test it here and possibly
-	 * enable it if it appears to work
-	 */
-	radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1), 0);
-
-	RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
-
-	for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
-		u32 val;
-
-		val = radeon_read_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1));
-		if (val == 0xdeadbeef)
-			break;
-		DRM_UDELAY(1);
-	}
-
-	if (tmp < dev_priv->usec_timeout) {
-		dev_priv->writeback_works = 1;
-		DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
-	} else {
-		dev_priv->writeback_works = 0;
-		DRM_INFO("writeback test failed\n");
-	}
-	if (radeon_no_wb == 1) {
-		dev_priv->writeback_works = 0;
-		DRM_INFO("writeback forced off\n");
-	}
-
-	if (!dev_priv->writeback_works) {
-		/* Disable writeback to avoid unnecessary bus master transfer */
-		RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) |
-			     RADEON_RB_NO_UPDATE);
-		RADEON_WRITE(RADEON_SCRATCH_UMSK, 0);
-	}
-}
-
-/* Enable or disable IGP GART on the chip */
-static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
-{
-	u32 temp;
-
-	if (on) {
-		DRM_DEBUG("programming igp gart %08X %08lX %08X\n",
-			  dev_priv->gart_vm_start,
-			  (long)dev_priv->gart_info.bus_addr,
-			  dev_priv->gart_size);
-
-		temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL);
-		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
-		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
-			IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN |
-							     RS690_BLOCK_GFX_D3_EN));
-		else
-			IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN);
-
-		IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
-							       RS480_VA_SIZE_32MB));
-
-		temp = IGP_READ_MCIND(dev_priv, RS480_GART_FEATURE_ID);
-		IGP_WRITE_MCIND(RS480_GART_FEATURE_ID, (RS480_HANG_EN |
-							RS480_TLB_ENABLE |
-							RS480_GTW_LAC_EN |
-							RS480_1LEVEL_GART));
-
-		temp = dev_priv->gart_info.bus_addr & 0xfffff000;
-		temp |= (upper_32_bits(dev_priv->gart_info.bus_addr) & 0xff) << 4;
-		IGP_WRITE_MCIND(RS480_GART_BASE, temp);
-
-		temp = IGP_READ_MCIND(dev_priv, RS480_AGP_MODE_CNTL);
-		IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) |
-						      RS480_REQ_TYPE_SNOOP_DIS));
-
-		radeon_write_agp_base(dev_priv, dev_priv->gart_vm_start);
-
-		dev_priv->gart_size = 32*1024*1024;
-		temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) &
-			 0xffff0000) | (dev_priv->gart_vm_start >> 16));
-
-		radeon_write_agp_location(dev_priv, temp);
-
-		temp = IGP_READ_MCIND(dev_priv, RS480_AGP_ADDRESS_SPACE_SIZE);
-		IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
-							       RS480_VA_SIZE_32MB));
-
-		do {
-			temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
-			if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
-				break;
-			DRM_UDELAY(1);
-		} while (1);
-
-		IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL,
-				RS480_GART_CACHE_INVALIDATE);
-
-		do {
-			temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
-			if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
-				break;
-			DRM_UDELAY(1);
-		} while (1);
-
-		IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0);
-	} else {
-		IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, 0);
-	}
-}
-
-/* Enable or disable IGP GART on the chip */
-static void rs600_set_igpgart(drm_radeon_private_t *dev_priv, int on)
-{
-	u32 temp;
-	int i;
-
-	if (on) {
-		DRM_DEBUG("programming igp gart %08X %08lX %08X\n",
-			 dev_priv->gart_vm_start,
-			 (long)dev_priv->gart_info.bus_addr,
-			 dev_priv->gart_size);
-
-		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (RS600_EFFECTIVE_L2_CACHE_SIZE(6) |
-						    RS600_EFFECTIVE_L2_QUEUE_SIZE(6)));
-
-		for (i = 0; i < 19; i++)
-			IGP_WRITE_MCIND(RS600_MC_PT0_CLIENT0_CNTL + i,
-					(RS600_ENABLE_TRANSLATION_MODE_OVERRIDE |
-					 RS600_SYSTEM_ACCESS_MODE_IN_SYS |
-					 RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH |
-					 RS600_EFFECTIVE_L1_CACHE_SIZE(3) |
-					 RS600_ENABLE_FRAGMENT_PROCESSING |
-					 RS600_EFFECTIVE_L1_QUEUE_SIZE(3)));
-
-		IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_CNTL, (RS600_ENABLE_PAGE_TABLE |
-							     RS600_PAGE_TABLE_TYPE_FLAT));
-
-		/* disable all other contexts */
-		for (i = 1; i < 8; i++)
-			IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_CNTL + i, 0);
-
-		/* setup the page table aperture */
-		IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR,
-				dev_priv->gart_info.bus_addr);
-		IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR,
-				dev_priv->gart_vm_start);
-		IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR,
-				(dev_priv->gart_vm_start + dev_priv->gart_size - 1));
-		IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0);
-
-		/* setup the system aperture */
-		IGP_WRITE_MCIND(RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR,
-				dev_priv->gart_vm_start);
-		IGP_WRITE_MCIND(RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR,
-				(dev_priv->gart_vm_start + dev_priv->gart_size - 1));
-
-		/* enable page tables */
-		temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL);
-		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (temp | RS600_ENABLE_PT));
-
-		temp = IGP_READ_MCIND(dev_priv, RS600_MC_CNTL1);
-		IGP_WRITE_MCIND(RS600_MC_CNTL1, (temp | RS600_ENABLE_PAGE_TABLES));
-
-		/* invalidate the cache */
-		temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL);
-
-		temp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE);
-		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp);
-		temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL);
-
-		temp |= RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE;
-		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp);
-		temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL);
-
-		temp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE);
-		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp);
-		temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL);
-
-	} else {
-		IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, 0);
-		temp = IGP_READ_MCIND(dev_priv, RS600_MC_CNTL1);
-		temp &= ~RS600_ENABLE_PAGE_TABLES;
-		IGP_WRITE_MCIND(RS600_MC_CNTL1, temp);
-	}
-}
-
-static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
-{
-	u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
-	if (on) {
-
-		DRM_DEBUG("programming pcie %08X %08lX %08X\n",
-			  dev_priv->gart_vm_start,
-			  (long)dev_priv->gart_info.bus_addr,
-			  dev_priv->gart_size);
-		RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO,
-				  dev_priv->gart_vm_start);
-		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE,
-				  dev_priv->gart_info.bus_addr);
-		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO,
-				  dev_priv->gart_vm_start);
-		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO,
-				  dev_priv->gart_vm_start +
-				  dev_priv->gart_size - 1);
-
-		radeon_write_agp_location(dev_priv, 0xffffffc0); /* ?? */
-
-		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
-				  RADEON_PCIE_TX_GART_EN);
-	} else {
-		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
-				  tmp & ~RADEON_PCIE_TX_GART_EN);
-	}
-}
-
-/* Enable or disable PCI GART on the chip */
-static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
-{
-	u32 tmp;
-
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740) ||
-	    (dev_priv->flags & RADEON_IS_IGPGART)) {
-		radeon_set_igpgart(dev_priv, on);
-		return;
-	}
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) {
-		rs600_set_igpgart(dev_priv, on);
-		return;
-	}
-
-	if (dev_priv->flags & RADEON_IS_PCIE) {
-		radeon_set_pciegart(dev_priv, on);
-		return;
-	}
-
-	tmp = RADEON_READ(RADEON_AIC_CNTL);
-
-	if (on) {
-		RADEON_WRITE(RADEON_AIC_CNTL,
-			     tmp | RADEON_PCIGART_TRANSLATE_EN);
-
-		/* set PCI GART page-table base address
-		 */
-		RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);
-
-		/* set address range for PCI address translate
-		 */
-		RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start);
-		RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
-			     + dev_priv->gart_size - 1);
-
-		/* Turn off AGP aperture -- is this required for PCI GART?
-		 */
-		radeon_write_agp_location(dev_priv, 0xffffffc0);
-		RADEON_WRITE(RADEON_AGP_COMMAND, 0);	/* clear AGP_COMMAND */
-	} else {
-		RADEON_WRITE(RADEON_AIC_CNTL,
-			     tmp & ~RADEON_PCIGART_TRANSLATE_EN);
-	}
-}
-
-static int radeon_setup_pcigart_surface(drm_radeon_private_t *dev_priv)
-{
-	struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info;
-	struct radeon_virt_surface *vp;
-	int i;
-
-	for (i = 0; i < RADEON_MAX_SURFACES * 2; i++) {
-		if (!dev_priv->virt_surfaces[i].file_priv ||
-		    dev_priv->virt_surfaces[i].file_priv == PCIGART_FILE_PRIV)
-			break;
-	}
-	if (i >= 2 * RADEON_MAX_SURFACES)
-		return -ENOMEM;
-	vp = &dev_priv->virt_surfaces[i];
-
-	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
-		struct radeon_surface *sp = &dev_priv->surfaces[i];
-		if (sp->refcount)
-			continue;
-
-		vp->surface_index = i;
-		vp->lower = gart_info->bus_addr;
-		vp->upper = vp->lower + gart_info->table_size;
-		vp->flags = 0;
-		vp->file_priv = PCIGART_FILE_PRIV;
-
-		sp->refcount = 1;
-		sp->lower = vp->lower;
-		sp->upper = vp->upper;
-		sp->flags = 0;
-
-		RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, sp->flags);
-		RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * i, sp->lower);
-		RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * i, sp->upper);
-		return 0;
-	}
-
-	return -ENOMEM;
-}
-
-static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
-			     struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
-
-	DRM_DEBUG("\n");
-
-	/* if we require new memory map but we don't have it fail */
-	if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
-		DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
-		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
-		DRM_DEBUG("Forcing AGP card to PCI mode\n");
-		dev_priv->flags &= ~RADEON_IS_AGP;
-	} else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
-		   && !init->is_pci) {
-		DRM_DEBUG("Restoring AGP flag\n");
-		dev_priv->flags |= RADEON_IS_AGP;
-	}
-
-	if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
-		DRM_ERROR("PCI GART memory not allocated!\n");
-		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	dev_priv->usec_timeout = init->usec_timeout;
-	if (dev_priv->usec_timeout < 1 ||
-	    dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
-		DRM_DEBUG("TIMEOUT problem!\n");
-		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	/* Enable vblank on CRTC1 for older X servers
-	 */
-	dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
-
-	switch(init->func) {
-	case RADEON_INIT_R200_CP:
-		dev_priv->microcode_version = UCODE_R200;
-		break;
-	case RADEON_INIT_R300_CP:
-		dev_priv->microcode_version = UCODE_R300;
-		break;
-	default:
-		dev_priv->microcode_version = UCODE_R100;
-	}
-
-	dev_priv->do_boxes = 0;
-	dev_priv->cp_mode = init->cp_mode;
-
-	/* We don't support anything other than bus-mastering ring mode,
-	 * but the ring can be in either AGP or PCI space for the ring
-	 * read pointer.
-	 */
-	if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
-	    (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
-		DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
-		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	switch (init->fb_bpp) {
-	case 16:
-		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
-		break;
-	case 32:
-	default:
-		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
-		break;
-	}
-	dev_priv->front_offset = init->front_offset;
-	dev_priv->front_pitch = init->front_pitch;
-	dev_priv->back_offset = init->back_offset;
-	dev_priv->back_pitch = init->back_pitch;
-
-	switch (init->depth_bpp) {
-	case 16:
-		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
-		break;
-	case 32:
-	default:
-		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
-		break;
-	}
-	dev_priv->depth_offset = init->depth_offset;
-	dev_priv->depth_pitch = init->depth_pitch;
-
-	/* Hardware state for depth clears.  Remove this if/when we no
-	 * longer clear the depth buffer with a 3D rectangle.  Hard-code
-	 * all values to prevent unwanted 3D state from slipping through
-	 * and screwing with the clear operation.
-	 */
-	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
-					   (dev_priv->color_fmt << 10) |
-					   (dev_priv->microcode_version ==
-					    UCODE_R100 ? RADEON_ZBLOCK16 : 0));
-
-	dev_priv->depth_clear.rb3d_zstencilcntl =
-	    (dev_priv->depth_fmt |
-	     RADEON_Z_TEST_ALWAYS |
-	     RADEON_STENCIL_TEST_ALWAYS |
-	     RADEON_STENCIL_S_FAIL_REPLACE |
-	     RADEON_STENCIL_ZPASS_REPLACE |
-	     RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE);
-
-	dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
-					 RADEON_BFACE_SOLID |
-					 RADEON_FFACE_SOLID |
-					 RADEON_FLAT_SHADE_VTX_LAST |
-					 RADEON_DIFFUSE_SHADE_FLAT |
-					 RADEON_ALPHA_SHADE_FLAT |
-					 RADEON_SPECULAR_SHADE_FLAT |
-					 RADEON_FOG_SHADE_FLAT |
-					 RADEON_VTX_PIX_CENTER_OGL |
-					 RADEON_ROUND_MODE_TRUNC |
-					 RADEON_ROUND_PREC_8TH_PIX);
-
-
-	dev_priv->ring_offset = init->ring_offset;
-	dev_priv->ring_rptr_offset = init->ring_rptr_offset;
-	dev_priv->buffers_offset = init->buffers_offset;
-	dev_priv->gart_textures_offset = init->gart_textures_offset;
-
-	master_priv->sarea = drm_legacy_getsarea(dev);
-	if (!master_priv->sarea) {
-		DRM_ERROR("could not find sarea!\n");
-		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	dev_priv->cp_ring = drm_legacy_findmap(dev, init->ring_offset);
-	if (!dev_priv->cp_ring) {
-		DRM_ERROR("could not find cp ring region!\n");
-		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-	dev_priv->ring_rptr = drm_legacy_findmap(dev, init->ring_rptr_offset);
-	if (!dev_priv->ring_rptr) {
-		DRM_ERROR("could not find ring read pointer!\n");
-		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-	dev->agp_buffer_token = init->buffers_offset;
-	dev->agp_buffer_map = drm_legacy_findmap(dev, init->buffers_offset);
-	if (!dev->agp_buffer_map) {
-		DRM_ERROR("could not find dma buffer region!\n");
-		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
-	}
-
-	if (init->gart_textures_offset) {
-		dev_priv->gart_textures =
-		    drm_legacy_findmap(dev, init->gart_textures_offset);
-		if (!dev_priv->gart_textures) {
-			DRM_ERROR("could not find GART texture region!\n");
-			radeon_do_cleanup_cp(dev);
-			return -EINVAL;
-		}
-	}
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		drm_legacy_ioremap_wc(dev_priv->cp_ring, dev);
-		drm_legacy_ioremap_wc(dev_priv->ring_rptr, dev);
-		drm_legacy_ioremap_wc(dev->agp_buffer_map, dev);
-		if (!dev_priv->cp_ring->handle ||
-		    !dev_priv->ring_rptr->handle ||
-		    !dev->agp_buffer_map->handle) {
-			DRM_ERROR("could not find ioremap agp regions!\n");
-			radeon_do_cleanup_cp(dev);
-			return -EINVAL;
-		}
-	} else
-#endif
-	{
-		dev_priv->cp_ring->handle =
-			(void *)(unsigned long)dev_priv->cp_ring->offset;
-		dev_priv->ring_rptr->handle =
-			(void *)(unsigned long)dev_priv->ring_rptr->offset;
-		dev->agp_buffer_map->handle =
-			(void *)(unsigned long)dev->agp_buffer_map->offset;
-
-		DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
-			  dev_priv->cp_ring->handle);
-		DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
-			  dev_priv->ring_rptr->handle);
-		DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
-			  dev->agp_buffer_map->handle);
-	}
-
-	dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16;
-	dev_priv->fb_size =
-		((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000)
-		- dev_priv->fb_location;
-
-	dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
-					((dev_priv->front_offset
-					  + dev_priv->fb_location) >> 10));
-
-	dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
-				       ((dev_priv->back_offset
-					 + dev_priv->fb_location) >> 10));
-
-	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
-					((dev_priv->depth_offset
-					  + dev_priv->fb_location) >> 10));
-
-	dev_priv->gart_size = init->gart_size;
-
-	/* New let's set the memory map ... */
-	if (dev_priv->new_memmap) {
-		u32 base = 0;
-
-		DRM_INFO("Setting GART location based on new memory map\n");
-
-		/* If using AGP, try to locate the AGP aperture at the same
-		 * location in the card and on the bus, though we have to
-		 * align it down.
-		 */
-#if IS_ENABLED(CONFIG_AGP)
-		if (dev_priv->flags & RADEON_IS_AGP) {
-			base = dev->agp->base;
-			/* Check if valid */
-			if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
-			    base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
-				DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
-					 dev->agp->base);
-				base = 0;
-			}
-		}
-#endif
-		/* If not or if AGP is at 0 (Macs), try to put it elsewhere */
-		if (base == 0) {
-			base = dev_priv->fb_location + dev_priv->fb_size;
-			if (base < dev_priv->fb_location ||
-			    ((base + dev_priv->gart_size) & 0xfffffffful) < base)
-				base = dev_priv->fb_location
-					- dev_priv->gart_size;
-		}
-		dev_priv->gart_vm_start = base & 0xffc00000u;
-		if (dev_priv->gart_vm_start != base)
-			DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
-				 base, dev_priv->gart_vm_start);
-	} else {
-		DRM_INFO("Setting GART location based on old memory map\n");
-		dev_priv->gart_vm_start = dev_priv->fb_location +
-			RADEON_READ(RADEON_CONFIG_APER_SIZE);
-	}
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP)
-		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
-						 - dev->agp->base
-						 + dev_priv->gart_vm_start);
-	else
-#endif
-		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
-					- (unsigned long)dev->sg->virtual
-					+ dev_priv->gart_vm_start);
-
-	DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
-	DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start);
-	DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",
-		  dev_priv->gart_buffers_offset);
-
-	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
-	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
-			      + init->ring_size / sizeof(u32));
-	dev_priv->ring.size = init->ring_size;
-	dev_priv->ring.size_l2qw = order_base_2(init->ring_size / 8);
-
-	dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
-	dev_priv->ring.rptr_update_l2qw = order_base_2( /* init->rptr_update */ 4096 / 8);
-
-	dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
-	dev_priv->ring.fetch_size_l2ow = order_base_2( /* init->fetch_size */ 32 / 16);
-	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
-
-	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		/* Turn off PCI GART */
-		radeon_set_pcigart(dev_priv, 0);
-	} else
-#endif
-	{
-		u32 sctrl;
-		int ret;
-
-		dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
-		/* if we have an offset set from userspace */
-		if (dev_priv->pcigart_offset_set) {
-			dev_priv->gart_info.bus_addr =
-				(resource_size_t)dev_priv->pcigart_offset + dev_priv->fb_location;
-			dev_priv->gart_info.mapping.offset =
-			    dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
-			dev_priv->gart_info.mapping.size =
-			    dev_priv->gart_info.table_size;
-
-			drm_legacy_ioremap_wc(&dev_priv->gart_info.mapping, dev);
-			dev_priv->gart_info.addr =
-			    dev_priv->gart_info.mapping.handle;
-
-			if (dev_priv->flags & RADEON_IS_PCIE)
-				dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
-			else
-				dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
-			dev_priv->gart_info.gart_table_location =
-			    DRM_ATI_GART_FB;
-
-			DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
-				  dev_priv->gart_info.addr,
-				  dev_priv->pcigart_offset);
-		} else {
-			if (dev_priv->flags & RADEON_IS_IGPGART)
-				dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP;
-			else
-				dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
-			dev_priv->gart_info.gart_table_location =
-			    DRM_ATI_GART_MAIN;
-			dev_priv->gart_info.addr = NULL;
-			dev_priv->gart_info.bus_addr = 0;
-			if (dev_priv->flags & RADEON_IS_PCIE) {
-				DRM_ERROR
-				    ("Cannot use PCI Express without GART in FB memory\n");
-				radeon_do_cleanup_cp(dev);
-				return -EINVAL;
-			}
-		}
-
-		sctrl = RADEON_READ(RADEON_SURFACE_CNTL);
-		RADEON_WRITE(RADEON_SURFACE_CNTL, 0);
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
-			ret = r600_page_table_init(dev);
-		else
-			ret = drm_ati_pcigart_init(dev, &dev_priv->gart_info);
-		RADEON_WRITE(RADEON_SURFACE_CNTL, sctrl);
-
-		if (!ret) {
-			DRM_ERROR("failed to init PCI GART!\n");
-			radeon_do_cleanup_cp(dev);
-			return -ENOMEM;
-		}
-
-		ret = radeon_setup_pcigart_surface(dev_priv);
-		if (ret) {
-			DRM_ERROR("failed to setup GART surface!\n");
-			if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
-				r600_page_table_cleanup(dev, &dev_priv->gart_info);
-			else
-				drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info);
-			radeon_do_cleanup_cp(dev);
-			return ret;
-		}
-
-		/* Turn on PCI GART */
-		radeon_set_pcigart(dev_priv, 1);
-	}
-
-	if (!dev_priv->me_fw) {
-		int err = radeon_cp_init_microcode(dev_priv);
-		if (err) {
-			DRM_ERROR("Failed to load firmware!\n");
-			radeon_do_cleanup_cp(dev);
-			return err;
-		}
-	}
-	radeon_cp_load_microcode(dev_priv);
-	radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
-
-	dev_priv->last_buf = 0;
-
-	radeon_do_engine_reset(dev);
-	radeon_test_writeback(dev_priv);
-
-	return 0;
-}
-
-static int radeon_do_cleanup_cp(struct drm_device * dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG("\n");
-
-	/* Make sure interrupts are disabled here because the uninstall ioctl
-	 * may not have been called from userspace and after dev_private
-	 * is freed, it's too late.
-	 */
-	if (dev->irq_enabled)
-		drm_irq_uninstall(dev);
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		if (dev_priv->cp_ring != NULL) {
-			drm_legacy_ioremapfree(dev_priv->cp_ring, dev);
-			dev_priv->cp_ring = NULL;
-		}
-		if (dev_priv->ring_rptr != NULL) {
-			drm_legacy_ioremapfree(dev_priv->ring_rptr, dev);
-			dev_priv->ring_rptr = NULL;
-		}
-		if (dev->agp_buffer_map != NULL) {
-			drm_legacy_ioremapfree(dev->agp_buffer_map, dev);
-			dev->agp_buffer_map = NULL;
-		}
-	} else
-#endif
-	{
-
-		if (dev_priv->gart_info.bus_addr) {
-			/* Turn off PCI GART */
-			radeon_set_pcigart(dev_priv, 0);
-			if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)
-				r600_page_table_cleanup(dev, &dev_priv->gart_info);
-			else {
-				if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
-					DRM_ERROR("failed to cleanup PCI GART!\n");
-			}
-		}
-
-		if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
-		{
-			drm_legacy_ioremapfree(&dev_priv->gart_info.mapping, dev);
-			dev_priv->gart_info.addr = NULL;
-		}
-	}
-	/* only clear to the start of flags */
-	memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
-
-	return 0;
-}
-
-/* This code will reinit the Radeon CP hardware after a resume from disc.
- * AFAIK, it would be very difficult to pickle the state at suspend time, so
- * here we make sure that all Radeon hardware initialisation is re-done without
- * affecting running applications.
- *
- * Charl P. Botha <http://cpbotha.net>
- */
-static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	if (!dev_priv) {
-		DRM_ERROR("Called with no initialization\n");
-		return -EINVAL;
-	}
-
-	DRM_DEBUG("Starting radeon_do_resume_cp()\n");
-
-#if IS_ENABLED(CONFIG_AGP)
-	if (dev_priv->flags & RADEON_IS_AGP) {
-		/* Turn off PCI GART */
-		radeon_set_pcigart(dev_priv, 0);
-	} else
-#endif
-	{
-		/* Turn on PCI GART */
-		radeon_set_pcigart(dev_priv, 1);
-	}
-
-	radeon_cp_load_microcode(dev_priv);
-	radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
-
-	dev_priv->have_z_offset = 0;
-	radeon_do_engine_reset(dev);
-	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
-
-	DRM_DEBUG("radeon_do_resume_cp() complete\n");
-
-	return 0;
-}
-
-int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_init_t *init = data;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if (init->func == RADEON_INIT_R300_CP)
-		r300_init_reg_flags(dev);
-
-	switch (init->func) {
-	case RADEON_INIT_CP:
-	case RADEON_INIT_R200_CP:
-	case RADEON_INIT_R300_CP:
-		return radeon_do_init_cp(dev, init, file_priv);
-	case RADEON_INIT_R600_CP:
-		return r600_do_init_cp(dev, init, file_priv);
-	case RADEON_CLEANUP_CP:
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-			return r600_do_cleanup_cp(dev);
-		else
-			return radeon_do_cleanup_cp(dev);
-	}
-
-	return -EINVAL;
-}
-
-int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG("\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if (dev_priv->cp_running) {
-		DRM_DEBUG("while CP running\n");
-		return 0;
-	}
-	if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
-		DRM_DEBUG("called with bogus CP mode (%d)\n",
-			  dev_priv->cp_mode);
-		return 0;
-	}
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		r600_do_cp_start(dev_priv);
-	else
-		radeon_do_cp_start(dev_priv);
-
-	return 0;
-}
-
-/* Stop the CP.  The engine must have been idled before calling this
- * routine.
- */
-int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_cp_stop_t *stop = data;
-	int ret;
-	DRM_DEBUG("\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if (!dev_priv->cp_running)
-		return 0;
-
-	/* Flush any pending CP commands.  This ensures any outstanding
-	 * commands are exectuted by the engine before we turn it off.
-	 */
-	if (stop->flush) {
-		radeon_do_cp_flush(dev_priv);
-	}
-
-	/* If we fail to make the engine go idle, we return an error
-	 * code so that the DRM ioctl wrapper can try again.
-	 */
-	if (stop->idle) {
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-			ret = r600_do_cp_idle(dev_priv);
-		else
-			ret = radeon_do_cp_idle(dev_priv);
-		if (ret)
-			return ret;
-	}
-
-	/* Finally, we can turn off the CP.  If the engine isn't idle,
-	 * we will get some dropped triangles as they won't be fully
-	 * rendered before the CP is shut down.
-	 */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		r600_do_cp_stop(dev_priv);
-	else
-		radeon_do_cp_stop(dev_priv);
-
-	/* Reset the engine */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		r600_do_engine_reset(dev);
-	else
-		radeon_do_engine_reset(dev);
-
-	return 0;
-}
-
-void radeon_do_release(struct drm_device * dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	int i, ret;
-
-	if (dev_priv) {
-		if (dev_priv->cp_running) {
-			/* Stop the cp */
-			if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
-				while ((ret = r600_do_cp_idle(dev_priv)) != 0) {
-					DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
-#ifdef __linux__
-					schedule();
-#else
-					tsleep(&ret, PZERO, "rdnrel", 1);
-#endif
-				}
-			} else {
-				while ((ret = radeon_do_cp_idle(dev_priv)) != 0) {
-					DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
-#ifdef __linux__
-					schedule();
-#else
-					tsleep(&ret, PZERO, "rdnrel", 1);
-#endif
-				}
-			}
-			if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
-				r600_do_cp_stop(dev_priv);
-				r600_do_engine_reset(dev);
-			} else {
-				radeon_do_cp_stop(dev_priv);
-				radeon_do_engine_reset(dev);
-			}
-		}
-
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_R600) {
-			/* Disable *all* interrupts */
-			if (dev_priv->mmio)	/* remove this after permanent addmaps */
-				RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
-
-			if (dev_priv->mmio) {	/* remove all surfaces */
-				for (i = 0; i < RADEON_MAX_SURFACES; i++) {
-					RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0);
-					RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND +
-						     16 * i, 0);
-					RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND +
-						     16 * i, 0);
-				}
-			}
-		}
-
-		/* Free memory heap structures */
-		radeon_mem_takedown(&(dev_priv->gart_heap));
-		radeon_mem_takedown(&(dev_priv->fb_heap));
-
-		/* deallocate kernel resources */
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-			r600_do_cleanup_cp(dev);
-		else
-			radeon_do_cleanup_cp(dev);
-		release_firmware(dev_priv->me_fw);
-		dev_priv->me_fw = NULL;
-		release_firmware(dev_priv->pfp_fw);
-		dev_priv->pfp_fw = NULL;
-	}
-}
-
-/* Just reset the CP ring.  Called as part of an X Server engine reset.
- */
-int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG("\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if (!dev_priv) {
-		DRM_DEBUG("called before init done\n");
-		return -EINVAL;
-	}
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		r600_do_cp_reset(dev_priv);
-	else
-		radeon_do_cp_reset(dev_priv);
-
-	/* The CP is no longer running after an engine reset */
-	dev_priv->cp_running = 0;
-
-	return 0;
-}
-
-int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG("\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return r600_do_cp_idle(dev_priv);
-	else
-		return radeon_do_cp_idle(dev_priv);
-}
-
-/* Added by Charl P. Botha to call radeon_do_resume_cp().
- */
-int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG("\n");
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return r600_do_resume_cp(dev, file_priv);
-	else
-		return radeon_do_resume_cp(dev, file_priv);
-}
-
-int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG("\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return r600_do_engine_reset(dev);
-	else
-		return radeon_do_engine_reset(dev);
-}
-
-/* ================================================================
- * Fullscreen mode
- */
-
-/* KW: Deprecated to say the least:
- */
-int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	return 0;
-}
-
-/* ================================================================
- * Freelist management
- */
-
-/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
- *   bufs until freelist code is used.  Note this hides a problem with
- *   the scratch register * (used to keep track of last buffer
- *   completed) being written to before * the last buffer has actually
- *   completed rendering.
- *
- * KW:  It's also a good way to find free buffers quickly.
- *
- * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
- * sleep.  However, bugs in older versions of radeon_accel.c mean that
- * we essentially have to do this, else old clients will break.
- *
- * However, it does leave open a potential deadlock where all the
- * buffers are held by other clients, which can't release them because
- * they can't get the lock.
- */
-
-struct drm_buf *radeon_freelist_get(struct drm_device * dev)
-{
-	struct drm_device_dma *dma = dev->dma;
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_buf_priv_t *buf_priv;
-	struct drm_buf *buf;
-	int i, t;
-	int start;
-
-	if (++dev_priv->last_buf >= dma->buf_count)
-		dev_priv->last_buf = 0;
-
-	start = dev_priv->last_buf;
-
-	for (t = 0; t < dev_priv->usec_timeout; t++) {
-		u32 done_age = GET_SCRATCH(dev_priv, 1);
-		DRM_DEBUG("done_age = %d\n", done_age);
-		for (i = 0; i < dma->buf_count; i++) {
-			buf = dma->buflist[start];
-			buf_priv = buf->dev_private;
-			if (buf->file_priv == NULL || (buf->pending &&
-						       buf_priv->age <=
-						       done_age)) {
-				dev_priv->stats.requested_bufs++;
-				buf->pending = 0;
-				return buf;
-			}
-			if (++start >= dma->buf_count)
-				start = 0;
-		}
-
-		if (t) {
-			DRM_UDELAY(1);
-			dev_priv->stats.freelist_loops++;
-		}
-	}
-
-	return NULL;
-}
-
-void radeon_freelist_reset(struct drm_device * dev)
-{
-	struct drm_device_dma *dma = dev->dma;
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	int i;
-
-	dev_priv->last_buf = 0;
-	for (i = 0; i < dma->buf_count; i++) {
-		struct drm_buf *buf = dma->buflist[i];
-		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
-		buf_priv->age = 0;
-	}
-}
-
-/* ================================================================
- * CP command submission
- */
-
-int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n)
-{
-	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
-	int i;
-	u32 last_head = GET_RING_HEAD(dev_priv);
-
-	for (i = 0; i < dev_priv->usec_timeout; i++) {
-		u32 head = GET_RING_HEAD(dev_priv);
-
-		ring->space = (head - ring->tail) * sizeof(u32);
-		if (ring->space <= 0)
-			ring->space += ring->size;
-		if (ring->space > n)
-			return 0;
-
-		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-		if (head != last_head)
-			i = 0;
-		last_head = head;
-
-		DRM_UDELAY(1);
-	}
-
-	/* FIXME: This return value is ignored in the BEGIN_RING macro! */
-#if RADEON_FIFO_DEBUG
-	radeon_status(dev_priv);
-	DRM_ERROR("failed!\n");
-#endif
-	return -EBUSY;
-}
-
-static int radeon_cp_get_buffers(struct drm_device *dev,
-				 struct drm_file *file_priv,
-				 struct drm_dma * d)
-{
-	int i;
-	struct drm_buf *buf;
-
-	for (i = d->granted_count; i < d->request_count; i++) {
-		buf = radeon_freelist_get(dev);
-		if (!buf)
-			return -EBUSY;	/* NOTE: broken client */
-
-		buf->file_priv = file_priv;
-
-		if (copy_to_user(&d->request_indices[i], &buf->idx,
-				     sizeof(buf->idx)))
-			return -EFAULT;
-		if (copy_to_user(&d->request_sizes[i], &buf->total,
-				     sizeof(buf->total)))
-			return -EFAULT;
-
-		d->granted_count++;
-	}
-	return 0;
-}
-
-int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	struct drm_device_dma *dma = dev->dma;
-	int ret = 0;
-	struct drm_dma *d = data;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	/* Please don't send us buffers.
-	 */
-	if (d->send_count != 0) {
-		DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-			  DRM_CURRENTPID, d->send_count);
-		return -EINVAL;
-	}
-
-	/* We'll send you buffers.
-	 */
-	if (d->request_count < 0 || d->request_count > dma->buf_count) {
-		DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-			  DRM_CURRENTPID, d->request_count, dma->buf_count);
-		return -EINVAL;
-	}
-
-	d->granted_count = 0;
-
-	if (d->request_count) {
-		ret = radeon_cp_get_buffers(dev, file_priv, d);
-	}
-
-	return ret;
-}
-
-int radeon_driver_load(struct drm_device *dev, unsigned long flags)
-{
-	drm_radeon_private_t *dev_priv;
-	int ret = 0;
-
-	dev_priv = kzalloc(sizeof(drm_radeon_private_t), GFP_KERNEL);
-	if (dev_priv == NULL)
-		return -ENOMEM;
-
-	dev->dev_private = (void *)dev_priv;
-	dev_priv->flags = flags;
-
-	switch (flags & RADEON_FAMILY_MASK) {
-	case CHIP_R100:
-	case CHIP_RV200:
-	case CHIP_R200:
-	case CHIP_R300:
-	case CHIP_R350:
-	case CHIP_R420:
-	case CHIP_R423:
-	case CHIP_RV410:
-	case CHIP_RV515:
-	case CHIP_R520:
-	case CHIP_RV570:
-	case CHIP_R580:
-		dev_priv->flags |= RADEON_HAS_HIERZ;
-		break;
-	default:
-		/* all other chips have no hierarchical z buffer */
-		break;
-	}
-
-	pci_set_master(dev->pdev);
-
-	if (drm_pci_device_is_agp(dev))
-		dev_priv->flags |= RADEON_IS_AGP;
-	else if (pci_is_pcie(dev->pdev))
-		dev_priv->flags |= RADEON_IS_PCIE;
-	else
-		dev_priv->flags |= RADEON_IS_PCI;
-
-	ret = drm_legacy_addmap(dev, pci_resource_start(dev->pdev, 2),
-				pci_resource_len(dev->pdev, 2), _DRM_REGISTERS,
-				_DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio);
-	if (ret != 0)
-		return ret;
-
-	ret = drm_vblank_init(dev, 2);
-	if (ret) {
-		radeon_driver_unload(dev);
-		return ret;
-	}
-
-	DRM_DEBUG("%s card detected\n",
-		  ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
-	return ret;
-}
-
-int radeon_master_create(struct drm_device *dev, struct drm_master *master)
-{
-	struct drm_radeon_master_private *master_priv;
-	unsigned long sareapage;
-	int ret;
-
-	master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
-	if (!master_priv)
-		return -ENOMEM;
-
-	/* prebuild the SAREA */
-	sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
-	ret = drm_legacy_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK,
-				&master_priv->sarea);
-	if (ret) {
-		DRM_ERROR("SAREA setup failed\n");
-		kfree(master_priv);
-		return ret;
-	}
-	master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
-	master_priv->sarea_priv->pfCurrentPage = 0;
-
-	master->driver_priv = master_priv;
-	return 0;
-}
-
-void radeon_master_destroy(struct drm_device *dev, struct drm_master *master)
-{
-	struct drm_radeon_master_private *master_priv = master->driver_priv;
-
-	if (!master_priv)
-		return;
-
-	if (master_priv->sarea_priv &&
-	    master_priv->sarea_priv->pfCurrentPage != 0)
-		radeon_cp_dispatch_flip(dev, master);
-
-	master_priv->sarea_priv = NULL;
-	if (master_priv->sarea)
-		drm_legacy_rmmap_locked(dev, master_priv->sarea);
-
-	kfree(master_priv);
-
-	master->driver_priv = NULL;
-}
-
-/* Create mappings for registers and framebuffer so userland doesn't necessarily
- * have to find them.
- */
-int radeon_driver_firstopen(struct drm_device *dev)
-{
-	int ret;
-	drm_local_map_t *map;
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
-
-	dev_priv->fb_aper_offset = pci_resource_start(dev->pdev, 0);
-	ret = drm_legacy_addmap(dev, dev_priv->fb_aper_offset,
-				pci_resource_len(dev->pdev, 0),
-				_DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING, &map);
-	if (ret != 0)
-		return ret;
-
-	return 0;
-}
-
-int radeon_driver_unload(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	DRM_DEBUG("\n");
-
-	drm_legacy_rmmap(dev, dev_priv->mmio);
-
-	kfree(dev_priv);
-
-	dev->dev_private = NULL;
-	return 0;
-}
-
-void radeon_commit_ring(drm_radeon_private_t *dev_priv)
-{
-	int i;
-	u32 *ring;
-	int tail_aligned;
-
-	/* check if the ring is padded out to 16-dword alignment */
-
-	tail_aligned = dev_priv->ring.tail & (RADEON_RING_ALIGN-1);
-	if (tail_aligned) {
-		int num_p2 = RADEON_RING_ALIGN - tail_aligned;
-
-		ring = dev_priv->ring.start;
-		/* pad with some CP_PACKET2 */
-		for (i = 0; i < num_p2; i++)
-			ring[dev_priv->ring.tail + i] = CP_PACKET2();
-
-		dev_priv->ring.tail += i;
-
-		dev_priv->ring.space -= num_p2 * sizeof(u32);
-	}
-
-	dev_priv->ring.tail &= dev_priv->ring.tail_mask;
-
-	mb();
-	GET_RING_HEAD( dev_priv );
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
-		RADEON_WRITE(R600_CP_RB_WPTR, dev_priv->ring.tail);
-		/* read from PCI bus to ensure correct posting */
-		RADEON_READ(R600_CP_RB_RPTR);
-	} else {
-		RADEON_WRITE(RADEON_CP_RB_WPTR, dev_priv->ring.tail);
-		/* read from PCI bus to ensure correct posting */
-		RADEON_READ(RADEON_CP_RB_RPTR);
-	}
-}
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index c566993..902b59c 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1150,7 +1150,7 @@
 	}
 
 	if (radeon_vm_size < 1) {
-		dev_warn(rdev->dev, "VM size (%d) to small, min is 1GB\n",
+		dev_warn(rdev->dev, "VM size (%d) too small, min is 1GB\n",
 			 radeon_vm_size);
 		radeon_vm_size = 4;
 	}
@@ -1744,6 +1744,7 @@
 	}
 
 	drm_kms_helper_poll_enable(dev);
+	drm_helper_hpd_irq_event(dev);
 
 	/* set the power state here in case we are a PX system or headless */
 	if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
index 8a02225..df7a171 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -525,11 +525,17 @@
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
 	{
 	  struct radeon_connector_atom_dig *dig_connector;
+	  int ret;
 
 	  dig_connector = mst_enc->connector->con_priv;
-	  dig_connector->dp_lane_count = drm_dp_max_lane_count(dig_connector->dpcd);
-	  dig_connector->dp_clock = radeon_dp_get_max_link_rate(&mst_enc->connector->base,
-								dig_connector->dpcd);
+	  ret = radeon_dp_get_dp_link_config(&mst_enc->connector->base,
+					     dig_connector->dpcd, adjusted_mode->clock,
+					     &dig_connector->dp_lane_count,
+					     &dig_connector->dp_clock);
+	  if (ret) {
+		  dig_connector->dp_lane_count = 0;
+		  dig_connector->dp_clock = 0;
+	  }
 	  DRM_DEBUG_KMS("dig clock %p %d %d\n", dig_connector,
 			dig_connector->dp_lane_count, dig_connector->dp_clock);
 	}
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 5b6a6f5..e266ffc 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -291,88 +291,6 @@
 
 MODULE_DEVICE_TABLE(pci, pciidlist);
 
-#ifdef CONFIG_DRM_RADEON_UMS
-
-static int radeon_suspend(struct drm_device *dev, pm_message_t state)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return 0;
-
-	/* Disable *all* interrupts */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
-		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
-	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
-	return 0;
-}
-
-static int radeon_resume(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return 0;
-
-	/* Restore interrupt registers */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
-		RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
-	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
-	return 0;
-}
-
-
-static const struct file_operations radeon_driver_old_fops = {
-	.owner = THIS_MODULE,
-	.open = drm_open,
-	.release = drm_release,
-	.unlocked_ioctl = drm_ioctl,
-	.mmap = drm_legacy_mmap,
-	.poll = drm_poll,
-	.read = drm_read,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl = radeon_compat_ioctl,
-#endif
-	.llseek = noop_llseek,
-};
-
-static struct drm_driver driver_old = {
-	.driver_features =
-	    DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
-	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
-	.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
-	.load = radeon_driver_load,
-	.firstopen = radeon_driver_firstopen,
-	.open = radeon_driver_open,
-	.preclose = radeon_driver_preclose,
-	.postclose = radeon_driver_postclose,
-	.lastclose = radeon_driver_lastclose,
-	.set_busid = drm_pci_set_busid,
-	.unload = radeon_driver_unload,
-	.suspend = radeon_suspend,
-	.resume = radeon_resume,
-	.get_vblank_counter = radeon_get_vblank_counter,
-	.enable_vblank = radeon_enable_vblank,
-	.disable_vblank = radeon_disable_vblank,
-	.master_create = radeon_master_create,
-	.master_destroy = radeon_master_destroy,
-	.irq_preinstall = radeon_driver_irq_preinstall,
-	.irq_postinstall = radeon_driver_irq_postinstall,
-	.irq_uninstall = radeon_driver_irq_uninstall,
-	.irq_handler = radeon_driver_irq_handler,
-	.ioctls = radeon_ioctls,
-	.dma_ioctl = radeon_cp_buffers,
-	.fops = &radeon_driver_old_fops,
-	.name = DRIVER_NAME,
-	.desc = DRIVER_DESC,
-	.date = DRIVER_DATE,
-	.major = DRIVER_MAJOR,
-	.minor = DRIVER_MINOR,
-	.patchlevel = DRIVER_PATCHLEVEL,
-};
-
-#endif
-
 static struct drm_driver kms_driver;
 
 static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
@@ -619,13 +537,6 @@
 static struct drm_driver *driver;
 static struct pci_driver *pdriver;
 
-#ifdef CONFIG_DRM_RADEON_UMS
-static struct pci_driver radeon_pci_driver = {
-	.name = DRIVER_NAME,
-	.id_table = pciidlist,
-};
-#endif
-
 static struct pci_driver radeon_kms_pci_driver = {
 	.name = DRIVER_NAME,
 	.id_table = pciidlist,
@@ -655,16 +566,8 @@
 		radeon_register_atpx_handler();
 
 	} else {
-#ifdef CONFIG_DRM_RADEON_UMS
-		DRM_INFO("radeon userspace modesetting enabled.\n");
-		driver = &driver_old;
-		pdriver = &radeon_pci_driver;
-		driver->driver_features &= ~DRIVER_MODESET;
-		driver->num_ioctls = radeon_max_ioctl;
-#else
 		DRM_ERROR("No UMS support in radeon module!\n");
 		return -EINVAL;
-#endif
 	}
 
 	radeon_kfd_init();
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index 0caafc7..afef2d9 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -119,2052 +119,4 @@
 long radeon_drm_ioctl(struct file *filp,
 		      unsigned int cmd, unsigned long arg);
 
-/* The rest of the file is DEPRECATED! */
-#ifdef CONFIG_DRM_RADEON_UMS
-
-enum radeon_cp_microcode_version {
-	UCODE_R100,
-	UCODE_R200,
-	UCODE_R300,
-};
-
-typedef struct drm_radeon_freelist {
-	unsigned int age;
-	struct drm_buf *buf;
-	struct drm_radeon_freelist *next;
-	struct drm_radeon_freelist *prev;
-} drm_radeon_freelist_t;
-
-typedef struct drm_radeon_ring_buffer {
-	u32 *start;
-	u32 *end;
-	int size;
-	int size_l2qw;
-
-	int rptr_update; /* Double Words */
-	int rptr_update_l2qw; /* log2 Quad Words */
-
-	int fetch_size; /* Double Words */
-	int fetch_size_l2ow; /* log2 Oct Words */
-
-	u32 tail;
-	u32 tail_mask;
-	int space;
-
-	int high_mark;
-} drm_radeon_ring_buffer_t;
-
-typedef struct drm_radeon_depth_clear_t {
-	u32 rb3d_cntl;
-	u32 rb3d_zstencilcntl;
-	u32 se_cntl;
-} drm_radeon_depth_clear_t;
-
-struct drm_radeon_driver_file_fields {
-	int64_t radeon_fb_delta;
-};
-
-struct mem_block {
-	struct mem_block *next;
-	struct mem_block *prev;
-	int start;
-	int size;
-	struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
-};
-
-struct radeon_surface {
-	int refcount;
-	u32 lower;
-	u32 upper;
-	u32 flags;
-};
-
-struct radeon_virt_surface {
-	int surface_index;
-	u32 lower;
-	u32 upper;
-	u32 flags;
-	struct drm_file *file_priv;
-#define PCIGART_FILE_PRIV	((void *) -1L)
-};
-
-#define RADEON_FLUSH_EMITED	(1 << 0)
-#define RADEON_PURGE_EMITED	(1 << 1)
-
-struct drm_radeon_master_private {
-	drm_local_map_t *sarea;
-	drm_radeon_sarea_t *sarea_priv;
-};
-
-typedef struct drm_radeon_private {
-	drm_radeon_ring_buffer_t ring;
-
-	u32 fb_location;
-	u32 fb_size;
-	int new_memmap;
-
-	int gart_size;
-	u32 gart_vm_start;
-	unsigned long gart_buffers_offset;
-
-	int cp_mode;
-	int cp_running;
-
-	drm_radeon_freelist_t *head;
-	drm_radeon_freelist_t *tail;
-	int last_buf;
-	int writeback_works;
-
-	int usec_timeout;
-
-	int microcode_version;
-
-	struct {
-		u32 boxes;
-		int freelist_timeouts;
-		int freelist_loops;
-		int requested_bufs;
-		int last_frame_reads;
-		int last_clear_reads;
-		int clears;
-		int texture_uploads;
-	} stats;
-
-	int do_boxes;
-	int page_flipping;
-
-	u32 color_fmt;
-	unsigned int front_offset;
-	unsigned int front_pitch;
-	unsigned int back_offset;
-	unsigned int back_pitch;
-
-	u32 depth_fmt;
-	unsigned int depth_offset;
-	unsigned int depth_pitch;
-
-	u32 front_pitch_offset;
-	u32 back_pitch_offset;
-	u32 depth_pitch_offset;
-
-	drm_radeon_depth_clear_t depth_clear;
-
-	unsigned long ring_offset;
-	unsigned long ring_rptr_offset;
-	unsigned long buffers_offset;
-	unsigned long gart_textures_offset;
-
-	drm_local_map_t *sarea;
-	drm_local_map_t *cp_ring;
-	drm_local_map_t *ring_rptr;
-	drm_local_map_t *gart_textures;
-
-	struct mem_block *gart_heap;
-	struct mem_block *fb_heap;
-
-	/* SW interrupt */
-	wait_queue_head_t swi_queue;
-	atomic_t swi_emitted;
-	int vblank_crtc;
-	uint32_t irq_enable_reg;
-	uint32_t r500_disp_irq_reg;
-
-	struct radeon_surface surfaces[RADEON_MAX_SURFACES];
-	struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
-
-	unsigned long pcigart_offset;
-	unsigned int pcigart_offset_set;
-	struct drm_ati_pcigart_info gart_info;
-
-	u32 scratch_ages[5];
-
-	int have_z_offset;
-
-	/* starting from here on, data is preserved across an open */
-	uint32_t flags;		/* see radeon_chip_flags */
-	resource_size_t fb_aper_offset;
-
-	int num_gb_pipes;
-	int num_z_pipes;
-	int track_flush;
-	drm_local_map_t *mmio;
-
-	/* r6xx/r7xx pipe/shader config */
-	int r600_max_pipes;
-	int r600_max_tile_pipes;
-	int r600_max_simds;
-	int r600_max_backends;
-	int r600_max_gprs;
-	int r600_max_threads;
-	int r600_max_stack_entries;
-	int r600_max_hw_contexts;
-	int r600_max_gs_threads;
-	int r600_sx_max_export_size;
-	int r600_sx_max_export_pos_size;
-	int r600_sx_max_export_smx_size;
-	int r600_sq_num_cf_insts;
-	int r700_sx_num_of_sets;
-	int r700_sc_prim_fifo_size;
-	int r700_sc_hiz_tile_fifo_size;
-	int r700_sc_earlyz_tile_fifo_fize;
-	int r600_group_size;
-	int r600_npipes;
-	int r600_nbanks;
-
-	struct mutex cs_mutex;
-	u32 cs_id_scnt;
-	u32 cs_id_wcnt;
-	/* r6xx/r7xx drm blit vertex buffer */
-	struct drm_buf *blit_vb;
-
-	/* firmware */
-	const struct firmware *me_fw, *pfp_fw;
-} drm_radeon_private_t;
-
-typedef struct drm_radeon_buf_priv {
-	u32 age;
-} drm_radeon_buf_priv_t;
-
-struct drm_buffer;
-
-typedef struct drm_radeon_kcmd_buffer {
-	int bufsz;
-	struct drm_buffer *buffer;
-	int nbox;
-	struct drm_clip_rect __user *boxes;
-} drm_radeon_kcmd_buffer_t;
-
-extern int radeon_no_wb;
-extern struct drm_ioctl_desc radeon_ioctls[];
-extern int radeon_max_ioctl;
-
-extern u32 radeon_get_ring_head(drm_radeon_private_t *dev_priv);
-extern void radeon_set_ring_head(drm_radeon_private_t *dev_priv, u32 val);
-
-#define GET_RING_HEAD(dev_priv)	radeon_get_ring_head(dev_priv)
-#define SET_RING_HEAD(dev_priv, val) radeon_set_ring_head(dev_priv, val)
-
-/* Check whether the given hardware address is inside the framebuffer or the
- * GART area.
- */
-static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv,
-					  u64 off)
-{
-	u32 fb_start = dev_priv->fb_location;
-	u32 fb_end = fb_start + dev_priv->fb_size - 1;
-	u32 gart_start = dev_priv->gart_vm_start;
-	u32 gart_end = gart_start + dev_priv->gart_size - 1;
-
-	return ((off >= fb_start && off <= fb_end) ||
-		(off >= gart_start && off <= gart_end));
-}
-
-/* radeon_state.c */
-extern void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf);
-
-				/* radeon_cp.c */
-extern int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv);
-extern void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc);
-extern void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base);
-
-extern void radeon_freelist_reset(struct drm_device * dev);
-extern struct drm_buf *radeon_freelist_get(struct drm_device * dev);
-
-extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n);
-
-extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv);
-
-extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags);
-extern int radeon_presetup(struct drm_device *dev);
-extern int radeon_driver_postcleanup(struct drm_device *dev);
-
-extern int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern void radeon_mem_takedown(struct mem_block **heap);
-extern void radeon_mem_release(struct drm_file *file_priv,
-			       struct mem_block *heap);
-
-extern void radeon_enable_bm(struct drm_radeon_private *dev_priv);
-extern u32 radeon_read_ring_rptr(drm_radeon_private_t *dev_priv, u32 off);
-extern void radeon_write_ring_rptr(drm_radeon_private_t *dev_priv, u32 off, u32 val);
-
-				/* radeon_irq.c */
-extern void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state);
-extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
-
-extern void radeon_do_release(struct drm_device * dev);
-extern u32 radeon_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
-extern int radeon_enable_vblank(struct drm_device *dev, unsigned int pipe);
-extern void radeon_disable_vblank(struct drm_device *dev, unsigned int pipe);
-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);
-extern void radeon_enable_interrupt(struct drm_device *dev);
-extern int radeon_vblank_crtc_get(struct drm_device *dev);
-extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
-
-extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
-extern int radeon_driver_unload(struct drm_device *dev);
-extern int radeon_driver_firstopen(struct drm_device *dev);
-extern void radeon_driver_preclose(struct drm_device *dev,
-				   struct drm_file *file_priv);
-extern void radeon_driver_postclose(struct drm_device *dev,
-				    struct drm_file *file_priv);
-extern void radeon_driver_lastclose(struct drm_device * dev);
-extern int radeon_driver_open(struct drm_device *dev,
-			      struct drm_file *file_priv);
-extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
-				unsigned long arg);
-
-extern int radeon_master_create(struct drm_device *dev, struct drm_master *master);
-extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master);
-extern void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master);
-/* r300_cmdbuf.c */
-extern void r300_init_reg_flags(struct drm_device *dev);
-
-extern int r300_do_cp_cmdbuf(struct drm_device *dev,
-			     struct drm_file *file_priv,
-			     drm_radeon_kcmd_buffer_t *cmdbuf);
-
-/* r600_cp.c */
-extern int r600_do_engine_reset(struct drm_device *dev);
-extern int r600_do_cleanup_cp(struct drm_device *dev);
-extern int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
-			   struct drm_file *file_priv);
-extern int r600_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv);
-extern int r600_do_cp_idle(drm_radeon_private_t *dev_priv);
-extern void r600_do_cp_start(drm_radeon_private_t *dev_priv);
-extern void r600_do_cp_reset(drm_radeon_private_t *dev_priv);
-extern void r600_do_cp_stop(drm_radeon_private_t *dev_priv);
-extern int r600_cp_dispatch_indirect(struct drm_device *dev,
-				     struct drm_buf *buf, int start, int end);
-extern int r600_page_table_init(struct drm_device *dev);
-extern void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info);
-extern int r600_cs_legacy_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv);
-extern void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv);
-extern int r600_cp_dispatch_texture(struct drm_device *dev,
-				    struct drm_file *file_priv,
-				    drm_radeon_texture_t *tex,
-				    drm_radeon_tex_image_t *image);
-/* r600_blit.c */
-extern int r600_prepare_blit_copy(struct drm_device *dev, struct drm_file *file_priv);
-extern void r600_done_blit_copy(struct drm_device *dev);
-extern void r600_blit_copy(struct drm_device *dev,
-			   uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
-			   int size_bytes);
-extern void r600_blit_swap(struct drm_device *dev,
-			   uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
-			   int sx, int sy, int dx, int dy,
-			   int w, int h, int src_pitch, int dst_pitch, int cpp);
-
-/* Flags for stats.boxes
- */
-#define RADEON_BOX_DMA_IDLE      0x1
-#define RADEON_BOX_RING_FULL     0x2
-#define RADEON_BOX_FLIP          0x4
-#define RADEON_BOX_WAIT_IDLE     0x8
-#define RADEON_BOX_TEXTURE_LOAD  0x10
-
-/* Register definitions, register access macros and drmAddMap constants
- * for Radeon kernel driver.
- */
-#define RADEON_MM_INDEX		        0x0000
-#define RADEON_MM_DATA		        0x0004
-
-#define RADEON_AGP_COMMAND		0x0f60
-#define RADEON_AGP_COMMAND_PCI_CONFIG   0x0060	/* offset in PCI config */
-#	define RADEON_AGP_ENABLE	(1<<8)
-#define RADEON_AUX_SCISSOR_CNTL		0x26f0
-#	define RADEON_EXCLUSIVE_SCISSOR_0	(1 << 24)
-#	define RADEON_EXCLUSIVE_SCISSOR_1	(1 << 25)
-#	define RADEON_EXCLUSIVE_SCISSOR_2	(1 << 26)
-#	define RADEON_SCISSOR_0_ENABLE		(1 << 28)
-#	define RADEON_SCISSOR_1_ENABLE		(1 << 29)
-#	define RADEON_SCISSOR_2_ENABLE		(1 << 30)
-
-/*
- * PCIE radeons (rv370/rv380, rv410, r423/r430/r480, r5xx)
- * don't have an explicit bus mastering disable bit.  It's handled
- * by the PCI D-states.  PMI_BM_DIS disables D-state bus master
- * handling, not bus mastering itself.
- */
-#define RADEON_BUS_CNTL			0x0030
-/* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */
-#	define RADEON_BUS_MASTER_DIS		(1 << 6)
-/* rs600/rs690/rs740 */
-#	define RS600_BUS_MASTER_DIS		(1 << 14)
-#	define RS600_MSI_REARM		        (1 << 20)
-/* see RS400_MSI_REARM in AIC_CNTL for rs480 */
-
-#define RADEON_BUS_CNTL1		0x0034
-#	define RADEON_PMI_BM_DIS		(1 << 2)
-#	define RADEON_PMI_INT_DIS		(1 << 3)
-
-#define RV370_BUS_CNTL			0x004c
-#	define RV370_PMI_BM_DIS		        (1 << 5)
-#	define RV370_PMI_INT_DIS		(1 << 6)
-
-#define RADEON_MSI_REARM_EN		0x0160
-/* rv370/rv380, rv410, r423/r430/r480, r5xx */
-#	define RV370_MSI_REARM_EN		(1 << 0)
-
-#define RADEON_CLOCK_CNTL_DATA		0x000c
-#	define RADEON_PLL_WR_EN			(1 << 7)
-#define RADEON_CLOCK_CNTL_INDEX		0x0008
-#define RADEON_CONFIG_APER_SIZE		0x0108
-#define RADEON_CONFIG_MEMSIZE		0x00f8
-#define RADEON_CRTC_OFFSET		0x0224
-#define RADEON_CRTC_OFFSET_CNTL		0x0228
-#	define RADEON_CRTC_TILE_EN		(1 << 15)
-#	define RADEON_CRTC_OFFSET_FLIP_CNTL	(1 << 16)
-#define RADEON_CRTC2_OFFSET		0x0324
-#define RADEON_CRTC2_OFFSET_CNTL	0x0328
-
-#define RADEON_PCIE_INDEX               0x0030
-#define RADEON_PCIE_DATA                0x0034
-#define RADEON_PCIE_TX_GART_CNTL	0x10
-#	define RADEON_PCIE_TX_GART_EN		(1 << 0)
-#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0 << 1)
-#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO  (1 << 1)
-#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD   (3 << 1)
-#	define RADEON_PCIE_TX_GART_MODE_32_128_CACHE	(0 << 3)
-#	define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE	(1 << 3)
-#	define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN      (1 << 5)
-#	define RADEON_PCIE_TX_GART_INVALIDATE_TLB	(1 << 8)
-#define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11
-#define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12
-#define RADEON_PCIE_TX_GART_BASE	0x13
-#define RADEON_PCIE_TX_GART_START_LO	0x14
-#define RADEON_PCIE_TX_GART_START_HI	0x15
-#define RADEON_PCIE_TX_GART_END_LO	0x16
-#define RADEON_PCIE_TX_GART_END_HI	0x17
-
-#define RS480_NB_MC_INDEX               0x168
-#	define RS480_NB_MC_IND_WR_EN	(1 << 8)
-#define RS480_NB_MC_DATA                0x16c
-
-#define RS690_MC_INDEX                  0x78
-#   define RS690_MC_INDEX_MASK          0x1ff
-#   define RS690_MC_INDEX_WR_EN         (1 << 9)
-#   define RS690_MC_INDEX_WR_ACK        0x7f
-#define RS690_MC_DATA                   0x7c
-
-/* MC indirect registers */
-#define RS480_MC_MISC_CNTL              0x18
-#	define RS480_DISABLE_GTW	(1 << 1)
-/* switch between MCIND GART and MM GART registers. 0 = mmgart, 1 = mcind gart */
-#	define RS480_GART_INDEX_REG_EN	(1 << 12)
-#	define RS690_BLOCK_GFX_D3_EN	(1 << 14)
-#define RS480_K8_FB_LOCATION            0x1e
-#define RS480_GART_FEATURE_ID           0x2b
-#	define RS480_HANG_EN	        (1 << 11)
-#	define RS480_TLB_ENABLE	        (1 << 18)
-#	define RS480_P2P_ENABLE	        (1 << 19)
-#	define RS480_GTW_LAC_EN	        (1 << 25)
-#	define RS480_2LEVEL_GART	(0 << 30)
-#	define RS480_1LEVEL_GART	(1 << 30)
-#	define RS480_PDC_EN	        (1 << 31)
-#define RS480_GART_BASE                 0x2c
-#define RS480_GART_CACHE_CNTRL          0x2e
-#	define RS480_GART_CACHE_INVALIDATE (1 << 0) /* wait for it to clear */
-#define RS480_AGP_ADDRESS_SPACE_SIZE    0x38
-#	define RS480_GART_EN	        (1 << 0)
-#	define RS480_VA_SIZE_32MB	(0 << 1)
-#	define RS480_VA_SIZE_64MB	(1 << 1)
-#	define RS480_VA_SIZE_128MB	(2 << 1)
-#	define RS480_VA_SIZE_256MB	(3 << 1)
-#	define RS480_VA_SIZE_512MB	(4 << 1)
-#	define RS480_VA_SIZE_1GB	(5 << 1)
-#	define RS480_VA_SIZE_2GB	(6 << 1)
-#define RS480_AGP_MODE_CNTL             0x39
-#	define RS480_POST_GART_Q_SIZE	(1 << 18)
-#	define RS480_NONGART_SNOOP	(1 << 19)
-#	define RS480_AGP_RD_BUF_SIZE	(1 << 20)
-#	define RS480_REQ_TYPE_SNOOP_SHIFT 22
-#	define RS480_REQ_TYPE_SNOOP_MASK  0x3
-#	define RS480_REQ_TYPE_SNOOP_DIS	(1 << 24)
-#define RS480_MC_MISC_UMA_CNTL          0x5f
-#define RS480_MC_MCLK_CNTL              0x7a
-#define RS480_MC_UMA_DUALCH_CNTL        0x86
-
-#define RS690_MC_FB_LOCATION            0x100
-#define RS690_MC_AGP_LOCATION           0x101
-#define RS690_MC_AGP_BASE               0x102
-#define RS690_MC_AGP_BASE_2             0x103
-
-#define RS600_MC_INDEX                          0x70
-#       define RS600_MC_ADDR_MASK               0xffff
-#       define RS600_MC_IND_SEQ_RBS_0           (1 << 16)
-#       define RS600_MC_IND_SEQ_RBS_1           (1 << 17)
-#       define RS600_MC_IND_SEQ_RBS_2           (1 << 18)
-#       define RS600_MC_IND_SEQ_RBS_3           (1 << 19)
-#       define RS600_MC_IND_AIC_RBS             (1 << 20)
-#       define RS600_MC_IND_CITF_ARB0           (1 << 21)
-#       define RS600_MC_IND_CITF_ARB1           (1 << 22)
-#       define RS600_MC_IND_WR_EN               (1 << 23)
-#define RS600_MC_DATA                           0x74
-
-#define RS600_MC_STATUS                         0x0
-#       define RS600_MC_IDLE                    (1 << 1)
-#define RS600_MC_FB_LOCATION                    0x4
-#define RS600_MC_AGP_LOCATION                   0x5
-#define RS600_AGP_BASE                          0x6
-#define RS600_AGP_BASE_2                        0x7
-#define RS600_MC_CNTL1                          0x9
-#       define RS600_ENABLE_PAGE_TABLES         (1 << 26)
-#define RS600_MC_PT0_CNTL                       0x100
-#       define RS600_ENABLE_PT                  (1 << 0)
-#       define RS600_EFFECTIVE_L2_CACHE_SIZE(x) ((x) << 15)
-#       define RS600_EFFECTIVE_L2_QUEUE_SIZE(x) ((x) << 21)
-#       define RS600_INVALIDATE_ALL_L1_TLBS     (1 << 28)
-#       define RS600_INVALIDATE_L2_CACHE        (1 << 29)
-#define RS600_MC_PT0_CONTEXT0_CNTL              0x102
-#       define RS600_ENABLE_PAGE_TABLE          (1 << 0)
-#       define RS600_PAGE_TABLE_TYPE_FLAT       (0 << 1)
-#define RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR   0x112
-#define RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR  0x114
-#define RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR 0x11c
-#define RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR    0x12c
-#define RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR   0x13c
-#define RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR     0x14c
-#define RS600_MC_PT0_CLIENT0_CNTL               0x16c
-#       define RS600_ENABLE_TRANSLATION_MODE_OVERRIDE       (1 << 0)
-#       define RS600_TRANSLATION_MODE_OVERRIDE              (1 << 1)
-#       define RS600_SYSTEM_ACCESS_MODE_MASK                (3 << 8)
-#       define RS600_SYSTEM_ACCESS_MODE_PA_ONLY             (0 << 8)
-#       define RS600_SYSTEM_ACCESS_MODE_USE_SYS_MAP         (1 << 8)
-#       define RS600_SYSTEM_ACCESS_MODE_IN_SYS              (2 << 8)
-#       define RS600_SYSTEM_ACCESS_MODE_NOT_IN_SYS          (3 << 8)
-#       define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH        (0 << 10)
-#       define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE       (1 << 10)
-#       define RS600_EFFECTIVE_L1_CACHE_SIZE(x) ((x) << 11)
-#       define RS600_ENABLE_FRAGMENT_PROCESSING (1 << 14)
-#       define RS600_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 15)
-#       define RS600_INVALIDATE_L1_TLB          (1 << 20)
-
-#define R520_MC_IND_INDEX 0x70
-#define R520_MC_IND_WR_EN (1 << 24)
-#define R520_MC_IND_DATA  0x74
-
-#define RV515_MC_FB_LOCATION 0x01
-#define RV515_MC_AGP_LOCATION 0x02
-#define RV515_MC_AGP_BASE     0x03
-#define RV515_MC_AGP_BASE_2   0x04
-
-#define R520_MC_FB_LOCATION 0x04
-#define R520_MC_AGP_LOCATION 0x05
-#define R520_MC_AGP_BASE     0x06
-#define R520_MC_AGP_BASE_2   0x07
-
-#define RADEON_MPP_TB_CONFIG		0x01c0
-#define RADEON_MEM_CNTL			0x0140
-#define RADEON_MEM_SDRAM_MODE_REG	0x0158
-#define RADEON_AGP_BASE_2		0x015c /* r200+ only */
-#define RS480_AGP_BASE_2		0x0164
-#define RADEON_AGP_BASE			0x0170
-
-/* pipe config regs */
-#define R400_GB_PIPE_SELECT             0x402c
-#define RV530_GB_PIPE_SELECT2           0x4124
-#define R500_DYN_SCLK_PWMEM_PIPE        0x000d /* PLL */
-#define R300_GB_TILE_CONFIG             0x4018
-#       define R300_ENABLE_TILING       (1 << 0)
-#       define R300_PIPE_COUNT_RV350    (0 << 1)
-#       define R300_PIPE_COUNT_R300     (3 << 1)
-#       define R300_PIPE_COUNT_R420_3P  (6 << 1)
-#       define R300_PIPE_COUNT_R420     (7 << 1)
-#       define R300_TILE_SIZE_8         (0 << 4)
-#       define R300_TILE_SIZE_16        (1 << 4)
-#       define R300_TILE_SIZE_32        (2 << 4)
-#       define R300_SUBPIXEL_1_12       (0 << 16)
-#       define R300_SUBPIXEL_1_16       (1 << 16)
-#define R300_DST_PIPE_CONFIG            0x170c
-#       define R300_PIPE_AUTO_CONFIG    (1 << 31)
-#define R300_RB2D_DSTCACHE_MODE         0x3428
-#       define R300_DC_AUTOFLUSH_ENABLE (1 << 8)
-#       define R300_DC_DC_DISABLE_IGNORE_PE (1 << 17)
-
-#define RADEON_RB3D_COLOROFFSET		0x1c40
-#define RADEON_RB3D_COLORPITCH		0x1c48
-
-#define	RADEON_SRC_X_Y			0x1590
-
-#define RADEON_DP_GUI_MASTER_CNTL	0x146c
-#	define RADEON_GMC_SRC_PITCH_OFFSET_CNTL	(1 << 0)
-#	define RADEON_GMC_DST_PITCH_OFFSET_CNTL	(1 << 1)
-#	define RADEON_GMC_BRUSH_SOLID_COLOR	(13 << 4)
-#	define RADEON_GMC_BRUSH_NONE		(15 << 4)
-#	define RADEON_GMC_DST_16BPP		(4 << 8)
-#	define RADEON_GMC_DST_24BPP		(5 << 8)
-#	define RADEON_GMC_DST_32BPP		(6 << 8)
-#	define RADEON_GMC_DST_DATATYPE_SHIFT	8
-#	define RADEON_GMC_SRC_DATATYPE_COLOR	(3 << 12)
-#	define RADEON_DP_SRC_SOURCE_MEMORY	(2 << 24)
-#	define RADEON_DP_SRC_SOURCE_HOST_DATA	(3 << 24)
-#	define RADEON_GMC_CLR_CMP_CNTL_DIS	(1 << 28)
-#	define RADEON_GMC_WR_MSK_DIS		(1 << 30)
-#	define RADEON_ROP3_S			0x00cc0000
-#	define RADEON_ROP3_P			0x00f00000
-#define RADEON_DP_WRITE_MASK		0x16cc
-#define RADEON_SRC_PITCH_OFFSET		0x1428
-#define RADEON_DST_PITCH_OFFSET		0x142c
-#define RADEON_DST_PITCH_OFFSET_C	0x1c80
-#	define RADEON_DST_TILE_LINEAR		(0 << 30)
-#	define RADEON_DST_TILE_MACRO		(1 << 30)
-#	define RADEON_DST_TILE_MICRO		(2 << 30)
-#	define RADEON_DST_TILE_BOTH		(3 << 30)
-
-#define RADEON_SCRATCH_REG0		0x15e0
-#define RADEON_SCRATCH_REG1		0x15e4
-#define RADEON_SCRATCH_REG2		0x15e8
-#define RADEON_SCRATCH_REG3		0x15ec
-#define RADEON_SCRATCH_REG4		0x15f0
-#define RADEON_SCRATCH_REG5		0x15f4
-#define RADEON_SCRATCH_UMSK		0x0770
-#define RADEON_SCRATCH_ADDR		0x0774
-
-#define RADEON_SCRATCHOFF( x )		(RADEON_SCRATCH_REG_OFFSET + 4*(x))
-
-extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index);
-
-#define GET_SCRATCH(dev_priv, x) radeon_get_scratch(dev_priv, x)
-
-#define R600_SCRATCH_REG0		0x8500
-#define R600_SCRATCH_REG1		0x8504
-#define R600_SCRATCH_REG2		0x8508
-#define R600_SCRATCH_REG3		0x850c
-#define R600_SCRATCH_REG4		0x8510
-#define R600_SCRATCH_REG5		0x8514
-#define R600_SCRATCH_REG6		0x8518
-#define R600_SCRATCH_REG7		0x851c
-#define R600_SCRATCH_UMSK		0x8540
-#define R600_SCRATCH_ADDR		0x8544
-
-#define R600_SCRATCHOFF(x)		(R600_SCRATCH_REG_OFFSET + 4*(x))
-
-#define RADEON_GEN_INT_CNTL		0x0040
-#	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
-#	define RADEON_CRTC2_VBLANK_MASK		(1 << 9)
-#	define RADEON_GUI_IDLE_INT_ENABLE	(1 << 19)
-#	define RADEON_SW_INT_ENABLE		(1 << 25)
-
-#define RADEON_GEN_INT_STATUS		0x0044
-#	define RADEON_CRTC_VBLANK_STAT		(1 << 0)
-#	define RADEON_CRTC_VBLANK_STAT_ACK	(1 << 0)
-#	define RADEON_CRTC2_VBLANK_STAT		(1 << 9)
-#	define RADEON_CRTC2_VBLANK_STAT_ACK	(1 << 9)
-#	define RADEON_GUI_IDLE_INT_TEST_ACK     (1 << 19)
-#	define RADEON_SW_INT_TEST		(1 << 25)
-#	define RADEON_SW_INT_TEST_ACK		(1 << 25)
-#	define RADEON_SW_INT_FIRE		(1 << 26)
-#       define R500_DISPLAY_INT_STATUS          (1 << 0)
-
-#define RADEON_HOST_PATH_CNTL		0x0130
-#	define RADEON_HDP_SOFT_RESET		(1 << 26)
-#	define RADEON_HDP_WC_TIMEOUT_MASK	(7 << 28)
-#	define RADEON_HDP_WC_TIMEOUT_28BCLK	(7 << 28)
-
-#define RADEON_ISYNC_CNTL		0x1724
-#	define RADEON_ISYNC_ANY2D_IDLE3D	(1 << 0)
-#	define RADEON_ISYNC_ANY3D_IDLE2D	(1 << 1)
-#	define RADEON_ISYNC_TRIG2D_IDLE3D	(1 << 2)
-#	define RADEON_ISYNC_TRIG3D_IDLE2D	(1 << 3)
-#	define RADEON_ISYNC_WAIT_IDLEGUI	(1 << 4)
-#	define RADEON_ISYNC_CPSCRATCH_IDLEGUI	(1 << 5)
-
-#define RADEON_RBBM_GUICNTL		0x172c
-#	define RADEON_HOST_DATA_SWAP_NONE	(0 << 0)
-#	define RADEON_HOST_DATA_SWAP_16BIT	(1 << 0)
-#	define RADEON_HOST_DATA_SWAP_32BIT	(2 << 0)
-#	define RADEON_HOST_DATA_SWAP_HDW	(3 << 0)
-
-#define RADEON_MC_AGP_LOCATION		0x014c
-#define RADEON_MC_FB_LOCATION		0x0148
-#define RADEON_MCLK_CNTL		0x0012
-#	define RADEON_FORCEON_MCLKA		(1 << 16)
-#	define RADEON_FORCEON_MCLKB		(1 << 17)
-#	define RADEON_FORCEON_YCLKA		(1 << 18)
-#	define RADEON_FORCEON_YCLKB		(1 << 19)
-#	define RADEON_FORCEON_MC		(1 << 20)
-#	define RADEON_FORCEON_AIC		(1 << 21)
-
-#define RADEON_PP_BORDER_COLOR_0	0x1d40
-#define RADEON_PP_BORDER_COLOR_1	0x1d44
-#define RADEON_PP_BORDER_COLOR_2	0x1d48
-#define RADEON_PP_CNTL			0x1c38
-#	define RADEON_SCISSOR_ENABLE		(1 <<  1)
-#define RADEON_PP_LUM_MATRIX		0x1d00
-#define RADEON_PP_MISC			0x1c14
-#define RADEON_PP_ROT_MATRIX_0		0x1d58
-#define RADEON_PP_TXFILTER_0		0x1c54
-#define RADEON_PP_TXOFFSET_0		0x1c5c
-#define RADEON_PP_TXFILTER_1		0x1c6c
-#define RADEON_PP_TXFILTER_2		0x1c84
-
-#define R300_RB2D_DSTCACHE_CTLSTAT	0x342c /* use R300_DSTCACHE_CTLSTAT */
-#define R300_DSTCACHE_CTLSTAT		0x1714
-#	define R300_RB2D_DC_FLUSH		(3 << 0)
-#	define R300_RB2D_DC_FREE		(3 << 2)
-#	define R300_RB2D_DC_FLUSH_ALL		0xf
-#	define R300_RB2D_DC_BUSY		(1 << 31)
-#define RADEON_RB3D_CNTL		0x1c3c
-#	define RADEON_ALPHA_BLEND_ENABLE	(1 << 0)
-#	define RADEON_PLANE_MASK_ENABLE		(1 << 1)
-#	define RADEON_DITHER_ENABLE		(1 << 2)
-#	define RADEON_ROUND_ENABLE		(1 << 3)
-#	define RADEON_SCALE_DITHER_ENABLE	(1 << 4)
-#	define RADEON_DITHER_INIT		(1 << 5)
-#	define RADEON_ROP_ENABLE		(1 << 6)
-#	define RADEON_STENCIL_ENABLE		(1 << 7)
-#	define RADEON_Z_ENABLE			(1 << 8)
-#	define RADEON_ZBLOCK16			(1 << 15)
-#define RADEON_RB3D_DEPTHOFFSET		0x1c24
-#define RADEON_RB3D_DEPTHCLEARVALUE	0x3230
-#define RADEON_RB3D_DEPTHPITCH		0x1c28
-#define RADEON_RB3D_PLANEMASK		0x1d84
-#define RADEON_RB3D_STENCILREFMASK	0x1d7c
-#define RADEON_RB3D_ZCACHE_MODE		0x3250
-#define RADEON_RB3D_ZCACHE_CTLSTAT	0x3254
-#	define RADEON_RB3D_ZC_FLUSH		(1 << 0)
-#	define RADEON_RB3D_ZC_FREE		(1 << 2)
-#	define RADEON_RB3D_ZC_FLUSH_ALL		0x5
-#	define RADEON_RB3D_ZC_BUSY		(1 << 31)
-#define R300_ZB_ZCACHE_CTLSTAT                  0x4f18
-#	define R300_ZC_FLUSH		        (1 << 0)
-#	define R300_ZC_FREE		        (1 << 1)
-#	define R300_ZC_BUSY		        (1 << 31)
-#define RADEON_RB3D_DSTCACHE_CTLSTAT	0x325c
-#	define RADEON_RB3D_DC_FLUSH		(3 << 0)
-#	define RADEON_RB3D_DC_FREE		(3 << 2)
-#	define RADEON_RB3D_DC_FLUSH_ALL		0xf
-#	define RADEON_RB3D_DC_BUSY		(1 << 31)
-#define R300_RB3D_DSTCACHE_CTLSTAT              0x4e4c
-#	define R300_RB3D_DC_FLUSH		(2 << 0)
-#	define R300_RB3D_DC_FREE		(2 << 2)
-#	define R300_RB3D_DC_FINISH		(1 << 4)
-#define RADEON_RB3D_ZSTENCILCNTL	0x1c2c
-#	define RADEON_Z_TEST_MASK		(7 << 4)
-#	define RADEON_Z_TEST_ALWAYS		(7 << 4)
-#	define RADEON_Z_HIERARCHY_ENABLE	(1 << 8)
-#	define RADEON_STENCIL_TEST_ALWAYS	(7 << 12)
-#	define RADEON_STENCIL_S_FAIL_REPLACE	(2 << 16)
-#	define RADEON_STENCIL_ZPASS_REPLACE	(2 << 20)
-#	define RADEON_STENCIL_ZFAIL_REPLACE	(2 << 24)
-#	define RADEON_Z_COMPRESSION_ENABLE	(1 << 28)
-#	define RADEON_FORCE_Z_DIRTY		(1 << 29)
-#	define RADEON_Z_WRITE_ENABLE		(1 << 30)
-#	define RADEON_Z_DECOMPRESSION_ENABLE	(1 << 31)
-#define RADEON_RBBM_SOFT_RESET		0x00f0
-#	define RADEON_SOFT_RESET_CP		(1 <<  0)
-#	define RADEON_SOFT_RESET_HI		(1 <<  1)
-#	define RADEON_SOFT_RESET_SE		(1 <<  2)
-#	define RADEON_SOFT_RESET_RE		(1 <<  3)
-#	define RADEON_SOFT_RESET_PP		(1 <<  4)
-#	define RADEON_SOFT_RESET_E2		(1 <<  5)
-#	define RADEON_SOFT_RESET_RB		(1 <<  6)
-#	define RADEON_SOFT_RESET_HDP		(1 <<  7)
-/*
- *   6:0  Available slots in the FIFO
- *   8    Host Interface active
- *   9    CP request active
- *   10   FIFO request active
- *   11   Host Interface retry active
- *   12   CP retry active
- *   13   FIFO retry active
- *   14   FIFO pipeline busy
- *   15   Event engine busy
- *   16   CP command stream busy
- *   17   2D engine busy
- *   18   2D portion of render backend busy
- *   20   3D setup engine busy
- *   26   GA engine busy
- *   27   CBA 2D engine busy
- *   31   2D engine busy or 3D engine busy or FIFO not empty or CP busy or
- *           command stream queue not empty or Ring Buffer not empty
- */
-#define RADEON_RBBM_STATUS		0x0e40
-/* Same as the previous RADEON_RBBM_STATUS; this is a mirror of that register.  */
-/* #define RADEON_RBBM_STATUS		0x1740 */
-/* bits 6:0 are dword slots available in the cmd fifo */
-#	define RADEON_RBBM_FIFOCNT_MASK		0x007f
-#	define RADEON_HIRQ_ON_RBB	(1 <<  8)
-#	define RADEON_CPRQ_ON_RBB	(1 <<  9)
-#	define RADEON_CFRQ_ON_RBB	(1 << 10)
-#	define RADEON_HIRQ_IN_RTBUF	(1 << 11)
-#	define RADEON_CPRQ_IN_RTBUF	(1 << 12)
-#	define RADEON_CFRQ_IN_RTBUF	(1 << 13)
-#	define RADEON_PIPE_BUSY		(1 << 14)
-#	define RADEON_ENG_EV_BUSY	(1 << 15)
-#	define RADEON_CP_CMDSTRM_BUSY	(1 << 16)
-#	define RADEON_E2_BUSY		(1 << 17)
-#	define RADEON_RB2D_BUSY		(1 << 18)
-#	define RADEON_RB3D_BUSY		(1 << 19) /* not used on r300 */
-#	define RADEON_VAP_BUSY		(1 << 20)
-#	define RADEON_RE_BUSY		(1 << 21) /* not used on r300 */
-#	define RADEON_TAM_BUSY		(1 << 22) /* not used on r300 */
-#	define RADEON_TDM_BUSY		(1 << 23) /* not used on r300 */
-#	define RADEON_PB_BUSY		(1 << 24) /* not used on r300 */
-#	define RADEON_TIM_BUSY		(1 << 25) /* not used on r300 */
-#	define RADEON_GA_BUSY		(1 << 26)
-#	define RADEON_CBA2D_BUSY	(1 << 27)
-#	define RADEON_RBBM_ACTIVE	(1 << 31)
-#define RADEON_RE_LINE_PATTERN		0x1cd0
-#define RADEON_RE_MISC			0x26c4
-#define RADEON_RE_TOP_LEFT		0x26c0
-#define RADEON_RE_WIDTH_HEIGHT		0x1c44
-#define RADEON_RE_STIPPLE_ADDR		0x1cc8
-#define RADEON_RE_STIPPLE_DATA		0x1ccc
-
-#define RADEON_SCISSOR_TL_0		0x1cd8
-#define RADEON_SCISSOR_BR_0		0x1cdc
-#define RADEON_SCISSOR_TL_1		0x1ce0
-#define RADEON_SCISSOR_BR_1		0x1ce4
-#define RADEON_SCISSOR_TL_2		0x1ce8
-#define RADEON_SCISSOR_BR_2		0x1cec
-#define RADEON_SE_COORD_FMT		0x1c50
-#define RADEON_SE_CNTL			0x1c4c
-#	define RADEON_FFACE_CULL_CW		(0 << 0)
-#	define RADEON_BFACE_SOLID		(3 << 1)
-#	define RADEON_FFACE_SOLID		(3 << 3)
-#	define RADEON_FLAT_SHADE_VTX_LAST	(3 << 6)
-#	define RADEON_DIFFUSE_SHADE_FLAT	(1 << 8)
-#	define RADEON_DIFFUSE_SHADE_GOURAUD	(2 << 8)
-#	define RADEON_ALPHA_SHADE_FLAT		(1 << 10)
-#	define RADEON_ALPHA_SHADE_GOURAUD	(2 << 10)
-#	define RADEON_SPECULAR_SHADE_FLAT	(1 << 12)
-#	define RADEON_SPECULAR_SHADE_GOURAUD	(2 << 12)
-#	define RADEON_FOG_SHADE_FLAT		(1 << 14)
-#	define RADEON_FOG_SHADE_GOURAUD		(2 << 14)
-#	define RADEON_VPORT_XY_XFORM_ENABLE	(1 << 24)
-#	define RADEON_VPORT_Z_XFORM_ENABLE	(1 << 25)
-#	define RADEON_VTX_PIX_CENTER_OGL	(1 << 27)
-#	define RADEON_ROUND_MODE_TRUNC		(0 << 28)
-#	define RADEON_ROUND_PREC_8TH_PIX	(1 << 30)
-#define RADEON_SE_CNTL_STATUS		0x2140
-#define RADEON_SE_LINE_WIDTH		0x1db8
-#define RADEON_SE_VPORT_XSCALE		0x1d98
-#define RADEON_SE_ZBIAS_FACTOR		0x1db0
-#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210
-#define RADEON_SE_TCL_OUTPUT_VTX_FMT         0x2254
-#define RADEON_SE_TCL_VECTOR_INDX_REG        0x2200
-#       define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT  16
-#       define RADEON_VEC_INDX_DWORD_COUNT_SHIFT     28
-#define RADEON_SE_TCL_VECTOR_DATA_REG       0x2204
-#define RADEON_SE_TCL_SCALAR_INDX_REG       0x2208
-#       define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT  16
-#define RADEON_SE_TCL_SCALAR_DATA_REG       0x220C
-#define RADEON_SURFACE_ACCESS_FLAGS	0x0bf8
-#define RADEON_SURFACE_ACCESS_CLR	0x0bfc
-#define RADEON_SURFACE_CNTL		0x0b00
-#	define RADEON_SURF_TRANSLATION_DIS	(1 << 8)
-#	define RADEON_NONSURF_AP0_SWP_MASK	(3 << 20)
-#	define RADEON_NONSURF_AP0_SWP_LITTLE	(0 << 20)
-#	define RADEON_NONSURF_AP0_SWP_BIG16	(1 << 20)
-#	define RADEON_NONSURF_AP0_SWP_BIG32	(2 << 20)
-#	define RADEON_NONSURF_AP1_SWP_MASK	(3 << 22)
-#	define RADEON_NONSURF_AP1_SWP_LITTLE	(0 << 22)
-#	define RADEON_NONSURF_AP1_SWP_BIG16	(1 << 22)
-#	define RADEON_NONSURF_AP1_SWP_BIG32	(2 << 22)
-#define RADEON_SURFACE0_INFO		0x0b0c
-#	define RADEON_SURF_PITCHSEL_MASK	(0x1ff << 0)
-#	define RADEON_SURF_TILE_MODE_MASK	(3 << 16)
-#	define RADEON_SURF_TILE_MODE_MACRO	(0 << 16)
-#	define RADEON_SURF_TILE_MODE_MICRO	(1 << 16)
-#	define RADEON_SURF_TILE_MODE_32BIT_Z	(2 << 16)
-#	define RADEON_SURF_TILE_MODE_16BIT_Z	(3 << 16)
-#define RADEON_SURFACE0_LOWER_BOUND	0x0b04
-#define RADEON_SURFACE0_UPPER_BOUND	0x0b08
-#	define RADEON_SURF_ADDRESS_FIXED_MASK	(0x3ff << 0)
-#define RADEON_SURFACE1_INFO		0x0b1c
-#define RADEON_SURFACE1_LOWER_BOUND	0x0b14
-#define RADEON_SURFACE1_UPPER_BOUND	0x0b18
-#define RADEON_SURFACE2_INFO		0x0b2c
-#define RADEON_SURFACE2_LOWER_BOUND	0x0b24
-#define RADEON_SURFACE2_UPPER_BOUND	0x0b28
-#define RADEON_SURFACE3_INFO		0x0b3c
-#define RADEON_SURFACE3_LOWER_BOUND	0x0b34
-#define RADEON_SURFACE3_UPPER_BOUND	0x0b38
-#define RADEON_SURFACE4_INFO		0x0b4c
-#define RADEON_SURFACE4_LOWER_BOUND	0x0b44
-#define RADEON_SURFACE4_UPPER_BOUND	0x0b48
-#define RADEON_SURFACE5_INFO		0x0b5c
-#define RADEON_SURFACE5_LOWER_BOUND	0x0b54
-#define RADEON_SURFACE5_UPPER_BOUND	0x0b58
-#define RADEON_SURFACE6_INFO		0x0b6c
-#define RADEON_SURFACE6_LOWER_BOUND	0x0b64
-#define RADEON_SURFACE6_UPPER_BOUND	0x0b68
-#define RADEON_SURFACE7_INFO		0x0b7c
-#define RADEON_SURFACE7_LOWER_BOUND	0x0b74
-#define RADEON_SURFACE7_UPPER_BOUND	0x0b78
-#define RADEON_SW_SEMAPHORE		0x013c
-
-#define RADEON_WAIT_UNTIL		0x1720
-#	define RADEON_WAIT_CRTC_PFLIP		(1 << 0)
-#	define RADEON_WAIT_2D_IDLE		(1 << 14)
-#	define RADEON_WAIT_3D_IDLE		(1 << 15)
-#	define RADEON_WAIT_2D_IDLECLEAN		(1 << 16)
-#	define RADEON_WAIT_3D_IDLECLEAN		(1 << 17)
-#	define RADEON_WAIT_HOST_IDLECLEAN	(1 << 18)
-
-#define RADEON_RB3D_ZMASKOFFSET		0x3234
-#define RADEON_RB3D_ZSTENCILCNTL	0x1c2c
-#	define RADEON_DEPTH_FORMAT_16BIT_INT_Z	(0 << 0)
-#	define RADEON_DEPTH_FORMAT_24BIT_INT_Z	(2 << 0)
-
-/* CP registers */
-#define RADEON_CP_ME_RAM_ADDR		0x07d4
-#define RADEON_CP_ME_RAM_RADDR		0x07d8
-#define RADEON_CP_ME_RAM_DATAH		0x07dc
-#define RADEON_CP_ME_RAM_DATAL		0x07e0
-
-#define RADEON_CP_RB_BASE		0x0700
-#define RADEON_CP_RB_CNTL		0x0704
-#	define RADEON_BUF_SWAP_32BIT		(2 << 16)
-#	define RADEON_RB_NO_UPDATE		(1 << 27)
-#	define RADEON_RB_RPTR_WR_ENA		(1 << 31)
-#define RADEON_CP_RB_RPTR_ADDR		0x070c
-#define RADEON_CP_RB_RPTR		0x0710
-#define RADEON_CP_RB_WPTR		0x0714
-
-#define RADEON_CP_RB_WPTR_DELAY		0x0718
-#	define RADEON_PRE_WRITE_TIMER_SHIFT	0
-#	define RADEON_PRE_WRITE_LIMIT_SHIFT	23
-
-#define RADEON_CP_IB_BASE		0x0738
-
-#define RADEON_CP_CSQ_CNTL		0x0740
-#	define RADEON_CSQ_CNT_PRIMARY_MASK	(0xff << 0)
-#	define RADEON_CSQ_PRIDIS_INDDIS		(0 << 28)
-#	define RADEON_CSQ_PRIPIO_INDDIS		(1 << 28)
-#	define RADEON_CSQ_PRIBM_INDDIS		(2 << 28)
-#	define RADEON_CSQ_PRIPIO_INDBM		(3 << 28)
-#	define RADEON_CSQ_PRIBM_INDBM		(4 << 28)
-#	define RADEON_CSQ_PRIPIO_INDPIO		(15 << 28)
-
-#define R300_CP_RESYNC_ADDR		0x0778
-#define R300_CP_RESYNC_DATA		0x077c
-
-#define RADEON_AIC_CNTL			0x01d0
-#	define RADEON_PCIGART_TRANSLATE_EN	(1 << 0)
-#	define RS400_MSI_REARM	                (1 << 3)
-#define RADEON_AIC_STAT			0x01d4
-#define RADEON_AIC_PT_BASE		0x01d8
-#define RADEON_AIC_LO_ADDR		0x01dc
-#define RADEON_AIC_HI_ADDR		0x01e0
-#define RADEON_AIC_TLB_ADDR		0x01e4
-#define RADEON_AIC_TLB_DATA		0x01e8
-
-/* CP command packets */
-#define RADEON_CP_PACKET0		0x00000000
-#	define RADEON_ONE_REG_WR		(1 << 15)
-#define RADEON_CP_PACKET1		0x40000000
-#define RADEON_CP_PACKET2		0x80000000
-#define RADEON_CP_PACKET3		0xC0000000
-#       define RADEON_CP_NOP                    0x00001000
-#       define RADEON_CP_NEXT_CHAR              0x00001900
-#       define RADEON_CP_PLY_NEXTSCAN           0x00001D00
-#       define RADEON_CP_SET_SCISSORS           0x00001E00
-	     /* GEN_INDX_PRIM is unsupported starting with R300 */
-#	define RADEON_3D_RNDR_GEN_INDX_PRIM	0x00002300
-#	define RADEON_WAIT_FOR_IDLE		0x00002600
-#	define RADEON_3D_DRAW_VBUF		0x00002800
-#	define RADEON_3D_DRAW_IMMD		0x00002900
-#	define RADEON_3D_DRAW_INDX		0x00002A00
-#       define RADEON_CP_LOAD_PALETTE           0x00002C00
-#	define RADEON_3D_LOAD_VBPNTR		0x00002F00
-#	define RADEON_MPEG_IDCT_MACROBLOCK	0x00003000
-#	define RADEON_MPEG_IDCT_MACROBLOCK_REV	0x00003100
-#	define RADEON_3D_CLEAR_ZMASK		0x00003200
-#	define RADEON_CP_INDX_BUFFER		0x00003300
-#       define RADEON_CP_3D_DRAW_VBUF_2         0x00003400
-#       define RADEON_CP_3D_DRAW_IMMD_2         0x00003500
-#       define RADEON_CP_3D_DRAW_INDX_2         0x00003600
-#	define RADEON_3D_CLEAR_HIZ		0x00003700
-#       define RADEON_CP_3D_CLEAR_CMASK         0x00003802
-#	define RADEON_CNTL_HOSTDATA_BLT		0x00009400
-#	define RADEON_CNTL_PAINT_MULTI		0x00009A00
-#	define RADEON_CNTL_BITBLT_MULTI		0x00009B00
-#	define RADEON_CNTL_SET_SCISSORS		0xC0001E00
-
-#       define R600_IT_INDIRECT_BUFFER_END      0x00001700
-#       define R600_IT_SET_PREDICATION          0x00002000
-#       define R600_IT_REG_RMW                  0x00002100
-#       define R600_IT_COND_EXEC                0x00002200
-#       define R600_IT_PRED_EXEC                0x00002300
-#       define R600_IT_START_3D_CMDBUF          0x00002400
-#       define R600_IT_DRAW_INDEX_2             0x00002700
-#       define R600_IT_CONTEXT_CONTROL          0x00002800
-#       define R600_IT_DRAW_INDEX_IMMD_BE       0x00002900
-#       define R600_IT_INDEX_TYPE               0x00002A00
-#       define R600_IT_DRAW_INDEX               0x00002B00
-#       define R600_IT_DRAW_INDEX_AUTO          0x00002D00
-#       define R600_IT_DRAW_INDEX_IMMD          0x00002E00
-#       define R600_IT_NUM_INSTANCES            0x00002F00
-#       define R600_IT_STRMOUT_BUFFER_UPDATE    0x00003400
-#       define R600_IT_INDIRECT_BUFFER_MP       0x00003800
-#       define R600_IT_MEM_SEMAPHORE            0x00003900
-#       define R600_IT_MPEG_INDEX               0x00003A00
-#       define R600_IT_WAIT_REG_MEM             0x00003C00
-#       define R600_IT_MEM_WRITE                0x00003D00
-#       define R600_IT_INDIRECT_BUFFER          0x00003200
-#       define R600_IT_SURFACE_SYNC             0x00004300
-#              define R600_CB0_DEST_BASE_ENA    (1 << 6)
-#              define R600_TC_ACTION_ENA        (1 << 23)
-#              define R600_VC_ACTION_ENA        (1 << 24)
-#              define R600_CB_ACTION_ENA        (1 << 25)
-#              define R600_DB_ACTION_ENA        (1 << 26)
-#              define R600_SH_ACTION_ENA        (1 << 27)
-#              define R600_SMX_ACTION_ENA       (1 << 28)
-#       define R600_IT_ME_INITIALIZE            0x00004400
-#	       define R600_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
-#       define R600_IT_COND_WRITE               0x00004500
-#       define R600_IT_EVENT_WRITE              0x00004600
-#       define R600_IT_EVENT_WRITE_EOP          0x00004700
-#       define R600_IT_ONE_REG_WRITE            0x00005700
-#       define R600_IT_SET_CONFIG_REG           0x00006800
-#              define R600_SET_CONFIG_REG_OFFSET 0x00008000
-#              define R600_SET_CONFIG_REG_END   0x0000ac00
-#       define R600_IT_SET_CONTEXT_REG          0x00006900
-#              define R600_SET_CONTEXT_REG_OFFSET 0x00028000
-#              define R600_SET_CONTEXT_REG_END  0x00029000
-#       define R600_IT_SET_ALU_CONST            0x00006A00
-#              define R600_SET_ALU_CONST_OFFSET 0x00030000
-#              define R600_SET_ALU_CONST_END    0x00032000
-#       define R600_IT_SET_BOOL_CONST           0x00006B00
-#              define R600_SET_BOOL_CONST_OFFSET 0x0003e380
-#              define R600_SET_BOOL_CONST_END   0x00040000
-#       define R600_IT_SET_LOOP_CONST           0x00006C00
-#              define R600_SET_LOOP_CONST_OFFSET 0x0003e200
-#              define R600_SET_LOOP_CONST_END   0x0003e380
-#       define R600_IT_SET_RESOURCE             0x00006D00
-#              define R600_SET_RESOURCE_OFFSET  0x00038000
-#              define R600_SET_RESOURCE_END     0x0003c000
-#              define R600_SQ_TEX_VTX_INVALID_TEXTURE  0x0
-#              define R600_SQ_TEX_VTX_INVALID_BUFFER   0x1
-#              define R600_SQ_TEX_VTX_VALID_TEXTURE    0x2
-#              define R600_SQ_TEX_VTX_VALID_BUFFER     0x3
-#       define R600_IT_SET_SAMPLER              0x00006E00
-#              define R600_SET_SAMPLER_OFFSET   0x0003c000
-#              define R600_SET_SAMPLER_END      0x0003cff0
-#       define R600_IT_SET_CTL_CONST            0x00006F00
-#              define R600_SET_CTL_CONST_OFFSET 0x0003cff0
-#              define R600_SET_CTL_CONST_END    0x0003e200
-#       define R600_IT_SURFACE_BASE_UPDATE      0x00007300
-
-#define RADEON_CP_PACKET_MASK		0xC0000000
-#define RADEON_CP_PACKET_COUNT_MASK	0x3fff0000
-#define RADEON_CP_PACKET0_REG_MASK	0x000007ff
-#define RADEON_CP_PACKET1_REG0_MASK	0x000007ff
-#define RADEON_CP_PACKET1_REG1_MASK	0x003ff800
-
-#define RADEON_VTX_Z_PRESENT			(1 << 31)
-#define RADEON_VTX_PKCOLOR_PRESENT		(1 << 3)
-
-#define RADEON_PRIM_TYPE_NONE			(0 << 0)
-#define RADEON_PRIM_TYPE_POINT			(1 << 0)
-#define RADEON_PRIM_TYPE_LINE			(2 << 0)
-#define RADEON_PRIM_TYPE_LINE_STRIP		(3 << 0)
-#define RADEON_PRIM_TYPE_TRI_LIST		(4 << 0)
-#define RADEON_PRIM_TYPE_TRI_FAN		(5 << 0)
-#define RADEON_PRIM_TYPE_TRI_STRIP		(6 << 0)
-#define RADEON_PRIM_TYPE_TRI_TYPE2		(7 << 0)
-#define RADEON_PRIM_TYPE_RECT_LIST		(8 << 0)
-#define RADEON_PRIM_TYPE_3VRT_POINT_LIST	(9 << 0)
-#define RADEON_PRIM_TYPE_3VRT_LINE_LIST		(10 << 0)
-#define RADEON_PRIM_TYPE_MASK                   0xf
-#define RADEON_PRIM_WALK_IND			(1 << 4)
-#define RADEON_PRIM_WALK_LIST			(2 << 4)
-#define RADEON_PRIM_WALK_RING			(3 << 4)
-#define RADEON_COLOR_ORDER_BGRA			(0 << 6)
-#define RADEON_COLOR_ORDER_RGBA			(1 << 6)
-#define RADEON_MAOS_ENABLE			(1 << 7)
-#define RADEON_VTX_FMT_R128_MODE		(0 << 8)
-#define RADEON_VTX_FMT_RADEON_MODE		(1 << 8)
-#define RADEON_NUM_VERTICES_SHIFT		16
-
-#define RADEON_COLOR_FORMAT_CI8		2
-#define RADEON_COLOR_FORMAT_ARGB1555	3
-#define RADEON_COLOR_FORMAT_RGB565	4
-#define RADEON_COLOR_FORMAT_ARGB8888	6
-#define RADEON_COLOR_FORMAT_RGB332	7
-#define RADEON_COLOR_FORMAT_RGB8	9
-#define RADEON_COLOR_FORMAT_ARGB4444	15
-
-#define RADEON_TXFORMAT_I8		0
-#define RADEON_TXFORMAT_AI88		1
-#define RADEON_TXFORMAT_RGB332		2
-#define RADEON_TXFORMAT_ARGB1555	3
-#define RADEON_TXFORMAT_RGB565		4
-#define RADEON_TXFORMAT_ARGB4444	5
-#define RADEON_TXFORMAT_ARGB8888	6
-#define RADEON_TXFORMAT_RGBA8888	7
-#define RADEON_TXFORMAT_Y8		8
-#define RADEON_TXFORMAT_VYUY422         10
-#define RADEON_TXFORMAT_YVYU422         11
-#define RADEON_TXFORMAT_DXT1            12
-#define RADEON_TXFORMAT_DXT23           14
-#define RADEON_TXFORMAT_DXT45           15
-
-#define R200_PP_TXCBLEND_0                0x2f00
-#define R200_PP_TXCBLEND_1                0x2f10
-#define R200_PP_TXCBLEND_2                0x2f20
-#define R200_PP_TXCBLEND_3                0x2f30
-#define R200_PP_TXCBLEND_4                0x2f40
-#define R200_PP_TXCBLEND_5                0x2f50
-#define R200_PP_TXCBLEND_6                0x2f60
-#define R200_PP_TXCBLEND_7                0x2f70
-#define R200_SE_TCL_LIGHT_MODEL_CTL_0     0x2268
-#define R200_PP_TFACTOR_0                 0x2ee0
-#define R200_SE_VTX_FMT_0                 0x2088
-#define R200_SE_VAP_CNTL                  0x2080
-#define R200_SE_TCL_MATRIX_SEL_0          0x2230
-#define R200_SE_TCL_TEX_PROC_CTL_2        0x22a8
-#define R200_SE_TCL_UCP_VERT_BLEND_CTL    0x22c0
-#define R200_PP_TXFILTER_5                0x2ca0
-#define R200_PP_TXFILTER_4                0x2c80
-#define R200_PP_TXFILTER_3                0x2c60
-#define R200_PP_TXFILTER_2                0x2c40
-#define R200_PP_TXFILTER_1                0x2c20
-#define R200_PP_TXFILTER_0                0x2c00
-#define R200_PP_TXOFFSET_5                0x2d78
-#define R200_PP_TXOFFSET_4                0x2d60
-#define R200_PP_TXOFFSET_3                0x2d48
-#define R200_PP_TXOFFSET_2                0x2d30
-#define R200_PP_TXOFFSET_1                0x2d18
-#define R200_PP_TXOFFSET_0                0x2d00
-
-#define R200_PP_CUBIC_FACES_0             0x2c18
-#define R200_PP_CUBIC_FACES_1             0x2c38
-#define R200_PP_CUBIC_FACES_2             0x2c58
-#define R200_PP_CUBIC_FACES_3             0x2c78
-#define R200_PP_CUBIC_FACES_4             0x2c98
-#define R200_PP_CUBIC_FACES_5             0x2cb8
-#define R200_PP_CUBIC_OFFSET_F1_0         0x2d04
-#define R200_PP_CUBIC_OFFSET_F2_0         0x2d08
-#define R200_PP_CUBIC_OFFSET_F3_0         0x2d0c
-#define R200_PP_CUBIC_OFFSET_F4_0         0x2d10
-#define R200_PP_CUBIC_OFFSET_F5_0         0x2d14
-#define R200_PP_CUBIC_OFFSET_F1_1         0x2d1c
-#define R200_PP_CUBIC_OFFSET_F2_1         0x2d20
-#define R200_PP_CUBIC_OFFSET_F3_1         0x2d24
-#define R200_PP_CUBIC_OFFSET_F4_1         0x2d28
-#define R200_PP_CUBIC_OFFSET_F5_1         0x2d2c
-#define R200_PP_CUBIC_OFFSET_F1_2         0x2d34
-#define R200_PP_CUBIC_OFFSET_F2_2         0x2d38
-#define R200_PP_CUBIC_OFFSET_F3_2         0x2d3c
-#define R200_PP_CUBIC_OFFSET_F4_2         0x2d40
-#define R200_PP_CUBIC_OFFSET_F5_2         0x2d44
-#define R200_PP_CUBIC_OFFSET_F1_3         0x2d4c
-#define R200_PP_CUBIC_OFFSET_F2_3         0x2d50
-#define R200_PP_CUBIC_OFFSET_F3_3         0x2d54
-#define R200_PP_CUBIC_OFFSET_F4_3         0x2d58
-#define R200_PP_CUBIC_OFFSET_F5_3         0x2d5c
-#define R200_PP_CUBIC_OFFSET_F1_4         0x2d64
-#define R200_PP_CUBIC_OFFSET_F2_4         0x2d68
-#define R200_PP_CUBIC_OFFSET_F3_4         0x2d6c
-#define R200_PP_CUBIC_OFFSET_F4_4         0x2d70
-#define R200_PP_CUBIC_OFFSET_F5_4         0x2d74
-#define R200_PP_CUBIC_OFFSET_F1_5         0x2d7c
-#define R200_PP_CUBIC_OFFSET_F2_5         0x2d80
-#define R200_PP_CUBIC_OFFSET_F3_5         0x2d84
-#define R200_PP_CUBIC_OFFSET_F4_5         0x2d88
-#define R200_PP_CUBIC_OFFSET_F5_5         0x2d8c
-
-#define R200_RE_AUX_SCISSOR_CNTL          0x26f0
-#define R200_SE_VTE_CNTL                  0x20b0
-#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL   0x2250
-#define R200_PP_TAM_DEBUG3                0x2d9c
-#define R200_PP_CNTL_X                    0x2cc4
-#define R200_SE_VAP_CNTL_STATUS           0x2140
-#define R200_RE_SCISSOR_TL_0              0x1cd8
-#define R200_RE_SCISSOR_TL_1              0x1ce0
-#define R200_RE_SCISSOR_TL_2              0x1ce8
-#define R200_RB3D_DEPTHXY_OFFSET          0x1d60
-#define R200_RE_AUX_SCISSOR_CNTL          0x26f0
-#define R200_SE_VTX_STATE_CNTL            0x2180
-#define R200_RE_POINTSIZE                 0x2648
-#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
-
-#define RADEON_PP_TEX_SIZE_0                0x1d04	/* NPOT */
-#define RADEON_PP_TEX_SIZE_1                0x1d0c
-#define RADEON_PP_TEX_SIZE_2                0x1d14
-
-#define RADEON_PP_CUBIC_FACES_0             0x1d24
-#define RADEON_PP_CUBIC_FACES_1             0x1d28
-#define RADEON_PP_CUBIC_FACES_2             0x1d2c
-#define RADEON_PP_CUBIC_OFFSET_T0_0         0x1dd0	/* bits [31:5] */
-#define RADEON_PP_CUBIC_OFFSET_T1_0         0x1e00
-#define RADEON_PP_CUBIC_OFFSET_T2_0         0x1e14
-
-#define RADEON_SE_TCL_STATE_FLUSH           0x2284
-
-#define SE_VAP_CNTL__TCL_ENA_MASK                          0x00000001
-#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK                   0x00010000
-#define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT                 0x00000012
-#define SE_VTE_CNTL__VTX_XY_FMT_MASK                       0x00000100
-#define SE_VTE_CNTL__VTX_Z_FMT_MASK                        0x00000200
-#define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK                  0x00000001
-#define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK                  0x00000002
-#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT               0x0000000b
-#define R200_3D_DRAW_IMMD_2      0xC0003500
-#define R200_SE_VTX_FMT_1                 0x208c
-#define R200_RE_CNTL                      0x1c50
-
-#define R200_RB3D_BLENDCOLOR              0x3218
-
-#define R200_SE_TCL_POINT_SPRITE_CNTL     0x22c4
-
-#define R200_PP_TRI_PERF 0x2cf8
-
-#define R200_PP_AFS_0                     0x2f80
-#define R200_PP_AFS_1                     0x2f00	/* same as txcblend_0 */
-
-#define R200_VAP_PVS_CNTL_1               0x22D0
-
-#define RADEON_CRTC_CRNT_FRAME 0x0214
-#define RADEON_CRTC2_CRNT_FRAME 0x0314
-
-#define R500_D1CRTC_STATUS 0x609c
-#define R500_D2CRTC_STATUS 0x689c
-#define R500_CRTC_V_BLANK (1<<0)
-
-#define R500_D1CRTC_FRAME_COUNT 0x60a4
-#define R500_D2CRTC_FRAME_COUNT 0x68a4
-
-#define R500_D1MODE_V_COUNTER 0x6530
-#define R500_D2MODE_V_COUNTER 0x6d30
-
-#define R500_D1MODE_VBLANK_STATUS 0x6534
-#define R500_D2MODE_VBLANK_STATUS 0x6d34
-#define R500_VBLANK_OCCURED (1<<0)
-#define R500_VBLANK_ACK     (1<<4)
-#define R500_VBLANK_STAT    (1<<12)
-#define R500_VBLANK_INT     (1<<16)
-
-#define R500_DxMODE_INT_MASK 0x6540
-#define R500_D1MODE_INT_MASK (1<<0)
-#define R500_D2MODE_INT_MASK (1<<8)
-
-#define R500_DISP_INTERRUPT_STATUS 0x7edc
-#define R500_D1_VBLANK_INTERRUPT (1 << 4)
-#define R500_D2_VBLANK_INTERRUPT (1 << 5)
-
-/* R6xx/R7xx registers */
-#define R600_MC_VM_FB_LOCATION                                 0x2180
-#define R600_MC_VM_AGP_TOP                                     0x2184
-#define R600_MC_VM_AGP_BOT                                     0x2188
-#define R600_MC_VM_AGP_BASE                                    0x218c
-#define R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR                    0x2190
-#define R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR                   0x2194
-#define R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR                0x2198
-
-#define R700_MC_VM_FB_LOCATION                                 0x2024
-#define R700_MC_VM_AGP_TOP                                     0x2028
-#define R700_MC_VM_AGP_BOT                                     0x202c
-#define R700_MC_VM_AGP_BASE                                    0x2030
-#define R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR                    0x2034
-#define R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR                   0x2038
-#define R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR                0x203c
-
-#define R600_MCD_RD_A_CNTL                                     0x219c
-#define R600_MCD_RD_B_CNTL                                     0x21a0
-
-#define R600_MCD_WR_A_CNTL                                     0x21a4
-#define R600_MCD_WR_B_CNTL                                     0x21a8
-
-#define R600_MCD_RD_SYS_CNTL                                   0x2200
-#define R600_MCD_WR_SYS_CNTL                                   0x2214
-
-#define R600_MCD_RD_GFX_CNTL                                   0x21fc
-#define R600_MCD_RD_HDP_CNTL                                   0x2204
-#define R600_MCD_RD_PDMA_CNTL                                  0x2208
-#define R600_MCD_RD_SEM_CNTL                                   0x220c
-#define R600_MCD_WR_GFX_CNTL                                   0x2210
-#define R600_MCD_WR_HDP_CNTL                                   0x2218
-#define R600_MCD_WR_PDMA_CNTL                                  0x221c
-#define R600_MCD_WR_SEM_CNTL                                   0x2220
-
-#       define R600_MCD_L1_TLB                                 (1 << 0)
-#       define R600_MCD_L1_FRAG_PROC                           (1 << 1)
-#       define R600_MCD_L1_STRICT_ORDERING                     (1 << 2)
-
-#       define R600_MCD_SYSTEM_ACCESS_MODE_MASK                (3 << 6)
-#       define R600_MCD_SYSTEM_ACCESS_MODE_PA_ONLY             (0 << 6)
-#       define R600_MCD_SYSTEM_ACCESS_MODE_USE_SYS_MAP         (1 << 6)
-#       define R600_MCD_SYSTEM_ACCESS_MODE_IN_SYS              (2 << 6)
-#       define R600_MCD_SYSTEM_ACCESS_MODE_NOT_IN_SYS          (3 << 6)
-
-#       define R600_MCD_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU    (0 << 8)
-#       define R600_MCD_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE (1 << 8)
-
-#       define R600_MCD_SEMAPHORE_MODE                         (1 << 10)
-#       define R600_MCD_WAIT_L2_QUERY                          (1 << 11)
-#       define R600_MCD_EFFECTIVE_L1_TLB_SIZE(x)               ((x) << 12)
-#       define R600_MCD_EFFECTIVE_L1_QUEUE_SIZE(x)             ((x) << 15)
-
-#define R700_MC_VM_MD_L1_TLB0_CNTL                             0x2654
-#define R700_MC_VM_MD_L1_TLB1_CNTL                             0x2658
-#define R700_MC_VM_MD_L1_TLB2_CNTL                             0x265c
-
-#define R700_MC_VM_MB_L1_TLB0_CNTL                             0x2234
-#define R700_MC_VM_MB_L1_TLB1_CNTL                             0x2238
-#define R700_MC_VM_MB_L1_TLB2_CNTL                             0x223c
-#define R700_MC_VM_MB_L1_TLB3_CNTL                             0x2240
-
-#       define R700_ENABLE_L1_TLB                              (1 << 0)
-#       define R700_ENABLE_L1_FRAGMENT_PROCESSING              (1 << 1)
-#       define R700_SYSTEM_ACCESS_MODE_IN_SYS                  (2 << 3)
-#       define R700_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU  (0 << 5)
-#       define R700_EFFECTIVE_L1_TLB_SIZE(x)                   ((x) << 15)
-#       define R700_EFFECTIVE_L1_QUEUE_SIZE(x)                 ((x) << 18)
-
-#define R700_MC_ARB_RAMCFG                                     0x2760
-#       define R700_NOOFBANK_SHIFT                             0
-#       define R700_NOOFBANK_MASK                              0x3
-#       define R700_NOOFRANK_SHIFT                             2
-#       define R700_NOOFRANK_MASK                              0x1
-#       define R700_NOOFROWS_SHIFT                             3
-#       define R700_NOOFROWS_MASK                              0x7
-#       define R700_NOOFCOLS_SHIFT                             6
-#       define R700_NOOFCOLS_MASK                              0x3
-#       define R700_CHANSIZE_SHIFT                             8
-#       define R700_CHANSIZE_MASK                              0x1
-#       define R700_BURSTLENGTH_SHIFT                          9
-#       define R700_BURSTLENGTH_MASK                           0x1
-#define R600_RAMCFG                                            0x2408
-#       define R600_NOOFBANK_SHIFT                             0
-#       define R600_NOOFBANK_MASK                              0x1
-#       define R600_NOOFRANK_SHIFT                             1
-#       define R600_NOOFRANK_MASK                              0x1
-#       define R600_NOOFROWS_SHIFT                             2
-#       define R600_NOOFROWS_MASK                              0x7
-#       define R600_NOOFCOLS_SHIFT                             5
-#       define R600_NOOFCOLS_MASK                              0x3
-#       define R600_CHANSIZE_SHIFT                             7
-#       define R600_CHANSIZE_MASK                              0x1
-#       define R600_BURSTLENGTH_SHIFT                          8
-#       define R600_BURSTLENGTH_MASK                           0x1
-
-#define R600_VM_L2_CNTL                                        0x1400
-#       define R600_VM_L2_CACHE_EN                             (1 << 0)
-#       define R600_VM_L2_FRAG_PROC                            (1 << 1)
-#       define R600_VM_ENABLE_PTE_CACHE_LRU_W                  (1 << 9)
-#       define R600_VM_L2_CNTL_QUEUE_SIZE(x)                   ((x) << 13)
-#       define R700_VM_L2_CNTL_QUEUE_SIZE(x)                   ((x) << 14)
-
-#define R600_VM_L2_CNTL2                                       0x1404
-#       define R600_VM_L2_CNTL2_INVALIDATE_ALL_L1_TLBS         (1 << 0)
-#       define R600_VM_L2_CNTL2_INVALIDATE_L2_CACHE            (1 << 1)
-#define R600_VM_L2_CNTL3                                       0x1408
-#       define R600_VM_L2_CNTL3_BANK_SELECT_0(x)               ((x) << 0)
-#       define R600_VM_L2_CNTL3_BANK_SELECT_1(x)               ((x) << 5)
-#       define R600_VM_L2_CNTL3_CACHE_UPDATE_MODE(x)           ((x) << 10)
-#       define R700_VM_L2_CNTL3_BANK_SELECT(x)                 ((x) << 0)
-#       define R700_VM_L2_CNTL3_CACHE_UPDATE_MODE(x)           ((x) << 6)
-
-#define R600_VM_L2_STATUS                                      0x140c
-
-#define R600_VM_CONTEXT0_CNTL                                  0x1410
-#       define R600_VM_ENABLE_CONTEXT                          (1 << 0)
-#       define R600_VM_PAGE_TABLE_DEPTH_FLAT                   (0 << 1)
-
-#define R600_VM_CONTEXT0_CNTL2                                 0x1430
-#define R600_VM_CONTEXT0_REQUEST_RESPONSE                      0x1470
-#define R600_VM_CONTEXT0_INVALIDATION_LOW_ADDR                 0x1490
-#define R600_VM_CONTEXT0_INVALIDATION_HIGH_ADDR                0x14b0
-#define R600_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR                  0x1574
-#define R600_VM_CONTEXT0_PAGE_TABLE_START_ADDR                 0x1594
-#define R600_VM_CONTEXT0_PAGE_TABLE_END_ADDR                   0x15b4
-
-#define R700_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR                  0x153c
-#define R700_VM_CONTEXT0_PAGE_TABLE_START_ADDR                 0x155c
-#define R700_VM_CONTEXT0_PAGE_TABLE_END_ADDR                   0x157c
-
-#define R600_HDP_HOST_PATH_CNTL                                0x2c00
-
-#define R600_GRBM_CNTL                                         0x8000
-#       define R600_GRBM_READ_TIMEOUT(x)                       ((x) << 0)
-
-#define R600_GRBM_STATUS                                       0x8010
-#       define R600_CMDFIFO_AVAIL_MASK                         0x1f
-#       define R700_CMDFIFO_AVAIL_MASK                         0xf
-#       define R600_GUI_ACTIVE                                 (1 << 31)
-#define R600_GRBM_STATUS2                                      0x8014
-#define R600_GRBM_SOFT_RESET                                   0x8020
-#       define R600_SOFT_RESET_CP                              (1 << 0)
-#define R600_WAIT_UNTIL		                               0x8040
-
-#define R600_CP_SEM_WAIT_TIMER                                 0x85bc
-#define R600_CP_ME_CNTL                                        0x86d8
-#       define R600_CP_ME_HALT                                 (1 << 28)
-#define R600_CP_QUEUE_THRESHOLDS                               0x8760
-#       define R600_ROQ_IB1_START(x)                           ((x) << 0)
-#       define R600_ROQ_IB2_START(x)                           ((x) << 8)
-#define R600_CP_MEQ_THRESHOLDS                                 0x8764
-#       define R700_STQ_SPLIT(x)                               ((x) << 0)
-#       define R600_MEQ_END(x)                                 ((x) << 16)
-#       define R600_ROQ_END(x)                                 ((x) << 24)
-#define R600_CP_PERFMON_CNTL                                   0x87fc
-#define R600_CP_RB_BASE                                        0xc100
-#define R600_CP_RB_CNTL                                        0xc104
-#       define R600_RB_BUFSZ(x)                                ((x) << 0)
-#       define R600_RB_BLKSZ(x)                                ((x) << 8)
-#	define R600_BUF_SWAP_32BIT		               (2 << 16)
-#       define R600_RB_NO_UPDATE                               (1 << 27)
-#       define R600_RB_RPTR_WR_ENA                             (1 << 31)
-#define R600_CP_RB_RPTR_WR                                     0xc108
-#define R600_CP_RB_RPTR_ADDR                                   0xc10c
-#define R600_CP_RB_RPTR_ADDR_HI                                0xc110
-#define R600_CP_RB_WPTR                                        0xc114
-#define R600_CP_RB_WPTR_ADDR                                   0xc118
-#define R600_CP_RB_WPTR_ADDR_HI                                0xc11c
-#define R600_CP_RB_RPTR                                        0x8700
-#define R600_CP_RB_WPTR_DELAY                                  0x8704
-#define R600_CP_PFP_UCODE_ADDR                                 0xc150
-#define R600_CP_PFP_UCODE_DATA                                 0xc154
-#define R600_CP_ME_RAM_RADDR                                   0xc158
-#define R600_CP_ME_RAM_WADDR                                   0xc15c
-#define R600_CP_ME_RAM_DATA                                    0xc160
-#define R600_CP_DEBUG                                          0xc1fc
-
-#define R600_PA_CL_ENHANCE                                     0x8a14
-#       define R600_CLIP_VTX_REORDER_ENA                       (1 << 0)
-#       define R600_NUM_CLIP_SEQ(x)                            ((x) << 1)
-#define R600_PA_SC_LINE_STIPPLE_STATE                          0x8b10
-#define R600_PA_SC_MULTI_CHIP_CNTL                             0x8b20
-#define R700_PA_SC_FORCE_EOV_MAX_CNTS                          0x8b24
-#       define R700_FORCE_EOV_MAX_CLK_CNT(x)                   ((x) << 0)
-#       define R700_FORCE_EOV_MAX_REZ_CNT(x)                   ((x) << 16)
-#define R600_PA_SC_AA_SAMPLE_LOCS_2S                           0x8b40
-#define R600_PA_SC_AA_SAMPLE_LOCS_4S                           0x8b44
-#define R600_PA_SC_AA_SAMPLE_LOCS_8S_WD0                       0x8b48
-#define R600_PA_SC_AA_SAMPLE_LOCS_8S_WD1                       0x8b4c
-#       define R600_S0_X(x)                                    ((x) << 0)
-#       define R600_S0_Y(x)                                    ((x) << 4)
-#       define R600_S1_X(x)                                    ((x) << 8)
-#       define R600_S1_Y(x)                                    ((x) << 12)
-#       define R600_S2_X(x)                                    ((x) << 16)
-#       define R600_S2_Y(x)                                    ((x) << 20)
-#       define R600_S3_X(x)                                    ((x) << 24)
-#       define R600_S3_Y(x)                                    ((x) << 28)
-#       define R600_S4_X(x)                                    ((x) << 0)
-#       define R600_S4_Y(x)                                    ((x) << 4)
-#       define R600_S5_X(x)                                    ((x) << 8)
-#       define R600_S5_Y(x)                                    ((x) << 12)
-#       define R600_S6_X(x)                                    ((x) << 16)
-#       define R600_S6_Y(x)                                    ((x) << 20)
-#       define R600_S7_X(x)                                    ((x) << 24)
-#       define R600_S7_Y(x)                                    ((x) << 28)
-#define R600_PA_SC_FIFO_SIZE                                   0x8bd0
-#       define R600_SC_PRIM_FIFO_SIZE(x)                       ((x) << 0)
-#       define R600_SC_HIZ_TILE_FIFO_SIZE(x)                   ((x) << 8)
-#       define R600_SC_EARLYZ_TILE_FIFO_SIZE(x)                ((x) << 16)
-#define R700_PA_SC_FIFO_SIZE_R7XX                              0x8bcc
-#       define R700_SC_PRIM_FIFO_SIZE(x)                       ((x) << 0)
-#       define R700_SC_HIZ_TILE_FIFO_SIZE(x)                   ((x) << 12)
-#       define R700_SC_EARLYZ_TILE_FIFO_SIZE(x)                ((x) << 20)
-#define R600_PA_SC_ENHANCE                                     0x8bf0
-#       define R600_FORCE_EOV_MAX_CLK_CNT(x)                   ((x) << 0)
-#       define R600_FORCE_EOV_MAX_TILE_CNT(x)                  ((x) << 12)
-#define R600_PA_SC_CLIPRECT_RULE                               0x2820c
-#define R700_PA_SC_EDGERULE                                    0x28230
-#define R600_PA_SC_LINE_STIPPLE                                0x28a0c
-#define R600_PA_SC_MODE_CNTL                                   0x28a4c
-#define R600_PA_SC_AA_CONFIG                                   0x28c04
-
-#define R600_SX_EXPORT_BUFFER_SIZES                            0x900c
-#       define R600_COLOR_BUFFER_SIZE(x)                       ((x) << 0)
-#       define R600_POSITION_BUFFER_SIZE(x)                    ((x) << 8)
-#       define R600_SMX_BUFFER_SIZE(x)                         ((x) << 16)
-#define R600_SX_DEBUG_1                                        0x9054
-#       define R600_SMX_EVENT_RELEASE                          (1 << 0)
-#       define R600_ENABLE_NEW_SMX_ADDRESS                     (1 << 16)
-#define R700_SX_DEBUG_1                                        0x9058
-#       define R700_ENABLE_NEW_SMX_ADDRESS                     (1 << 16)
-#define R600_SX_MISC                                           0x28350
-
-#define R600_DB_DEBUG                                          0x9830
-#       define R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE              (1 << 31)
-#define R600_DB_WATERMARKS                                     0x9838
-#       define R600_DEPTH_FREE(x)                              ((x) << 0)
-#       define R600_DEPTH_FLUSH(x)                             ((x) << 5)
-#       define R600_DEPTH_PENDING_FREE(x)                      ((x) << 15)
-#       define R600_DEPTH_CACHELINE_FREE(x)                    ((x) << 20)
-#define R700_DB_DEBUG3                                         0x98b0
-#       define R700_DB_CLK_OFF_DELAY(x)                        ((x) << 11)
-#define RV700_DB_DEBUG4                                        0x9b8c
-#       define RV700_DISABLE_TILE_COVERED_FOR_PS_ITER          (1 << 6)
-
-#define R600_VGT_CACHE_INVALIDATION                            0x88c4
-#       define R600_CACHE_INVALIDATION(x)                      ((x) << 0)
-#       define R600_VC_ONLY                                    0
-#       define R600_TC_ONLY                                    1
-#       define R600_VC_AND_TC                                  2
-#       define R700_AUTO_INVLD_EN(x)                           ((x) << 6)
-#       define R700_NO_AUTO                                    0
-#       define R700_ES_AUTO                                    1
-#       define R700_GS_AUTO                                    2
-#       define R700_ES_AND_GS_AUTO                             3
-#define R600_VGT_GS_PER_ES                                     0x88c8
-#define R600_VGT_ES_PER_GS                                     0x88cc
-#define R600_VGT_GS_PER_VS                                     0x88e8
-#define R600_VGT_GS_VERTEX_REUSE                               0x88d4
-#define R600_VGT_NUM_INSTANCES                                 0x8974
-#define R600_VGT_STRMOUT_EN                                    0x28ab0
-#define R600_VGT_EVENT_INITIATOR                               0x28a90
-#       define R600_CACHE_FLUSH_AND_INV_EVENT                  (0x16 << 0)
-#define R600_VGT_VERTEX_REUSE_BLOCK_CNTL                       0x28c58
-#       define R600_VTX_REUSE_DEPTH_MASK                       0xff
-#define R600_VGT_OUT_DEALLOC_CNTL                              0x28c5c
-#       define R600_DEALLOC_DIST_MASK                          0x7f
-
-#define R600_CB_COLOR0_BASE                                    0x28040
-#define R600_CB_COLOR1_BASE                                    0x28044
-#define R600_CB_COLOR2_BASE                                    0x28048
-#define R600_CB_COLOR3_BASE                                    0x2804c
-#define R600_CB_COLOR4_BASE                                    0x28050
-#define R600_CB_COLOR5_BASE                                    0x28054
-#define R600_CB_COLOR6_BASE                                    0x28058
-#define R600_CB_COLOR7_BASE                                    0x2805c
-#define R600_CB_COLOR7_FRAG                                    0x280fc
-
-#define R600_CB_COLOR0_SIZE                                    0x28060
-#define R600_CB_COLOR0_VIEW                                    0x28080
-#define R600_CB_COLOR0_INFO                                    0x280a0
-#define R600_CB_COLOR0_TILE                                    0x280c0
-#define R600_CB_COLOR0_FRAG                                    0x280e0
-#define R600_CB_COLOR0_MASK                                    0x28100
-
-#define AVIVO_D1MODE_VLINE_START_END                           0x6538
-#define AVIVO_D2MODE_VLINE_START_END                           0x6d38
-#define R600_CP_COHER_BASE                                     0x85f8
-#define R600_DB_DEPTH_BASE                                     0x2800c
-#define R600_SQ_PGM_START_FS                                   0x28894
-#define R600_SQ_PGM_START_ES                                   0x28880
-#define R600_SQ_PGM_START_VS                                   0x28858
-#define R600_SQ_PGM_RESOURCES_VS                               0x28868
-#define R600_SQ_PGM_CF_OFFSET_VS                               0x288d0
-#define R600_SQ_PGM_START_GS                                   0x2886c
-#define R600_SQ_PGM_START_PS                                   0x28840
-#define R600_SQ_PGM_RESOURCES_PS                               0x28850
-#define R600_SQ_PGM_EXPORTS_PS                                 0x28854
-#define R600_SQ_PGM_CF_OFFSET_PS                               0x288cc
-#define R600_VGT_DMA_BASE                                      0x287e8
-#define R600_VGT_DMA_BASE_HI                                   0x287e4
-#define R600_VGT_STRMOUT_BASE_OFFSET_0                         0x28b10
-#define R600_VGT_STRMOUT_BASE_OFFSET_1                         0x28b14
-#define R600_VGT_STRMOUT_BASE_OFFSET_2                         0x28b18
-#define R600_VGT_STRMOUT_BASE_OFFSET_3                         0x28b1c
-#define R600_VGT_STRMOUT_BASE_OFFSET_HI_0                      0x28b44
-#define R600_VGT_STRMOUT_BASE_OFFSET_HI_1                      0x28b48
-#define R600_VGT_STRMOUT_BASE_OFFSET_HI_2                      0x28b4c
-#define R600_VGT_STRMOUT_BASE_OFFSET_HI_3                      0x28b50
-#define R600_VGT_STRMOUT_BUFFER_BASE_0                         0x28ad8
-#define R600_VGT_STRMOUT_BUFFER_BASE_1                         0x28ae8
-#define R600_VGT_STRMOUT_BUFFER_BASE_2                         0x28af8
-#define R600_VGT_STRMOUT_BUFFER_BASE_3                         0x28b08
-#define R600_VGT_STRMOUT_BUFFER_OFFSET_0                       0x28adc
-#define R600_VGT_STRMOUT_BUFFER_OFFSET_1                       0x28aec
-#define R600_VGT_STRMOUT_BUFFER_OFFSET_2                       0x28afc
-#define R600_VGT_STRMOUT_BUFFER_OFFSET_3                       0x28b0c
-
-#define R600_VGT_PRIMITIVE_TYPE                                0x8958
-
-#define R600_PA_SC_SCREEN_SCISSOR_TL                           0x28030
-#define R600_PA_SC_GENERIC_SCISSOR_TL                          0x28240
-#define R600_PA_SC_WINDOW_SCISSOR_TL                           0x28204
-
-#define R600_TC_CNTL                                           0x9608
-#       define R600_TC_L2_SIZE(x)                              ((x) << 5)
-#       define R600_L2_DISABLE_LATE_HIT                        (1 << 9)
-
-#define R600_ARB_POP                                           0x2418
-#       define R600_ENABLE_TC128                               (1 << 30)
-#define R600_ARB_GDEC_RD_CNTL                                  0x246c
-
-#define R600_TA_CNTL_AUX                                       0x9508
-#       define R600_DISABLE_CUBE_WRAP                          (1 << 0)
-#       define R600_DISABLE_CUBE_ANISO                         (1 << 1)
-#       define R700_GETLOD_SELECT(x)                           ((x) << 2)
-#       define R600_SYNC_GRADIENT                              (1 << 24)
-#       define R600_SYNC_WALKER                                (1 << 25)
-#       define R600_SYNC_ALIGNER                               (1 << 26)
-#       define R600_BILINEAR_PRECISION_6_BIT                   (0 << 31)
-#       define R600_BILINEAR_PRECISION_8_BIT                   (1 << 31)
-
-#define R700_TCP_CNTL                                          0x9610
-
-#define R600_SMX_DC_CTL0                                       0xa020
-#       define R700_USE_HASH_FUNCTION                          (1 << 0)
-#       define R700_CACHE_DEPTH(x)                             ((x) << 1)
-#       define R700_FLUSH_ALL_ON_EVENT                         (1 << 10)
-#       define R700_STALL_ON_EVENT                             (1 << 11)
-#define R700_SMX_EVENT_CTL                                     0xa02c
-#       define R700_ES_FLUSH_CTL(x)                            ((x) << 0)
-#       define R700_GS_FLUSH_CTL(x)                            ((x) << 3)
-#       define R700_ACK_FLUSH_CTL(x)                           ((x) << 6)
-#       define R700_SYNC_FLUSH_CTL                             (1 << 8)
-
-#define R600_SQ_CONFIG                                         0x8c00
-#       define R600_VC_ENABLE                                  (1 << 0)
-#       define R600_EXPORT_SRC_C                               (1 << 1)
-#       define R600_DX9_CONSTS                                 (1 << 2)
-#       define R600_ALU_INST_PREFER_VECTOR                     (1 << 3)
-#       define R600_DX10_CLAMP                                 (1 << 4)
-#       define R600_CLAUSE_SEQ_PRIO(x)                         ((x) << 8)
-#       define R600_PS_PRIO(x)                                 ((x) << 24)
-#       define R600_VS_PRIO(x)                                 ((x) << 26)
-#       define R600_GS_PRIO(x)                                 ((x) << 28)
-#       define R600_ES_PRIO(x)                                 ((x) << 30)
-#define R600_SQ_GPR_RESOURCE_MGMT_1                            0x8c04
-#       define R600_NUM_PS_GPRS(x)                             ((x) << 0)
-#       define R600_NUM_VS_GPRS(x)                             ((x) << 16)
-#       define R700_DYN_GPR_ENABLE                             (1 << 27)
-#       define R600_NUM_CLAUSE_TEMP_GPRS(x)                    ((x) << 28)
-#define R600_SQ_GPR_RESOURCE_MGMT_2                            0x8c08
-#       define R600_NUM_GS_GPRS(x)                             ((x) << 0)
-#       define R600_NUM_ES_GPRS(x)                             ((x) << 16)
-#define R600_SQ_THREAD_RESOURCE_MGMT                           0x8c0c
-#       define R600_NUM_PS_THREADS(x)                          ((x) << 0)
-#       define R600_NUM_VS_THREADS(x)                          ((x) << 8)
-#       define R600_NUM_GS_THREADS(x)                          ((x) << 16)
-#       define R600_NUM_ES_THREADS(x)                          ((x) << 24)
-#define R600_SQ_STACK_RESOURCE_MGMT_1                          0x8c10
-#       define R600_NUM_PS_STACK_ENTRIES(x)                    ((x) << 0)
-#       define R600_NUM_VS_STACK_ENTRIES(x)                    ((x) << 16)
-#define R600_SQ_STACK_RESOURCE_MGMT_2                          0x8c14
-#       define R600_NUM_GS_STACK_ENTRIES(x)                    ((x) << 0)
-#       define R600_NUM_ES_STACK_ENTRIES(x)                    ((x) << 16)
-#define R600_SQ_MS_FIFO_SIZES                                  0x8cf0
-#       define R600_CACHE_FIFO_SIZE(x)                         ((x) << 0)
-#       define R600_FETCH_FIFO_HIWATER(x)                      ((x) << 8)
-#       define R600_DONE_FIFO_HIWATER(x)                       ((x) << 16)
-#       define R600_ALU_UPDATE_FIFO_HIWATER(x)                 ((x) << 24)
-#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_0                         0x8db0
-#       define R700_SIMDA_RING0(x)                             ((x) << 0)
-#       define R700_SIMDA_RING1(x)                             ((x) << 8)
-#       define R700_SIMDB_RING0(x)                             ((x) << 16)
-#       define R700_SIMDB_RING1(x)                             ((x) << 24)
-#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_1                         0x8db4
-#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_2                         0x8db8
-#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_3                         0x8dbc
-#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_4                         0x8dc0
-#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_5                         0x8dc4
-#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_6                         0x8dc8
-#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_7                         0x8dcc
-
-#define R600_SPI_PS_IN_CONTROL_0                               0x286cc
-#       define R600_NUM_INTERP(x)                              ((x) << 0)
-#       define R600_POSITION_ENA                               (1 << 8)
-#       define R600_POSITION_CENTROID                          (1 << 9)
-#       define R600_POSITION_ADDR(x)                           ((x) << 10)
-#       define R600_PARAM_GEN(x)                               ((x) << 15)
-#       define R600_PARAM_GEN_ADDR(x)                          ((x) << 19)
-#       define R600_BARYC_SAMPLE_CNTL(x)                       ((x) << 26)
-#       define R600_PERSP_GRADIENT_ENA                         (1 << 28)
-#       define R600_LINEAR_GRADIENT_ENA                        (1 << 29)
-#       define R600_POSITION_SAMPLE                            (1 << 30)
-#       define R600_BARYC_AT_SAMPLE_ENA                        (1 << 31)
-#define R600_SPI_PS_IN_CONTROL_1                               0x286d0
-#       define R600_GEN_INDEX_PIX                              (1 << 0)
-#       define R600_GEN_INDEX_PIX_ADDR(x)                      ((x) << 1)
-#       define R600_FRONT_FACE_ENA                             (1 << 8)
-#       define R600_FRONT_FACE_CHAN(x)                         ((x) << 9)
-#       define R600_FRONT_FACE_ALL_BITS                        (1 << 11)
-#       define R600_FRONT_FACE_ADDR(x)                         ((x) << 12)
-#       define R600_FOG_ADDR(x)                                ((x) << 17)
-#       define R600_FIXED_PT_POSITION_ENA                      (1 << 24)
-#       define R600_FIXED_PT_POSITION_ADDR(x)                  ((x) << 25)
-#       define R700_POSITION_ULC                               (1 << 30)
-#define R600_SPI_INPUT_Z                                       0x286d8
-
-#define R600_SPI_CONFIG_CNTL                                   0x9100
-#       define R600_GPR_WRITE_PRIORITY(x)                      ((x) << 0)
-#       define R600_DISABLE_INTERP_1                           (1 << 5)
-#define R600_SPI_CONFIG_CNTL_1                                 0x913c
-#       define R600_VTX_DONE_DELAY(x)                          ((x) << 0)
-#       define R600_INTERP_ONE_PRIM_PER_ROW                    (1 << 4)
-
-#define R600_GB_TILING_CONFIG                                  0x98f0
-#       define R600_PIPE_TILING(x)                             ((x) << 1)
-#       define R600_BANK_TILING(x)                             ((x) << 4)
-#       define R600_GROUP_SIZE(x)                              ((x) << 6)
-#       define R600_ROW_TILING(x)                              ((x) << 8)
-#       define R600_BANK_SWAPS(x)                              ((x) << 11)
-#       define R600_SAMPLE_SPLIT(x)                            ((x) << 14)
-#       define R600_BACKEND_MAP(x)                             ((x) << 16)
-#define R600_DCP_TILING_CONFIG                                 0x6ca0
-#define R600_HDP_TILING_CONFIG                                 0x2f3c
-
-#define R600_CC_RB_BACKEND_DISABLE                             0x98f4
-#define R700_CC_SYS_RB_BACKEND_DISABLE                         0x3f88
-#       define R600_BACKEND_DISABLE(x)                         ((x) << 16)
-
-#define R600_CC_GC_SHADER_PIPE_CONFIG                          0x8950
-#define R600_GC_USER_SHADER_PIPE_CONFIG                        0x8954
-#       define R600_INACTIVE_QD_PIPES(x)                       ((x) << 8)
-#       define R600_INACTIVE_QD_PIPES_MASK                     (0xff << 8)
-#       define R600_INACTIVE_SIMDS(x)                          ((x) << 16)
-#       define R600_INACTIVE_SIMDS_MASK                        (0xff << 16)
-
-#define R700_CGTS_SYS_TCC_DISABLE                              0x3f90
-#define R700_CGTS_USER_SYS_TCC_DISABLE                         0x3f94
-#define R700_CGTS_TCC_DISABLE                                  0x9148
-#define R700_CGTS_USER_TCC_DISABLE                             0x914c
-
-/* Constants */
-#define RADEON_MAX_USEC_TIMEOUT		100000	/* 100 ms */
-
-#define RADEON_LAST_FRAME_REG		RADEON_SCRATCH_REG0
-#define RADEON_LAST_DISPATCH_REG	RADEON_SCRATCH_REG1
-#define RADEON_LAST_CLEAR_REG		RADEON_SCRATCH_REG2
-#define RADEON_LAST_SWI_REG		RADEON_SCRATCH_REG3
-#define RADEON_LAST_DISPATCH		1
-
-#define R600_LAST_FRAME_REG		R600_SCRATCH_REG0
-#define R600_LAST_DISPATCH_REG	        R600_SCRATCH_REG1
-#define R600_LAST_CLEAR_REG		R600_SCRATCH_REG2
-#define R600_LAST_SWI_REG		R600_SCRATCH_REG3
-
-#define RADEON_MAX_VB_AGE		0x7fffffff
-#define RADEON_MAX_VB_VERTS		(0xffff)
-
-#define RADEON_RING_HIGH_MARK		128
-
-#define RADEON_PCIGART_TABLE_SIZE      (32*1024)
-
-#define RADEON_READ(reg)	DRM_READ32(  dev_priv->mmio, (reg) )
-#define RADEON_WRITE(reg, val)                                          \
-do {									\
-	if (reg < 0x10000) {				                \
-		DRM_WRITE32(dev_priv->mmio, (reg), (val));		\
-	} else {                                                        \
-		DRM_WRITE32(dev_priv->mmio, RADEON_MM_INDEX, (reg));	\
-		DRM_WRITE32(dev_priv->mmio, RADEON_MM_DATA, (val));	\
-	}                                                               \
-} while (0)
-#define RADEON_READ8(reg)	DRM_READ8(  dev_priv->mmio, (reg) )
-#define RADEON_WRITE8(reg,val)	DRM_WRITE8( dev_priv->mmio, (reg), (val) )
-
-#define RADEON_WRITE_PLL(addr, val)					\
-do {									\
-	RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX,				\
-		       ((addr) & 0x1f) | RADEON_PLL_WR_EN );		\
-	RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val));			\
-} while (0)
-
-#define RADEON_WRITE_PCIE(addr, val)					\
-do {									\
-	RADEON_WRITE8(RADEON_PCIE_INDEX,				\
-			((addr) & 0xff));				\
-	RADEON_WRITE(RADEON_PCIE_DATA, (val));			\
-} while (0)
-
-#define R500_WRITE_MCIND(addr, val)					\
-do {								\
-	RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff));	\
-	RADEON_WRITE(R520_MC_IND_DATA, (val));			\
-	RADEON_WRITE(R520_MC_IND_INDEX, 0);	\
-} while (0)
-
-#define RS480_WRITE_MCIND(addr, val)				\
-do {									\
-	RADEON_WRITE(RS480_NB_MC_INDEX,				\
-			((addr) & 0xff) | RS480_NB_MC_IND_WR_EN);	\
-	RADEON_WRITE(RS480_NB_MC_DATA, (val));			\
-	RADEON_WRITE(RS480_NB_MC_INDEX, 0xff);			\
-} while (0)
-
-#define RS690_WRITE_MCIND(addr, val)					\
-do {								\
-	RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_EN | ((addr) & RS690_MC_INDEX_MASK));	\
-	RADEON_WRITE(RS690_MC_DATA, val);			\
-	RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK);	\
-} while (0)
-
-#define RS600_WRITE_MCIND(addr, val)				\
-do {							        \
-	RADEON_WRITE(RS600_MC_INDEX, RS600_MC_IND_WR_EN | RS600_MC_IND_CITF_ARB0 | ((addr) & RS600_MC_ADDR_MASK)); \
-	RADEON_WRITE(RS600_MC_DATA, val);                       \
-} while (0)
-
-#define IGP_WRITE_MCIND(addr, val)				\
-do {									\
-	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||   \
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))      \
-		RS690_WRITE_MCIND(addr, val);				\
-	else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600)  \
-		RS600_WRITE_MCIND(addr, val);				\
-	else								\
-		RS480_WRITE_MCIND(addr, val);				\
-} while (0)
-
-#define CP_PACKET0( reg, n )						\
-	(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
-#define CP_PACKET0_TABLE( reg, n )					\
-	(RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2))
-#define CP_PACKET1( reg0, reg1 )					\
-	(RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2))
-#define CP_PACKET2()							\
-	(RADEON_CP_PACKET2)
-#define CP_PACKET3( pkt, n )						\
-	(RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
-
-/* ================================================================
- * Engine control helper macros
- */
-
-#define RADEON_WAIT_UNTIL_2D_IDLE() do {				\
-	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
-	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
-		   RADEON_WAIT_HOST_IDLECLEAN) );			\
-} while (0)
-
-#define RADEON_WAIT_UNTIL_3D_IDLE() do {				\
-	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
-	OUT_RING( (RADEON_WAIT_3D_IDLECLEAN |				\
-		   RADEON_WAIT_HOST_IDLECLEAN) );			\
-} while (0)
-
-#define RADEON_WAIT_UNTIL_IDLE() do {					\
-	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
-	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
-		   RADEON_WAIT_3D_IDLECLEAN |				\
-		   RADEON_WAIT_HOST_IDLECLEAN) );			\
-} while (0)
-
-#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do {				\
-	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
-	OUT_RING( RADEON_WAIT_CRTC_PFLIP );				\
-} while (0)
-
-#define RADEON_FLUSH_CACHE() do {					\
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {	\
-		OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0));	\
-		OUT_RING(RADEON_RB3D_DC_FLUSH);				\
-	} else {                                                        \
-		OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));	\
-		OUT_RING(R300_RB3D_DC_FLUSH);				\
-	}                                                               \
-} while (0)
-
-#define RADEON_PURGE_CACHE() do {					\
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {	\
-		OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0));	\
-		OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE);	\
-	} else {                                                        \
-		OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));	\
-		OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE);	\
-	}                                                               \
-} while (0)
-
-#define RADEON_FLUSH_ZCACHE() do {					\
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {	\
-		OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));	\
-		OUT_RING(RADEON_RB3D_ZC_FLUSH);				\
-	} else {                                                        \
-		OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));	\
-		OUT_RING(R300_ZC_FLUSH);				\
-	}                                                               \
-} while (0)
-
-#define RADEON_PURGE_ZCACHE() do {					\
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {	\
-		OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));	\
-		OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE);			\
-	} else {                                                        \
-		OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));	\
-		OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE);				\
-	}                                                               \
-} while (0)
-
-/* ================================================================
- * Misc helper macros
- */
-
-/* Perfbox functionality only.
- */
-#define RING_SPACE_TEST_WITH_RETURN( dev_priv )				\
-do {									\
-	if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) {		\
-		u32 head = GET_RING_HEAD( dev_priv );			\
-		if (head == dev_priv->ring.tail)			\
-			dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE;	\
-	}								\
-} while (0)
-
-#define VB_AGE_TEST_WITH_RETURN( dev_priv )				\
-do {								\
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;	\
-	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;	\
-	if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) {		\
-		int __ret;						\
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) \
-			__ret = r600_do_cp_idle(dev_priv);		\
-		else							\
-			__ret = radeon_do_cp_idle(dev_priv);		\
-		if ( __ret ) return __ret;				\
-		sarea_priv->last_dispatch = 0;				\
-		radeon_freelist_reset( dev );				\
-	}								\
-} while (0)
-
-#define RADEON_DISPATCH_AGE( age ) do {					\
-	OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) );		\
-	OUT_RING( age );						\
-} while (0)
-
-#define RADEON_FRAME_AGE( age ) do {					\
-	OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) );		\
-	OUT_RING( age );						\
-} while (0)
-
-#define RADEON_CLEAR_AGE( age ) do {					\
-	OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) );		\
-	OUT_RING( age );						\
-} while (0)
-
-#define R600_DISPATCH_AGE(age) do {					\
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));		\
-	OUT_RING((R600_LAST_DISPATCH_REG - R600_SET_CONFIG_REG_OFFSET) >> 2);  \
-	OUT_RING(age);							\
-} while (0)
-
-#define R600_FRAME_AGE(age) do {					\
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));		\
-	OUT_RING((R600_LAST_FRAME_REG - R600_SET_CONFIG_REG_OFFSET) >> 2);  \
-	OUT_RING(age);							\
-} while (0)
-
-#define R600_CLEAR_AGE(age) do {					\
-	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));		\
-	OUT_RING((R600_LAST_CLEAR_REG - R600_SET_CONFIG_REG_OFFSET) >> 2);  \
-	OUT_RING(age);							\
-} while (0)
-
-/* ================================================================
- * Ring control
- */
-
-#define RADEON_VERBOSE	0
-
-#define RING_LOCALS	int write, _nr, _align_nr; unsigned int mask; u32 *ring;
-
-#define RADEON_RING_ALIGN 16
-
-#define BEGIN_RING( n ) do {						\
-	if ( RADEON_VERBOSE ) {						\
-		DRM_INFO( "BEGIN_RING( %d )\n", (n));			\
-	}								\
-	_align_nr = RADEON_RING_ALIGN - ((dev_priv->ring.tail + n) & (RADEON_RING_ALIGN-1));	\
-	_align_nr += n;							\
-	if (dev_priv->ring.space <= (_align_nr * sizeof(u32))) {	\
-                COMMIT_RING();						\
-		radeon_wait_ring( dev_priv, _align_nr * sizeof(u32));	\
-	}								\
-	_nr = n; dev_priv->ring.space -= (n) * sizeof(u32);		\
-	ring = dev_priv->ring.start;					\
-	write = dev_priv->ring.tail;					\
-	mask = dev_priv->ring.tail_mask;				\
-} while (0)
-
-#define ADVANCE_RING() do {						\
-	if ( RADEON_VERBOSE ) {						\
-		DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",	\
-			  write, dev_priv->ring.tail );			\
-	}								\
-	if (((dev_priv->ring.tail + _nr) & mask) != write) {		\
-		DRM_ERROR(						\
-			"ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",	\
-			((dev_priv->ring.tail + _nr) & mask),		\
-			write, __LINE__);				\
-	} else								\
-		dev_priv->ring.tail = write;				\
-} while (0)
-
-extern void radeon_commit_ring(drm_radeon_private_t *dev_priv);
-
-#define COMMIT_RING() do {						\
-		radeon_commit_ring(dev_priv);				\
-	} while(0)
-
-#define OUT_RING( x ) do {						\
-	if ( RADEON_VERBOSE ) {						\
-		DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",		\
-			   (unsigned int)(x), write );			\
-	}								\
-	ring[write++] = (x);						\
-	write &= mask;							\
-} while (0)
-
-#define OUT_RING_REG( reg, val ) do {					\
-	OUT_RING( CP_PACKET0( reg, 0 ) );				\
-	OUT_RING( val );						\
-} while (0)
-
-#define OUT_RING_TABLE( tab, sz ) do {					\
-	int _size = (sz);					\
-	int *_tab = (int *)(tab);				\
-								\
-	if (write + _size > mask) {				\
-		int _i = (mask+1) - write;			\
-		_size -= _i;					\
-		while (_i > 0 ) {				\
-			*(int *)(ring + write) = *_tab++;	\
-			write++;				\
-			_i--;					\
-		}						\
-		write = 0;					\
-		_tab += _i;					\
-	}							\
-	while (_size > 0) {					\
-		*(ring + write) = *_tab++;			\
-		write++;					\
-		_size--;					\
-	}							\
-	write &= mask;						\
-} while (0)
-
-/**
- * Copy given number of dwords from drm buffer to the ring buffer.
- */
-#define OUT_RING_DRM_BUFFER(buf, sz) do {				\
-	int _size = (sz) * 4;						\
-	struct drm_buffer *_buf = (buf);				\
-	int _part_size;							\
-	while (_size > 0) {						\
-		_part_size = _size;					\
-									\
-		if (write + _part_size/4 > mask)			\
-			_part_size = ((mask + 1) - write)*4;		\
-									\
-		if (drm_buffer_index(_buf) + _part_size > PAGE_SIZE)	\
-			_part_size = PAGE_SIZE - drm_buffer_index(_buf);\
-									\
-									\
-									\
-		memcpy(ring + write, &_buf->data[drm_buffer_page(_buf)]	\
-			[drm_buffer_index(_buf)], _part_size);		\
-									\
-		_size -= _part_size;					\
-		write = (write + _part_size/4) & mask;			\
-		drm_buffer_advance(_buf, _part_size);			\
-	}								\
-} while (0)
-
-
-#endif				/* CONFIG_DRM_RADEON_UMS */
-
 #endif				/* __RADEON_DRV_H__ */
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index adc44bb..d2e628e 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -282,7 +282,7 @@
 
 	}
 	if (fb && ret) {
-		drm_gem_object_unreference(gobj);
+		drm_gem_object_unreference_unlocked(gobj);
 		drm_framebuffer_unregister_private(fb);
 		drm_framebuffer_cleanup(fb);
 		kfree(fb);
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index df09ca7..05815c4 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -130,7 +130,7 @@
 		      struct radeon_fence **fence,
 		      int ring)
 {
-	u64 seq = ++rdev->fence_drv[ring].sync_seq[ring];
+	u64 seq;
 
 	/* we are protected by the ring emission mutex */
 	*fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL);
@@ -138,7 +138,7 @@
 		return -ENOMEM;
 	}
 	(*fence)->rdev = rdev;
-	(*fence)->seq = seq;
+	(*fence)->seq = seq = ++rdev->fence_drv[ring].sync_seq[ring];
 	(*fence)->ring = ring;
 	(*fence)->is_vm_update = false;
 	fence_init(&(*fence)->base, &radeon_fence_ops,
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c
deleted file mode 100644
index 688afb6..0000000
--- a/drivers/gpu/drm/radeon/radeon_irq.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */
-/*
- * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
- *
- * The Weather Channel (TM) funded Tungsten Graphics to develop the
- * initial release of the Radeon 8500 driver under the XFree86 license.
- * This notice must be preserved.
- *
- * 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
- * PRECISION INSIGHT 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.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- *    Michel D�zer <michel@daenzer.net>
- *
- * ------------------------ This file is DEPRECATED! -------------------------
- */
-
-#include <drm/drmP.h>
-#include <drm/radeon_drm.h>
-#include "radeon_drv.h"
-
-void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	if (state)
-		dev_priv->irq_enable_reg |= mask;
-	else
-		dev_priv->irq_enable_reg &= ~mask;
-
-	if (dev->irq_enabled)
-		RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
-}
-
-static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	if (state)
-		dev_priv->r500_disp_irq_reg |= mask;
-	else
-		dev_priv->r500_disp_irq_reg &= ~mask;
-
-	if (dev->irq_enabled)
-		RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
-}
-
-int radeon_enable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
-		switch (pipe) {
-		case 0:
-			r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1);
-			break;
-		case 1:
-			r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 1);
-			break;
-		default:
-			DRM_ERROR("tried to enable vblank on non-existent crtc %u\n",
-				  pipe);
-			return -EINVAL;
-		}
-	} else {
-		switch (pipe) {
-		case 0:
-			radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
-			break;
-		case 1:
-			radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
-			break;
-		default:
-			DRM_ERROR("tried to enable vblank on non-existent crtc %u\n",
-				  pipe);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-void radeon_disable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
-		switch (pipe) {
-		case 0:
-			r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0);
-			break;
-		case 1:
-			r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 0);
-			break;
-		default:
-			DRM_ERROR("tried to enable vblank on non-existent crtc %u\n",
-				  pipe);
-			break;
-		}
-	} else {
-		switch (pipe) {
-		case 0:
-			radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
-			break;
-		case 1:
-			radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
-			break;
-		default:
-			DRM_ERROR("tried to enable vblank on non-existent crtc %u\n",
-				  pipe);
-			break;
-		}
-	}
-}
-
-static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
-{
-	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS);
-	u32 irq_mask = RADEON_SW_INT_TEST;
-
-	*r500_disp_int = 0;
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
-		/* vbl interrupts in a different place */
-
-		if (irqs & R500_DISPLAY_INT_STATUS) {
-			/* if a display interrupt */
-			u32 disp_irq;
-
-			disp_irq = RADEON_READ(R500_DISP_INTERRUPT_STATUS);
-
-			*r500_disp_int = disp_irq;
-			if (disp_irq & R500_D1_VBLANK_INTERRUPT)
-				RADEON_WRITE(R500_D1MODE_VBLANK_STATUS, R500_VBLANK_ACK);
-			if (disp_irq & R500_D2_VBLANK_INTERRUPT)
-				RADEON_WRITE(R500_D2MODE_VBLANK_STATUS, R500_VBLANK_ACK);
-		}
-		irq_mask |= R500_DISPLAY_INT_STATUS;
-	} else
-		irq_mask |= RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT;
-
-	irqs &=	irq_mask;
-
-	if (irqs)
-		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
-
-	return irqs;
-}
-
-/* Interrupts - Used for device synchronization and flushing in the
- * following circumstances:
- *
- * - Exclusive FB access with hw idle:
- *    - Wait for GUI Idle (?) interrupt, then do normal flush.
- *
- * - Frame throttling, NV_fence:
- *    - Drop marker irq's into command stream ahead of time.
- *    - Wait on irq's with lock *not held*
- *    - Check each for termination condition
- *
- * - Internally in cp_getbuffer, etc:
- *    - as above, but wait with lock held???
- *
- * NOTE: These functions are misleadingly named -- the irq's aren't
- * tied to dma at all, this is just a hangover from dri prehistory.
- */
-
-irqreturn_t radeon_driver_irq_handler(int irq, void *arg)
-{
-	struct drm_device *dev = (struct drm_device *) arg;
-	drm_radeon_private_t *dev_priv =
-	    (drm_radeon_private_t *) dev->dev_private;
-	u32 stat;
-	u32 r500_disp_int;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return IRQ_NONE;
-
-	/* Only consider the bits we're interested in - others could be used
-	 * outside the DRM
-	 */
-	stat = radeon_acknowledge_irqs(dev_priv, &r500_disp_int);
-	if (!stat)
-		return IRQ_NONE;
-
-	stat &= dev_priv->irq_enable_reg;
-
-	/* SW interrupt */
-	if (stat & RADEON_SW_INT_TEST)
-		wake_up(&dev_priv->swi_queue);
-
-	/* VBLANK interrupt */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
-		if (r500_disp_int & R500_D1_VBLANK_INTERRUPT)
-			drm_handle_vblank(dev, 0);
-		if (r500_disp_int & R500_D2_VBLANK_INTERRUPT)
-			drm_handle_vblank(dev, 1);
-	} else {
-		if (stat & RADEON_CRTC_VBLANK_STAT)
-			drm_handle_vblank(dev, 0);
-		if (stat & RADEON_CRTC2_VBLANK_STAT)
-			drm_handle_vblank(dev, 1);
-	}
-	return IRQ_HANDLED;
-}
-
-static int radeon_emit_irq(struct drm_device * dev)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	unsigned int ret;
-	RING_LOCALS;
-
-	atomic_inc(&dev_priv->swi_emitted);
-	ret = atomic_read(&dev_priv->swi_emitted);
-
-	BEGIN_RING(4);
-	OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
-	OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
-	ADVANCE_RING();
-	COMMIT_RING();
-
-	return ret;
-}
-
-static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
-{
-	drm_radeon_private_t *dev_priv =
-	    (drm_radeon_private_t *) dev->dev_private;
-	int ret = 0;
-
-	if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
-		return 0;
-
-	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-	DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * HZ,
-		    RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
-
-	return ret;
-}
-
-u32 radeon_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-
-	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
-		return -EINVAL;
-	}
-
-	if (pipe > 1) {
-		DRM_ERROR("Invalid crtc %u\n", pipe);
-		return -EINVAL;
-	}
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
-		if (pipe == 0)
-			return RADEON_READ(R500_D1CRTC_FRAME_COUNT);
-		else
-			return RADEON_READ(R500_D2CRTC_FRAME_COUNT);
-	} else {
-		if (pipe == 0)
-			return RADEON_READ(RADEON_CRTC_CRNT_FRAME);
-		else
-			return RADEON_READ(RADEON_CRTC2_CRNT_FRAME);
-	}
-}
-
-/* Needs the lock as it touches the ring.
- */
-int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_irq_emit_t *emit = data;
-	int result;
-
-	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
-		return -EINVAL;
-	}
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return -EINVAL;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	result = radeon_emit_irq(dev);
-
-	if (copy_to_user(emit->irq_seq, &result, sizeof(int))) {
-		DRM_ERROR("copy_to_user\n");
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-/* Doesn't need the hardware lock.
- */
-int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_irq_wait_t *irqwait = data;
-
-	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
-		return -EINVAL;
-	}
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return -EINVAL;
-
-	return radeon_wait_irq(dev, irqwait->irq_seq);
-}
-
-/* drm_dma.h hooks
-*/
-void radeon_driver_irq_preinstall(struct drm_device * dev)
-{
-	drm_radeon_private_t *dev_priv =
-	    (drm_radeon_private_t *) dev->dev_private;
-	u32 dummy;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return;
-
-	/* Disable *all* interrupts */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
-		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
-	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
-
-	/* Clear bits if they're already high */
-	radeon_acknowledge_irqs(dev_priv, &dummy);
-}
-
-int radeon_driver_irq_postinstall(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv =
-	    (drm_radeon_private_t *) dev->dev_private;
-
-	atomic_set(&dev_priv->swi_emitted, 0);
-	init_waitqueue_head(&dev_priv->swi_queue);
-
-	dev->max_vblank_count = 0x001fffff;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return 0;
-
-	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
-
-	return 0;
-}
-
-void radeon_driver_irq_uninstall(struct drm_device * dev)
-{
-	drm_radeon_private_t *dev_priv =
-	    (drm_radeon_private_t *) dev->dev_private;
-	if (!dev_priv)
-		return;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
-		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
-	/* Disable *all* interrupts */
-	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
-}
-
-
-int radeon_vblank_crtc_get(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-
-	return dev_priv->vblank_crtc;
-}
-
-int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
-{
-	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-	if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
-		DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
-		return -EINVAL;
-	}
-	dev_priv->vblank_crtc = (unsigned int)value;
-	return 0;
-}
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index d290a8a..414953c 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -748,19 +748,19 @@
  * radeon_get_vblank_counter_kms - get frame count
  *
  * @dev: drm dev pointer
- * @crtc: crtc to get the frame count from
+ * @pipe: crtc to get the frame count from
  *
  * Gets the frame count on the requested crtc (all asics).
  * Returns frame count on success, -EINVAL on failure.
  */
-u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
+u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe)
 {
 	int vpos, hpos, stat;
 	u32 count;
 	struct radeon_device *rdev = dev->dev_private;
 
-	if (crtc < 0 || crtc >= rdev->num_crtc) {
-		DRM_ERROR("Invalid crtc %d\n", crtc);
+	if (pipe >= rdev->num_crtc) {
+		DRM_ERROR("Invalid crtc %u\n", pipe);
 		return -EINVAL;
 	}
 
@@ -772,29 +772,29 @@
 	 * and start of vsync, so vpos >= 0 means to bump the hw frame counter
 	 * result by 1 to give the proper appearance to caller.
 	 */
-	if (rdev->mode_info.crtcs[crtc]) {
+	if (rdev->mode_info.crtcs[pipe]) {
 		/* Repeat readout if needed to provide stable result if
 		 * we cross start of vsync during the queries.
 		 */
 		do {
-			count = radeon_get_vblank_counter(rdev, crtc);
+			count = radeon_get_vblank_counter(rdev, pipe);
 			/* Ask radeon_get_crtc_scanoutpos to return vpos as
 			 * distance to start of vblank, instead of regular
 			 * vertical scanout pos.
 			 */
 			stat = radeon_get_crtc_scanoutpos(
-				dev, crtc, GET_DISTANCE_TO_VBLANKSTART,
+				dev, pipe, GET_DISTANCE_TO_VBLANKSTART,
 				&vpos, &hpos, NULL, NULL,
-				&rdev->mode_info.crtcs[crtc]->base.hwmode);
-		} while (count != radeon_get_vblank_counter(rdev, crtc));
+				&rdev->mode_info.crtcs[pipe]->base.hwmode);
+		} while (count != radeon_get_vblank_counter(rdev, pipe));
 
 		if (((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) !=
 		    (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE))) {
 			DRM_DEBUG_VBL("Query failed! stat %d\n", stat);
 		}
 		else {
-			DRM_DEBUG_VBL("crtc %d: dist from vblank start %d\n",
-				      crtc, vpos);
+			DRM_DEBUG_VBL("crtc %u: dist from vblank start %d\n",
+				      pipe, vpos);
 
 			/* Bump counter if we are at >= leading edge of vblank,
 			 * but before vsync where vpos would turn negative and
@@ -806,7 +806,7 @@
 	}
 	else {
 	    /* Fallback to use value as is. */
-	    count = radeon_get_vblank_counter(rdev, crtc);
+	    count = radeon_get_vblank_counter(rdev, pipe);
 	    DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n");
 	}
 
diff --git a/drivers/gpu/drm/radeon/radeon_mem.c b/drivers/gpu/drm/radeon/radeon_mem.c
deleted file mode 100644
index 146d253..0000000
--- a/drivers/gpu/drm/radeon/radeon_mem.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */
-/*
- * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
- *
- * The Weather Channel (TM) funded Tungsten Graphics to develop the
- * initial release of the Radeon 8500 driver under the XFree86 license.
- * This notice must be preserved.
- *
- * 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
- * PRECISION INSIGHT 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.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- *
- * ------------------------ This file is DEPRECATED! -------------------------
- */
-
-#include <drm/drmP.h>
-#include <drm/radeon_drm.h>
-#include "radeon_drv.h"
-
-/* Very simple allocator for GART memory, working on a static range
- * already mapped into each client's address space.
- */
-
-static struct mem_block *split_block(struct mem_block *p, int start, int size,
-				     struct drm_file *file_priv)
-{
-	/* Maybe cut off the start of an existing block */
-	if (start > p->start) {
-		struct mem_block *newblock = kmalloc(sizeof(*newblock),
-						     GFP_KERNEL);
-		if (!newblock)
-			goto out;
-		newblock->start = start;
-		newblock->size = p->size - (start - p->start);
-		newblock->file_priv = NULL;
-		newblock->next = p->next;
-		newblock->prev = p;
-		p->next->prev = newblock;
-		p->next = newblock;
-		p->size -= newblock->size;
-		p = newblock;
-	}
-
-	/* Maybe cut off the end of an existing block */
-	if (size < p->size) {
-		struct mem_block *newblock = kmalloc(sizeof(*newblock),
-						     GFP_KERNEL);
-		if (!newblock)
-			goto out;
-		newblock->start = start + size;
-		newblock->size = p->size - size;
-		newblock->file_priv = NULL;
-		newblock->next = p->next;
-		newblock->prev = p;
-		p->next->prev = newblock;
-		p->next = newblock;
-		p->size = size;
-	}
-
-      out:
-	/* Our block is in the middle */
-	p->file_priv = file_priv;
-	return p;
-}
-
-static struct mem_block *alloc_block(struct mem_block *heap, int size,
-				     int align2, struct drm_file *file_priv)
-{
-	struct mem_block *p;
-	int mask = (1 << align2) - 1;
-
-	list_for_each(p, heap) {
-		int start = (p->start + mask) & ~mask;
-		if (p->file_priv == NULL && start + size <= p->start + p->size)
-			return split_block(p, start, size, file_priv);
-	}
-
-	return NULL;
-}
-
-static struct mem_block *find_block(struct mem_block *heap, int start)
-{
-	struct mem_block *p;
-
-	list_for_each(p, heap)
-	    if (p->start == start)
-		return p;
-
-	return NULL;
-}
-
-static void free_block(struct mem_block *p)
-{
-	p->file_priv = NULL;
-
-	/* Assumes a single contiguous range.  Needs a special file_priv in
-	 * 'heap' to stop it being subsumed.
-	 */
-	if (p->next->file_priv == NULL) {
-		struct mem_block *q = p->next;
-		p->size += q->size;
-		p->next = q->next;
-		p->next->prev = p;
-		kfree(q);
-	}
-
-	if (p->prev->file_priv == NULL) {
-		struct mem_block *q = p->prev;
-		q->size += p->size;
-		q->next = p->next;
-		q->next->prev = q;
-		kfree(p);
-	}
-}
-
-/* Initialize.  How to check for an uninitialized heap?
- */
-static int init_heap(struct mem_block **heap, int start, int size)
-{
-	struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
-
-	if (!blocks)
-		return -ENOMEM;
-
-	*heap = kzalloc(sizeof(**heap), GFP_KERNEL);
-	if (!*heap) {
-		kfree(blocks);
-		return -ENOMEM;
-	}
-
-	blocks->start = start;
-	blocks->size = size;
-	blocks->file_priv = NULL;
-	blocks->next = blocks->prev = *heap;
-
-	(*heap)->file_priv = (struct drm_file *) - 1;
-	(*heap)->next = (*heap)->prev = blocks;
-	return 0;
-}
-
-/* Free all blocks associated with the releasing file.
- */
-void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap)
-{
-	struct mem_block *p;
-
-	if (!heap || !heap->next)
-		return;
-
-	list_for_each(p, heap) {
-		if (p->file_priv == file_priv)
-			p->file_priv = NULL;
-	}
-
-	/* Assumes a single contiguous range.  Needs a special file_priv in
-	 * 'heap' to stop it being subsumed.
-	 */
-	list_for_each(p, heap) {
-		while (p->file_priv == NULL && p->next->file_priv == NULL) {
-			struct mem_block *q = p->next;
-			p->size += q->size;
-			p->next = q->next;
-			p->next->prev = p;
-			kfree(q);
-		}
-	}
-}
-
-/* Shutdown.
- */
-void radeon_mem_takedown(struct mem_block **heap)
-{
-	struct mem_block *p;
-
-	if (!*heap)
-		return;
-
-	for (p = (*heap)->next; p != *heap;) {
-		struct mem_block *q = p;
-		p = p->next;
-		kfree(q);
-	}
-
-	kfree(*heap);
-	*heap = NULL;
-}
-
-/* IOCTL HANDLERS */
-
-static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region)
-{
-	switch (region) {
-	case RADEON_MEM_REGION_GART:
-		return &dev_priv->gart_heap;
-	case RADEON_MEM_REGION_FB:
-		return &dev_priv->fb_heap;
-	default:
-		return NULL;
-	}
-}
-
-int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_mem_alloc_t *alloc = data;
-	struct mem_block *block, **heap;
-
-	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
-		return -EINVAL;
-	}
-
-	heap = get_heap(dev_priv, alloc->region);
-	if (!heap || !*heap)
-		return -EFAULT;
-
-	/* Make things easier on ourselves: all allocations at least
-	 * 4k aligned.
-	 */
-	if (alloc->alignment < 12)
-		alloc->alignment = 12;
-
-	block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv);
-
-	if (!block)
-		return -ENOMEM;
-
-	if (copy_to_user(alloc->region_offset, &block->start,
-			     sizeof(int))) {
-		DRM_ERROR("copy_to_user\n");
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_mem_free_t *memfree = data;
-	struct mem_block *block, **heap;
-
-	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
-		return -EINVAL;
-	}
-
-	heap = get_heap(dev_priv, memfree->region);
-	if (!heap || !*heap)
-		return -EFAULT;
-
-	block = find_block(*heap, memfree->region_offset);
-	if (!block)
-		return -EFAULT;
-
-	if (block->file_priv != file_priv)
-		return -EPERM;
-
-	free_block(block);
-	return 0;
-}
-
-int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_mem_init_heap_t *initheap = data;
-	struct mem_block **heap;
-
-	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
-		return -EINVAL;
-	}
-
-	heap = get_heap(dev_priv, initheap->region);
-	if (!heap)
-		return -EFAULT;
-
-	if (*heap) {
-		DRM_ERROR("heap already initialized?");
-		return -EFAULT;
-	}
-
-	return init_heap(heap, initheap->start, initheap->size);
-}
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index cddd41b..bb75201a 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -757,8 +757,10 @@
 extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
 extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
 				    struct drm_connector *connector);
-int radeon_dp_get_max_link_rate(struct drm_connector *connector,
-				const u8 *dpcd);
+extern int radeon_dp_get_dp_link_config(struct drm_connector *connector,
+					const u8 *dpcd,
+					unsigned pix_clock,
+					unsigned *dp_lanes, unsigned *dp_rate);
 extern void radeon_dp_set_rx_power_state(struct drm_connector *connector,
 					 u8 power_state);
 extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector);
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 59abebd..460c8f2 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -713,7 +713,7 @@
 static umode_t hwmon_attributes_visible(struct kobject *kobj,
 					struct attribute *attr, int index)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
+	struct device *dev = kobj_to_dev(kobj);
 	struct radeon_device *rdev = dev_get_drvdata(dev);
 	umode_t effective_mode = attr->mode;
 
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
deleted file mode 100644
index 15aee72..0000000
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ /dev/null
@@ -1,3261 +0,0 @@
-/* radeon_state.c -- State support for Radeon -*- linux-c -*- */
-/*
- * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT 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.
- *
- * Authors:
- *    Gareth Hughes <gareth@valinux.com>
- *    Kevin E. Martin <martin@valinux.com>
- *
- * ------------------------ This file is DEPRECATED! -------------------------
- */
-
-#include <drm/drmP.h>
-#include <drm/radeon_drm.h>
-#include "radeon_drv.h"
-#include "drm_buffer.h"
-
-/* ================================================================
- * Helper functions for client state checking and fixup
- */
-
-static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
-						    dev_priv,
-						    struct drm_file * file_priv,
-						    u32 *offset)
-{
-	u64 off = *offset;
-	u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1;
-	struct drm_radeon_driver_file_fields *radeon_priv;
-
-	/* Hrm ... the story of the offset ... So this function converts
-	 * the various ideas of what userland clients might have for an
-	 * offset in the card address space into an offset into the card
-	 * address space :) So with a sane client, it should just keep
-	 * the value intact and just do some boundary checking. However,
-	 * not all clients are sane. Some older clients pass us 0 based
-	 * offsets relative to the start of the framebuffer and some may
-	 * assume the AGP aperture it appended to the framebuffer, so we
-	 * try to detect those cases and fix them up.
-	 *
-	 * Note: It might be a good idea here to make sure the offset lands
-	 * in some "allowed" area to protect things like the PCIE GART...
-	 */
-
-	/* First, the best case, the offset already lands in either the
-	 * framebuffer or the GART mapped space
-	 */
-	if (radeon_check_offset(dev_priv, off))
-		return 0;
-
-	/* Ok, that didn't happen... now check if we have a zero based
-	 * offset that fits in the framebuffer + gart space, apply the
-	 * magic offset we get from SETPARAM or calculated from fb_location
-	 */
-	if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
-		radeon_priv = file_priv->driver_priv;
-		off += radeon_priv->radeon_fb_delta;
-	}
-
-	/* Finally, assume we aimed at a GART offset if beyond the fb */
-	if (off > fb_end)
-		off = off - fb_end - 1 + dev_priv->gart_vm_start;
-
-	/* Now recheck and fail if out of bounds */
-	if (radeon_check_offset(dev_priv, off)) {
-		DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
-		*offset = off;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
-						     dev_priv,
-						     struct drm_file *file_priv,
-						     int id, struct drm_buffer *buf)
-{
-	u32 *data;
-	switch (id) {
-
-	case RADEON_EMIT_PP_MISC:
-		data = drm_buffer_pointer_to_dword(buf,
-			(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4);
-
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
-			DRM_ERROR("Invalid depth buffer offset\n");
-			return -EINVAL;
-		}
-		dev_priv->have_z_offset = 1;
-		break;
-
-	case RADEON_EMIT_PP_CNTL:
-		data = drm_buffer_pointer_to_dword(buf,
-			(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4);
-
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
-			DRM_ERROR("Invalid colour buffer offset\n");
-			return -EINVAL;
-		}
-		break;
-
-	case R200_EMIT_PP_TXOFFSET_0:
-	case R200_EMIT_PP_TXOFFSET_1:
-	case R200_EMIT_PP_TXOFFSET_2:
-	case R200_EMIT_PP_TXOFFSET_3:
-	case R200_EMIT_PP_TXOFFSET_4:
-	case R200_EMIT_PP_TXOFFSET_5:
-		data = drm_buffer_pointer_to_dword(buf, 0);
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
-			DRM_ERROR("Invalid R200 texture offset\n");
-			return -EINVAL;
-		}
-		break;
-
-	case RADEON_EMIT_PP_TXFILTER_0:
-	case RADEON_EMIT_PP_TXFILTER_1:
-	case RADEON_EMIT_PP_TXFILTER_2:
-		data = drm_buffer_pointer_to_dword(buf,
-			(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4);
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
-			DRM_ERROR("Invalid R100 texture offset\n");
-			return -EINVAL;
-		}
-		break;
-
-	case R200_EMIT_PP_CUBIC_OFFSETS_0:
-	case R200_EMIT_PP_CUBIC_OFFSETS_1:
-	case R200_EMIT_PP_CUBIC_OFFSETS_2:
-	case R200_EMIT_PP_CUBIC_OFFSETS_3:
-	case R200_EMIT_PP_CUBIC_OFFSETS_4:
-	case R200_EMIT_PP_CUBIC_OFFSETS_5:{
-			int i;
-			for (i = 0; i < 5; i++) {
-				data = drm_buffer_pointer_to_dword(buf, i);
-				if (radeon_check_and_fixup_offset(dev_priv,
-								  file_priv,
-								  data)) {
-					DRM_ERROR
-					    ("Invalid R200 cubic texture offset\n");
-					return -EINVAL;
-				}
-			}
-			break;
-		}
-
-	case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
-	case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
-	case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
-			int i;
-			for (i = 0; i < 5; i++) {
-				data = drm_buffer_pointer_to_dword(buf, i);
-				if (radeon_check_and_fixup_offset(dev_priv,
-								  file_priv,
-								  data)) {
-					DRM_ERROR
-					    ("Invalid R100 cubic texture offset\n");
-					return -EINVAL;
-				}
-			}
-		}
-		break;
-
-	case R200_EMIT_VAP_CTL:{
-			RING_LOCALS;
-			BEGIN_RING(2);
-			OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
-			ADVANCE_RING();
-		}
-		break;
-
-	case RADEON_EMIT_RB3D_COLORPITCH:
-	case RADEON_EMIT_RE_LINE_PATTERN:
-	case RADEON_EMIT_SE_LINE_WIDTH:
-	case RADEON_EMIT_PP_LUM_MATRIX:
-	case RADEON_EMIT_PP_ROT_MATRIX_0:
-	case RADEON_EMIT_RB3D_STENCILREFMASK:
-	case RADEON_EMIT_SE_VPORT_XSCALE:
-	case RADEON_EMIT_SE_CNTL:
-	case RADEON_EMIT_SE_CNTL_STATUS:
-	case RADEON_EMIT_RE_MISC:
-	case RADEON_EMIT_PP_BORDER_COLOR_0:
-	case RADEON_EMIT_PP_BORDER_COLOR_1:
-	case RADEON_EMIT_PP_BORDER_COLOR_2:
-	case RADEON_EMIT_SE_ZBIAS_FACTOR:
-	case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
-	case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
-	case R200_EMIT_PP_TXCBLEND_0:
-	case R200_EMIT_PP_TXCBLEND_1:
-	case R200_EMIT_PP_TXCBLEND_2:
-	case R200_EMIT_PP_TXCBLEND_3:
-	case R200_EMIT_PP_TXCBLEND_4:
-	case R200_EMIT_PP_TXCBLEND_5:
-	case R200_EMIT_PP_TXCBLEND_6:
-	case R200_EMIT_PP_TXCBLEND_7:
-	case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
-	case R200_EMIT_TFACTOR_0:
-	case R200_EMIT_VTX_FMT_0:
-	case R200_EMIT_MATRIX_SELECT_0:
-	case R200_EMIT_TEX_PROC_CTL_2:
-	case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
-	case R200_EMIT_PP_TXFILTER_0:
-	case R200_EMIT_PP_TXFILTER_1:
-	case R200_EMIT_PP_TXFILTER_2:
-	case R200_EMIT_PP_TXFILTER_3:
-	case R200_EMIT_PP_TXFILTER_4:
-	case R200_EMIT_PP_TXFILTER_5:
-	case R200_EMIT_VTE_CNTL:
-	case R200_EMIT_OUTPUT_VTX_COMP_SEL:
-	case R200_EMIT_PP_TAM_DEBUG3:
-	case R200_EMIT_PP_CNTL_X:
-	case R200_EMIT_RB3D_DEPTHXY_OFFSET:
-	case R200_EMIT_RE_AUX_SCISSOR_CNTL:
-	case R200_EMIT_RE_SCISSOR_TL_0:
-	case R200_EMIT_RE_SCISSOR_TL_1:
-	case R200_EMIT_RE_SCISSOR_TL_2:
-	case R200_EMIT_SE_VAP_CNTL_STATUS:
-	case R200_EMIT_SE_VTX_STATE_CNTL:
-	case R200_EMIT_RE_POINTSIZE:
-	case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0:
-	case R200_EMIT_PP_CUBIC_FACES_0:
-	case R200_EMIT_PP_CUBIC_FACES_1:
-	case R200_EMIT_PP_CUBIC_FACES_2:
-	case R200_EMIT_PP_CUBIC_FACES_3:
-	case R200_EMIT_PP_CUBIC_FACES_4:
-	case R200_EMIT_PP_CUBIC_FACES_5:
-	case RADEON_EMIT_PP_TEX_SIZE_0:
-	case RADEON_EMIT_PP_TEX_SIZE_1:
-	case RADEON_EMIT_PP_TEX_SIZE_2:
-	case R200_EMIT_RB3D_BLENDCOLOR:
-	case R200_EMIT_TCL_POINT_SPRITE_CNTL:
-	case RADEON_EMIT_PP_CUBIC_FACES_0:
-	case RADEON_EMIT_PP_CUBIC_FACES_1:
-	case RADEON_EMIT_PP_CUBIC_FACES_2:
-	case R200_EMIT_PP_TRI_PERF_CNTL:
-	case R200_EMIT_PP_AFS_0:
-	case R200_EMIT_PP_AFS_1:
-	case R200_EMIT_ATF_TFACTOR:
-	case R200_EMIT_PP_TXCTLALL_0:
-	case R200_EMIT_PP_TXCTLALL_1:
-	case R200_EMIT_PP_TXCTLALL_2:
-	case R200_EMIT_PP_TXCTLALL_3:
-	case R200_EMIT_PP_TXCTLALL_4:
-	case R200_EMIT_PP_TXCTLALL_5:
-	case R200_EMIT_VAP_PVS_CNTL:
-		/* These packets don't contain memory offsets */
-		break;
-
-	default:
-		DRM_ERROR("Unknown state packet ID %d\n", id);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int radeon_check_and_fixup_packet3(drm_radeon_private_t *
-					  dev_priv,
-					  struct drm_file *file_priv,
-					  drm_radeon_kcmd_buffer_t *
-					  cmdbuf,
-					  unsigned int *cmdsz)
-{
-	u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
-	u32 offset, narrays;
-	int count, i, k;
-
-	count = ((*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16);
-	*cmdsz = 2 + count;
-
-	if ((*cmd & 0xc0000000) != RADEON_CP_PACKET3) {
-		DRM_ERROR("Not a type 3 packet\n");
-		return -EINVAL;
-	}
-
-	if (4 * *cmdsz > drm_buffer_unprocessed(cmdbuf->buffer)) {
-		DRM_ERROR("Packet size larger than size of data provided\n");
-		return -EINVAL;
-	}
-
-	switch (*cmd & 0xff00) {
-	/* XXX Are there old drivers needing other packets? */
-
-	case RADEON_3D_DRAW_IMMD:
-	case RADEON_3D_DRAW_VBUF:
-	case RADEON_3D_DRAW_INDX:
-	case RADEON_WAIT_FOR_IDLE:
-	case RADEON_CP_NOP:
-	case RADEON_3D_CLEAR_ZMASK:
-/*	case RADEON_CP_NEXT_CHAR:
-	case RADEON_CP_PLY_NEXTSCAN:
-	case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */
-		/* these packets are safe */
-		break;
-
-	case RADEON_CP_3D_DRAW_IMMD_2:
-	case RADEON_CP_3D_DRAW_VBUF_2:
-	case RADEON_CP_3D_DRAW_INDX_2:
-	case RADEON_3D_CLEAR_HIZ:
-		/* safe but r200 only */
-		if (dev_priv->microcode_version != UCODE_R200) {
-			DRM_ERROR("Invalid 3d packet for r100-class chip\n");
-			return -EINVAL;
-		}
-		break;
-
-	case RADEON_3D_LOAD_VBPNTR:
-
-		if (count > 18) { /* 12 arrays max */
-			DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
-				  count);
-			return -EINVAL;
-		}
-
-		/* carefully check packet contents */
-		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
-
-		narrays = *cmd & ~0xc000;
-		k = 0;
-		i = 2;
-		while ((k < narrays) && (i < (count + 2))) {
-			i++;		/* skip attribute field */
-			cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
-			if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-							  cmd)) {
-				DRM_ERROR
-				    ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
-				     k, i);
-				return -EINVAL;
-			}
-			k++;
-			i++;
-			if (k == narrays)
-				break;
-			/* have one more to process, they come in pairs */
-			cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
-
-			if (radeon_check_and_fixup_offset(dev_priv,
-							  file_priv, cmd))
-			{
-				DRM_ERROR
-				    ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
-				     k, i);
-				return -EINVAL;
-			}
-			k++;
-			i++;
-		}
-		/* do the counts match what we expect ? */
-		if ((k != narrays) || (i != (count + 2))) {
-			DRM_ERROR
-			    ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
-			      k, i, narrays, count + 1);
-			return -EINVAL;
-		}
-		break;
-
-	case RADEON_3D_RNDR_GEN_INDX_PRIM:
-		if (dev_priv->microcode_version != UCODE_R100) {
-			DRM_ERROR("Invalid 3d packet for r200-class chip\n");
-			return -EINVAL;
-		}
-
-		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
-				DRM_ERROR("Invalid rndr_gen_indx offset\n");
-				return -EINVAL;
-		}
-		break;
-
-	case RADEON_CP_INDX_BUFFER:
-		if (dev_priv->microcode_version != UCODE_R200) {
-			DRM_ERROR("Invalid 3d packet for r100-class chip\n");
-			return -EINVAL;
-		}
-
-		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
-		if ((*cmd & 0x8000ffff) != 0x80000810) {
-			DRM_ERROR("Invalid indx_buffer reg address %08X\n", *cmd);
-			return -EINVAL;
-		}
-		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
-			DRM_ERROR("Invalid indx_buffer offset is %08X\n", *cmd);
-			return -EINVAL;
-		}
-		break;
-
-	case RADEON_CNTL_HOSTDATA_BLT:
-	case RADEON_CNTL_PAINT_MULTI:
-	case RADEON_CNTL_BITBLT_MULTI:
-		/* MSB of opcode: next DWORD GUI_CNTL */
-		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
-		if (*cmd & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
-			      | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-			u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
-			offset = *cmd2 << 10;
-			if (radeon_check_and_fixup_offset
-			    (dev_priv, file_priv, &offset)) {
-				DRM_ERROR("Invalid first packet offset\n");
-				return -EINVAL;
-			}
-			*cmd2 = (*cmd2 & 0xffc00000) | offset >> 10;
-		}
-
-		if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
-		    (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-			u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
-			offset = *cmd3 << 10;
-			if (radeon_check_and_fixup_offset
-			    (dev_priv, file_priv, &offset)) {
-				DRM_ERROR("Invalid second packet offset\n");
-				return -EINVAL;
-			}
-			*cmd3 = (*cmd3 & 0xffc00000) | offset >> 10;
-		}
-		break;
-
-	default:
-		DRM_ERROR("Invalid packet type %x\n", *cmd & 0xff00);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* ================================================================
- * CP hardware state programming functions
- */
-
-static void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
-				  struct drm_clip_rect * box)
-{
-	RING_LOCALS;
-
-	DRM_DEBUG("   box:  x1=%d y1=%d  x2=%d y2=%d\n",
-		  box->x1, box->y1, box->x2, box->y2);
-
-	BEGIN_RING(4);
-	OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
-	OUT_RING((box->y1 << 16) | box->x1);
-	OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
-	OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1));
-	ADVANCE_RING();
-}
-
-/* Emit 1.1 state
- */
-static int radeon_emit_state(drm_radeon_private_t * dev_priv,
-			     struct drm_file *file_priv,
-			     drm_radeon_context_regs_t * ctx,
-			     drm_radeon_texture_regs_t * tex,
-			     unsigned int dirty)
-{
-	RING_LOCALS;
-	DRM_DEBUG("dirty=0x%08x\n", dirty);
-
-	if (dirty & RADEON_UPLOAD_CONTEXT) {
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-						  &ctx->rb3d_depthoffset)) {
-			DRM_ERROR("Invalid depth buffer offset\n");
-			return -EINVAL;
-		}
-
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-						  &ctx->rb3d_coloroffset)) {
-			DRM_ERROR("Invalid depth buffer offset\n");
-			return -EINVAL;
-		}
-
-		BEGIN_RING(14);
-		OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6));
-		OUT_RING(ctx->pp_misc);
-		OUT_RING(ctx->pp_fog_color);
-		OUT_RING(ctx->re_solid_color);
-		OUT_RING(ctx->rb3d_blendcntl);
-		OUT_RING(ctx->rb3d_depthoffset);
-		OUT_RING(ctx->rb3d_depthpitch);
-		OUT_RING(ctx->rb3d_zstencilcntl);
-		OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2));
-		OUT_RING(ctx->pp_cntl);
-		OUT_RING(ctx->rb3d_cntl);
-		OUT_RING(ctx->rb3d_coloroffset);
-		OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
-		OUT_RING(ctx->rb3d_colorpitch);
-		ADVANCE_RING();
-	}
-
-	if (dirty & RADEON_UPLOAD_VERTFMT) {
-		BEGIN_RING(2);
-		OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0));
-		OUT_RING(ctx->se_coord_fmt);
-		ADVANCE_RING();
-	}
-
-	if (dirty & RADEON_UPLOAD_LINE) {
-		BEGIN_RING(5);
-		OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1));
-		OUT_RING(ctx->re_line_pattern);
-		OUT_RING(ctx->re_line_state);
-		OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0));
-		OUT_RING(ctx->se_line_width);
-		ADVANCE_RING();
-	}
-
-	if (dirty & RADEON_UPLOAD_BUMPMAP) {
-		BEGIN_RING(5);
-		OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0));
-		OUT_RING(ctx->pp_lum_matrix);
-		OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1));
-		OUT_RING(ctx->pp_rot_matrix_0);
-		OUT_RING(ctx->pp_rot_matrix_1);
-		ADVANCE_RING();
-	}
-
-	if (dirty & RADEON_UPLOAD_MASKS) {
-		BEGIN_RING(4);
-		OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2));
-		OUT_RING(ctx->rb3d_stencilrefmask);
-		OUT_RING(ctx->rb3d_ropcntl);
-		OUT_RING(ctx->rb3d_planemask);
-		ADVANCE_RING();
-	}
-
-	if (dirty & RADEON_UPLOAD_VIEWPORT) {
-		BEGIN_RING(7);
-		OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5));
-		OUT_RING(ctx->se_vport_xscale);
-		OUT_RING(ctx->se_vport_xoffset);
-		OUT_RING(ctx->se_vport_yscale);
-		OUT_RING(ctx->se_vport_yoffset);
-		OUT_RING(ctx->se_vport_zscale);
-		OUT_RING(ctx->se_vport_zoffset);
-		ADVANCE_RING();
-	}
-
-	if (dirty & RADEON_UPLOAD_SETUP) {
-		BEGIN_RING(4);
-		OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0));
-		OUT_RING(ctx->se_cntl);
-		OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0));
-		OUT_RING(ctx->se_cntl_status);
-		ADVANCE_RING();
-	}
-
-	if (dirty & RADEON_UPLOAD_MISC) {
-		BEGIN_RING(2);
-		OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0));
-		OUT_RING(ctx->re_misc);
-		ADVANCE_RING();
-	}
-
-	if (dirty & RADEON_UPLOAD_TEX0) {
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-						  &tex[0].pp_txoffset)) {
-			DRM_ERROR("Invalid texture offset for unit 0\n");
-			return -EINVAL;
-		}
-
-		BEGIN_RING(9);
-		OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5));
-		OUT_RING(tex[0].pp_txfilter);
-		OUT_RING(tex[0].pp_txformat);
-		OUT_RING(tex[0].pp_txoffset);
-		OUT_RING(tex[0].pp_txcblend);
-		OUT_RING(tex[0].pp_txablend);
-		OUT_RING(tex[0].pp_tfactor);
-		OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0));
-		OUT_RING(tex[0].pp_border_color);
-		ADVANCE_RING();
-	}
-
-	if (dirty & RADEON_UPLOAD_TEX1) {
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-						  &tex[1].pp_txoffset)) {
-			DRM_ERROR("Invalid texture offset for unit 1\n");
-			return -EINVAL;
-		}
-
-		BEGIN_RING(9);
-		OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5));
-		OUT_RING(tex[1].pp_txfilter);
-		OUT_RING(tex[1].pp_txformat);
-		OUT_RING(tex[1].pp_txoffset);
-		OUT_RING(tex[1].pp_txcblend);
-		OUT_RING(tex[1].pp_txablend);
-		OUT_RING(tex[1].pp_tfactor);
-		OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0));
-		OUT_RING(tex[1].pp_border_color);
-		ADVANCE_RING();
-	}
-
-	if (dirty & RADEON_UPLOAD_TEX2) {
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-						  &tex[2].pp_txoffset)) {
-			DRM_ERROR("Invalid texture offset for unit 2\n");
-			return -EINVAL;
-		}
-
-		BEGIN_RING(9);
-		OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5));
-		OUT_RING(tex[2].pp_txfilter);
-		OUT_RING(tex[2].pp_txformat);
-		OUT_RING(tex[2].pp_txoffset);
-		OUT_RING(tex[2].pp_txcblend);
-		OUT_RING(tex[2].pp_txablend);
-		OUT_RING(tex[2].pp_tfactor);
-		OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0));
-		OUT_RING(tex[2].pp_border_color);
-		ADVANCE_RING();
-	}
-
-	return 0;
-}
-
-/* Emit 1.2 state
- */
-static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
-			      struct drm_file *file_priv,
-			      drm_radeon_state_t * state)
-{
-	RING_LOCALS;
-
-	if (state->dirty & RADEON_UPLOAD_ZBIAS) {
-		BEGIN_RING(3);
-		OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1));
-		OUT_RING(state->context2.se_zbias_factor);
-		OUT_RING(state->context2.se_zbias_constant);
-		ADVANCE_RING();
-	}
-
-	return radeon_emit_state(dev_priv, file_priv, &state->context,
-				 state->tex, state->dirty);
-}
-
-/* New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
- * 1.3 cmdbuffers allow all previous state to be updated as well as
- * the tcl scalar and vector areas.
- */
-static struct {
-	int start;
-	int len;
-	const char *name;
-} packet[RADEON_MAX_STATE_PACKETS] = {
-	{RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
-	{RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
-	{RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
-	{RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
-	{RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
-	{RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
-	{RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
-	{RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
-	{RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
-	{RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
-	{RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
-	{RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
-	{RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
-	{RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
-	{RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
-	{RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
-	{RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
-	{RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
-	{RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
-	{RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
-	{RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
-		    "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
-	{R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
-	{R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
-	{R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
-	{R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
-	{R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
-	{R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
-	{R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
-	{R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
-	{R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
-	{R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
-	{R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
-	{R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
-	{R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
-	{R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
-	{R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
-	{R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
-	{R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
-	{R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
-	{R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
-	{R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
-	{R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
-	{R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
-	{R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
-	{R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
-	{R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
-	{R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
-	{R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
-	{R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
-	{R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1,
-	 "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
-	{R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
-	{R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
-	{R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
-	{R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
-	{R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
-	{R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
-	{R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
-	{R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
-	{R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
-	{R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
-	{R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
-		    "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
-	{R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"},	/* 61 */
-	{R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
-	{R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
-	{R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
-	{R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
-	{R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
-	{R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
-	{R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
-	{R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
-	{R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
-	{R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
-	{R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
-	{RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
-	{RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
-	{RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
-	{R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
-	{R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
-	{RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
-	{RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
-	{RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
-	{RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
-	{RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
-	{RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
-	{R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
-	{R200_PP_AFS_0, 32, "R200_PP_AFS_0"},     /* 85 */
-	{R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
-	{R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
-	{R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
-	{R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
-	{R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
-	{R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
-	{R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
-	{R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
-	{R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
-};
-
-/* ================================================================
- * Performance monitoring functions
- */
-
-static void radeon_clear_box(drm_radeon_private_t * dev_priv,
-			     struct drm_radeon_master_private *master_priv,
-			     int x, int y, int w, int h, int r, int g, int b)
-{
-	u32 color;
-	RING_LOCALS;
-
-	x += master_priv->sarea_priv->boxes[0].x1;
-	y += master_priv->sarea_priv->boxes[0].y1;
-
-	switch (dev_priv->color_fmt) {
-	case RADEON_COLOR_FORMAT_RGB565:
-		color = (((r & 0xf8) << 8) |
-			 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
-		break;
-	case RADEON_COLOR_FORMAT_ARGB8888:
-	default:
-		color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
-		break;
-	}
-
-	BEGIN_RING(4);
-	RADEON_WAIT_UNTIL_3D_IDLE();
-	OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
-	OUT_RING(0xffffffff);
-	ADVANCE_RING();
-
-	BEGIN_RING(6);
-
-	OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4));
-	OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-		 RADEON_GMC_BRUSH_SOLID_COLOR |
-		 (dev_priv->color_fmt << 8) |
-		 RADEON_GMC_SRC_DATATYPE_COLOR |
-		 RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
-
-	if (master_priv->sarea_priv->pfCurrentPage == 1) {
-		OUT_RING(dev_priv->front_pitch_offset);
-	} else {
-		OUT_RING(dev_priv->back_pitch_offset);
-	}
-
-	OUT_RING(color);
-
-	OUT_RING((x << 16) | y);
-	OUT_RING((w << 16) | h);
-
-	ADVANCE_RING();
-}
-
-static void radeon_cp_performance_boxes(drm_radeon_private_t *dev_priv, struct drm_radeon_master_private *master_priv)
-{
-	/* Collapse various things into a wait flag -- trying to
-	 * guess if userspase slept -- better just to have them tell us.
-	 */
-	if (dev_priv->stats.last_frame_reads > 1 ||
-	    dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
-		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-	}
-
-	if (dev_priv->stats.freelist_loops) {
-		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-	}
-
-	/* Purple box for page flipping
-	 */
-	if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
-		radeon_clear_box(dev_priv, master_priv, 4, 4, 8, 8, 255, 0, 255);
-
-	/* Red box if we have to wait for idle at any point
-	 */
-	if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
-		radeon_clear_box(dev_priv, master_priv, 16, 4, 8, 8, 255, 0, 0);
-
-	/* Blue box: lost context?
-	 */
-
-	/* Yellow box for texture swaps
-	 */
-	if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
-		radeon_clear_box(dev_priv, master_priv, 40, 4, 8, 8, 255, 255, 0);
-
-	/* Green box if hardware never idles (as far as we can tell)
-	 */
-	if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
-		radeon_clear_box(dev_priv, master_priv, 64, 4, 8, 8, 0, 255, 0);
-
-	/* Draw bars indicating number of buffers allocated
-	 * (not a great measure, easily confused)
-	 */
-	if (dev_priv->stats.requested_bufs) {
-		if (dev_priv->stats.requested_bufs > 100)
-			dev_priv->stats.requested_bufs = 100;
-
-		radeon_clear_box(dev_priv, master_priv, 4, 16,
-				 dev_priv->stats.requested_bufs, 4,
-				 196, 128, 128);
-	}
-
-	memset(&dev_priv->stats, 0, sizeof(dev_priv->stats));
-
-}
-
-/* ================================================================
- * CP command dispatch functions
- */
-
-static void radeon_cp_dispatch_clear(struct drm_device * dev,
-				     struct drm_master *master,
-				     drm_radeon_clear_t * clear,
-				     drm_radeon_clear_rect_t * depth_boxes)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = master->driver_priv;
-	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
-	drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
-	int nbox = sarea_priv->nbox;
-	struct drm_clip_rect *pbox = sarea_priv->boxes;
-	unsigned int flags = clear->flags;
-	u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
-	int i;
-	RING_LOCALS;
-	DRM_DEBUG("flags = 0x%x\n", flags);
-
-	dev_priv->stats.clears++;
-
-	if (sarea_priv->pfCurrentPage == 1) {
-		unsigned int tmp = flags;
-
-		flags &= ~(RADEON_FRONT | RADEON_BACK);
-		if (tmp & RADEON_FRONT)
-			flags |= RADEON_BACK;
-		if (tmp & RADEON_BACK)
-			flags |= RADEON_FRONT;
-	}
-	if (flags & (RADEON_DEPTH|RADEON_STENCIL)) {
-		if (!dev_priv->have_z_offset) {
-			printk_once(KERN_ERR "radeon: illegal depth clear request. Buggy mesa detected - please update.\n");
-			flags &= ~(RADEON_DEPTH | RADEON_STENCIL);
-		}
-	}
-
-	if (flags & (RADEON_FRONT | RADEON_BACK)) {
-
-		BEGIN_RING(4);
-
-		/* Ensure the 3D stream is idle before doing a
-		 * 2D fill to clear the front or back buffer.
-		 */
-		RADEON_WAIT_UNTIL_3D_IDLE();
-
-		OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
-		OUT_RING(clear->color_mask);
-
-		ADVANCE_RING();
-
-		/* Make sure we restore the 3D state next time.
-		 */
-		sarea_priv->ctx_owner = 0;
-
-		for (i = 0; i < nbox; i++) {
-			int x = pbox[i].x1;
-			int y = pbox[i].y1;
-			int w = pbox[i].x2 - x;
-			int h = pbox[i].y2 - y;
-
-			DRM_DEBUG("%d,%d-%d,%d flags 0x%x\n",
-				  x, y, w, h, flags);
-
-			if (flags & RADEON_FRONT) {
-				BEGIN_RING(6);
-
-				OUT_RING(CP_PACKET3
-					 (RADEON_CNTL_PAINT_MULTI, 4));
-				OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-					 RADEON_GMC_BRUSH_SOLID_COLOR |
-					 (dev_priv->
-					  color_fmt << 8) |
-					 RADEON_GMC_SRC_DATATYPE_COLOR |
-					 RADEON_ROP3_P |
-					 RADEON_GMC_CLR_CMP_CNTL_DIS);
-
-				OUT_RING(dev_priv->front_pitch_offset);
-				OUT_RING(clear->clear_color);
-
-				OUT_RING((x << 16) | y);
-				OUT_RING((w << 16) | h);
-
-				ADVANCE_RING();
-			}
-
-			if (flags & RADEON_BACK) {
-				BEGIN_RING(6);
-
-				OUT_RING(CP_PACKET3
-					 (RADEON_CNTL_PAINT_MULTI, 4));
-				OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-					 RADEON_GMC_BRUSH_SOLID_COLOR |
-					 (dev_priv->
-					  color_fmt << 8) |
-					 RADEON_GMC_SRC_DATATYPE_COLOR |
-					 RADEON_ROP3_P |
-					 RADEON_GMC_CLR_CMP_CNTL_DIS);
-
-				OUT_RING(dev_priv->back_pitch_offset);
-				OUT_RING(clear->clear_color);
-
-				OUT_RING((x << 16) | y);
-				OUT_RING((w << 16) | h);
-
-				ADVANCE_RING();
-			}
-		}
-	}
-
-	/* hyper z clear */
-	/* no docs available, based on reverse engineering by Stephane Marchesin */
-	if ((flags & (RADEON_DEPTH | RADEON_STENCIL))
-	    && (flags & RADEON_CLEAR_FASTZ)) {
-
-		int i;
-		int depthpixperline =
-		    dev_priv->depth_fmt ==
-		    RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch /
-						       2) : (dev_priv->
-							     depth_pitch / 4);
-
-		u32 clearmask;
-
-		u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth |
-		    ((clear->depth_mask & 0xff) << 24);
-
-		/* Make sure we restore the 3D state next time.
-		 * we haven't touched any "normal" state - still need this?
-		 */
-		sarea_priv->ctx_owner = 0;
-
-		if ((dev_priv->flags & RADEON_HAS_HIERZ)
-		    && (flags & RADEON_USE_HIERZ)) {
-			/* FIXME : reverse engineer that for Rx00 cards */
-			/* FIXME : the mask supposedly contains low-res z values. So can't set
-			   just to the max (0xff? or actually 0x3fff?), need to take z clear
-			   value into account? */
-			/* pattern seems to work for r100, though get slight
-			   rendering errors with glxgears. If hierz is not enabled for r100,
-			   only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
-			   other ones are ignored, and the same clear mask can be used. That's
-			   very different behaviour than R200 which needs different clear mask
-			   and different number of tiles to clear if hierz is enabled or not !?!
-			 */
-			clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f;
-		} else {
-			/* clear mask : chooses the clearing pattern.
-			   rv250: could be used to clear only parts of macrotiles
-			   (but that would get really complicated...)?
-			   bit 0 and 1 (either or both of them ?!?!) are used to
-			   not clear tile (or maybe one of the bits indicates if the tile is
-			   compressed or not), bit 2 and 3 to not clear tile 1,...,.
-			   Pattern is as follows:
-			   | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
-			   bits -------------------------------------------------
-			   | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
-			   rv100: clearmask covers 2x8 4x1 tiles, but one clear still
-			   covers 256 pixels ?!?
-			 */
-			clearmask = 0x0;
-		}
-
-		BEGIN_RING(8);
-		RADEON_WAIT_UNTIL_2D_IDLE();
-		OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE,
-			     tempRB3D_DEPTHCLEARVALUE);
-		/* what offset is this exactly ? */
-		OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0);
-		/* need ctlstat, otherwise get some strange black flickering */
-		OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT,
-			     RADEON_RB3D_ZC_FLUSH_ALL);
-		ADVANCE_RING();
-
-		for (i = 0; i < nbox; i++) {
-			int tileoffset, nrtilesx, nrtilesy, j;
-			/* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
-			if ((dev_priv->flags & RADEON_HAS_HIERZ)
-			    && !(dev_priv->microcode_version == UCODE_R200)) {
-				/* FIXME : figure this out for r200 (when hierz is enabled). Or
-				   maybe r200 actually doesn't need to put the low-res z value into
-				   the tile cache like r100, but just needs to clear the hi-level z-buffer?
-				   Works for R100, both with hierz and without.
-				   R100 seems to operate on 2x1 8x8 tiles, but...
-				   odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially
-				   problematic with resolutions which are not 64 pix aligned? */
-				tileoffset =
-				    ((pbox[i].y1 >> 3) * depthpixperline +
-				     pbox[i].x1) >> 6;
-				nrtilesx =
-				    ((pbox[i].x2 & ~63) -
-				     (pbox[i].x1 & ~63)) >> 4;
-				nrtilesy =
-				    (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
-				for (j = 0; j <= nrtilesy; j++) {
-					BEGIN_RING(4);
-					OUT_RING(CP_PACKET3
-						 (RADEON_3D_CLEAR_ZMASK, 2));
-					/* first tile */
-					OUT_RING(tileoffset * 8);
-					/* the number of tiles to clear */
-					OUT_RING(nrtilesx + 4);
-					/* clear mask : chooses the clearing pattern. */
-					OUT_RING(clearmask);
-					ADVANCE_RING();
-					tileoffset += depthpixperline >> 6;
-				}
-			} else if (dev_priv->microcode_version == UCODE_R200) {
-				/* works for rv250. */
-				/* find first macro tile (8x2 4x4 z-pixels on rv250) */
-				tileoffset =
-				    ((pbox[i].y1 >> 3) * depthpixperline +
-				     pbox[i].x1) >> 5;
-				nrtilesx =
-				    (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
-				nrtilesy =
-				    (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
-				for (j = 0; j <= nrtilesy; j++) {
-					BEGIN_RING(4);
-					OUT_RING(CP_PACKET3
-						 (RADEON_3D_CLEAR_ZMASK, 2));
-					/* first tile */
-					/* judging by the first tile offset needed, could possibly
-					   directly address/clear 4x4 tiles instead of 8x2 * 4x4
-					   macro tiles, though would still need clear mask for
-					   right/bottom if truly 4x4 granularity is desired ? */
-					OUT_RING(tileoffset * 16);
-					/* the number of tiles to clear */
-					OUT_RING(nrtilesx + 1);
-					/* clear mask : chooses the clearing pattern. */
-					OUT_RING(clearmask);
-					ADVANCE_RING();
-					tileoffset += depthpixperline >> 5;
-				}
-			} else {	/* rv 100 */
-				/* rv100 might not need 64 pix alignment, who knows */
-				/* offsets are, hmm, weird */
-				tileoffset =
-				    ((pbox[i].y1 >> 4) * depthpixperline +
-				     pbox[i].x1) >> 6;
-				nrtilesx =
-				    ((pbox[i].x2 & ~63) -
-				     (pbox[i].x1 & ~63)) >> 4;
-				nrtilesy =
-				    (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
-				for (j = 0; j <= nrtilesy; j++) {
-					BEGIN_RING(4);
-					OUT_RING(CP_PACKET3
-						 (RADEON_3D_CLEAR_ZMASK, 2));
-					OUT_RING(tileoffset * 128);
-					/* the number of tiles to clear */
-					OUT_RING(nrtilesx + 4);
-					/* clear mask : chooses the clearing pattern. */
-					OUT_RING(clearmask);
-					ADVANCE_RING();
-					tileoffset += depthpixperline >> 6;
-				}
-			}
-		}
-
-		/* TODO don't always clear all hi-level z tiles */
-		if ((dev_priv->flags & RADEON_HAS_HIERZ)
-		    && (dev_priv->microcode_version == UCODE_R200)
-		    && (flags & RADEON_USE_HIERZ))
-			/* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
-			/* FIXME : the mask supposedly contains low-res z values. So can't set
-			   just to the max (0xff? or actually 0x3fff?), need to take z clear
-			   value into account? */
-		{
-			BEGIN_RING(4);
-			OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2));
-			OUT_RING(0x0);	/* First tile */
-			OUT_RING(0x3cc0);
-			OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f);
-			ADVANCE_RING();
-		}
-	}
-
-	/* We have to clear the depth and/or stencil buffers by
-	 * rendering a quad into just those buffers.  Thus, we have to
-	 * make sure the 3D engine is configured correctly.
-	 */
-	else if ((dev_priv->microcode_version == UCODE_R200) &&
-		(flags & (RADEON_DEPTH | RADEON_STENCIL))) {
-
-		int tempPP_CNTL;
-		int tempRE_CNTL;
-		int tempRB3D_CNTL;
-		int tempRB3D_ZSTENCILCNTL;
-		int tempRB3D_STENCILREFMASK;
-		int tempRB3D_PLANEMASK;
-		int tempSE_CNTL;
-		int tempSE_VTE_CNTL;
-		int tempSE_VTX_FMT_0;
-		int tempSE_VTX_FMT_1;
-		int tempSE_VAP_CNTL;
-		int tempRE_AUX_SCISSOR_CNTL;
-
-		tempPP_CNTL = 0;
-		tempRE_CNTL = 0;
-
-		tempRB3D_CNTL = depth_clear->rb3d_cntl;
-
-		tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
-		tempRB3D_STENCILREFMASK = 0x0;
-
-		tempSE_CNTL = depth_clear->se_cntl;
-
-		/* Disable TCL */
-
-		tempSE_VAP_CNTL = (	/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK |  */
-					  (0x9 <<
-					   SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
-
-		tempRB3D_PLANEMASK = 0x0;
-
-		tempRE_AUX_SCISSOR_CNTL = 0x0;
-
-		tempSE_VTE_CNTL =
-		    SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK;
-
-		/* Vertex format (X, Y, Z, W) */
-		tempSE_VTX_FMT_0 =
-		    SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
-		    SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
-		tempSE_VTX_FMT_1 = 0x0;
-
-		/*
-		 * Depth buffer specific enables
-		 */
-		if (flags & RADEON_DEPTH) {
-			/* Enable depth buffer */
-			tempRB3D_CNTL |= RADEON_Z_ENABLE;
-		} else {
-			/* Disable depth buffer */
-			tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
-		}
-
-		/*
-		 * Stencil buffer specific enables
-		 */
-		if (flags & RADEON_STENCIL) {
-			tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
-			tempRB3D_STENCILREFMASK = clear->depth_mask;
-		} else {
-			tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
-			tempRB3D_STENCILREFMASK = 0x00000000;
-		}
-
-		if (flags & RADEON_USE_COMP_ZBUF) {
-			tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
-			    RADEON_Z_DECOMPRESSION_ENABLE;
-		}
-		if (flags & RADEON_USE_HIERZ) {
-			tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
-		}
-
-		BEGIN_RING(26);
-		RADEON_WAIT_UNTIL_2D_IDLE();
-
-		OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL);
-		OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL);
-		OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL);
-		OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
-		OUT_RING_REG(RADEON_RB3D_STENCILREFMASK,
-			     tempRB3D_STENCILREFMASK);
-		OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK);
-		OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL);
-		OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL);
-		OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0);
-		OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1);
-		OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL);
-		OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL);
-		ADVANCE_RING();
-
-		/* Make sure we restore the 3D state next time.
-		 */
-		sarea_priv->ctx_owner = 0;
-
-		for (i = 0; i < nbox; i++) {
-
-			/* Funny that this should be required --
-			 *  sets top-left?
-			 */
-			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
-
-			BEGIN_RING(14);
-			OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12));
-			OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
-				  RADEON_PRIM_WALK_RING |
-				  (3 << RADEON_NUM_VERTICES_SHIFT)));
-			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-			OUT_RING(0x3f800000);
-			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-			OUT_RING(0x3f800000);
-			OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-			OUT_RING(0x3f800000);
-			ADVANCE_RING();
-		}
-	} else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) {
-
-		int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
-
-		rb3d_cntl = depth_clear->rb3d_cntl;
-
-		if (flags & RADEON_DEPTH) {
-			rb3d_cntl |= RADEON_Z_ENABLE;
-		} else {
-			rb3d_cntl &= ~RADEON_Z_ENABLE;
-		}
-
-		if (flags & RADEON_STENCIL) {
-			rb3d_cntl |= RADEON_STENCIL_ENABLE;
-			rb3d_stencilrefmask = clear->depth_mask;	/* misnamed field */
-		} else {
-			rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
-			rb3d_stencilrefmask = 0x00000000;
-		}
-
-		if (flags & RADEON_USE_COMP_ZBUF) {
-			tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
-			    RADEON_Z_DECOMPRESSION_ENABLE;
-		}
-		if (flags & RADEON_USE_HIERZ) {
-			tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
-		}
-
-		BEGIN_RING(13);
-		RADEON_WAIT_UNTIL_2D_IDLE();
-
-		OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1));
-		OUT_RING(0x00000000);
-		OUT_RING(rb3d_cntl);
-
-		OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
-		OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask);
-		OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000);
-		OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl);
-		ADVANCE_RING();
-
-		/* Make sure we restore the 3D state next time.
-		 */
-		sarea_priv->ctx_owner = 0;
-
-		for (i = 0; i < nbox; i++) {
-
-			/* Funny that this should be required --
-			 *  sets top-left?
-			 */
-			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
-
-			BEGIN_RING(15);
-
-			OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13));
-			OUT_RING(RADEON_VTX_Z_PRESENT |
-				 RADEON_VTX_PKCOLOR_PRESENT);
-			OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
-				  RADEON_PRIM_WALK_RING |
-				  RADEON_MAOS_ENABLE |
-				  RADEON_VTX_FMT_RADEON_MODE |
-				  (3 << RADEON_NUM_VERTICES_SHIFT)));
-
-			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-			OUT_RING(0x0);
-
-			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-			OUT_RING(0x0);
-
-			OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
-			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-			OUT_RING(0x0);
-
-			ADVANCE_RING();
-		}
-	}
-
-	/* Increment the clear counter.  The client-side 3D driver must
-	 * wait on this value before performing the clear ioctl.  We
-	 * need this because the card's so damned fast...
-	 */
-	sarea_priv->last_clear++;
-
-	BEGIN_RING(4);
-
-	RADEON_CLEAR_AGE(sarea_priv->last_clear);
-	RADEON_WAIT_UNTIL_IDLE();
-
-	ADVANCE_RING();
-}
-
-static void radeon_cp_dispatch_swap(struct drm_device *dev, struct drm_master *master)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = master->driver_priv;
-	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
-	int nbox = sarea_priv->nbox;
-	struct drm_clip_rect *pbox = sarea_priv->boxes;
-	int i;
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	/* Do some trivial performance monitoring...
-	 */
-	if (dev_priv->do_boxes)
-		radeon_cp_performance_boxes(dev_priv, master_priv);
-
-	/* Wait for the 3D stream to idle before dispatching the bitblt.
-	 * This will prevent data corruption between the two streams.
-	 */
-	BEGIN_RING(2);
-
-	RADEON_WAIT_UNTIL_3D_IDLE();
-
-	ADVANCE_RING();
-
-	for (i = 0; i < nbox; i++) {
-		int x = pbox[i].x1;
-		int y = pbox[i].y1;
-		int w = pbox[i].x2 - x;
-		int h = pbox[i].y2 - y;
-
-		DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h);
-
-		BEGIN_RING(9);
-
-		OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0));
-		OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
-			 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-			 RADEON_GMC_BRUSH_NONE |
-			 (dev_priv->color_fmt << 8) |
-			 RADEON_GMC_SRC_DATATYPE_COLOR |
-			 RADEON_ROP3_S |
-			 RADEON_DP_SRC_SOURCE_MEMORY |
-			 RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
-
-		/* Make this work even if front & back are flipped:
-		 */
-		OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
-		if (sarea_priv->pfCurrentPage == 0) {
-			OUT_RING(dev_priv->back_pitch_offset);
-			OUT_RING(dev_priv->front_pitch_offset);
-		} else {
-			OUT_RING(dev_priv->front_pitch_offset);
-			OUT_RING(dev_priv->back_pitch_offset);
-		}
-
-		OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2));
-		OUT_RING((x << 16) | y);
-		OUT_RING((x << 16) | y);
-		OUT_RING((w << 16) | h);
-
-		ADVANCE_RING();
-	}
-
-	/* Increment the frame counter.  The client-side 3D driver must
-	 * throttle the framerate by waiting for this value before
-	 * performing the swapbuffer ioctl.
-	 */
-	sarea_priv->last_frame++;
-
-	BEGIN_RING(4);
-
-	RADEON_FRAME_AGE(sarea_priv->last_frame);
-	RADEON_WAIT_UNTIL_2D_IDLE();
-
-	ADVANCE_RING();
-}
-
-void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = master->driver_priv;
-	struct drm_sarea *sarea = (struct drm_sarea *)master_priv->sarea->handle;
-	int offset = (master_priv->sarea_priv->pfCurrentPage == 1)
-	    ? dev_priv->front_offset : dev_priv->back_offset;
-	RING_LOCALS;
-	DRM_DEBUG("pfCurrentPage=%d\n",
-		  master_priv->sarea_priv->pfCurrentPage);
-
-	/* Do some trivial performance monitoring...
-	 */
-	if (dev_priv->do_boxes) {
-		dev_priv->stats.boxes |= RADEON_BOX_FLIP;
-		radeon_cp_performance_boxes(dev_priv, master_priv);
-	}
-
-	/* Update the frame offsets for both CRTCs
-	 */
-	BEGIN_RING(6);
-
-	RADEON_WAIT_UNTIL_3D_IDLE();
-	OUT_RING_REG(RADEON_CRTC_OFFSET,
-		     ((sarea->frame.y * dev_priv->front_pitch +
-		       sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)
-		     + offset);
-	OUT_RING_REG(RADEON_CRTC2_OFFSET, master_priv->sarea_priv->crtc2_base
-		     + offset);
-
-	ADVANCE_RING();
-
-	/* Increment the frame counter.  The client-side 3D driver must
-	 * throttle the framerate by waiting for this value before
-	 * performing the swapbuffer ioctl.
-	 */
-	master_priv->sarea_priv->last_frame++;
-	master_priv->sarea_priv->pfCurrentPage =
-		1 - master_priv->sarea_priv->pfCurrentPage;
-
-	BEGIN_RING(2);
-
-	RADEON_FRAME_AGE(master_priv->sarea_priv->last_frame);
-
-	ADVANCE_RING();
-}
-
-static int bad_prim_vertex_nr(int primitive, int nr)
-{
-	switch (primitive & RADEON_PRIM_TYPE_MASK) {
-	case RADEON_PRIM_TYPE_NONE:
-	case RADEON_PRIM_TYPE_POINT:
-		return nr < 1;
-	case RADEON_PRIM_TYPE_LINE:
-		return (nr & 1) || nr == 0;
-	case RADEON_PRIM_TYPE_LINE_STRIP:
-		return nr < 2;
-	case RADEON_PRIM_TYPE_TRI_LIST:
-	case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
-	case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
-	case RADEON_PRIM_TYPE_RECT_LIST:
-		return nr % 3 || nr == 0;
-	case RADEON_PRIM_TYPE_TRI_FAN:
-	case RADEON_PRIM_TYPE_TRI_STRIP:
-		return nr < 3;
-	default:
-		return 1;
-	}
-}
-
-typedef struct {
-	unsigned int start;
-	unsigned int finish;
-	unsigned int prim;
-	unsigned int numverts;
-	unsigned int offset;
-	unsigned int vc_format;
-} drm_radeon_tcl_prim_t;
-
-static void radeon_cp_dispatch_vertex(struct drm_device * dev,
-				      struct drm_file *file_priv,
-				      struct drm_buf * buf,
-				      drm_radeon_tcl_prim_t * prim)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
-	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
-	int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
-	int numverts = (int)prim->numverts;
-	int nbox = sarea_priv->nbox;
-	int i = 0;
-	RING_LOCALS;
-
-	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
-		  prim->prim,
-		  prim->vc_format, prim->start, prim->finish, prim->numverts);
-
-	if (bad_prim_vertex_nr(prim->prim, prim->numverts)) {
-		DRM_ERROR("bad prim %x numverts %d\n",
-			  prim->prim, prim->numverts);
-		return;
-	}
-
-	do {
-		/* Emit the next cliprect */
-		if (i < nbox) {
-			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
-		}
-
-		/* Emit the vertex buffer rendering commands */
-		BEGIN_RING(5);
-
-		OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3));
-		OUT_RING(offset);
-		OUT_RING(numverts);
-		OUT_RING(prim->vc_format);
-		OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST |
-			 RADEON_COLOR_ORDER_RGBA |
-			 RADEON_VTX_FMT_RADEON_MODE |
-			 (numverts << RADEON_NUM_VERTICES_SHIFT));
-
-		ADVANCE_RING();
-
-		i++;
-	} while (i < nbox);
-}
-
-void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = master->driver_priv;
-	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
-	RING_LOCALS;
-
-	buf_priv->age = ++master_priv->sarea_priv->last_dispatch;
-
-	/* Emit the vertex buffer age */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
-		BEGIN_RING(3);
-		R600_DISPATCH_AGE(buf_priv->age);
-		ADVANCE_RING();
-	} else {
-		BEGIN_RING(2);
-		RADEON_DISPATCH_AGE(buf_priv->age);
-		ADVANCE_RING();
-	}
-
-	buf->pending = 1;
-	buf->used = 0;
-}
-
-static void radeon_cp_dispatch_indirect(struct drm_device * dev,
-					struct drm_buf * buf, int start, int end)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-	DRM_DEBUG("buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
-
-	if (start != end) {
-		int offset = (dev_priv->gart_buffers_offset
-			      + buf->offset + start);
-		int dwords = (end - start + 3) / sizeof(u32);
-
-		/* Indirect buffer data must be an even number of
-		 * dwords, so if we've been given an odd number we must
-		 * pad the data with a Type-2 CP packet.
-		 */
-		if (dwords & 1) {
-			u32 *data = (u32 *)
-			    ((char *)dev->agp_buffer_map->handle
-			     + buf->offset + start);
-			data[dwords++] = RADEON_CP_PACKET2;
-		}
-
-		/* Fire off the indirect buffer */
-		BEGIN_RING(3);
-
-		OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
-		OUT_RING(offset);
-		OUT_RING(dwords);
-
-		ADVANCE_RING();
-	}
-}
-
-static void radeon_cp_dispatch_indices(struct drm_device *dev,
-				       struct drm_master *master,
-				       struct drm_buf * elt_buf,
-				       drm_radeon_tcl_prim_t * prim)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = master->driver_priv;
-	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
-	int offset = dev_priv->gart_buffers_offset + prim->offset;
-	u32 *data;
-	int dwords;
-	int i = 0;
-	int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
-	int count = (prim->finish - start) / sizeof(u16);
-	int nbox = sarea_priv->nbox;
-
-	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
-		  prim->prim,
-		  prim->vc_format,
-		  prim->start, prim->finish, prim->offset, prim->numverts);
-
-	if (bad_prim_vertex_nr(prim->prim, count)) {
-		DRM_ERROR("bad prim %x count %d\n", prim->prim, count);
-		return;
-	}
-
-	if (start >= prim->finish || (prim->start & 0x7)) {
-		DRM_ERROR("buffer prim %d\n", prim->prim);
-		return;
-	}
-
-	dwords = (prim->finish - prim->start + 3) / sizeof(u32);
-
-	data = (u32 *) ((char *)dev->agp_buffer_map->handle +
-			elt_buf->offset + prim->start);
-
-	data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);
-	data[1] = offset;
-	data[2] = prim->numverts;
-	data[3] = prim->vc_format;
-	data[4] = (prim->prim |
-		   RADEON_PRIM_WALK_IND |
-		   RADEON_COLOR_ORDER_RGBA |
-		   RADEON_VTX_FMT_RADEON_MODE |
-		   (count << RADEON_NUM_VERTICES_SHIFT));
-
-	do {
-		if (i < nbox)
-			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
-
-		radeon_cp_dispatch_indirect(dev, elt_buf,
-					    prim->start, prim->finish);
-
-		i++;
-	} while (i < nbox);
-
-}
-
-#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
-
-static int radeon_cp_dispatch_texture(struct drm_device * dev,
-				      struct drm_file *file_priv,
-				      drm_radeon_texture_t * tex,
-				      drm_radeon_tex_image_t * image)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_buf *buf;
-	u32 format;
-	u32 *buffer;
-	const u8 __user *data;
-	unsigned int size, dwords, tex_width, blit_width, spitch;
-	u32 height;
-	int i;
-	u32 texpitch, microtile;
-	u32 offset, byte_offset;
-	RING_LOCALS;
-
-	if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) {
-		DRM_ERROR("Invalid destination offset\n");
-		return -EINVAL;
-	}
-
-	dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
-
-	/* Flush the pixel cache.  This ensures no pixel data gets mixed
-	 * up with the texture data from the host data blit, otherwise
-	 * part of the texture image may be corrupted.
-	 */
-	BEGIN_RING(4);
-	RADEON_FLUSH_CACHE();
-	RADEON_WAIT_UNTIL_IDLE();
-	ADVANCE_RING();
-
-	/* The compiler won't optimize away a division by a variable,
-	 * even if the only legal values are powers of two.  Thus, we'll
-	 * use a shift instead.
-	 */
-	switch (tex->format) {
-	case RADEON_TXFORMAT_ARGB8888:
-	case RADEON_TXFORMAT_RGBA8888:
-		format = RADEON_COLOR_FORMAT_ARGB8888;
-		tex_width = tex->width * 4;
-		blit_width = image->width * 4;
-		break;
-	case RADEON_TXFORMAT_AI88:
-	case RADEON_TXFORMAT_ARGB1555:
-	case RADEON_TXFORMAT_RGB565:
-	case RADEON_TXFORMAT_ARGB4444:
-	case RADEON_TXFORMAT_VYUY422:
-	case RADEON_TXFORMAT_YVYU422:
-		format = RADEON_COLOR_FORMAT_RGB565;
-		tex_width = tex->width * 2;
-		blit_width = image->width * 2;
-		break;
-	case RADEON_TXFORMAT_I8:
-	case RADEON_TXFORMAT_RGB332:
-		format = RADEON_COLOR_FORMAT_CI8;
-		tex_width = tex->width * 1;
-		blit_width = image->width * 1;
-		break;
-	default:
-		DRM_ERROR("invalid texture format %d\n", tex->format);
-		return -EINVAL;
-	}
-	spitch = blit_width >> 6;
-	if (spitch == 0 && image->height > 1)
-		return -EINVAL;
-
-	texpitch = tex->pitch;
-	if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
-		microtile = 1;
-		if (tex_width < 64) {
-			texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
-			/* we got tiled coordinates, untile them */
-			image->x *= 2;
-		}
-	} else
-		microtile = 0;
-
-	/* this might fail for zero-sized uploads - are those illegal? */
-	if (!radeon_check_offset(dev_priv, tex->offset + image->height *
-				blit_width - 1)) {
-		DRM_ERROR("Invalid final destination offset\n");
-		return -EINVAL;
-	}
-
-	DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);
-
-	do {
-		DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
-			  tex->offset >> 10, tex->pitch, tex->format,
-			  image->x, image->y, image->width, image->height);
-
-		/* Make a copy of some parameters in case we have to
-		 * update them for a multi-pass texture blit.
-		 */
-		height = image->height;
-		data = (const u8 __user *)image->data;
-
-		size = height * blit_width;
-
-		if (size > RADEON_MAX_TEXTURE_SIZE) {
-			height = RADEON_MAX_TEXTURE_SIZE / blit_width;
-			size = height * blit_width;
-		} else if (size < 4 && size > 0) {
-			size = 4;
-		} else if (size == 0) {
-			return 0;
-		}
-
-		buf = radeon_freelist_get(dev);
-		if (0 && !buf) {
-			radeon_do_cp_idle(dev_priv);
-			buf = radeon_freelist_get(dev);
-		}
-		if (!buf) {
-			DRM_DEBUG("EAGAIN\n");
-			if (copy_to_user(tex->image, image, sizeof(*image)))
-				return -EFAULT;
-			return -EAGAIN;
-		}
-
-		/* Dispatch the indirect buffer.
-		 */
-		buffer =
-		    (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
-		dwords = size / 4;
-
-#define RADEON_COPY_MT(_buf, _data, _width) \
-	do { \
-		if (copy_from_user(_buf, _data, (_width))) {\
-			DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \
-			return -EFAULT; \
-		} \
-	} while(0)
-
-		if (microtile) {
-			/* texture micro tiling in use, minimum texture width is thus 16 bytes.
-			   however, we cannot use blitter directly for texture width < 64 bytes,
-			   since minimum tex pitch is 64 bytes and we need this to match
-			   the texture width, otherwise the blitter will tile it wrong.
-			   Thus, tiling manually in this case. Additionally, need to special
-			   case tex height = 1, since our actual image will have height 2
-			   and we need to ensure we don't read beyond the texture size
-			   from user space. */
-			if (tex->height == 1) {
-				if (tex_width >= 64 || tex_width <= 16) {
-					RADEON_COPY_MT(buffer, data,
-						(int)(tex_width * sizeof(u32)));
-				} else if (tex_width == 32) {
-					RADEON_COPY_MT(buffer, data, 16);
-					RADEON_COPY_MT(buffer + 8,
-						       data + 16, 16);
-				}
-			} else if (tex_width >= 64 || tex_width == 16) {
-				RADEON_COPY_MT(buffer, data,
-					       (int)(dwords * sizeof(u32)));
-			} else if (tex_width < 16) {
-				for (i = 0; i < tex->height; i++) {
-					RADEON_COPY_MT(buffer, data, tex_width);
-					buffer += 4;
-					data += tex_width;
-				}
-			} else if (tex_width == 32) {
-				/* TODO: make sure this works when not fitting in one buffer
-				   (i.e. 32bytes x 2048...) */
-				for (i = 0; i < tex->height; i += 2) {
-					RADEON_COPY_MT(buffer, data, 16);
-					data += 16;
-					RADEON_COPY_MT(buffer + 8, data, 16);
-					data += 16;
-					RADEON_COPY_MT(buffer + 4, data, 16);
-					data += 16;
-					RADEON_COPY_MT(buffer + 12, data, 16);
-					data += 16;
-					buffer += 16;
-				}
-			}
-		} else {
-			if (tex_width >= 32) {
-				/* Texture image width is larger than the minimum, so we
-				 * can upload it directly.
-				 */
-				RADEON_COPY_MT(buffer, data,
-					       (int)(dwords * sizeof(u32)));
-			} else {
-				/* Texture image width is less than the minimum, so we
-				 * need to pad out each image scanline to the minimum
-				 * width.
-				 */
-				for (i = 0; i < tex->height; i++) {
-					RADEON_COPY_MT(buffer, data, tex_width);
-					buffer += 8;
-					data += tex_width;
-				}
-			}
-		}
-
-#undef RADEON_COPY_MT
-		byte_offset = (image->y & ~2047) * blit_width;
-		buf->file_priv = file_priv;
-		buf->used = size;
-		offset = dev_priv->gart_buffers_offset + buf->offset;
-		BEGIN_RING(9);
-		OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
-		OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
-			 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-			 RADEON_GMC_BRUSH_NONE |
-			 (format << 8) |
-			 RADEON_GMC_SRC_DATATYPE_COLOR |
-			 RADEON_ROP3_S |
-			 RADEON_DP_SRC_SOURCE_MEMORY |
-			 RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
-		OUT_RING((spitch << 22) | (offset >> 10));
-		OUT_RING((texpitch << 22) | ((tex->offset >> 10) + (byte_offset >> 10)));
-		OUT_RING(0);
-		OUT_RING((image->x << 16) | (image->y % 2048));
-		OUT_RING((image->width << 16) | height);
-		RADEON_WAIT_UNTIL_2D_IDLE();
-		ADVANCE_RING();
-		COMMIT_RING();
-
-		radeon_cp_discard_buffer(dev, file_priv->master, buf);
-
-		/* Update the input parameters for next time */
-		image->y += height;
-		image->height -= height;
-		image->data = (const u8 __user *)image->data + size;
-	} while (image->height > 0);
-
-	/* Flush the pixel cache after the blit completes.  This ensures
-	 * the texture data is written out to memory before rendering
-	 * continues.
-	 */
-	BEGIN_RING(4);
-	RADEON_FLUSH_CACHE();
-	RADEON_WAIT_UNTIL_2D_IDLE();
-	ADVANCE_RING();
-	COMMIT_RING();
-
-	return 0;
-}
-
-static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	int i;
-	RING_LOCALS;
-	DRM_DEBUG("\n");
-
-	BEGIN_RING(35);
-
-	OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0));
-	OUT_RING(0x00000000);
-
-	OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31));
-	for (i = 0; i < 32; i++) {
-		OUT_RING(stipple[i]);
-	}
-
-	ADVANCE_RING();
-}
-
-static void radeon_apply_surface_regs(int surf_index,
-				      drm_radeon_private_t *dev_priv)
-{
-	if (!dev_priv->mmio)
-		return;
-
-	radeon_do_cp_idle(dev_priv);
-
-	RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index,
-		     dev_priv->surfaces[surf_index].flags);
-	RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index,
-		     dev_priv->surfaces[surf_index].lower);
-	RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index,
-		     dev_priv->surfaces[surf_index].upper);
-}
-
-/* Allocates a virtual surface
- * doesn't always allocate a real surface, will stretch an existing
- * surface when possible.
- *
- * Note that refcount can be at most 2, since during a free refcount=3
- * might mean we have to allocate a new surface which might not always
- * be available.
- * For example : we allocate three contiguous surfaces ABC. If B is
- * freed, we suddenly need two surfaces to store A and C, which might
- * not always be available.
- */
-static int alloc_surface(drm_radeon_surface_alloc_t *new,
-			 drm_radeon_private_t *dev_priv,
-			 struct drm_file *file_priv)
-{
-	struct radeon_virt_surface *s;
-	int i;
-	int virt_surface_index;
-	uint32_t new_upper, new_lower;
-
-	new_lower = new->address;
-	new_upper = new_lower + new->size - 1;
-
-	/* sanity check */
-	if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) ||
-	    ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) !=
-	     RADEON_SURF_ADDRESS_FIXED_MASK)
-	    || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
-		return -1;
-
-	/* make sure there is no overlap with existing surfaces */
-	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
-		if ((dev_priv->surfaces[i].refcount != 0) &&
-		    (((new_lower >= dev_priv->surfaces[i].lower) &&
-		      (new_lower < dev_priv->surfaces[i].upper)) ||
-		     ((new_lower < dev_priv->surfaces[i].lower) &&
-		      (new_upper > dev_priv->surfaces[i].lower)))) {
-			return -1;
-		}
-	}
-
-	/* find a virtual surface */
-	for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
-		if (dev_priv->virt_surfaces[i].file_priv == NULL)
-			break;
-	if (i == 2 * RADEON_MAX_SURFACES) {
-		return -1;
-	}
-	virt_surface_index = i;
-
-	/* try to reuse an existing surface */
-	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
-		/* extend before */
-		if ((dev_priv->surfaces[i].refcount == 1) &&
-		    (new->flags == dev_priv->surfaces[i].flags) &&
-		    (new_upper + 1 == dev_priv->surfaces[i].lower)) {
-			s = &(dev_priv->virt_surfaces[virt_surface_index]);
-			s->surface_index = i;
-			s->lower = new_lower;
-			s->upper = new_upper;
-			s->flags = new->flags;
-			s->file_priv = file_priv;
-			dev_priv->surfaces[i].refcount++;
-			dev_priv->surfaces[i].lower = s->lower;
-			radeon_apply_surface_regs(s->surface_index, dev_priv);
-			return virt_surface_index;
-		}
-
-		/* extend after */
-		if ((dev_priv->surfaces[i].refcount == 1) &&
-		    (new->flags == dev_priv->surfaces[i].flags) &&
-		    (new_lower == dev_priv->surfaces[i].upper + 1)) {
-			s = &(dev_priv->virt_surfaces[virt_surface_index]);
-			s->surface_index = i;
-			s->lower = new_lower;
-			s->upper = new_upper;
-			s->flags = new->flags;
-			s->file_priv = file_priv;
-			dev_priv->surfaces[i].refcount++;
-			dev_priv->surfaces[i].upper = s->upper;
-			radeon_apply_surface_regs(s->surface_index, dev_priv);
-			return virt_surface_index;
-		}
-	}
-
-	/* okay, we need a new one */
-	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
-		if (dev_priv->surfaces[i].refcount == 0) {
-			s = &(dev_priv->virt_surfaces[virt_surface_index]);
-			s->surface_index = i;
-			s->lower = new_lower;
-			s->upper = new_upper;
-			s->flags = new->flags;
-			s->file_priv = file_priv;
-			dev_priv->surfaces[i].refcount = 1;
-			dev_priv->surfaces[i].lower = s->lower;
-			dev_priv->surfaces[i].upper = s->upper;
-			dev_priv->surfaces[i].flags = s->flags;
-			radeon_apply_surface_regs(s->surface_index, dev_priv);
-			return virt_surface_index;
-		}
-	}
-
-	/* we didn't find anything */
-	return -1;
-}
-
-static int free_surface(struct drm_file *file_priv,
-			drm_radeon_private_t * dev_priv,
-			int lower)
-{
-	struct radeon_virt_surface *s;
-	int i;
-	/* find the virtual surface */
-	for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
-		s = &(dev_priv->virt_surfaces[i]);
-		if (s->file_priv) {
-			if ((lower == s->lower) && (file_priv == s->file_priv))
-			{
-				if (dev_priv->surfaces[s->surface_index].
-				    lower == s->lower)
-					dev_priv->surfaces[s->surface_index].
-					    lower = s->upper;
-
-				if (dev_priv->surfaces[s->surface_index].
-				    upper == s->upper)
-					dev_priv->surfaces[s->surface_index].
-					    upper = s->lower;
-
-				dev_priv->surfaces[s->surface_index].refcount--;
-				if (dev_priv->surfaces[s->surface_index].
-				    refcount == 0)
-					dev_priv->surfaces[s->surface_index].
-					    flags = 0;
-				s->file_priv = NULL;
-				radeon_apply_surface_regs(s->surface_index,
-							  dev_priv);
-				return 0;
-			}
-		}
-	}
-	return 1;
-}
-
-static void radeon_surfaces_release(struct drm_file *file_priv,
-				    drm_radeon_private_t * dev_priv)
-{
-	int i;
-	for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
-		if (dev_priv->virt_surfaces[i].file_priv == file_priv)
-			free_surface(file_priv, dev_priv,
-				     dev_priv->virt_surfaces[i].lower);
-	}
-}
-
-/* ================================================================
- * IOCTL functions
- */
-static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_surface_alloc_t *alloc = data;
-
-	if (alloc_surface(alloc, dev_priv, file_priv) == -1)
-		return -EINVAL;
-	else
-		return 0;
-}
-
-static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_surface_free_t *memfree = data;
-
-	if (free_surface(file_priv, dev_priv, memfree->address))
-		return -EINVAL;
-	else
-		return 0;
-}
-
-static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
-	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
-	drm_radeon_clear_t *clear = data;
-	drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
-	DRM_DEBUG("\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
-		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
-
-	if (copy_from_user(&depth_boxes, clear->depth_boxes,
-			       sarea_priv->nbox * sizeof(depth_boxes[0])))
-		return -EFAULT;
-
-	radeon_cp_dispatch_clear(dev, file_priv->master, clear, depth_boxes);
-
-	COMMIT_RING();
-	return 0;
-}
-
-/* Not sure why this isn't set all the time:
- */
-static int radeon_do_init_pageflip(struct drm_device *dev, struct drm_master *master)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = master->driver_priv;
-	RING_LOCALS;
-
-	DRM_DEBUG("\n");
-
-	BEGIN_RING(6);
-	RADEON_WAIT_UNTIL_3D_IDLE();
-	OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0));
-	OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) |
-		 RADEON_CRTC_OFFSET_FLIP_CNTL);
-	OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0));
-	OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) |
-		 RADEON_CRTC_OFFSET_FLIP_CNTL);
-	ADVANCE_RING();
-
-	dev_priv->page_flipping = 1;
-
-	if (master_priv->sarea_priv->pfCurrentPage != 1)
-		master_priv->sarea_priv->pfCurrentPage = 0;
-
-	return 0;
-}
-
-/* Swapping and flipping are different operations, need different ioctls.
- * They can & should be intermixed to support multiple 3d windows.
- */
-static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG("\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-	if (!dev_priv->page_flipping)
-		radeon_do_init_pageflip(dev, file_priv->master);
-
-	radeon_cp_dispatch_flip(dev, file_priv->master);
-
-	COMMIT_RING();
-	return 0;
-}
-
-static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
-	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
-
-	DRM_DEBUG("\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
-		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		r600_cp_dispatch_swap(dev, file_priv);
-	else
-		radeon_cp_dispatch_swap(dev, file_priv->master);
-	sarea_priv->ctx_owner = 0;
-
-	COMMIT_RING();
-	return 0;
-}
-
-static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
-	drm_radeon_sarea_t *sarea_priv;
-	struct drm_device_dma *dma = dev->dma;
-	struct drm_buf *buf;
-	drm_radeon_vertex_t *vertex = data;
-	drm_radeon_tcl_prim_t prim;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	sarea_priv = master_priv->sarea_priv;
-
-	DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
-		  DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
-
-	if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
-		DRM_ERROR("buffer index %d (of %d max)\n",
-			  vertex->idx, dma->buf_count - 1);
-		return -EINVAL;
-	}
-	if (vertex->prim < 0 || vertex->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
-		DRM_ERROR("buffer prim %d\n", vertex->prim);
-		return -EINVAL;
-	}
-
-	RING_SPACE_TEST_WITH_RETURN(dev_priv);
-	VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-	buf = dma->buflist[vertex->idx];
-
-	if (buf->file_priv != file_priv) {
-		DRM_ERROR("process %d using buffer owned by %p\n",
-			  DRM_CURRENTPID, buf->file_priv);
-		return -EINVAL;
-	}
-	if (buf->pending) {
-		DRM_ERROR("sending pending buffer %d\n", vertex->idx);
-		return -EINVAL;
-	}
-
-	/* Build up a prim_t record:
-	 */
-	if (vertex->count) {
-		buf->used = vertex->count;	/* not used? */
-
-		if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
-			if (radeon_emit_state(dev_priv, file_priv,
-					      &sarea_priv->context_state,
-					      sarea_priv->tex_state,
-					      sarea_priv->dirty)) {
-				DRM_ERROR("radeon_emit_state failed\n");
-				return -EINVAL;
-			}
-
-			sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
-					       RADEON_UPLOAD_TEX1IMAGES |
-					       RADEON_UPLOAD_TEX2IMAGES |
-					       RADEON_REQUIRE_QUIESCENCE);
-		}
-
-		prim.start = 0;
-		prim.finish = vertex->count;	/* unused */
-		prim.prim = vertex->prim;
-		prim.numverts = vertex->count;
-		prim.vc_format = sarea_priv->vc_format;
-
-		radeon_cp_dispatch_vertex(dev, file_priv, buf, &prim);
-	}
-
-	if (vertex->discard) {
-		radeon_cp_discard_buffer(dev, file_priv->master, buf);
-	}
-
-	COMMIT_RING();
-	return 0;
-}
-
-static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
-	drm_radeon_sarea_t *sarea_priv;
-	struct drm_device_dma *dma = dev->dma;
-	struct drm_buf *buf;
-	drm_radeon_indices_t *elts = data;
-	drm_radeon_tcl_prim_t prim;
-	int count;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	sarea_priv = master_priv->sarea_priv;
-
-	DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
-		  DRM_CURRENTPID, elts->idx, elts->start, elts->end,
-		  elts->discard);
-
-	if (elts->idx < 0 || elts->idx >= dma->buf_count) {
-		DRM_ERROR("buffer index %d (of %d max)\n",
-			  elts->idx, dma->buf_count - 1);
-		return -EINVAL;
-	}
-	if (elts->prim < 0 || elts->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
-		DRM_ERROR("buffer prim %d\n", elts->prim);
-		return -EINVAL;
-	}
-
-	RING_SPACE_TEST_WITH_RETURN(dev_priv);
-	VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-	buf = dma->buflist[elts->idx];
-
-	if (buf->file_priv != file_priv) {
-		DRM_ERROR("process %d using buffer owned by %p\n",
-			  DRM_CURRENTPID, buf->file_priv);
-		return -EINVAL;
-	}
-	if (buf->pending) {
-		DRM_ERROR("sending pending buffer %d\n", elts->idx);
-		return -EINVAL;
-	}
-
-	count = (elts->end - elts->start) / sizeof(u16);
-	elts->start -= RADEON_INDEX_PRIM_OFFSET;
-
-	if (elts->start & 0x7) {
-		DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
-		return -EINVAL;
-	}
-	if (elts->start < buf->used) {
-		DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
-		return -EINVAL;
-	}
-
-	buf->used = elts->end;
-
-	if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
-		if (radeon_emit_state(dev_priv, file_priv,
-				      &sarea_priv->context_state,
-				      sarea_priv->tex_state,
-				      sarea_priv->dirty)) {
-			DRM_ERROR("radeon_emit_state failed\n");
-			return -EINVAL;
-		}
-
-		sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
-				       RADEON_UPLOAD_TEX1IMAGES |
-				       RADEON_UPLOAD_TEX2IMAGES |
-				       RADEON_REQUIRE_QUIESCENCE);
-	}
-
-	/* Build up a prim_t record:
-	 */
-	prim.start = elts->start;
-	prim.finish = elts->end;
-	prim.prim = elts->prim;
-	prim.offset = 0;	/* offset from start of dma buffers */
-	prim.numverts = RADEON_MAX_VB_VERTS;	/* duh */
-	prim.vc_format = sarea_priv->vc_format;
-
-	radeon_cp_dispatch_indices(dev, file_priv->master, buf, &prim);
-	if (elts->discard) {
-		radeon_cp_discard_buffer(dev, file_priv->master, buf);
-	}
-
-	COMMIT_RING();
-	return 0;
-}
-
-static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_texture_t *tex = data;
-	drm_radeon_tex_image_t image;
-	int ret;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if (tex->image == NULL) {
-		DRM_ERROR("null texture image!\n");
-		return -EINVAL;
-	}
-
-	if (copy_from_user(&image,
-			       (drm_radeon_tex_image_t __user *) tex->image,
-			       sizeof(image)))
-		return -EFAULT;
-
-	RING_SPACE_TEST_WITH_RETURN(dev_priv);
-	VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		ret = r600_cp_dispatch_texture(dev, file_priv, tex, &image);
-	else
-		ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image);
-
-	return ret;
-}
-
-static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_stipple_t *stipple = data;
-	u32 mask[32];
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32)))
-		return -EFAULT;
-
-	RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-	radeon_cp_dispatch_stipple(dev, mask);
-
-	COMMIT_RING();
-	return 0;
-}
-
-static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_device_dma *dma = dev->dma;
-	struct drm_buf *buf;
-	drm_radeon_indirect_t *indirect = data;
-	RING_LOCALS;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
-		  indirect->idx, indirect->start, indirect->end,
-		  indirect->discard);
-
-	if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {
-		DRM_ERROR("buffer index %d (of %d max)\n",
-			  indirect->idx, dma->buf_count - 1);
-		return -EINVAL;
-	}
-
-	buf = dma->buflist[indirect->idx];
-
-	if (buf->file_priv != file_priv) {
-		DRM_ERROR("process %d using buffer owned by %p\n",
-			  DRM_CURRENTPID, buf->file_priv);
-		return -EINVAL;
-	}
-	if (buf->pending) {
-		DRM_ERROR("sending pending buffer %d\n", indirect->idx);
-		return -EINVAL;
-	}
-
-	if (indirect->start < buf->used) {
-		DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
-			  indirect->start, buf->used);
-		return -EINVAL;
-	}
-
-	RING_SPACE_TEST_WITH_RETURN(dev_priv);
-	VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-	buf->used = indirect->end;
-
-	/* Dispatch the indirect buffer full of commands from the
-	 * X server.  This is insecure and is thus only available to
-	 * privileged clients.
-	 */
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		r600_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
-	else {
-		/* Wait for the 3D stream to idle before the indirect buffer
-		 * containing 2D acceleration commands is processed.
-		 */
-		BEGIN_RING(2);
-		RADEON_WAIT_UNTIL_3D_IDLE();
-		ADVANCE_RING();
-		radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
-	}
-
-	if (indirect->discard) {
-		radeon_cp_discard_buffer(dev, file_priv->master, buf);
-	}
-
-	COMMIT_RING();
-	return 0;
-}
-
-static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
-	drm_radeon_sarea_t *sarea_priv;
-	struct drm_device_dma *dma = dev->dma;
-	struct drm_buf *buf;
-	drm_radeon_vertex2_t *vertex = data;
-	int i;
-	unsigned char laststate;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	sarea_priv = master_priv->sarea_priv;
-
-	DRM_DEBUG("pid=%d index=%d discard=%d\n",
-		  DRM_CURRENTPID, vertex->idx, vertex->discard);
-
-	if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
-		DRM_ERROR("buffer index %d (of %d max)\n",
-			  vertex->idx, dma->buf_count - 1);
-		return -EINVAL;
-	}
-
-	RING_SPACE_TEST_WITH_RETURN(dev_priv);
-	VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-	buf = dma->buflist[vertex->idx];
-
-	if (buf->file_priv != file_priv) {
-		DRM_ERROR("process %d using buffer owned by %p\n",
-			  DRM_CURRENTPID, buf->file_priv);
-		return -EINVAL;
-	}
-
-	if (buf->pending) {
-		DRM_ERROR("sending pending buffer %d\n", vertex->idx);
-		return -EINVAL;
-	}
-
-	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
-		return -EINVAL;
-
-	for (laststate = 0xff, i = 0; i < vertex->nr_prims; i++) {
-		drm_radeon_prim_t prim;
-		drm_radeon_tcl_prim_t tclprim;
-
-		if (copy_from_user(&prim, &vertex->prim[i], sizeof(prim)))
-			return -EFAULT;
-
-		if (prim.stateidx != laststate) {
-			drm_radeon_state_t state;
-
-			if (copy_from_user(&state,
-					       &vertex->state[prim.stateidx],
-					       sizeof(state)))
-				return -EFAULT;
-
-			if (radeon_emit_state2(dev_priv, file_priv, &state)) {
-				DRM_ERROR("radeon_emit_state2 failed\n");
-				return -EINVAL;
-			}
-
-			laststate = prim.stateidx;
-		}
-
-		tclprim.start = prim.start;
-		tclprim.finish = prim.finish;
-		tclprim.prim = prim.prim;
-		tclprim.vc_format = prim.vc_format;
-
-		if (prim.prim & RADEON_PRIM_WALK_IND) {
-			tclprim.offset = prim.numverts * 64;
-			tclprim.numverts = RADEON_MAX_VB_VERTS;	/* duh */
-
-			radeon_cp_dispatch_indices(dev, file_priv->master, buf, &tclprim);
-		} else {
-			tclprim.numverts = prim.numverts;
-			tclprim.offset = 0;	/* not used */
-
-			radeon_cp_dispatch_vertex(dev, file_priv, buf, &tclprim);
-		}
-
-		if (sarea_priv->nbox == 1)
-			sarea_priv->nbox = 0;
-	}
-
-	if (vertex->discard) {
-		radeon_cp_discard_buffer(dev, file_priv->master, buf);
-	}
-
-	COMMIT_RING();
-	return 0;
-}
-
-static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
-			       struct drm_file *file_priv,
-			       drm_radeon_cmd_header_t header,
-			       drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	int id = (int)header.packet.packet_id;
-	int sz, reg;
-	RING_LOCALS;
-
-	if (id >= RADEON_MAX_STATE_PACKETS)
-		return -EINVAL;
-
-	sz = packet[id].len;
-	reg = packet[id].start;
-
-	if (sz * sizeof(u32) > drm_buffer_unprocessed(cmdbuf->buffer)) {
-		DRM_ERROR("Packet size provided larger than data provided\n");
-		return -EINVAL;
-	}
-
-	if (radeon_check_and_fixup_packets(dev_priv, file_priv, id,
-				cmdbuf->buffer)) {
-		DRM_ERROR("Packet verification failed\n");
-		return -EINVAL;
-	}
-
-	BEGIN_RING(sz + 1);
-	OUT_RING(CP_PACKET0(reg, (sz - 1)));
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
-	ADVANCE_RING();
-
-	return 0;
-}
-
-static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
-					  drm_radeon_cmd_header_t header,
-					  drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	int sz = header.scalars.count;
-	int start = header.scalars.offset;
-	int stride = header.scalars.stride;
-	RING_LOCALS;
-
-	BEGIN_RING(3 + sz);
-	OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
-	OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
-	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
-	ADVANCE_RING();
-	return 0;
-}
-
-/* God this is ugly
- */
-static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
-					   drm_radeon_cmd_header_t header,
-					   drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	int sz = header.scalars.count;
-	int start = ((unsigned int)header.scalars.offset) + 0x100;
-	int stride = header.scalars.stride;
-	RING_LOCALS;
-
-	BEGIN_RING(3 + sz);
-	OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
-	OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
-	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
-	ADVANCE_RING();
-	return 0;
-}
-
-static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
-					  drm_radeon_cmd_header_t header,
-					  drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	int sz = header.vectors.count;
-	int start = header.vectors.offset;
-	int stride = header.vectors.stride;
-	RING_LOCALS;
-
-	BEGIN_RING(5 + sz);
-	OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
-	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
-	OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
-	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
-	ADVANCE_RING();
-
-	return 0;
-}
-
-static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
-					  drm_radeon_cmd_header_t header,
-					  drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	int sz = header.veclinear.count * 4;
-	int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8);
-	RING_LOCALS;
-
-        if (!sz)
-                return 0;
-	if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
-                return -EINVAL;
-
-	BEGIN_RING(5 + sz);
-	OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
-	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
-	OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
-	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
-	ADVANCE_RING();
-
-	return 0;
-}
-
-static int radeon_emit_packet3(struct drm_device * dev,
-			       struct drm_file *file_priv,
-			       drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	unsigned int cmdsz;
-	int ret;
-	RING_LOCALS;
-
-	DRM_DEBUG("\n");
-
-	if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv,
-						  cmdbuf, &cmdsz))) {
-		DRM_ERROR("Packet verification failed\n");
-		return ret;
-	}
-
-	BEGIN_RING(cmdsz);
-	OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
-	ADVANCE_RING();
-
-	return 0;
-}
-
-static int radeon_emit_packet3_cliprect(struct drm_device *dev,
-					struct drm_file *file_priv,
-					drm_radeon_kcmd_buffer_t *cmdbuf,
-					int orig_nbox)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_clip_rect box;
-	unsigned int cmdsz;
-	int ret;
-	struct drm_clip_rect __user *boxes = cmdbuf->boxes;
-	int i = 0;
-	RING_LOCALS;
-
-	DRM_DEBUG("\n");
-
-	if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv,
-						  cmdbuf, &cmdsz))) {
-		DRM_ERROR("Packet verification failed\n");
-		return ret;
-	}
-
-	if (!orig_nbox)
-		goto out;
-
-	do {
-		if (i < cmdbuf->nbox) {
-			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
-			 * calling emit_clip_rect(). This fixes a
-			 * lockup on fast machines when sending
-			 * several cliprects with a cmdbuf, as when
-			 * waving a 2D window over a 3D
-			 * window. Something in the commands from user
-			 * space seems to hang the card when they're
-			 * sent several times in a row. That would be
-			 * the correct place to fix it but this works
-			 * around it until I can figure that out - Tim
-			 * Smith */
-			if (i) {
-				BEGIN_RING(2);
-				RADEON_WAIT_UNTIL_3D_IDLE();
-				ADVANCE_RING();
-			}
-			radeon_emit_clip_rect(dev_priv, &box);
-		}
-
-		BEGIN_RING(cmdsz);
-		OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
-		ADVANCE_RING();
-
-	} while (++i < cmdbuf->nbox);
-	if (cmdbuf->nbox == 1)
-		cmdbuf->nbox = 0;
-
-	return 0;
-      out:
-	drm_buffer_advance(cmdbuf->buffer, cmdsz * 4);
-	return 0;
-}
-
-static int radeon_emit_wait(struct drm_device * dev, int flags)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-
-	DRM_DEBUG("%x\n", flags);
-	switch (flags) {
-	case RADEON_WAIT_2D:
-		BEGIN_RING(2);
-		RADEON_WAIT_UNTIL_2D_IDLE();
-		ADVANCE_RING();
-		break;
-	case RADEON_WAIT_3D:
-		BEGIN_RING(2);
-		RADEON_WAIT_UNTIL_3D_IDLE();
-		ADVANCE_RING();
-		break;
-	case RADEON_WAIT_2D | RADEON_WAIT_3D:
-		BEGIN_RING(2);
-		RADEON_WAIT_UNTIL_IDLE();
-		ADVANCE_RING();
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,
-		struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_device_dma *dma = dev->dma;
-	struct drm_buf *buf = NULL;
-	drm_radeon_cmd_header_t stack_header;
-	int idx;
-	drm_radeon_kcmd_buffer_t *cmdbuf = data;
-	int orig_nbox;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	RING_SPACE_TEST_WITH_RETURN(dev_priv);
-	VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-	if (cmdbuf->bufsz > 64 * 1024 || cmdbuf->bufsz < 0) {
-		return -EINVAL;
-	}
-
-	/* Allocate an in-kernel area and copy in the cmdbuf.  Do this to avoid
-	 * races between checking values and using those values in other code,
-	 * and simply to avoid a lot of function calls to copy in data.
-	 */
-	if (cmdbuf->bufsz != 0) {
-		int rv;
-		void __user *buffer = cmdbuf->buffer;
-		rv = drm_buffer_alloc(&cmdbuf->buffer, cmdbuf->bufsz);
-		if (rv)
-			return rv;
-		rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer,
-						cmdbuf->bufsz);
-		if (rv) {
-			drm_buffer_free(cmdbuf->buffer);
-			return rv;
-		}
-	} else
-		goto done;
-
-	orig_nbox = cmdbuf->nbox;
-
-	if (dev_priv->microcode_version == UCODE_R300) {
-		int temp;
-		temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
-
-		drm_buffer_free(cmdbuf->buffer);
-
-		return temp;
-	}
-
-	/* microcode_version != r300 */
-	while (drm_buffer_unprocessed(cmdbuf->buffer) >= sizeof(stack_header)) {
-
-		drm_radeon_cmd_header_t *header;
-		header = drm_buffer_read_object(cmdbuf->buffer,
-				sizeof(stack_header), &stack_header);
-
-		switch (header->header.cmd_type) {
-		case RADEON_CMD_PACKET:
-			DRM_DEBUG("RADEON_CMD_PACKET\n");
-			if (radeon_emit_packets
-			    (dev_priv, file_priv, *header, cmdbuf)) {
-				DRM_ERROR("radeon_emit_packets failed\n");
-				goto err;
-			}
-			break;
-
-		case RADEON_CMD_SCALARS:
-			DRM_DEBUG("RADEON_CMD_SCALARS\n");
-			if (radeon_emit_scalars(dev_priv, *header, cmdbuf)) {
-				DRM_ERROR("radeon_emit_scalars failed\n");
-				goto err;
-			}
-			break;
-
-		case RADEON_CMD_VECTORS:
-			DRM_DEBUG("RADEON_CMD_VECTORS\n");
-			if (radeon_emit_vectors(dev_priv, *header, cmdbuf)) {
-				DRM_ERROR("radeon_emit_vectors failed\n");
-				goto err;
-			}
-			break;
-
-		case RADEON_CMD_DMA_DISCARD:
-			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
-			idx = header->dma.buf_idx;
-			if (idx < 0 || idx >= dma->buf_count) {
-				DRM_ERROR("buffer index %d (of %d max)\n",
-					  idx, dma->buf_count - 1);
-				goto err;
-			}
-
-			buf = dma->buflist[idx];
-			if (buf->file_priv != file_priv || buf->pending) {
-				DRM_ERROR("bad buffer %p %p %d\n",
-					  buf->file_priv, file_priv,
-					  buf->pending);
-				goto err;
-			}
-
-			radeon_cp_discard_buffer(dev, file_priv->master, buf);
-			break;
-
-		case RADEON_CMD_PACKET3:
-			DRM_DEBUG("RADEON_CMD_PACKET3\n");
-			if (radeon_emit_packet3(dev, file_priv, cmdbuf)) {
-				DRM_ERROR("radeon_emit_packet3 failed\n");
-				goto err;
-			}
-			break;
-
-		case RADEON_CMD_PACKET3_CLIP:
-			DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
-			if (radeon_emit_packet3_cliprect
-			    (dev, file_priv, cmdbuf, orig_nbox)) {
-				DRM_ERROR("radeon_emit_packet3_clip failed\n");
-				goto err;
-			}
-			break;
-
-		case RADEON_CMD_SCALARS2:
-			DRM_DEBUG("RADEON_CMD_SCALARS2\n");
-			if (radeon_emit_scalars2(dev_priv, *header, cmdbuf)) {
-				DRM_ERROR("radeon_emit_scalars2 failed\n");
-				goto err;
-			}
-			break;
-
-		case RADEON_CMD_WAIT:
-			DRM_DEBUG("RADEON_CMD_WAIT\n");
-			if (radeon_emit_wait(dev, header->wait.flags)) {
-				DRM_ERROR("radeon_emit_wait failed\n");
-				goto err;
-			}
-			break;
-		case RADEON_CMD_VECLINEAR:
-			DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
-			if (radeon_emit_veclinear(dev_priv, *header, cmdbuf)) {
-				DRM_ERROR("radeon_emit_veclinear failed\n");
-				goto err;
-			}
-			break;
-
-		default:
-			DRM_ERROR("bad cmd_type %d at byte %d\n",
-				  header->header.cmd_type,
-				  cmdbuf->buffer->iterator);
-			goto err;
-		}
-	}
-
-	drm_buffer_free(cmdbuf->buffer);
-
-      done:
-	DRM_DEBUG("DONE\n");
-	COMMIT_RING();
-	return 0;
-
-      err:
-	drm_buffer_free(cmdbuf->buffer);
-	return -EINVAL;
-}
-
-static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_getparam_t *param = data;
-	int value;
-
-	DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
-
-	switch (param->param) {
-	case RADEON_PARAM_GART_BUFFER_OFFSET:
-		value = dev_priv->gart_buffers_offset;
-		break;
-	case RADEON_PARAM_LAST_FRAME:
-		dev_priv->stats.last_frame_reads++;
-		value = GET_SCRATCH(dev_priv, 0);
-		break;
-	case RADEON_PARAM_LAST_DISPATCH:
-		value = GET_SCRATCH(dev_priv, 1);
-		break;
-	case RADEON_PARAM_LAST_CLEAR:
-		dev_priv->stats.last_clear_reads++;
-		value = GET_SCRATCH(dev_priv, 2);
-		break;
-	case RADEON_PARAM_IRQ_NR:
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-			value = 0;
-		else
-			value = dev->pdev->irq;
-		break;
-	case RADEON_PARAM_GART_BASE:
-		value = dev_priv->gart_vm_start;
-		break;
-	case RADEON_PARAM_REGISTER_HANDLE:
-		value = dev_priv->mmio->offset;
-		break;
-	case RADEON_PARAM_STATUS_HANDLE:
-		value = dev_priv->ring_rptr_offset;
-		break;
-#if BITS_PER_LONG == 32
-		/*
-		 * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
-		 * pointer which can't fit into an int-sized variable.  According to
-		 * Michel Dänzer, the ioctl() is only used on embedded platforms, so
-		 * not supporting it shouldn't be a problem.  If the same functionality
-		 * is needed on 64-bit platforms, a new ioctl() would have to be added,
-		 * so backwards-compatibility for the embedded platforms can be
-		 * maintained.  --davidm 4-Feb-2004.
-		 */
-	case RADEON_PARAM_SAREA_HANDLE:
-		/* The lock is the first dword in the sarea. */
-		/* no users of this parameter */
-		break;
-#endif
-	case RADEON_PARAM_GART_TEX_HANDLE:
-		value = dev_priv->gart_textures_offset;
-		break;
-	case RADEON_PARAM_SCRATCH_OFFSET:
-		if (!dev_priv->writeback_works)
-			return -EINVAL;
-		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-			value = R600_SCRATCH_REG_OFFSET;
-		else
-			value = RADEON_SCRATCH_REG_OFFSET;
-		break;
-	case RADEON_PARAM_CARD_TYPE:
-		if (dev_priv->flags & RADEON_IS_PCIE)
-			value = RADEON_CARD_PCIE;
-		else if (dev_priv->flags & RADEON_IS_AGP)
-			value = RADEON_CARD_AGP;
-		else
-			value = RADEON_CARD_PCI;
-		break;
-	case RADEON_PARAM_VBLANK_CRTC:
-		value = radeon_vblank_crtc_get(dev);
-		break;
-	case RADEON_PARAM_FB_LOCATION:
-		value = radeon_read_fb_location(dev_priv);
-		break;
-	case RADEON_PARAM_NUM_GB_PIPES:
-		value = dev_priv->num_gb_pipes;
-		break;
-	case RADEON_PARAM_NUM_Z_PIPES:
-		value = dev_priv->num_z_pipes;
-		break;
-	default:
-		DRM_DEBUG("Invalid parameter %d\n", param->param);
-		return -EINVAL;
-	}
-
-	if (copy_to_user(param->value, &value, sizeof(int))) {
-		DRM_ERROR("copy_to_user\n");
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
-	drm_radeon_setparam_t *sp = data;
-	struct drm_radeon_driver_file_fields *radeon_priv;
-
-	switch (sp->param) {
-	case RADEON_SETPARAM_FB_LOCATION:
-		radeon_priv = file_priv->driver_priv;
-		radeon_priv->radeon_fb_delta = dev_priv->fb_location -
-		    sp->value;
-		break;
-	case RADEON_SETPARAM_SWITCH_TILING:
-		if (sp->value == 0) {
-			DRM_DEBUG("color tiling disabled\n");
-			dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
-			dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
-			if (master_priv->sarea_priv)
-				master_priv->sarea_priv->tiling_enabled = 0;
-		} else if (sp->value == 1) {
-			DRM_DEBUG("color tiling enabled\n");
-			dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
-			dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
-			if (master_priv->sarea_priv)
-				master_priv->sarea_priv->tiling_enabled = 1;
-		}
-		break;
-	case RADEON_SETPARAM_PCIGART_LOCATION:
-		dev_priv->pcigart_offset = sp->value;
-		dev_priv->pcigart_offset_set = 1;
-		break;
-	case RADEON_SETPARAM_NEW_MEMMAP:
-		dev_priv->new_memmap = sp->value;
-		break;
-	case RADEON_SETPARAM_PCIGART_TABLE_SIZE:
-		dev_priv->gart_info.table_size = sp->value;
-		if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
-			dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
-		break;
-	case RADEON_SETPARAM_VBLANK_CRTC:
-		return radeon_vblank_crtc_set(dev, sp->value);
-		break;
-	default:
-		DRM_DEBUG("Invalid parameter %d\n", sp->param);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* When a client dies:
- *    - Check for and clean up flipped page state
- *    - Free any alloced GART memory.
- *    - Free any alloced radeon surfaces.
- *
- * DRM infrastructure takes care of reclaiming dma buffers.
- */
-void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
-{
-	if (dev->dev_private) {
-		drm_radeon_private_t *dev_priv = dev->dev_private;
-		dev_priv->page_flipping = 0;
-		radeon_mem_release(file_priv, dev_priv->gart_heap);
-		radeon_mem_release(file_priv, dev_priv->fb_heap);
-		radeon_surfaces_release(file_priv, dev_priv);
-	}
-}
-
-void radeon_driver_lastclose(struct drm_device *dev)
-{
-	radeon_surfaces_release(PCIGART_FILE_PRIV, dev->dev_private);
-	radeon_do_release(dev);
-}
-
-int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv)
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	struct drm_radeon_driver_file_fields *radeon_priv;
-
-	DRM_DEBUG("\n");
-	radeon_priv = kmalloc(sizeof(*radeon_priv), GFP_KERNEL);
-
-	if (!radeon_priv)
-		return -ENOMEM;
-
-	file_priv->driver_priv = radeon_priv;
-
-	if (dev_priv)
-		radeon_priv->radeon_fb_delta = dev_priv->fb_location;
-	else
-		radeon_priv->radeon_fb_delta = 0;
-	return 0;
-}
-
-void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
-{
-	struct drm_radeon_driver_file_fields *radeon_priv =
-	    file_priv->driver_priv;
-
-	kfree(radeon_priv);
-}
-
-struct drm_ioctl_desc radeon_ioctls[] = {
-	DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_RESET, radeon_engine_reset, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_SWAP, radeon_cp_swap, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_CLEAR, radeon_cp_clear, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_INDICES, radeon_cp_indices, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_FLIP, radeon_cp_flip, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_FREE, radeon_mem_free, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH),
-	DRM_IOCTL_DEF_DRV(RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH)
-};
-
-int radeon_max_ioctl = ARRAY_SIZE(radeon_ioctls);
diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c
index 574f62b..7eb1ae7 100644
--- a/drivers/gpu/drm/radeon/radeon_vce.c
+++ b/drivers/gpu/drm/radeon/radeon_vce.c
@@ -361,31 +361,31 @@
 
 	/* stitch together an VCE create msg */
 	ib.length_dw = 0;
-	ib.ptr[ib.length_dw++] = 0x0000000c; /* len */
-	ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */
-	ib.ptr[ib.length_dw++] = handle;
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x0000000c); /* len */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000001); /* session cmd */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(handle);
 
-	ib.ptr[ib.length_dw++] = 0x00000030; /* len */
-	ib.ptr[ib.length_dw++] = 0x01000001; /* create cmd */
-	ib.ptr[ib.length_dw++] = 0x00000000;
-	ib.ptr[ib.length_dw++] = 0x00000042;
-	ib.ptr[ib.length_dw++] = 0x0000000a;
-	ib.ptr[ib.length_dw++] = 0x00000001;
-	ib.ptr[ib.length_dw++] = 0x00000080;
-	ib.ptr[ib.length_dw++] = 0x00000060;
-	ib.ptr[ib.length_dw++] = 0x00000100;
-	ib.ptr[ib.length_dw++] = 0x00000100;
-	ib.ptr[ib.length_dw++] = 0x0000000c;
-	ib.ptr[ib.length_dw++] = 0x00000000;
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000030); /* len */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x01000001); /* create cmd */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000000);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000042);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x0000000a);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000001);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000080);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000060);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000100);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000100);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x0000000c);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000000);
 
-	ib.ptr[ib.length_dw++] = 0x00000014; /* len */
-	ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */
-	ib.ptr[ib.length_dw++] = upper_32_bits(dummy);
-	ib.ptr[ib.length_dw++] = dummy;
-	ib.ptr[ib.length_dw++] = 0x00000001;
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000014); /* len */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x05000005); /* feedback buffer */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(upper_32_bits(dummy));
+	ib.ptr[ib.length_dw++] = cpu_to_le32(dummy);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000001);
 
 	for (i = ib.length_dw; i < ib_size_dw; ++i)
-		ib.ptr[i] = 0x0;
+		ib.ptr[i] = cpu_to_le32(0x0);
 
 	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r) {
@@ -428,21 +428,21 @@
 
 	/* stitch together an VCE destroy msg */
 	ib.length_dw = 0;
-	ib.ptr[ib.length_dw++] = 0x0000000c; /* len */
-	ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */
-	ib.ptr[ib.length_dw++] = handle;
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x0000000c); /* len */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000001); /* session cmd */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(handle);
 
-	ib.ptr[ib.length_dw++] = 0x00000014; /* len */
-	ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */
-	ib.ptr[ib.length_dw++] = upper_32_bits(dummy);
-	ib.ptr[ib.length_dw++] = dummy;
-	ib.ptr[ib.length_dw++] = 0x00000001;
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000014); /* len */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x05000005); /* feedback buffer */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(upper_32_bits(dummy));
+	ib.ptr[ib.length_dw++] = cpu_to_le32(dummy);
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000001);
 
-	ib.ptr[ib.length_dw++] = 0x00000008; /* len */
-	ib.ptr[ib.length_dw++] = 0x02000001; /* destroy cmd */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000008); /* len */
+	ib.ptr[ib.length_dw++] = cpu_to_le32(0x02000001); /* destroy cmd */
 
 	for (i = ib.length_dw; i < ib_size_dw; ++i)
-		ib.ptr[i] = 0x0;
+		ib.ptr[i] = cpu_to_le32(0x0);
 
 	r = radeon_ib_schedule(rdev, &ib, NULL, false);
 	if (r) {
@@ -699,12 +699,12 @@
 {
 	uint64_t addr = semaphore->gpu_addr;
 
-	radeon_ring_write(ring, VCE_CMD_SEMAPHORE);
-	radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
-	radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
-	radeon_ring_write(ring, 0x01003000 | (emit_wait ? 1 : 0));
+	radeon_ring_write(ring, cpu_to_le32(VCE_CMD_SEMAPHORE));
+	radeon_ring_write(ring, cpu_to_le32((addr >> 3) & 0x000FFFFF));
+	radeon_ring_write(ring, cpu_to_le32((addr >> 23) & 0x000FFFFF));
+	radeon_ring_write(ring, cpu_to_le32(0x01003000 | (emit_wait ? 1 : 0)));
 	if (!emit_wait)
-		radeon_ring_write(ring, VCE_CMD_END);
+		radeon_ring_write(ring, cpu_to_le32(VCE_CMD_END));
 
 	return true;
 }
@@ -719,10 +719,10 @@
 void radeon_vce_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
 {
 	struct radeon_ring *ring = &rdev->ring[ib->ring];
-	radeon_ring_write(ring, VCE_CMD_IB);
-	radeon_ring_write(ring, ib->gpu_addr);
-	radeon_ring_write(ring, upper_32_bits(ib->gpu_addr));
-	radeon_ring_write(ring, ib->length_dw);
+	radeon_ring_write(ring, cpu_to_le32(VCE_CMD_IB));
+	radeon_ring_write(ring, cpu_to_le32(ib->gpu_addr));
+	radeon_ring_write(ring, cpu_to_le32(upper_32_bits(ib->gpu_addr)));
+	radeon_ring_write(ring, cpu_to_le32(ib->length_dw));
 }
 
 /**
@@ -738,12 +738,12 @@
 	struct radeon_ring *ring = &rdev->ring[fence->ring];
 	uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr;
 
-	radeon_ring_write(ring, VCE_CMD_FENCE);
-	radeon_ring_write(ring, addr);
-	radeon_ring_write(ring, upper_32_bits(addr));
-	radeon_ring_write(ring, fence->seq);
-	radeon_ring_write(ring, VCE_CMD_TRAP);
-	radeon_ring_write(ring, VCE_CMD_END);
+	radeon_ring_write(ring, cpu_to_le32(VCE_CMD_FENCE));
+	radeon_ring_write(ring, cpu_to_le32(addr));
+	radeon_ring_write(ring, cpu_to_le32(upper_32_bits(addr)));
+	radeon_ring_write(ring, cpu_to_le32(fence->seq));
+	radeon_ring_write(ring, cpu_to_le32(VCE_CMD_TRAP));
+	radeon_ring_write(ring, cpu_to_le32(VCE_CMD_END));
 }
 
 /**
@@ -765,7 +765,7 @@
 			  ring->idx, r);
 		return r;
 	}
-	radeon_ring_write(ring, VCE_CMD_END);
+	radeon_ring_write(ring, cpu_to_le32(VCE_CMD_END));
 	radeon_ring_unlock_commit(rdev, ring, false);
 
 	for (i = 0; i < rdev->usec_timeout; i++) {
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c
index 48d97c0..3979632 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -455,15 +455,15 @@
 
 	if (soffset) {
 		/* make sure object fit at this offset */
-		eoffset = soffset + size;
+		eoffset = soffset + size - 1;
 		if (soffset >= eoffset) {
 			r = -EINVAL;
 			goto error_unreserve;
 		}
 
 		last_pfn = eoffset / RADEON_GPU_PAGE_SIZE;
-		if (last_pfn > rdev->vm_manager.max_pfn) {
-			dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n",
+		if (last_pfn >= rdev->vm_manager.max_pfn) {
+			dev_err(rdev->dev, "va above limit (0x%08X >= 0x%08X)\n",
 				last_pfn, rdev->vm_manager.max_pfn);
 			r = -EINVAL;
 			goto error_unreserve;
@@ -478,7 +478,7 @@
 	eoffset /= RADEON_GPU_PAGE_SIZE;
 	if (soffset || eoffset) {
 		struct interval_tree_node *it;
-		it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1);
+		it = interval_tree_iter_first(&vm->va, soffset, eoffset);
 		if (it && it != &bo_va->it) {
 			struct radeon_bo_va *tmp;
 			tmp = container_of(it, struct radeon_bo_va, it);
@@ -518,7 +518,7 @@
 	if (soffset || eoffset) {
 		spin_lock(&vm->status_lock);
 		bo_va->it.start = soffset;
-		bo_va->it.last = eoffset - 1;
+		bo_va->it.last = eoffset;
 		list_add(&bo_va->vm_status, &vm->cleared);
 		spin_unlock(&vm->status_lock);
 		interval_tree_insert(&bo_va->it, &vm->va);
@@ -888,7 +888,7 @@
 	unsigned i;
 
 	start >>= radeon_vm_block_size;
-	end >>= radeon_vm_block_size;
+	end = (end - 1) >> radeon_vm_block_size;
 
 	for (i = start; i <= end; ++i)
 		radeon_bo_fence(vm->page_tables[i].bo, fence, true);
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index 4c4a721..d1a7b58 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -915,6 +915,11 @@
 #define DCCG_AUDIO_DTO1_PHASE                           0x05c0
 #define DCCG_AUDIO_DTO1_MODULE                          0x05c4
 
+#define DENTIST_DISPCLK_CNTL				0x0490
+#	define DENTIST_DPREFCLK_WDIVIDER(x)		(((x) & 0x7f) << 24)
+#	define DENTIST_DPREFCLK_WDIVIDER_MASK		(0x7f << 24)
+#	define DENTIST_DPREFCLK_WDIVIDER_SHIFT		24
+
 #define AFMT_AUDIO_SRC_CONTROL                          0x713c
 #define		AFMT_AUDIO_SRC_SELECT(x)		(((x) & 7) << 0)
 /* AFMT_AUDIO_SRC_SELECT
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 35215f6..8573985 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -25,3 +25,13 @@
 	  for the Synopsys DesignWare HDMI driver. If you want to
 	  enable HDMI on RK3288 based SoC, you should selet this
 	  option.
+
+config ROCKCHIP_DW_MIPI_DSI
+	tristate "Rockchip specific extensions for Synopsys DW MIPI DSI"
+	depends on DRM_ROCKCHIP
+	select DRM_MIPI_DSI
+	help
+	 This selects support for Rockchip SoC specific extensions
+	 for the Synopsys DesignWare HDMI driver. If you want to
+	 enable MIPI DSI on RK3288 based SoC, you should selet this
+	 option.
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index f3d8a19..d1dc0f7 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -6,5 +6,7 @@
 		rockchip_drm_gem.o
 
 obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
+obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 
-obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o
+obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o \
+				rockchip_vop_reg.o
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
new file mode 100644
index 0000000..7bfe243
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -0,0 +1,1194 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/iopoll.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drmP.h>
+#include <video/mipi_display.h>
+
+#include "rockchip_drm_drv.h"
+#include "rockchip_drm_vop.h"
+
+#define DRIVER_NAME    "dw-mipi-dsi"
+
+#define GRF_SOC_CON6                    0x025c
+#define DSI0_SEL_VOP_LIT                (1 << 6)
+#define DSI1_SEL_VOP_LIT                (1 << 9)
+
+#define DSI_VERSION			0x00
+#define DSI_PWR_UP			0x04
+#define RESET				0
+#define POWERUP				BIT(0)
+
+#define DSI_CLKMGR_CFG			0x08
+#define TO_CLK_DIVIDSION(div)		(((div) & 0xff) << 8)
+#define TX_ESC_CLK_DIVIDSION(div)	(((div) & 0xff) << 0)
+
+#define DSI_DPI_VCID			0x0c
+#define DPI_VID(vid)			(((vid) & 0x3) << 0)
+
+#define DSI_DPI_COLOR_CODING		0x10
+#define EN18_LOOSELY			BIT(8)
+#define DPI_COLOR_CODING_16BIT_1	0x0
+#define DPI_COLOR_CODING_16BIT_2	0x1
+#define DPI_COLOR_CODING_16BIT_3	0x2
+#define DPI_COLOR_CODING_18BIT_1	0x3
+#define DPI_COLOR_CODING_18BIT_2	0x4
+#define DPI_COLOR_CODING_24BIT		0x5
+
+#define DSI_DPI_CFG_POL			0x14
+#define COLORM_ACTIVE_LOW		BIT(4)
+#define SHUTD_ACTIVE_LOW		BIT(3)
+#define HSYNC_ACTIVE_LOW		BIT(2)
+#define VSYNC_ACTIVE_LOW		BIT(1)
+#define DATAEN_ACTIVE_LOW		BIT(0)
+
+#define DSI_DPI_LP_CMD_TIM		0x18
+#define OUTVACT_LPCMD_TIME(p)		(((p) & 0xff) << 16)
+#define INVACT_LPCMD_TIME(p)		((p) & 0xff)
+
+#define DSI_DBI_CFG			0x20
+#define DSI_DBI_CMDSIZE			0x28
+
+#define DSI_PCKHDL_CFG			0x2c
+#define EN_CRC_RX			BIT(4)
+#define EN_ECC_RX			BIT(3)
+#define EN_BTA				BIT(2)
+#define EN_EOTP_RX			BIT(1)
+#define EN_EOTP_TX			BIT(0)
+
+#define DSI_MODE_CFG			0x34
+#define ENABLE_VIDEO_MODE		0
+#define ENABLE_CMD_MODE			BIT(0)
+
+#define DSI_VID_MODE_CFG		0x38
+#define FRAME_BTA_ACK			BIT(14)
+#define ENABLE_LOW_POWER		(0x3f << 8)
+#define ENABLE_LOW_POWER_MASK		(0x3f << 8)
+#define VID_MODE_TYPE_BURST_SYNC_PULSES		0x2
+#define VID_MODE_TYPE_MASK			0x3
+
+#define DSI_VID_PKT_SIZE		0x3c
+#define VID_PKT_SIZE(p)			(((p) & 0x3fff) << 0)
+#define VID_PKT_MAX_SIZE		0x3fff
+
+#define DSI_VID_HSA_TIME		0x48
+#define DSI_VID_HBP_TIME		0x4c
+#define DSI_VID_HLINE_TIME		0x50
+#define DSI_VID_VSA_LINES		0x54
+#define DSI_VID_VBP_LINES		0x58
+#define DSI_VID_VFP_LINES		0x5c
+#define DSI_VID_VACTIVE_LINES		0x60
+#define DSI_CMD_MODE_CFG		0x68
+#define MAX_RD_PKT_SIZE_LP		BIT(24)
+#define DCS_LW_TX_LP			BIT(19)
+#define DCS_SR_0P_TX_LP			BIT(18)
+#define DCS_SW_1P_TX_LP			BIT(17)
+#define DCS_SW_0P_TX_LP			BIT(16)
+#define GEN_LW_TX_LP			BIT(14)
+#define GEN_SR_2P_TX_LP			BIT(13)
+#define GEN_SR_1P_TX_LP			BIT(12)
+#define GEN_SR_0P_TX_LP			BIT(11)
+#define GEN_SW_2P_TX_LP			BIT(10)
+#define GEN_SW_1P_TX_LP			BIT(9)
+#define GEN_SW_0P_TX_LP			BIT(8)
+#define EN_ACK_RQST			BIT(1)
+#define EN_TEAR_FX			BIT(0)
+
+#define CMD_MODE_ALL_LP			(MAX_RD_PKT_SIZE_LP | \
+					 DCS_LW_TX_LP | \
+					 DCS_SR_0P_TX_LP | \
+					 DCS_SW_1P_TX_LP | \
+					 DCS_SW_0P_TX_LP | \
+					 GEN_LW_TX_LP | \
+					 GEN_SR_2P_TX_LP | \
+					 GEN_SR_1P_TX_LP | \
+					 GEN_SR_0P_TX_LP | \
+					 GEN_SW_2P_TX_LP | \
+					 GEN_SW_1P_TX_LP | \
+					 GEN_SW_0P_TX_LP)
+
+#define DSI_GEN_HDR			0x6c
+#define GEN_HDATA(data)			(((data) & 0xffff) << 8)
+#define GEN_HDATA_MASK			(0xffff << 8)
+#define GEN_HTYPE(type)			(((type) & 0xff) << 0)
+#define GEN_HTYPE_MASK			0xff
+
+#define DSI_GEN_PLD_DATA		0x70
+
+#define DSI_CMD_PKT_STATUS		0x74
+#define GEN_CMD_EMPTY			BIT(0)
+#define GEN_CMD_FULL			BIT(1)
+#define GEN_PLD_W_EMPTY			BIT(2)
+#define GEN_PLD_W_FULL			BIT(3)
+#define GEN_PLD_R_EMPTY			BIT(4)
+#define GEN_PLD_R_FULL			BIT(5)
+#define GEN_RD_CMD_BUSY			BIT(6)
+
+#define DSI_TO_CNT_CFG			0x78
+#define HSTX_TO_CNT(p)			(((p) & 0xffff) << 16)
+#define LPRX_TO_CNT(p)			((p) & 0xffff)
+
+#define DSI_BTA_TO_CNT			0x8c
+
+#define DSI_LPCLK_CTRL			0x94
+#define AUTO_CLKLANE_CTRL		BIT(1)
+#define PHY_TXREQUESTCLKHS		BIT(0)
+
+#define DSI_PHY_TMR_LPCLK_CFG		0x98
+#define PHY_CLKHS2LP_TIME(lbcc)		(((lbcc) & 0x3ff) << 16)
+#define PHY_CLKLP2HS_TIME(lbcc)		((lbcc) & 0x3ff)
+
+#define DSI_PHY_TMR_CFG			0x9c
+#define PHY_HS2LP_TIME(lbcc)		(((lbcc) & 0xff) << 24)
+#define PHY_LP2HS_TIME(lbcc)		(((lbcc) & 0xff) << 16)
+#define MAX_RD_TIME(lbcc)		((lbcc) & 0x7fff)
+
+#define DSI_PHY_RSTZ			0xa0
+#define PHY_DISFORCEPLL			0
+#define PHY_ENFORCEPLL			BIT(3)
+#define PHY_DISABLECLK			0
+#define PHY_ENABLECLK			BIT(2)
+#define PHY_RSTZ			0
+#define PHY_UNRSTZ			BIT(1)
+#define PHY_SHUTDOWNZ			0
+#define PHY_UNSHUTDOWNZ			BIT(0)
+
+#define DSI_PHY_IF_CFG			0xa4
+#define N_LANES(n)			((((n) - 1) & 0x3) << 0)
+#define PHY_STOP_WAIT_TIME(cycle)	(((cycle) & 0xff) << 8)
+
+#define DSI_PHY_STATUS			0xb0
+#define LOCK				BIT(0)
+#define STOP_STATE_CLK_LANE		BIT(2)
+
+#define DSI_PHY_TST_CTRL0		0xb4
+#define PHY_TESTCLK			BIT(1)
+#define PHY_UNTESTCLK			0
+#define PHY_TESTCLR			BIT(0)
+#define PHY_UNTESTCLR			0
+
+#define DSI_PHY_TST_CTRL1		0xb8
+#define PHY_TESTEN			BIT(16)
+#define PHY_UNTESTEN			0
+#define PHY_TESTDOUT(n)			(((n) & 0xff) << 8)
+#define PHY_TESTDIN(n)			(((n) & 0xff) << 0)
+
+#define DSI_INT_ST0			0xbc
+#define DSI_INT_ST1			0xc0
+#define DSI_INT_MSK0			0xc4
+#define DSI_INT_MSK1			0xc8
+
+#define PHY_STATUS_TIMEOUT_US		10000
+#define CMD_PKT_STATUS_TIMEOUT_US	20000
+
+#define BYPASS_VCO_RANGE	BIT(7)
+#define VCO_RANGE_CON_SEL(val)	(((val) & 0x7) << 3)
+#define VCO_IN_CAP_CON_DEFAULT	(0x0 << 1)
+#define VCO_IN_CAP_CON_LOW	(0x1 << 1)
+#define VCO_IN_CAP_CON_HIGH	(0x2 << 1)
+#define REF_BIAS_CUR_SEL	BIT(0)
+
+#define CP_CURRENT_3MA		BIT(3)
+#define CP_PROGRAM_EN		BIT(7)
+#define LPF_PROGRAM_EN		BIT(6)
+#define LPF_RESISTORS_20_KOHM	0
+
+#define HSFREQRANGE_SEL(val)	(((val) & 0x3f) << 1)
+
+#define INPUT_DIVIDER(val)	((val - 1) & 0x7f)
+#define LOW_PROGRAM_EN		0
+#define HIGH_PROGRAM_EN		BIT(7)
+#define LOOP_DIV_LOW_SEL(val)	((val - 1) & 0x1f)
+#define LOOP_DIV_HIGH_SEL(val)	(((val - 1) >> 5) & 0x1f)
+#define PLL_LOOP_DIV_EN		BIT(5)
+#define PLL_INPUT_DIV_EN	BIT(4)
+
+#define POWER_CONTROL		BIT(6)
+#define INTERNAL_REG_CURRENT	BIT(3)
+#define BIAS_BLOCK_ON		BIT(2)
+#define BANDGAP_ON		BIT(0)
+
+#define TER_RESISTOR_HIGH	BIT(7)
+#define	TER_RESISTOR_LOW	0
+#define LEVEL_SHIFTERS_ON	BIT(6)
+#define TER_CAL_DONE		BIT(5)
+#define SETRD_MAX		(0x7 << 2)
+#define POWER_MANAGE		BIT(1)
+#define TER_RESISTORS_ON	BIT(0)
+
+#define BIASEXTR_SEL(val)	((val) & 0x7)
+#define BANDGAP_SEL(val)	((val) & 0x7)
+#define TLP_PROGRAM_EN		BIT(7)
+#define THS_PRE_PROGRAM_EN	BIT(7)
+#define THS_ZERO_PROGRAM_EN	BIT(6)
+
+enum {
+	BANDGAP_97_07,
+	BANDGAP_98_05,
+	BANDGAP_99_02,
+	BANDGAP_100_00,
+	BANDGAP_93_17,
+	BANDGAP_94_15,
+	BANDGAP_95_12,
+	BANDGAP_96_10,
+};
+
+enum {
+	BIASEXTR_87_1,
+	BIASEXTR_91_5,
+	BIASEXTR_95_9,
+	BIASEXTR_100,
+	BIASEXTR_105_94,
+	BIASEXTR_111_88,
+	BIASEXTR_118_8,
+	BIASEXTR_127_7,
+};
+
+struct dw_mipi_dsi_plat_data {
+	unsigned int max_data_lanes;
+	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
+					   struct drm_display_mode *mode);
+};
+
+struct dw_mipi_dsi {
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+	struct mipi_dsi_host dsi_host;
+	struct drm_panel *panel;
+	struct device *dev;
+	struct regmap *grf_regmap;
+	void __iomem *base;
+
+	struct clk *pllref_clk;
+	struct clk *pclk;
+
+	unsigned int lane_mbps; /* per lane */
+	u32 channel;
+	u32 lanes;
+	u32 format;
+	u16 input_div;
+	u16 feedback_div;
+	struct drm_display_mode *mode;
+
+	const struct dw_mipi_dsi_plat_data *pdata;
+};
+
+enum dw_mipi_dsi_mode {
+	DW_MIPI_DSI_CMD_MODE,
+	DW_MIPI_DSI_VID_MODE,
+};
+
+struct dphy_pll_testdin_map {
+	unsigned int max_mbps;
+	u8 testdin;
+};
+
+/* The table is based on 27MHz DPHY pll reference clock. */
+static const struct dphy_pll_testdin_map dptdin_map[] = {
+	{  90, 0x00}, { 100, 0x10}, { 110, 0x20}, { 130, 0x01},
+	{ 140, 0x11}, { 150, 0x21}, { 170, 0x02}, { 180, 0x12},
+	{ 200, 0x22}, { 220, 0x03}, { 240, 0x13}, { 250, 0x23},
+	{ 270, 0x04}, { 300, 0x14}, { 330, 0x05}, { 360, 0x15},
+	{ 400, 0x25}, { 450, 0x06}, { 500, 0x16}, { 550, 0x07},
+	{ 600, 0x17}, { 650, 0x08}, { 700, 0x18}, { 750, 0x09},
+	{ 800, 0x19}, { 850, 0x29}, { 900, 0x39}, { 950, 0x0a},
+	{1000, 0x1a}, {1050, 0x2a}, {1100, 0x3a}, {1150, 0x0b},
+	{1200, 0x1b}, {1250, 0x2b}, {1300, 0x3b}, {1350, 0x0c},
+	{1400, 0x1c}, {1450, 0x2c}, {1500, 0x3c}
+};
+
+static int max_mbps_to_testdin(unsigned int max_mbps)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dptdin_map); i++)
+		if (dptdin_map[i].max_mbps > max_mbps)
+			return dptdin_map[i].testdin;
+
+	return -EINVAL;
+}
+
+/*
+ * The controller should generate 2 frames before
+ * preparing the peripheral.
+ */
+static void dw_mipi_dsi_wait_for_two_frames(struct dw_mipi_dsi *dsi)
+{
+	int refresh, two_frames;
+
+	refresh = drm_mode_vrefresh(dsi->mode);
+	two_frames = DIV_ROUND_UP(MSEC_PER_SEC, refresh) * 2;
+	msleep(two_frames);
+}
+
+static inline struct dw_mipi_dsi *host_to_dsi(struct mipi_dsi_host *host)
+{
+	return container_of(host, struct dw_mipi_dsi, dsi_host);
+}
+
+static inline struct dw_mipi_dsi *con_to_dsi(struct drm_connector *con)
+{
+	return container_of(con, struct dw_mipi_dsi, connector);
+}
+
+static inline struct dw_mipi_dsi *encoder_to_dsi(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct dw_mipi_dsi, encoder);
+}
+static inline void dsi_write(struct dw_mipi_dsi *dsi, u32 reg, u32 val)
+{
+	writel(val, dsi->base + reg);
+}
+
+static inline u32 dsi_read(struct dw_mipi_dsi *dsi, u32 reg)
+{
+	return readl(dsi->base + reg);
+}
+
+static void dw_mipi_dsi_phy_write(struct dw_mipi_dsi *dsi, u8 test_code,
+				 u8 test_data)
+{
+	/*
+	 * With the falling edge on TESTCLK, the TESTDIN[7:0] signal content
+	 * is latched internally as the current test code. Test data is
+	 * programmed internally by rising edge on TESTCLK.
+	 */
+	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
+
+	dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_TESTEN | PHY_TESTDOUT(0) |
+					  PHY_TESTDIN(test_code));
+
+	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLK | PHY_UNTESTCLR);
+
+	dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_UNTESTEN | PHY_TESTDOUT(0) |
+					  PHY_TESTDIN(test_data));
+
+	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
+}
+
+static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
+{
+	int ret, testdin, vco, val;
+
+	vco = (dsi->lane_mbps < 200) ? 0 : (dsi->lane_mbps + 100) / 200;
+
+	testdin = max_mbps_to_testdin(dsi->lane_mbps);
+	if (testdin < 0) {
+		dev_err(dsi->dev,
+			"failed to get testdin for %dmbps lane clock\n",
+			dsi->lane_mbps);
+		return testdin;
+	}
+
+	dsi_write(dsi, DSI_PWR_UP, POWERUP);
+
+	dw_mipi_dsi_phy_write(dsi, 0x10, BYPASS_VCO_RANGE |
+					 VCO_RANGE_CON_SEL(vco) |
+					 VCO_IN_CAP_CON_LOW |
+					 REF_BIAS_CUR_SEL);
+
+	dw_mipi_dsi_phy_write(dsi, 0x11, CP_CURRENT_3MA);
+	dw_mipi_dsi_phy_write(dsi, 0x12, CP_PROGRAM_EN | LPF_PROGRAM_EN |
+					 LPF_RESISTORS_20_KOHM);
+
+	dw_mipi_dsi_phy_write(dsi, 0x44, HSFREQRANGE_SEL(testdin));
+
+	dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
+	dw_mipi_dsi_phy_write(dsi, 0x17, INPUT_DIVIDER(dsi->input_div));
+	dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_LOW_SEL(dsi->feedback_div) |
+					 LOW_PROGRAM_EN);
+	dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
+					 HIGH_PROGRAM_EN);
+
+	dw_mipi_dsi_phy_write(dsi, 0x20, POWER_CONTROL | INTERNAL_REG_CURRENT |
+					 BIAS_BLOCK_ON | BANDGAP_ON);
+
+	dw_mipi_dsi_phy_write(dsi, 0x21, TER_RESISTOR_LOW | TER_CAL_DONE |
+					 SETRD_MAX | TER_RESISTORS_ON);
+	dw_mipi_dsi_phy_write(dsi, 0x21, TER_RESISTOR_HIGH | LEVEL_SHIFTERS_ON |
+					 SETRD_MAX | POWER_MANAGE |
+					 TER_RESISTORS_ON);
+
+	dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN |
+					 BIASEXTR_SEL(BIASEXTR_127_7));
+	dw_mipi_dsi_phy_write(dsi, 0x22, HIGH_PROGRAM_EN |
+					 BANDGAP_SEL(BANDGAP_96_10));
+
+	dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | 0xf);
+	dw_mipi_dsi_phy_write(dsi, 0x71, THS_PRE_PROGRAM_EN | 0x55);
+	dw_mipi_dsi_phy_write(dsi, 0x72, THS_ZERO_PROGRAM_EN | 0xa);
+
+	dsi_write(dsi, DSI_PHY_RSTZ, PHY_ENFORCEPLL | PHY_ENABLECLK |
+				     PHY_UNRSTZ | PHY_UNSHUTDOWNZ);
+
+
+	ret = readx_poll_timeout(readl, dsi->base + DSI_PHY_STATUS,
+				 val, val & LOCK, 1000, PHY_STATUS_TIMEOUT_US);
+	if (ret < 0) {
+		dev_err(dsi->dev, "failed to wait for phy lock state\n");
+		return ret;
+	}
+
+	ret = readx_poll_timeout(readl, dsi->base + DSI_PHY_STATUS,
+				 val, val & STOP_STATE_CLK_LANE, 1000,
+				 PHY_STATUS_TIMEOUT_US);
+	if (ret < 0) {
+		dev_err(dsi->dev,
+			"failed to wait for phy clk lane stop state\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi)
+{
+	unsigned int bpp, i, pre;
+	unsigned long mpclk, pllref, tmp;
+	unsigned int m = 1, n = 1, target_mbps = 1000;
+	unsigned int max_mbps = dptdin_map[ARRAY_SIZE(dptdin_map) - 1].max_mbps;
+
+	bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+	if (bpp < 0) {
+		dev_err(dsi->dev, "failed to get bpp for pixel format %d\n",
+			dsi->format);
+		return bpp;
+	}
+
+	mpclk = DIV_ROUND_UP(dsi->mode->clock, MSEC_PER_SEC);
+	if (mpclk) {
+		/* take 1 / 0.9, since mbps must big than bandwidth of RGB */
+		tmp = mpclk * (bpp / dsi->lanes) * 10 / 9;
+		if (tmp < max_mbps)
+			target_mbps = tmp;
+		else
+			dev_err(dsi->dev, "DPHY clock frequency is out of range\n");
+	}
+
+	pllref = DIV_ROUND_UP(clk_get_rate(dsi->pllref_clk), USEC_PER_SEC);
+	tmp = pllref;
+
+	for (i = 1; i < 6; i++) {
+		pre = pllref / i;
+		if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) {
+			tmp = target_mbps % pre;
+			n = i;
+			m = target_mbps / pre;
+		}
+		if (tmp == 0)
+			break;
+	}
+
+	dsi->lane_mbps = pllref / n * m;
+	dsi->input_div = n;
+	dsi->feedback_div = m;
+
+	return 0;
+}
+
+static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
+				   struct mipi_dsi_device *device)
+{
+	struct dw_mipi_dsi *dsi = host_to_dsi(host);
+
+	if (device->lanes > dsi->pdata->max_data_lanes) {
+		dev_err(dsi->dev, "the number of data lanes(%u) is too many\n",
+				device->lanes);
+		return -EINVAL;
+	}
+
+	if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) ||
+	    !(device->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) {
+		dev_err(dsi->dev, "device mode is unsupported\n");
+		return -EINVAL;
+	}
+
+	dsi->lanes = device->lanes;
+	dsi->channel = device->channel;
+	dsi->format = device->format;
+	dsi->panel = of_drm_find_panel(device->dev.of_node);
+	if (dsi->panel)
+		return drm_panel_attach(dsi->panel, &dsi->connector);
+
+	return -EINVAL;
+}
+
+static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,
+				   struct mipi_dsi_device *device)
+{
+	struct dw_mipi_dsi *dsi = host_to_dsi(host);
+
+	drm_panel_detach(dsi->panel);
+
+	return 0;
+}
+
+static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 val)
+{
+	int ret;
+
+	ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
+				 val, !(val & GEN_CMD_FULL), 1000,
+				 CMD_PKT_STATUS_TIMEOUT_US);
+	if (ret < 0) {
+		dev_err(dsi->dev, "failed to get available command FIFO\n");
+		return ret;
+	}
+
+	dsi_write(dsi, DSI_GEN_HDR, val);
+
+	ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
+				 val, val & (GEN_CMD_EMPTY | GEN_PLD_W_EMPTY),
+				 1000, CMD_PKT_STATUS_TIMEOUT_US);
+	if (ret < 0) {
+		dev_err(dsi->dev, "failed to write command FIFO\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dw_mipi_dsi_dcs_short_write(struct dw_mipi_dsi *dsi,
+				       const struct mipi_dsi_msg *msg)
+{
+	const u16 *tx_buf = msg->tx_buf;
+	u32 val = GEN_HDATA(*tx_buf) | GEN_HTYPE(msg->type);
+
+	if (msg->tx_len > 2) {
+		dev_err(dsi->dev, "too long tx buf length %zu for short write\n",
+			msg->tx_len);
+		return -EINVAL;
+	}
+
+	return dw_mipi_dsi_gen_pkt_hdr_write(dsi, val);
+}
+
+static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,
+				      const struct mipi_dsi_msg *msg)
+{
+	const u32 *tx_buf = msg->tx_buf;
+	int len = msg->tx_len, pld_data_bytes = sizeof(*tx_buf), ret;
+	u32 val = GEN_HDATA(msg->tx_len) | GEN_HTYPE(msg->type);
+	u32 remainder = 0;
+
+	if (msg->tx_len < 3) {
+		dev_err(dsi->dev, "wrong tx buf length %zu for long write\n",
+			msg->tx_len);
+		return -EINVAL;
+	}
+
+	while (DIV_ROUND_UP(len, pld_data_bytes)) {
+		if (len < pld_data_bytes) {
+			memcpy(&remainder, tx_buf, len);
+			dsi_write(dsi, DSI_GEN_PLD_DATA, remainder);
+			len = 0;
+		} else {
+			dsi_write(dsi, DSI_GEN_PLD_DATA, *tx_buf);
+			tx_buf++;
+			len -= pld_data_bytes;
+		}
+
+		ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
+					 val, !(val & GEN_PLD_W_FULL), 1000,
+					 CMD_PKT_STATUS_TIMEOUT_US);
+		if (ret < 0) {
+			dev_err(dsi->dev,
+				"failed to get available write payload FIFO\n");
+			return ret;
+		}
+	}
+
+	return dw_mipi_dsi_gen_pkt_hdr_write(dsi, val);
+}
+
+static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
+					 const struct mipi_dsi_msg *msg)
+{
+	struct dw_mipi_dsi *dsi = host_to_dsi(host);
+	int ret;
+
+	switch (msg->type) {
+	case MIPI_DSI_DCS_SHORT_WRITE:
+	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+	case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
+		ret = dw_mipi_dsi_dcs_short_write(dsi, msg);
+		break;
+	case MIPI_DSI_DCS_LONG_WRITE:
+		ret = dw_mipi_dsi_dcs_long_write(dsi, msg);
+		break;
+	default:
+		dev_err(dsi->dev, "unsupported message type\n");
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct mipi_dsi_host_ops dw_mipi_dsi_host_ops = {
+	.attach = dw_mipi_dsi_host_attach,
+	.detach = dw_mipi_dsi_host_detach,
+	.transfer = dw_mipi_dsi_host_transfer,
+};
+
+static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
+{
+	u32 val;
+
+	val = VID_MODE_TYPE_BURST_SYNC_PULSES | ENABLE_LOW_POWER;
+
+	dsi_write(dsi, DSI_VID_MODE_CFG, val);
+}
+
+static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi,
+				 enum dw_mipi_dsi_mode mode)
+{
+	if (mode == DW_MIPI_DSI_CMD_MODE) {
+		dsi_write(dsi, DSI_PWR_UP, RESET);
+		dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE);
+		dsi_write(dsi, DSI_PWR_UP, POWERUP);
+	} else {
+		dsi_write(dsi, DSI_PWR_UP, RESET);
+		dsi_write(dsi, DSI_MODE_CFG, ENABLE_VIDEO_MODE);
+		dw_mipi_dsi_video_mode_config(dsi);
+		dsi_write(dsi, DSI_PWR_UP, POWERUP);
+	}
+}
+
+static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi)
+{
+	dsi_write(dsi, DSI_PWR_UP, RESET);
+	dsi_write(dsi, DSI_PHY_RSTZ, PHY_RSTZ);
+}
+
+static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi)
+{
+	dsi_write(dsi, DSI_PWR_UP, RESET);
+	dsi_write(dsi, DSI_PHY_RSTZ, PHY_DISFORCEPLL | PHY_DISABLECLK
+		  | PHY_RSTZ | PHY_SHUTDOWNZ);
+	dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVIDSION(10) |
+		  TX_ESC_CLK_DIVIDSION(7));
+	dsi_write(dsi, DSI_LPCLK_CTRL, PHY_TXREQUESTCLKHS);
+}
+
+static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi,
+				   struct drm_display_mode *mode)
+{
+	u32 val = 0, color = 0;
+
+	switch (dsi->format) {
+	case MIPI_DSI_FMT_RGB888:
+		color = DPI_COLOR_CODING_24BIT;
+		break;
+	case MIPI_DSI_FMT_RGB666:
+		color = DPI_COLOR_CODING_18BIT_2 | EN18_LOOSELY;
+		break;
+	case MIPI_DSI_FMT_RGB666_PACKED:
+		color = DPI_COLOR_CODING_18BIT_1;
+		break;
+	case MIPI_DSI_FMT_RGB565:
+		color = DPI_COLOR_CODING_16BIT_1;
+		break;
+	}
+
+	if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
+		val |= VSYNC_ACTIVE_LOW;
+	if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
+		val |= HSYNC_ACTIVE_LOW;
+
+	dsi_write(dsi, DSI_DPI_VCID, DPI_VID(dsi->channel));
+	dsi_write(dsi, DSI_DPI_COLOR_CODING, color);
+	dsi_write(dsi, DSI_DPI_CFG_POL, val);
+	dsi_write(dsi, DSI_DPI_LP_CMD_TIM, OUTVACT_LPCMD_TIME(4)
+		  | INVACT_LPCMD_TIME(4));
+}
+
+static void dw_mipi_dsi_packet_handler_config(struct dw_mipi_dsi *dsi)
+{
+	dsi_write(dsi, DSI_PCKHDL_CFG, EN_CRC_RX | EN_ECC_RX | EN_BTA);
+}
+
+static void dw_mipi_dsi_video_packet_config(struct dw_mipi_dsi *dsi,
+					    struct drm_display_mode *mode)
+{
+	dsi_write(dsi, DSI_VID_PKT_SIZE, VID_PKT_SIZE(mode->hdisplay));
+}
+
+static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi)
+{
+	dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(1000) | LPRX_TO_CNT(1000));
+	dsi_write(dsi, DSI_BTA_TO_CNT, 0xd00);
+	dsi_write(dsi, DSI_CMD_MODE_CFG, CMD_MODE_ALL_LP);
+	dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE);
+}
+
+/* Get lane byte clock cycles. */
+static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi,
+					   u32 hcomponent)
+{
+	u32 frac, lbcc;
+
+	lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8;
+
+	frac = lbcc % dsi->mode->clock;
+	lbcc = lbcc / dsi->mode->clock;
+	if (frac)
+		lbcc++;
+
+	return lbcc;
+}
+
+static void dw_mipi_dsi_line_timer_config(struct dw_mipi_dsi *dsi)
+{
+	u32 htotal, hsa, hbp, lbcc;
+	struct drm_display_mode *mode = dsi->mode;
+
+	htotal = mode->htotal;
+	hsa = mode->hsync_end - mode->hsync_start;
+	hbp = mode->htotal - mode->hsync_end;
+
+	lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, htotal);
+	dsi_write(dsi, DSI_VID_HLINE_TIME, lbcc);
+
+	lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, hsa);
+	dsi_write(dsi, DSI_VID_HSA_TIME, lbcc);
+
+	lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, hbp);
+	dsi_write(dsi, DSI_VID_HBP_TIME, lbcc);
+}
+
+static void dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi)
+{
+	u32 vactive, vsa, vfp, vbp;
+	struct drm_display_mode *mode = dsi->mode;
+
+	vactive = mode->vdisplay;
+	vsa = mode->vsync_end - mode->vsync_start;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vbp = mode->vtotal - mode->vsync_end;
+
+	dsi_write(dsi, DSI_VID_VACTIVE_LINES, vactive);
+	dsi_write(dsi, DSI_VID_VSA_LINES, vsa);
+	dsi_write(dsi, DSI_VID_VFP_LINES, vfp);
+	dsi_write(dsi, DSI_VID_VBP_LINES, vbp);
+}
+
+static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi)
+{
+	dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME(0x40)
+		  | PHY_LP2HS_TIME(0x40) | MAX_RD_TIME(10000));
+
+	dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG, PHY_CLKHS2LP_TIME(0x40)
+		  | PHY_CLKLP2HS_TIME(0x40));
+}
+
+static void dw_mipi_dsi_dphy_interface_config(struct dw_mipi_dsi *dsi)
+{
+	dsi_write(dsi, DSI_PHY_IF_CFG, PHY_STOP_WAIT_TIME(0x20) |
+		  N_LANES(dsi->lanes));
+}
+
+static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi)
+{
+	dsi_read(dsi, DSI_INT_ST0);
+	dsi_read(dsi, DSI_INT_ST1);
+	dsi_write(dsi, DSI_INT_MSK0, 0);
+	dsi_write(dsi, DSI_INT_MSK1, 0);
+}
+
+static void dw_mipi_dsi_encoder_mode_set(struct drm_encoder *encoder,
+					struct drm_display_mode *mode,
+					struct drm_display_mode *adjusted_mode)
+{
+	struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
+	int ret;
+
+	dsi->mode = adjusted_mode;
+
+	ret = dw_mipi_dsi_get_lane_bps(dsi);
+	if (ret < 0)
+		return;
+
+	if (clk_prepare_enable(dsi->pclk)) {
+		dev_err(dsi->dev, "%s: Failed to enable pclk\n", __func__);
+		return;
+	}
+
+	dw_mipi_dsi_init(dsi);
+	dw_mipi_dsi_dpi_config(dsi, mode);
+	dw_mipi_dsi_packet_handler_config(dsi);
+	dw_mipi_dsi_video_mode_config(dsi);
+	dw_mipi_dsi_video_packet_config(dsi, mode);
+	dw_mipi_dsi_command_mode_config(dsi);
+	dw_mipi_dsi_line_timer_config(dsi);
+	dw_mipi_dsi_vertical_timing_config(dsi);
+	dw_mipi_dsi_dphy_timing_config(dsi);
+	dw_mipi_dsi_dphy_interface_config(dsi);
+	dw_mipi_dsi_clear_err(dsi);
+	if (drm_panel_prepare(dsi->panel))
+		dev_err(dsi->dev, "failed to prepare panel\n");
+
+	clk_disable_unprepare(dsi->pclk);
+}
+
+static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder)
+{
+	struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
+
+	drm_panel_disable(dsi->panel);
+
+	if (clk_prepare_enable(dsi->pclk)) {
+		dev_err(dsi->dev, "%s: Failed to enable pclk\n", __func__);
+		return;
+	}
+
+	dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_CMD_MODE);
+	drm_panel_unprepare(dsi->panel);
+	dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_VID_MODE);
+
+	/*
+	 * This is necessary to make sure the peripheral will be driven
+	 * normally when the display is enabled again later.
+	 */
+	msleep(120);
+
+	dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_CMD_MODE);
+	dw_mipi_dsi_disable(dsi);
+	clk_disable_unprepare(dsi->pclk);
+}
+
+static bool dw_mipi_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
+					const struct drm_display_mode *mode,
+					struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder)
+{
+	struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
+	int mux  = rockchip_drm_encoder_get_mux_id(dsi->dev->of_node, encoder);
+	u32 interface_pix_fmt;
+	u32 val;
+
+	if (clk_prepare_enable(dsi->pclk)) {
+		dev_err(dsi->dev, "%s: Failed to enable pclk\n", __func__);
+		return;
+	}
+
+	dw_mipi_dsi_phy_init(dsi);
+	dw_mipi_dsi_wait_for_two_frames(dsi);
+
+	dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_VID_MODE);
+	drm_panel_enable(dsi->panel);
+
+	clk_disable_unprepare(dsi->pclk);
+
+	switch (dsi->format) {
+	case MIPI_DSI_FMT_RGB888:
+		interface_pix_fmt = ROCKCHIP_OUT_MODE_P888;
+		break;
+	case MIPI_DSI_FMT_RGB666:
+		interface_pix_fmt = ROCKCHIP_OUT_MODE_P666;
+		break;
+	case MIPI_DSI_FMT_RGB565:
+		interface_pix_fmt = ROCKCHIP_OUT_MODE_P565;
+		break;
+	default:
+		WARN_ON(1);
+		return;
+	}
+
+	rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_DSI,
+				      interface_pix_fmt);
+
+	if (mux)
+		val = DSI0_SEL_VOP_LIT | (DSI0_SEL_VOP_LIT << 16);
+	else
+		val = DSI0_SEL_VOP_LIT << 16;
+
+	regmap_write(dsi->grf_regmap, GRF_SOC_CON6, val);
+	dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
+}
+
+static struct drm_encoder_helper_funcs
+dw_mipi_dsi_encoder_helper_funcs = {
+	.mode_fixup = dw_mipi_dsi_encoder_mode_fixup,
+	.commit = dw_mipi_dsi_encoder_commit,
+	.mode_set = dw_mipi_dsi_encoder_mode_set,
+	.disable = dw_mipi_dsi_encoder_disable,
+};
+
+static struct drm_encoder_funcs dw_mipi_dsi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static int dw_mipi_dsi_connector_get_modes(struct drm_connector *connector)
+{
+	struct dw_mipi_dsi *dsi = con_to_dsi(connector);
+
+	return drm_panel_get_modes(dsi->panel);
+}
+
+static enum drm_mode_status dw_mipi_dsi_mode_valid(
+					struct drm_connector *connector,
+					struct drm_display_mode *mode)
+{
+	struct dw_mipi_dsi *dsi = con_to_dsi(connector);
+
+	enum drm_mode_status mode_status = MODE_OK;
+
+	if (dsi->pdata->mode_valid)
+		mode_status = dsi->pdata->mode_valid(connector, mode);
+
+	return mode_status;
+}
+
+static struct drm_encoder *dw_mipi_dsi_connector_best_encoder(
+					struct drm_connector *connector)
+{
+	struct dw_mipi_dsi *dsi = con_to_dsi(connector);
+
+	return &dsi->encoder;
+}
+
+static struct drm_connector_helper_funcs dw_mipi_dsi_connector_helper_funcs = {
+	.get_modes = dw_mipi_dsi_connector_get_modes,
+	.mode_valid = dw_mipi_dsi_mode_valid,
+	.best_encoder = dw_mipi_dsi_connector_best_encoder,
+};
+
+static enum drm_connector_status
+dw_mipi_dsi_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static void dw_mipi_dsi_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static struct drm_connector_funcs dw_mipi_dsi_atomic_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = dw_mipi_dsi_detect,
+	.destroy = dw_mipi_dsi_drm_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int dw_mipi_dsi_register(struct drm_device *drm,
+				      struct dw_mipi_dsi *dsi)
+{
+	struct drm_encoder *encoder = &dsi->encoder;
+	struct drm_connector *connector = &dsi->connector;
+	struct device *dev = dsi->dev;
+	int ret;
+
+	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm,
+							     dev->of_node);
+	/*
+	 * If we failed to find the CRTC(s) which this encoder is
+	 * supposed to be connected to, it's because the CRTC has
+	 * not been registered yet.  Defer probing, and hope that
+	 * the required CRTC is added later.
+	 */
+	if (encoder->possible_crtcs == 0)
+		return -EPROBE_DEFER;
+
+	drm_encoder_helper_add(&dsi->encoder,
+			       &dw_mipi_dsi_encoder_helper_funcs);
+	ret = drm_encoder_init(drm, &dsi->encoder, &dw_mipi_dsi_encoder_funcs,
+			 DRM_MODE_ENCODER_DSI, NULL);
+	if (ret) {
+		dev_err(dev, "Failed to initialize encoder with drm\n");
+		return ret;
+	}
+
+	drm_connector_helper_add(connector,
+			&dw_mipi_dsi_connector_helper_funcs);
+
+	drm_connector_init(drm, &dsi->connector,
+			   &dw_mipi_dsi_atomic_connector_funcs,
+			   DRM_MODE_CONNECTOR_DSI);
+
+	drm_mode_connector_attach_encoder(connector, encoder);
+
+	return 0;
+}
+
+static int rockchip_mipi_parse_dt(struct dw_mipi_dsi *dsi)
+{
+	struct device_node *np = dsi->dev->of_node;
+
+	dsi->grf_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	if (IS_ERR(dsi->grf_regmap)) {
+		dev_err(dsi->dev, "Unable to get rockchip,grf\n");
+		return PTR_ERR(dsi->grf_regmap);
+	}
+
+	return 0;
+}
+
+static enum drm_mode_status rk3288_mipi_dsi_mode_valid(
+					struct drm_connector *connector,
+					struct drm_display_mode *mode)
+{
+	/*
+	 * The VID_PKT_SIZE field in the DSI_VID_PKT_CFG
+	 * register is 11-bit.
+	 */
+	if (mode->hdisplay > 0x7ff)
+		return MODE_BAD_HVALUE;
+
+	/*
+	 * The V_ACTIVE_LINES field in the DSI_VTIMING_CFG
+	 * register is 11-bit.
+	 */
+	if (mode->vdisplay > 0x7ff)
+		return MODE_BAD_VVALUE;
+
+	return MODE_OK;
+}
+
+static struct dw_mipi_dsi_plat_data rk3288_mipi_dsi_drv_data = {
+	.max_data_lanes = 4,
+	.mode_valid = rk3288_mipi_dsi_mode_valid,
+};
+
+static const struct of_device_id dw_mipi_dsi_dt_ids[] = {
+	{
+	 .compatible = "rockchip,rk3288-mipi-dsi",
+	 .data = &rk3288_mipi_dsi_drv_data,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dw_mipi_dsi_dt_ids);
+
+static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
+			     void *data)
+{
+	const struct of_device_id *of_id =
+			of_match_device(dw_mipi_dsi_dt_ids, dev);
+	const struct dw_mipi_dsi_plat_data *pdata = of_id->data;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct dw_mipi_dsi *dsi;
+	struct resource *res;
+	int ret;
+
+	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
+	if (!dsi)
+		return -ENOMEM;
+
+	dsi->dev = dev;
+	dsi->pdata = pdata;
+
+	ret = rockchip_mipi_parse_dt(dsi);
+	if (ret)
+		return ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	dsi->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(dsi->base))
+		return PTR_ERR(dsi->base);
+
+	dsi->pllref_clk = devm_clk_get(dev, "ref");
+	if (IS_ERR(dsi->pllref_clk)) {
+		ret = PTR_ERR(dsi->pllref_clk);
+		dev_err(dev, "Unable to get pll reference clock: %d\n", ret);
+		return ret;
+	}
+
+	dsi->pclk = devm_clk_get(dev, "pclk");
+	if (IS_ERR(dsi->pclk)) {
+		ret = PTR_ERR(dsi->pclk);
+		dev_err(dev, "Unable to get pclk: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(dsi->pllref_clk);
+	if (ret) {
+		dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
+		return ret;
+	}
+
+	ret = dw_mipi_dsi_register(drm, dsi);
+	if (ret) {
+		dev_err(dev, "Failed to register mipi_dsi: %d\n", ret);
+		goto err_pllref;
+	}
+
+	dev_set_drvdata(dev, dsi);
+
+	dsi->dsi_host.ops = &dw_mipi_dsi_host_ops;
+	dsi->dsi_host.dev = dev;
+	return mipi_dsi_host_register(&dsi->dsi_host);
+
+err_pllref:
+	clk_disable_unprepare(dsi->pllref_clk);
+	return ret;
+}
+
+static void dw_mipi_dsi_unbind(struct device *dev, struct device *master,
+	void *data)
+{
+	struct dw_mipi_dsi *dsi = dev_get_drvdata(dev);
+
+	mipi_dsi_host_unregister(&dsi->dsi_host);
+	clk_disable_unprepare(dsi->pllref_clk);
+}
+
+static const struct component_ops dw_mipi_dsi_ops = {
+	.bind	= dw_mipi_dsi_bind,
+	.unbind	= dw_mipi_dsi_unbind,
+};
+
+static int dw_mipi_dsi_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &dw_mipi_dsi_ops);
+}
+
+static int dw_mipi_dsi_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &dw_mipi_dsi_ops);
+	return 0;
+}
+
+static struct platform_driver dw_mipi_dsi_driver = {
+	.probe		= dw_mipi_dsi_probe,
+	.remove		= dw_mipi_dsi_remove,
+	.driver		= {
+		.of_match_table = dw_mipi_dsi_dt_ids,
+		.name	= DRIVER_NAME,
+	},
+};
+module_platform_driver(dw_mipi_dsi_driver);
+
+MODULE_DESCRIPTION("ROCKCHIP MIPI DSI host controller driver");
+MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index bddcabd..c65ce8c 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -195,12 +195,15 @@
 {
 }
 
-static void dw_hdmi_rockchip_encoder_commit(struct drm_encoder *encoder)
+static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
 {
 	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
 	u32 val;
 	int mux;
 
+	rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
+				      ROCKCHIP_OUT_MODE_AAAA);
+
 	mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
 	if (mux)
 		val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16);
@@ -212,17 +215,10 @@
 		(mux) ? "LIT" : "BIG");
 }
 
-static void dw_hdmi_rockchip_encoder_prepare(struct drm_encoder *encoder)
-{
-	rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
-				      ROCKCHIP_OUT_MODE_AAAA);
-}
-
 static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
 	.mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup,
 	.mode_set   = dw_hdmi_rockchip_encoder_mode_set,
-	.prepare    = dw_hdmi_rockchip_encoder_prepare,
-	.commit     = dw_hdmi_rockchip_encoder_commit,
+	.enable     = dw_hdmi_rockchip_encoder_enable,
 	.disable    = dw_hdmi_rockchip_encoder_disable,
 };
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index afbb740..8397d1b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -64,11 +64,11 @@
 }
 EXPORT_SYMBOL_GPL(rockchip_drm_dma_detach_device);
 
-int rockchip_register_crtc_funcs(struct drm_device *dev,
-				 const struct rockchip_crtc_funcs *crtc_funcs,
-				 int pipe)
+int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
+				 const struct rockchip_crtc_funcs *crtc_funcs)
 {
-	struct rockchip_drm_private *priv = dev->dev_private;
+	int pipe = drm_crtc_index(crtc);
+	struct rockchip_drm_private *priv = crtc->dev->dev_private;
 
 	if (pipe > ROCKCHIP_MAX_CRTC)
 		return -EINVAL;
@@ -79,9 +79,10 @@
 }
 EXPORT_SYMBOL_GPL(rockchip_register_crtc_funcs);
 
-void rockchip_unregister_crtc_funcs(struct drm_device *dev, int pipe)
+void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc)
 {
-	struct rockchip_drm_private *priv = dev->dev_private;
+	int pipe = drm_crtc_index(crtc);
+	struct rockchip_drm_private *priv = crtc->dev->dev_private;
 
 	if (pipe > ROCKCHIP_MAX_CRTC)
 		return;
@@ -139,6 +140,9 @@
 	if (!private)
 		return -ENOMEM;
 
+	mutex_init(&private->commit.lock);
+	INIT_WORK(&private->commit.work, rockchip_drm_atomic_work);
+
 	drm_dev->dev_private = private;
 
 	drm_mode_config_init(drm_dev);
@@ -212,6 +216,8 @@
 	 */
 	drm_dev->vblank_disable_allowed = true;
 
+	drm_mode_config_reset(drm_dev);
+
 	ret = rockchip_drm_fbdev_init(drm_dev);
 	if (ret)
 		goto err_vblank_cleanup;
@@ -275,7 +281,8 @@
 };
 
 static struct drm_driver rockchip_drm_driver = {
-	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
+	.driver_features	= DRIVER_MODESET | DRIVER_GEM |
+				  DRIVER_PRIME | DRIVER_ATOMIC,
 	.load			= rockchip_drm_load,
 	.unload			= rockchip_drm_unload,
 	.lastclose		= rockchip_drm_lastclose,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index dc4e5f0..bb8b076 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -18,6 +18,7 @@
 #define _ROCKCHIP_DRM_DRV_H
 
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_gem.h>
 
 #include <linux/module.h>
@@ -38,6 +39,14 @@
 struct rockchip_crtc_funcs {
 	int (*enable_vblank)(struct drm_crtc *crtc);
 	void (*disable_vblank)(struct drm_crtc *crtc);
+	void (*wait_for_update)(struct drm_crtc *crtc);
+};
+
+struct rockchip_atomic_commit {
+	struct work_struct	work;
+	struct drm_atomic_state *state;
+	struct drm_device *dev;
+	struct mutex lock;
 };
 
 /*
@@ -50,12 +59,14 @@
 	struct drm_fb_helper fbdev_helper;
 	struct drm_gem_object *fbdev_bo;
 	const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
+
+	struct rockchip_atomic_commit commit;
 };
 
-int rockchip_register_crtc_funcs(struct drm_device *dev,
-				 const struct rockchip_crtc_funcs *crtc_funcs,
-				 int pipe);
-void rockchip_unregister_crtc_funcs(struct drm_device *dev, int pipe);
+void rockchip_drm_atomic_work(struct work_struct *work);
+int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
+				 const struct rockchip_crtc_funcs *crtc_funcs);
+void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
 int rockchip_drm_encoder_get_mux_id(struct device_node *node,
 				    struct drm_encoder *encoder);
 int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int connector_type,
@@ -64,5 +75,4 @@
 				   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
 				    struct device *dev);
-
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 621f25c..f784488 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <drm/drm.h>
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 
@@ -166,9 +167,131 @@
 		drm_fb_helper_hotplug_event(fb_helper);
 }
 
+static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc)
+{
+	struct rockchip_drm_private *priv = crtc->dev->dev_private;
+	int pipe = drm_crtc_index(crtc);
+	const struct rockchip_crtc_funcs *crtc_funcs = priv->crtc_funcs[pipe];
+
+	if (crtc_funcs && crtc_funcs->wait_for_update)
+		crtc_funcs->wait_for_update(crtc);
+}
+
+static void
+rockchip_atomic_wait_for_complete(struct drm_atomic_state *old_state)
+{
+	struct drm_crtc_state *old_crtc_state;
+	struct drm_crtc *crtc;
+	int i, ret;
+
+	for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+		/* No one cares about the old state, so abuse it for tracking
+		 * and store whether we hold a vblank reference (and should do a
+		 * vblank wait) in the ->enable boolean.
+		 */
+		old_crtc_state->enable = false;
+
+		if (!crtc->state->active)
+			continue;
+
+		ret = drm_crtc_vblank_get(crtc);
+		if (ret != 0)
+			continue;
+
+		old_crtc_state->enable = true;
+	}
+
+	for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+		if (!old_crtc_state->enable)
+			continue;
+
+		rockchip_crtc_wait_for_update(crtc);
+		drm_crtc_vblank_put(crtc);
+	}
+}
+
+static void
+rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit)
+{
+	struct drm_atomic_state *state = commit->state;
+	struct drm_device *dev = commit->dev;
+
+	/*
+	 * TODO: do fence wait here.
+	 */
+
+	/*
+	 * Rockchip crtc support runtime PM, can't update display planes
+	 * when crtc is disabled.
+	 *
+	 * drm_atomic_helper_commit comments detail that:
+	 *     For drivers supporting runtime PM the recommended sequence is
+	 *
+	 *     drm_atomic_helper_commit_modeset_disables(dev, state);
+	 *
+	 *     drm_atomic_helper_commit_modeset_enables(dev, state);
+	 *
+	 *     drm_atomic_helper_commit_planes(dev, state, true);
+	 *
+	 * See the kerneldoc entries for these three functions for more details.
+	 */
+	drm_atomic_helper_commit_modeset_disables(dev, state);
+
+	drm_atomic_helper_commit_modeset_enables(dev, state);
+
+	drm_atomic_helper_commit_planes(dev, state, true);
+
+	rockchip_atomic_wait_for_complete(state);
+
+	drm_atomic_helper_cleanup_planes(dev, state);
+
+	drm_atomic_state_free(state);
+}
+
+void rockchip_drm_atomic_work(struct work_struct *work)
+{
+	struct rockchip_atomic_commit *commit = container_of(work,
+					struct rockchip_atomic_commit, work);
+
+	rockchip_atomic_commit_complete(commit);
+}
+
+int rockchip_drm_atomic_commit(struct drm_device *dev,
+			       struct drm_atomic_state *state,
+			       bool async)
+{
+	struct rockchip_drm_private *private = dev->dev_private;
+	struct rockchip_atomic_commit *commit = &private->commit;
+	int ret;
+
+	ret = drm_atomic_helper_prepare_planes(dev, state);
+	if (ret)
+		return ret;
+
+	/* serialize outstanding asynchronous commits */
+	mutex_lock(&commit->lock);
+	flush_work(&commit->work);
+
+	drm_atomic_helper_swap_state(dev, state);
+
+	commit->dev = dev;
+	commit->state = state;
+
+	if (async)
+		schedule_work(&commit->work);
+	else
+		rockchip_atomic_commit_complete(commit);
+
+	mutex_unlock(&commit->lock);
+
+	return 0;
+}
+
 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
 	.fb_create = rockchip_user_fb_create,
 	.output_poll_changed = rockchip_drm_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = rockchip_drm_atomic_commit,
 };
 
 struct drm_framebuffer *
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index dd8e086..46c2a8d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -14,6 +14,7 @@
 
 #include <drm/drm.h>
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_plane_helper.h>
@@ -35,11 +36,6 @@
 #include "rockchip_drm_fb.h"
 #include "rockchip_drm_vop.h"
 
-#define VOP_REG(off, _mask, s) \
-		{.offset = off, \
-		 .mask = _mask, \
-		 .shift = s,}
-
 #define __REG_SET_RELAXED(x, off, mask, shift, v) \
 		vop_mask_write_relaxed(x, off, (mask) << shift, (v) << shift)
 #define __REG_SET_NORMAL(x, off, mask, shift, v) \
@@ -47,14 +43,35 @@
 
 #define REG_SET(x, base, reg, v, mode) \
 		__REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
+#define REG_SET_MASK(x, base, reg, v, mode) \
+		__REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
 
 #define VOP_WIN_SET(x, win, name, v) \
 		REG_SET(x, win->base, win->phy->name, v, RELAXED)
 #define VOP_SCL_SET(x, win, name, v) \
 		REG_SET(x, win->base, win->phy->scl->name, v, RELAXED)
+#define VOP_SCL_SET_EXT(x, win, name, v) \
+		REG_SET(x, win->base, win->phy->scl->ext->name, v, RELAXED)
 #define VOP_CTRL_SET(x, name, v) \
 		REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL)
 
+#define VOP_INTR_GET(vop, name) \
+		vop_read_reg(vop, 0, &vop->data->ctrl->name)
+
+#define VOP_INTR_SET(vop, name, v) \
+		REG_SET(vop, 0, vop->data->intr->name, v, NORMAL)
+#define VOP_INTR_SET_TYPE(vop, name, type, v) \
+	do { \
+		int i, reg = 0; \
+		for (i = 0; i < vop->data->intr->nintrs; i++) { \
+			if (vop->data->intr->intrs[i] & type) \
+				reg |= (v) << i; \
+		} \
+		VOP_INTR_SET(vop, name, reg); \
+	} while (0)
+#define VOP_INTR_GET_TYPE(vop, name, type) \
+		vop_get_intr_type(vop, &vop->data->intr->name, type)
+
 #define VOP_WIN_GET(x, win, name) \
 		vop_read_reg(x, win->base, &win->phy->name)
 
@@ -63,12 +80,15 @@
 
 #define to_vop(x) container_of(x, struct vop, crtc)
 #define to_vop_win(x) container_of(x, struct vop_win, base)
+#define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base)
 
-struct vop_win_state {
-	struct list_head head;
-	struct drm_framebuffer *fb;
+struct vop_plane_state {
+	struct drm_plane_state base;
+	int format;
+	struct drm_rect src;
+	struct drm_rect dest;
 	dma_addr_t yrgb_mst;
-	struct drm_pending_vblank_event *event;
+	bool enable;
 };
 
 struct vop_win {
@@ -76,8 +96,7 @@
 	const struct vop_win_data *data;
 	struct vop *vop;
 
-	struct list_head pending;
-	struct vop_win_state *active;
+	struct vop_plane_state state;
 };
 
 struct vop {
@@ -86,13 +105,12 @@
 	struct drm_device *drm_dev;
 	bool is_enabled;
 
-	int connector_type;
-	int connector_out_mode;
-
 	/* mutex vsync_ work */
 	struct mutex vsync_mutex;
 	bool vsync_work_pending;
 	struct completion dsp_hold_completion;
+	struct completion wait_update_complete;
+	struct drm_pending_vblank_event *event;
 
 	const struct vop_data *data;
 
@@ -119,263 +137,9 @@
 	/* vop dclk reset */
 	struct reset_control *dclk_rst;
 
-	int pipe;
-
 	struct vop_win win[];
 };
 
-enum vop_data_format {
-	VOP_FMT_ARGB8888 = 0,
-	VOP_FMT_RGB888,
-	VOP_FMT_RGB565,
-	VOP_FMT_YUV420SP = 4,
-	VOP_FMT_YUV422SP,
-	VOP_FMT_YUV444SP,
-};
-
-struct vop_reg_data {
-	uint32_t offset;
-	uint32_t value;
-};
-
-struct vop_reg {
-	uint32_t offset;
-	uint32_t shift;
-	uint32_t mask;
-};
-
-struct vop_ctrl {
-	struct vop_reg standby;
-	struct vop_reg data_blank;
-	struct vop_reg gate_en;
-	struct vop_reg mmu_en;
-	struct vop_reg rgb_en;
-	struct vop_reg edp_en;
-	struct vop_reg hdmi_en;
-	struct vop_reg mipi_en;
-	struct vop_reg out_mode;
-	struct vop_reg dither_down;
-	struct vop_reg dither_up;
-	struct vop_reg pin_pol;
-
-	struct vop_reg htotal_pw;
-	struct vop_reg hact_st_end;
-	struct vop_reg vtotal_pw;
-	struct vop_reg vact_st_end;
-	struct vop_reg hpost_st_end;
-	struct vop_reg vpost_st_end;
-};
-
-struct vop_scl_regs {
-	struct vop_reg cbcr_vsd_mode;
-	struct vop_reg cbcr_vsu_mode;
-	struct vop_reg cbcr_hsd_mode;
-	struct vop_reg cbcr_ver_scl_mode;
-	struct vop_reg cbcr_hor_scl_mode;
-	struct vop_reg yrgb_vsd_mode;
-	struct vop_reg yrgb_vsu_mode;
-	struct vop_reg yrgb_hsd_mode;
-	struct vop_reg yrgb_ver_scl_mode;
-	struct vop_reg yrgb_hor_scl_mode;
-	struct vop_reg line_load_mode;
-	struct vop_reg cbcr_axi_gather_num;
-	struct vop_reg yrgb_axi_gather_num;
-	struct vop_reg vsd_cbcr_gt2;
-	struct vop_reg vsd_cbcr_gt4;
-	struct vop_reg vsd_yrgb_gt2;
-	struct vop_reg vsd_yrgb_gt4;
-	struct vop_reg bic_coe_sel;
-	struct vop_reg cbcr_axi_gather_en;
-	struct vop_reg yrgb_axi_gather_en;
-
-	struct vop_reg lb_mode;
-	struct vop_reg scale_yrgb_x;
-	struct vop_reg scale_yrgb_y;
-	struct vop_reg scale_cbcr_x;
-	struct vop_reg scale_cbcr_y;
-};
-
-struct vop_win_phy {
-	const struct vop_scl_regs *scl;
-	const uint32_t *data_formats;
-	uint32_t nformats;
-
-	struct vop_reg enable;
-	struct vop_reg format;
-	struct vop_reg rb_swap;
-	struct vop_reg act_info;
-	struct vop_reg dsp_info;
-	struct vop_reg dsp_st;
-	struct vop_reg yrgb_mst;
-	struct vop_reg uv_mst;
-	struct vop_reg yrgb_vir;
-	struct vop_reg uv_vir;
-
-	struct vop_reg dst_alpha_ctl;
-	struct vop_reg src_alpha_ctl;
-};
-
-struct vop_win_data {
-	uint32_t base;
-	const struct vop_win_phy *phy;
-	enum drm_plane_type type;
-};
-
-struct vop_data {
-	const struct vop_reg_data *init_table;
-	unsigned int table_size;
-	const struct vop_ctrl *ctrl;
-	const struct vop_win_data *win;
-	unsigned int win_size;
-};
-
-static const uint32_t formats_01[] = {
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_RGB888,
-	DRM_FORMAT_BGR888,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_BGR565,
-	DRM_FORMAT_NV12,
-	DRM_FORMAT_NV16,
-	DRM_FORMAT_NV24,
-};
-
-static const uint32_t formats_234[] = {
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_RGB888,
-	DRM_FORMAT_BGR888,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_BGR565,
-};
-
-static const struct vop_scl_regs win_full_scl = {
-	.cbcr_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 31),
-	.cbcr_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 30),
-	.cbcr_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 28),
-	.cbcr_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 26),
-	.cbcr_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 24),
-	.yrgb_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 23),
-	.yrgb_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 22),
-	.yrgb_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 20),
-	.yrgb_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 18),
-	.yrgb_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 16),
-	.line_load_mode = VOP_REG(WIN0_CTRL1, 0x1, 15),
-	.cbcr_axi_gather_num = VOP_REG(WIN0_CTRL1, 0x7, 12),
-	.yrgb_axi_gather_num = VOP_REG(WIN0_CTRL1, 0xf, 8),
-	.vsd_cbcr_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 7),
-	.vsd_cbcr_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 6),
-	.vsd_yrgb_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 5),
-	.vsd_yrgb_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 4),
-	.bic_coe_sel = VOP_REG(WIN0_CTRL1, 0x3, 2),
-	.cbcr_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 1),
-	.yrgb_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 0),
-	.lb_mode = VOP_REG(WIN0_CTRL0, 0x7, 5),
-	.scale_yrgb_x = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
-	.scale_yrgb_y = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
-	.scale_cbcr_x = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
-	.scale_cbcr_y = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 16),
-};
-
-static const struct vop_win_phy win01_data = {
-	.scl = &win_full_scl,
-	.data_formats = formats_01,
-	.nformats = ARRAY_SIZE(formats_01),
-	.enable = VOP_REG(WIN0_CTRL0, 0x1, 0),
-	.format = VOP_REG(WIN0_CTRL0, 0x7, 1),
-	.rb_swap = VOP_REG(WIN0_CTRL0, 0x1, 12),
-	.act_info = VOP_REG(WIN0_ACT_INFO, 0x1fff1fff, 0),
-	.dsp_info = VOP_REG(WIN0_DSP_INFO, 0x0fff0fff, 0),
-	.dsp_st = VOP_REG(WIN0_DSP_ST, 0x1fff1fff, 0),
-	.yrgb_mst = VOP_REG(WIN0_YRGB_MST, 0xffffffff, 0),
-	.uv_mst = VOP_REG(WIN0_CBR_MST, 0xffffffff, 0),
-	.yrgb_vir = VOP_REG(WIN0_VIR, 0x3fff, 0),
-	.uv_vir = VOP_REG(WIN0_VIR, 0x3fff, 16),
-	.src_alpha_ctl = VOP_REG(WIN0_SRC_ALPHA_CTRL, 0xff, 0),
-	.dst_alpha_ctl = VOP_REG(WIN0_DST_ALPHA_CTRL, 0xff, 0),
-};
-
-static const struct vop_win_phy win23_data = {
-	.data_formats = formats_234,
-	.nformats = ARRAY_SIZE(formats_234),
-	.enable = VOP_REG(WIN2_CTRL0, 0x1, 0),
-	.format = VOP_REG(WIN2_CTRL0, 0x7, 1),
-	.rb_swap = VOP_REG(WIN2_CTRL0, 0x1, 12),
-	.dsp_info = VOP_REG(WIN2_DSP_INFO0, 0x0fff0fff, 0),
-	.dsp_st = VOP_REG(WIN2_DSP_ST0, 0x1fff1fff, 0),
-	.yrgb_mst = VOP_REG(WIN2_MST0, 0xffffffff, 0),
-	.yrgb_vir = VOP_REG(WIN2_VIR0_1, 0x1fff, 0),
-	.src_alpha_ctl = VOP_REG(WIN2_SRC_ALPHA_CTRL, 0xff, 0),
-	.dst_alpha_ctl = VOP_REG(WIN2_DST_ALPHA_CTRL, 0xff, 0),
-};
-
-static const struct vop_ctrl ctrl_data = {
-	.standby = VOP_REG(SYS_CTRL, 0x1, 22),
-	.gate_en = VOP_REG(SYS_CTRL, 0x1, 23),
-	.mmu_en = VOP_REG(SYS_CTRL, 0x1, 20),
-	.rgb_en = VOP_REG(SYS_CTRL, 0x1, 12),
-	.hdmi_en = VOP_REG(SYS_CTRL, 0x1, 13),
-	.edp_en = VOP_REG(SYS_CTRL, 0x1, 14),
-	.mipi_en = VOP_REG(SYS_CTRL, 0x1, 15),
-	.dither_down = VOP_REG(DSP_CTRL1, 0xf, 1),
-	.dither_up = VOP_REG(DSP_CTRL1, 0x1, 6),
-	.data_blank = VOP_REG(DSP_CTRL0, 0x1, 19),
-	.out_mode = VOP_REG(DSP_CTRL0, 0xf, 0),
-	.pin_pol = VOP_REG(DSP_CTRL0, 0xf, 4),
-	.htotal_pw = VOP_REG(DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
-	.hact_st_end = VOP_REG(DSP_HACT_ST_END, 0x1fff1fff, 0),
-	.vtotal_pw = VOP_REG(DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
-	.vact_st_end = VOP_REG(DSP_VACT_ST_END, 0x1fff1fff, 0),
-	.hpost_st_end = VOP_REG(POST_DSP_HACT_INFO, 0x1fff1fff, 0),
-	.vpost_st_end = VOP_REG(POST_DSP_VACT_INFO, 0x1fff1fff, 0),
-};
-
-static const struct vop_reg_data vop_init_reg_table[] = {
-	{SYS_CTRL, 0x00c00000},
-	{DSP_CTRL0, 0x00000000},
-	{WIN0_CTRL0, 0x00000080},
-	{WIN1_CTRL0, 0x00000080},
-	/* TODO: Win2/3 support multiple area function, but we haven't found
-	 * a suitable way to use it yet, so let's just use them as other windows
-	 * with only area 0 enabled.
-	 */
-	{WIN2_CTRL0, 0x00000010},
-	{WIN3_CTRL0, 0x00000010},
-};
-
-/*
- * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
- * special support to get alpha blending working.  For now, just use overlay
- * window 3 for the drm cursor.
- *
- */
-static const struct vop_win_data rk3288_vop_win_data[] = {
-	{ .base = 0x00, .phy = &win01_data, .type = DRM_PLANE_TYPE_PRIMARY },
-	{ .base = 0x40, .phy = &win01_data, .type = DRM_PLANE_TYPE_OVERLAY },
-	{ .base = 0x00, .phy = &win23_data, .type = DRM_PLANE_TYPE_OVERLAY },
-	{ .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_CURSOR },
-};
-
-static const struct vop_data rk3288_vop = {
-	.init_table = vop_init_reg_table,
-	.table_size = ARRAY_SIZE(vop_init_reg_table),
-	.ctrl = &ctrl_data,
-	.win = rk3288_vop_win_data,
-	.win_size = ARRAY_SIZE(rk3288_vop_win_data),
-};
-
-static const struct of_device_id vop_driver_dt_match[] = {
-	{ .compatible = "rockchip,rk3288-vop",
-	  .data = &rk3288_vop },
-	{},
-};
-MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
-
 static inline void vop_writel(struct vop *vop, uint32_t offset, uint32_t v)
 {
 	writel(v, vop->regs + offset);
@@ -393,11 +157,6 @@
 	return (vop_readl(vop, base + reg->offset) >> reg->shift) & reg->mask;
 }
 
-static inline void vop_cfg_done(struct vop *vop)
-{
-	writel(0x01, vop->regs + REG_CFG_DONE);
-}
-
 static inline void vop_mask_write(struct vop *vop, uint32_t offset,
 				  uint32_t mask, uint32_t v)
 {
@@ -422,6 +181,25 @@
 	}
 }
 
+static inline uint32_t vop_get_intr_type(struct vop *vop,
+					 const struct vop_reg *reg, int type)
+{
+	uint32_t i, ret = 0;
+	uint32_t regs = vop_read_reg(vop, 0, reg);
+
+	for (i = 0; i < vop->data->intr->nintrs; i++) {
+		if ((type & vop->data->intr->intrs[i]) && (regs & 1 << i))
+			ret |= vop->data->intr->intrs[i];
+	}
+
+	return ret;
+}
+
+static inline void vop_cfg_done(struct vop *vop)
+{
+	VOP_CTRL_SET(vop, cfg_done, 1);
+}
+
 static bool has_rb_swapped(uint32_t format)
 {
 	switch (format) {
@@ -537,6 +315,20 @@
 		return;
 	}
 
+	if (!win->phy->scl->ext) {
+		VOP_SCL_SET(vop, win, scale_yrgb_x,
+			    scl_cal_scale2(src_w, dst_w));
+		VOP_SCL_SET(vop, win, scale_yrgb_y,
+			    scl_cal_scale2(src_h, dst_h));
+		if (is_yuv) {
+			VOP_SCL_SET(vop, win, scale_cbcr_x,
+				    scl_cal_scale2(src_w, dst_w));
+			VOP_SCL_SET(vop, win, scale_cbcr_y,
+				    scl_cal_scale2(src_h, dst_h));
+		}
+		return;
+	}
+
 	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
 	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
 
@@ -554,7 +346,7 @@
 			lb_mode = scl_vop_cal_lb_mode(src_w, false);
 	}
 
-	VOP_SCL_SET(vop, win, lb_mode, lb_mode);
+	VOP_SCL_SET_EXT(vop, win, lb_mode, lb_mode);
 	if (lb_mode == LB_RGB_3840X2) {
 		if (yrgb_ver_scl_mode != SCALE_NONE) {
 			DRM_ERROR("ERROR : not allow yrgb ver scale\n");
@@ -578,14 +370,14 @@
 				false, vsu_mode, &vskiplines);
 	VOP_SCL_SET(vop, win, scale_yrgb_y, val);
 
-	VOP_SCL_SET(vop, win, vsd_yrgb_gt4, vskiplines == 4);
-	VOP_SCL_SET(vop, win, vsd_yrgb_gt2, vskiplines == 2);
+	VOP_SCL_SET_EXT(vop, win, vsd_yrgb_gt4, vskiplines == 4);
+	VOP_SCL_SET_EXT(vop, win, vsd_yrgb_gt2, vskiplines == 2);
 
-	VOP_SCL_SET(vop, win, yrgb_hor_scl_mode, yrgb_hor_scl_mode);
-	VOP_SCL_SET(vop, win, yrgb_ver_scl_mode, yrgb_ver_scl_mode);
-	VOP_SCL_SET(vop, win, yrgb_hsd_mode, SCALE_DOWN_BIL);
-	VOP_SCL_SET(vop, win, yrgb_vsd_mode, SCALE_DOWN_BIL);
-	VOP_SCL_SET(vop, win, yrgb_vsu_mode, vsu_mode);
+	VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, yrgb_hor_scl_mode);
+	VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, yrgb_ver_scl_mode);
+	VOP_SCL_SET_EXT(vop, win, yrgb_hsd_mode, SCALE_DOWN_BIL);
+	VOP_SCL_SET_EXT(vop, win, yrgb_vsd_mode, SCALE_DOWN_BIL);
+	VOP_SCL_SET_EXT(vop, win, yrgb_vsu_mode, vsu_mode);
 	if (is_yuv) {
 		val = scl_vop_cal_scale(cbcr_hor_scl_mode, cbcr_src_w,
 					dst_w, true, 0, NULL);
@@ -594,13 +386,13 @@
 					dst_h, false, vsu_mode, &vskiplines);
 		VOP_SCL_SET(vop, win, scale_cbcr_y, val);
 
-		VOP_SCL_SET(vop, win, vsd_cbcr_gt4, vskiplines == 4);
-		VOP_SCL_SET(vop, win, vsd_cbcr_gt2, vskiplines == 2);
-		VOP_SCL_SET(vop, win, cbcr_hor_scl_mode, cbcr_hor_scl_mode);
-		VOP_SCL_SET(vop, win, cbcr_ver_scl_mode, cbcr_ver_scl_mode);
-		VOP_SCL_SET(vop, win, cbcr_hsd_mode, SCALE_DOWN_BIL);
-		VOP_SCL_SET(vop, win, cbcr_vsd_mode, SCALE_DOWN_BIL);
-		VOP_SCL_SET(vop, win, cbcr_vsu_mode, vsu_mode);
+		VOP_SCL_SET_EXT(vop, win, vsd_cbcr_gt4, vskiplines == 4);
+		VOP_SCL_SET_EXT(vop, win, vsd_cbcr_gt2, vskiplines == 2);
+		VOP_SCL_SET_EXT(vop, win, cbcr_hor_scl_mode, cbcr_hor_scl_mode);
+		VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, cbcr_ver_scl_mode);
+		VOP_SCL_SET_EXT(vop, win, cbcr_hsd_mode, SCALE_DOWN_BIL);
+		VOP_SCL_SET_EXT(vop, win, cbcr_vsd_mode, SCALE_DOWN_BIL);
+		VOP_SCL_SET_EXT(vop, win, cbcr_vsu_mode, vsu_mode);
 	}
 }
 
@@ -613,8 +405,7 @@
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
 
-	vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK,
-		       DSP_HOLD_VALID_INTR_EN(1));
+	VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 1);
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 }
@@ -628,8 +419,7 @@
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
 
-	vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK,
-		       DSP_HOLD_VALID_INTR_EN(0));
+	VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 0);
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 }
@@ -692,7 +482,7 @@
 
 	enable_irq(vop->irq);
 
-	drm_vblank_on(vop->drm_dev, vop->pipe);
+	drm_crtc_vblank_on(crtc);
 
 	return;
 
@@ -704,14 +494,14 @@
 	clk_disable(vop->hclk);
 }
 
-static void vop_disable(struct drm_crtc *crtc)
+static void vop_crtc_disable(struct drm_crtc *crtc)
 {
 	struct vop *vop = to_vop(crtc);
 
 	if (!vop->is_enabled)
 		return;
 
-	drm_vblank_off(crtc->dev, vop->pipe);
+	drm_crtc_vblank_off(crtc);
 
 	/*
 	 * Vop standby will take effect at end of current frame,
@@ -748,224 +538,188 @@
 	pm_runtime_put(vop->dev);
 }
 
-/*
- * Caller must hold vsync_mutex.
- */
-static struct drm_framebuffer *vop_win_last_pending_fb(struct vop_win *vop_win)
+static void vop_plane_destroy(struct drm_plane *plane)
 {
-	struct vop_win_state *last;
-	struct vop_win_state *active = vop_win->active;
-
-	if (list_empty(&vop_win->pending))
-		return active ? active->fb : NULL;
-
-	last = list_last_entry(&vop_win->pending, struct vop_win_state, head);
-	return last ? last->fb : NULL;
+	drm_plane_cleanup(plane);
 }
 
-/*
- * Caller must hold vsync_mutex.
- */
-static int vop_win_queue_fb(struct vop_win *vop_win,
-			    struct drm_framebuffer *fb, dma_addr_t yrgb_mst,
-			    struct drm_pending_vblank_event *event)
+static int vop_plane_atomic_check(struct drm_plane *plane,
+			   struct drm_plane_state *state)
 {
-	struct vop_win_state *state;
-
-	state = kzalloc(sizeof(*state), GFP_KERNEL);
-	if (!state)
-		return -ENOMEM;
-
-	state->fb = fb;
-	state->yrgb_mst = yrgb_mst;
-	state->event = event;
-
-	list_add_tail(&state->head, &vop_win->pending);
-
-	return 0;
-}
-
-static int vop_update_plane_event(struct drm_plane *plane,
-				  struct drm_crtc *crtc,
-				  struct drm_framebuffer *fb, int crtc_x,
-				  int crtc_y, unsigned int crtc_w,
-				  unsigned int crtc_h, uint32_t src_x,
-				  uint32_t src_y, uint32_t src_w,
-				  uint32_t src_h,
-				  struct drm_pending_vblank_event *event)
-{
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_framebuffer *fb = state->fb;
 	struct vop_win *vop_win = to_vop_win(plane);
+	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
 	const struct vop_win_data *win = vop_win->data;
-	struct vop *vop = to_vop(crtc);
-	struct drm_gem_object *obj;
-	struct rockchip_gem_object *rk_obj;
-	struct drm_gem_object *uv_obj;
-	struct rockchip_gem_object *rk_uv_obj;
-	unsigned long offset;
-	unsigned int actual_w;
-	unsigned int actual_h;
-	unsigned int dsp_stx;
-	unsigned int dsp_sty;
-	unsigned int y_vir_stride;
-	unsigned int uv_vir_stride = 0;
-	dma_addr_t yrgb_mst;
-	dma_addr_t uv_mst = 0;
-	enum vop_data_format format;
-	uint32_t val;
-	bool is_alpha;
-	bool rb_swap;
-	bool is_yuv;
 	bool visible;
 	int ret;
-	struct drm_rect dest = {
-		.x1 = crtc_x,
-		.y1 = crtc_y,
-		.x2 = crtc_x + crtc_w,
-		.y2 = crtc_y + crtc_h,
-	};
-	struct drm_rect src = {
-		/* 16.16 fixed point */
-		.x1 = src_x,
-		.y1 = src_y,
-		.x2 = src_x + src_w,
-		.y2 = src_y + src_h,
-	};
-	const struct drm_rect clip = {
-		.x2 = crtc->mode.hdisplay,
-		.y2 = crtc->mode.vdisplay,
-	};
-	bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY;
+	struct drm_rect *dest = &vop_plane_state->dest;
+	struct drm_rect *src = &vop_plane_state->src;
+	struct drm_rect clip;
 	int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
 					DRM_PLANE_HELPER_NO_SCALING;
 	int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
 					DRM_PLANE_HELPER_NO_SCALING;
 
-	ret = drm_plane_helper_check_update(plane, crtc, fb,
-					    &src, &dest, &clip,
+	crtc = crtc ? crtc : plane->state->crtc;
+	/*
+	 * Both crtc or plane->state->crtc can be null.
+	 */
+	if (!crtc || !fb)
+		goto out_disable;
+	src->x1 = state->src_x;
+	src->y1 = state->src_y;
+	src->x2 = state->src_x + state->src_w;
+	src->y2 = state->src_y + state->src_h;
+	dest->x1 = state->crtc_x;
+	dest->y1 = state->crtc_y;
+	dest->x2 = state->crtc_x + state->crtc_w;
+	dest->y2 = state->crtc_y + state->crtc_h;
+
+	clip.x1 = 0;
+	clip.y1 = 0;
+	clip.x2 = crtc->mode.hdisplay;
+	clip.y2 = crtc->mode.vdisplay;
+
+	ret = drm_plane_helper_check_update(plane, crtc, state->fb,
+					    src, dest, &clip,
 					    min_scale,
 					    max_scale,
-					    can_position, false, &visible);
+					    true, true, &visible);
 	if (ret)
 		return ret;
 
 	if (!visible)
-		return 0;
+		goto out_disable;
 
-	is_alpha = is_alpha_support(fb->pixel_format);
-	rb_swap = has_rb_swapped(fb->pixel_format);
-	is_yuv = is_yuv_support(fb->pixel_format);
+	vop_plane_state->format = vop_convert_format(fb->pixel_format);
+	if (vop_plane_state->format < 0)
+		return vop_plane_state->format;
 
-	format = vop_convert_format(fb->pixel_format);
-	if (format < 0)
-		return format;
+	/*
+	 * Src.x1 can be odd when do clip, but yuv plane start point
+	 * need align with 2 pixel.
+	 */
+	if (is_yuv_support(fb->pixel_format) && ((src->x1 >> 16) % 2))
+		return -EINVAL;
+
+	vop_plane_state->enable = true;
+
+	return 0;
+
+out_disable:
+	vop_plane_state->enable = false;
+	return 0;
+}
+
+static void vop_plane_atomic_disable(struct drm_plane *plane,
+				     struct drm_plane_state *old_state)
+{
+	struct vop_plane_state *vop_plane_state = to_vop_plane_state(old_state);
+	struct vop_win *vop_win = to_vop_win(plane);
+	const struct vop_win_data *win = vop_win->data;
+	struct vop *vop = to_vop(old_state->crtc);
+
+	if (!old_state->crtc)
+		return;
+
+	spin_lock(&vop->reg_lock);
+
+	VOP_WIN_SET(vop, win, enable, 0);
+
+	spin_unlock(&vop->reg_lock);
+
+	vop_plane_state->enable = false;
+}
+
+static void vop_plane_atomic_update(struct drm_plane *plane,
+		struct drm_plane_state *old_state)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_crtc *crtc = state->crtc;
+	struct vop_win *vop_win = to_vop_win(plane);
+	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
+	const struct vop_win_data *win = vop_win->data;
+	struct vop *vop = to_vop(state->crtc);
+	struct drm_framebuffer *fb = state->fb;
+	unsigned int actual_w, actual_h;
+	unsigned int dsp_stx, dsp_sty;
+	uint32_t act_info, dsp_info, dsp_st;
+	struct drm_rect *src = &vop_plane_state->src;
+	struct drm_rect *dest = &vop_plane_state->dest;
+	struct drm_gem_object *obj, *uv_obj;
+	struct rockchip_gem_object *rk_obj, *rk_uv_obj;
+	unsigned long offset;
+	dma_addr_t dma_addr;
+	uint32_t val;
+	bool rb_swap;
+
+	/*
+	 * can't update plane when vop is disabled.
+	 */
+	if (!crtc)
+		return;
+
+	if (WARN_ON(!vop->is_enabled))
+		return;
+
+	if (!vop_plane_state->enable) {
+		vop_plane_atomic_disable(plane, old_state);
+		return;
+	}
 
 	obj = rockchip_fb_get_gem_obj(fb, 0);
-	if (!obj) {
-		DRM_ERROR("fail to get rockchip gem object from framebuffer\n");
-		return -EINVAL;
-	}
-
 	rk_obj = to_rockchip_obj(obj);
 
-	if (is_yuv) {
-		/*
-		 * Src.x1 can be odd when do clip, but yuv plane start point
-		 * need align with 2 pixel.
-		 */
-		val = (src.x1 >> 16) % 2;
-		src.x1 += val << 16;
-		src.x2 += val << 16;
-	}
+	actual_w = drm_rect_width(src) >> 16;
+	actual_h = drm_rect_height(src) >> 16;
+	act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
 
-	actual_w = (src.x2 - src.x1) >> 16;
-	actual_h = (src.y2 - src.y1) >> 16;
+	dsp_info = (drm_rect_height(dest) - 1) << 16;
+	dsp_info |= (drm_rect_width(dest) - 1) & 0xffff;
 
-	dsp_stx = dest.x1 + crtc->mode.htotal - crtc->mode.hsync_start;
-	dsp_sty = dest.y1 + crtc->mode.vtotal - crtc->mode.vsync_start;
+	dsp_stx = dest->x1 + crtc->mode.htotal - crtc->mode.hsync_start;
+	dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start;
+	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
 
-	offset = (src.x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
-	offset += (src.y1 >> 16) * fb->pitches[0];
+	offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
+	offset += (src->y1 >> 16) * fb->pitches[0];
+	vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
 
-	yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
-	y_vir_stride = fb->pitches[0] >> 2;
+	spin_lock(&vop->reg_lock);
 
-	if (is_yuv) {
+	VOP_WIN_SET(vop, win, format, vop_plane_state->format);
+	VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2);
+	VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst);
+	if (is_yuv_support(fb->pixel_format)) {
 		int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
 		int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
 		int bpp = drm_format_plane_cpp(fb->pixel_format, 1);
 
 		uv_obj = rockchip_fb_get_gem_obj(fb, 1);
-		if (!uv_obj) {
-			DRM_ERROR("fail to get uv object from framebuffer\n");
-			return -EINVAL;
-		}
 		rk_uv_obj = to_rockchip_obj(uv_obj);
-		uv_vir_stride = fb->pitches[1] >> 2;
 
-		offset = (src.x1 >> 16) * bpp / hsub;
-		offset += (src.y1 >> 16) * fb->pitches[1] / vsub;
+		offset = (src->x1 >> 16) * bpp / hsub;
+		offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
 
-		uv_mst = rk_uv_obj->dma_addr + offset + fb->offsets[1];
-	}
-
-	/*
-	 * If this plane update changes the plane's framebuffer, (or more
-	 * precisely, if this update has a different framebuffer than the last
-	 * update), enqueue it so we can track when it completes.
-	 *
-	 * Only when we discover that this update has completed, can we
-	 * unreference any previous framebuffers.
-	 */
-	mutex_lock(&vop->vsync_mutex);
-	if (fb != vop_win_last_pending_fb(vop_win)) {
-		ret = drm_vblank_get(plane->dev, vop->pipe);
-		if (ret) {
-			DRM_ERROR("failed to get vblank, %d\n", ret);
-			mutex_unlock(&vop->vsync_mutex);
-			return ret;
-		}
-
-		drm_framebuffer_reference(fb);
-
-		ret = vop_win_queue_fb(vop_win, fb, yrgb_mst, event);
-		if (ret) {
-			drm_vblank_put(plane->dev, vop->pipe);
-			mutex_unlock(&vop->vsync_mutex);
-			return ret;
-		}
-
-		vop->vsync_work_pending = true;
-	}
-	mutex_unlock(&vop->vsync_mutex);
-
-	spin_lock(&vop->reg_lock);
-
-	VOP_WIN_SET(vop, win, format, format);
-	VOP_WIN_SET(vop, win, yrgb_vir, y_vir_stride);
-	VOP_WIN_SET(vop, win, yrgb_mst, yrgb_mst);
-	if (is_yuv) {
-		VOP_WIN_SET(vop, win, uv_vir, uv_vir_stride);
-		VOP_WIN_SET(vop, win, uv_mst, uv_mst);
+		dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
+		VOP_WIN_SET(vop, win, uv_vir, fb->pitches[1] >> 2);
+		VOP_WIN_SET(vop, win, uv_mst, dma_addr);
 	}
 
 	if (win->phy->scl)
 		scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
-				    dest.x2 - dest.x1, dest.y2 - dest.y1,
+				    drm_rect_width(dest), drm_rect_height(dest),
 				    fb->pixel_format);
 
-	val = (actual_h - 1) << 16;
-	val |= (actual_w - 1) & 0xffff;
-	VOP_WIN_SET(vop, win, act_info, val);
+	VOP_WIN_SET(vop, win, act_info, act_info);
+	VOP_WIN_SET(vop, win, dsp_info, dsp_info);
+	VOP_WIN_SET(vop, win, dsp_st, dsp_st);
 
-	val = (dest.y2 - dest.y1 - 1) << 16;
-	val |= (dest.x2 - dest.x1 - 1) & 0xffff;
-	VOP_WIN_SET(vop, win, dsp_info, val);
-	val = dsp_sty << 16;
-	val |= dsp_stx & 0xffff;
-	VOP_WIN_SET(vop, win, dsp_st, val);
+	rb_swap = has_rb_swapped(fb->pixel_format);
 	VOP_WIN_SET(vop, win, rb_swap, rb_swap);
 
-	if (is_alpha) {
+	if (is_alpha_support(fb->pixel_format)) {
 		VOP_WIN_SET(vop, win, dst_alpha_ctl,
 			    DST_FACTOR_M0(ALPHA_SRC_INVERSE));
 		val = SRC_ALPHA_EN(1) | SRC_COLOR_M0(ALPHA_SRC_PRE_MUL) |
@@ -979,86 +733,70 @@
 	}
 
 	VOP_WIN_SET(vop, win, enable, 1);
-
-	vop_cfg_done(vop);
 	spin_unlock(&vop->reg_lock);
-
-	return 0;
 }
 
-static int vop_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)
+static const struct drm_plane_helper_funcs plane_helper_funcs = {
+	.atomic_check = vop_plane_atomic_check,
+	.atomic_update = vop_plane_atomic_update,
+	.atomic_disable = vop_plane_atomic_disable,
+};
+
+void vop_atomic_plane_reset(struct drm_plane *plane)
 {
-	return vop_update_plane_event(plane, crtc, fb, crtc_x, crtc_y, crtc_w,
-				      crtc_h, src_x, src_y, src_w, src_h,
-				      NULL);
+	struct vop_plane_state *vop_plane_state =
+					to_vop_plane_state(plane->state);
+
+	if (plane->state && plane->state->fb)
+		drm_framebuffer_unreference(plane->state->fb);
+
+	kfree(vop_plane_state);
+	vop_plane_state = kzalloc(sizeof(*vop_plane_state), GFP_KERNEL);
+	if (!vop_plane_state)
+		return;
+
+	plane->state = &vop_plane_state->base;
+	plane->state->plane = plane;
 }
 
-static int vop_update_primary_plane(struct drm_crtc *crtc,
-				    struct drm_pending_vblank_event *event)
+struct drm_plane_state *
+vop_atomic_plane_duplicate_state(struct drm_plane *plane)
 {
-	unsigned int crtc_w, crtc_h;
+	struct vop_plane_state *old_vop_plane_state;
+	struct vop_plane_state *vop_plane_state;
 
-	crtc_w = crtc->primary->fb->width - crtc->x;
-	crtc_h = crtc->primary->fb->height - crtc->y;
+	if (WARN_ON(!plane->state))
+		return NULL;
 
-	return vop_update_plane_event(crtc->primary, crtc, crtc->primary->fb,
-				      0, 0, crtc_w, crtc_h, crtc->x << 16,
-				      crtc->y << 16, crtc_w << 16,
-				      crtc_h << 16, event);
+	old_vop_plane_state = to_vop_plane_state(plane->state);
+	vop_plane_state = kmemdup(old_vop_plane_state,
+				  sizeof(*vop_plane_state), GFP_KERNEL);
+	if (!vop_plane_state)
+		return NULL;
+
+	__drm_atomic_helper_plane_duplicate_state(plane,
+						  &vop_plane_state->base);
+
+	return &vop_plane_state->base;
 }
 
-static int vop_disable_plane(struct drm_plane *plane)
+static void vop_atomic_plane_destroy_state(struct drm_plane *plane,
+					   struct drm_plane_state *state)
 {
-	struct vop_win *vop_win = to_vop_win(plane);
-	const struct vop_win_data *win = vop_win->data;
-	struct vop *vop;
-	int ret;
+	struct vop_plane_state *vop_state = to_vop_plane_state(state);
 
-	if (!plane->crtc)
-		return 0;
+	__drm_atomic_helper_plane_destroy_state(plane, state);
 
-	vop = to_vop(plane->crtc);
-
-	ret = drm_vblank_get(plane->dev, vop->pipe);
-	if (ret) {
-		DRM_ERROR("failed to get vblank, %d\n", ret);
-		return ret;
-	}
-
-	mutex_lock(&vop->vsync_mutex);
-
-	ret = vop_win_queue_fb(vop_win, NULL, 0, NULL);
-	if (ret) {
-		drm_vblank_put(plane->dev, vop->pipe);
-		mutex_unlock(&vop->vsync_mutex);
-		return ret;
-	}
-
-	vop->vsync_work_pending = true;
-	mutex_unlock(&vop->vsync_mutex);
-
-	spin_lock(&vop->reg_lock);
-	VOP_WIN_SET(vop, win, enable, 0);
-	vop_cfg_done(vop);
-	spin_unlock(&vop->reg_lock);
-
-	return 0;
-}
-
-static void vop_plane_destroy(struct drm_plane *plane)
-{
-	vop_disable_plane(plane);
-	drm_plane_cleanup(plane);
+	kfree(vop_state);
 }
 
 static const struct drm_plane_funcs vop_plane_funcs = {
-	.update_plane = vop_update_plane,
-	.disable_plane = vop_disable_plane,
+	.update_plane	= drm_atomic_helper_update_plane,
+	.disable_plane	= drm_atomic_helper_disable_plane,
 	.destroy = vop_plane_destroy,
+	.reset = vop_atomic_plane_reset,
+	.atomic_duplicate_state = vop_atomic_plane_duplicate_state,
+	.atomic_destroy_state = vop_atomic_plane_destroy_state,
 };
 
 int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc,
@@ -1067,8 +805,27 @@
 {
 	struct vop *vop = to_vop(crtc);
 
-	vop->connector_type = connector_type;
-	vop->connector_out_mode = out_mode;
+	if (WARN_ON(!vop->is_enabled))
+		return -EINVAL;
+
+	switch (connector_type) {
+	case DRM_MODE_CONNECTOR_LVDS:
+		VOP_CTRL_SET(vop, rgb_en, 1);
+		break;
+	case DRM_MODE_CONNECTOR_eDP:
+		VOP_CTRL_SET(vop, edp_en, 1);
+		break;
+	case DRM_MODE_CONNECTOR_HDMIA:
+		VOP_CTRL_SET(vop, hdmi_en, 1);
+		break;
+	case DRM_MODE_CONNECTOR_DSI:
+		VOP_CTRL_SET(vop, mipi_en, 1);
+		break;
+	default:
+		DRM_ERROR("unsupport connector_type[%d]\n", connector_type);
+		return -EINVAL;
+	};
+	VOP_CTRL_SET(vop, out_mode, out_mode);
 
 	return 0;
 }
@@ -1079,12 +836,12 @@
 	struct vop *vop = to_vop(crtc);
 	unsigned long flags;
 
-	if (!vop->is_enabled)
+	if (WARN_ON(!vop->is_enabled))
 		return -EPERM;
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
 
-	vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(1));
+	VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1);
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 
@@ -1096,76 +853,49 @@
 	struct vop *vop = to_vop(crtc);
 	unsigned long flags;
 
-	if (!vop->is_enabled)
+	if (WARN_ON(!vop->is_enabled))
 		return;
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
-	vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(0));
+
+	VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
+
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 }
 
+static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
+{
+	struct vop *vop = to_vop(crtc);
+
+	reinit_completion(&vop->wait_update_complete);
+	WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100));
+}
+
 static const struct rockchip_crtc_funcs private_crtc_funcs = {
 	.enable_vblank = vop_crtc_enable_vblank,
 	.disable_vblank = vop_crtc_disable_vblank,
+	.wait_for_update = vop_crtc_wait_for_update,
 };
 
-static void vop_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-	DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
-
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		vop_enable(crtc);
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-	case DRM_MODE_DPMS_OFF:
-		vop_disable(crtc);
-		break;
-	default:
-		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
-		break;
-	}
-}
-
-static void vop_crtc_prepare(struct drm_crtc *crtc)
-{
-	vop_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
 static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
 				const struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
 {
+	struct vop *vop = to_vop(crtc);
+
 	if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
 		return false;
 
+	adjusted_mode->clock =
+		clk_round_rate(vop->dclk, mode->clock * 1000) / 1000;
+
 	return true;
 }
 
-static int vop_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-				  struct drm_framebuffer *old_fb)
-{
-	int ret;
-
-	crtc->x = x;
-	crtc->y = y;
-
-	ret = vop_update_primary_plane(crtc, NULL);
-	if (ret < 0) {
-		DRM_ERROR("fail to update plane\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static int vop_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 *fb)
+static void vop_crtc_enable(struct drm_crtc *crtc)
 {
 	struct vop *vop = to_vop(crtc);
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
 	u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
 	u16 hdisplay = adjusted_mode->hdisplay;
 	u16 htotal = adjusted_mode->htotal;
@@ -1176,32 +906,44 @@
 	u16 vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start;
 	u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start;
 	u16 vact_end = vact_st + vdisplay;
-	int ret, ret_clk;
 	uint32_t val;
 
+	vop_enable(crtc);
 	/*
-	 * disable dclk to stop frame scan, so that we can safe config mode and
-	 * enable iommu.
+	 * If dclk rate is zero, mean that scanout is stop,
+	 * we don't need wait any more.
 	 */
-	clk_disable(vop->dclk);
+	if (clk_get_rate(vop->dclk)) {
+		/*
+		 * Rk3288 vop timing register is immediately, when configure
+		 * display timing on display time, may cause tearing.
+		 *
+		 * Vop standby will take effect at end of current frame,
+		 * if dsp hold valid irq happen, it means standby complete.
+		 *
+		 * mode set:
+		 *    standby and wait complete --> |----
+		 *                                  | display time
+		 *                                  |----
+		 *                                  |---> dsp hold irq
+		 *     configure display timing --> |
+		 *         standby exit             |
+		 *                                  | new frame start.
+		 */
 
-	switch (vop->connector_type) {
-	case DRM_MODE_CONNECTOR_LVDS:
-		VOP_CTRL_SET(vop, rgb_en, 1);
-		break;
-	case DRM_MODE_CONNECTOR_eDP:
-		VOP_CTRL_SET(vop, edp_en, 1);
-		break;
-	case DRM_MODE_CONNECTOR_HDMIA:
-		VOP_CTRL_SET(vop, hdmi_en, 1);
-		break;
-	default:
-		DRM_ERROR("unsupport connector_type[%d]\n",
-			  vop->connector_type);
-		ret = -EINVAL;
-		goto out;
-	};
-	VOP_CTRL_SET(vop, out_mode, vop->connector_out_mode);
+		reinit_completion(&vop->dsp_hold_completion);
+		vop_dsp_hold_valid_irq_enable(vop);
+
+		spin_lock(&vop->reg_lock);
+
+		VOP_CTRL_SET(vop, standby, 1);
+
+		spin_unlock(&vop->reg_lock);
+
+		wait_for_completion(&vop->dsp_hold_completion);
+
+		vop_dsp_hold_valid_irq_disable(vop);
+	}
 
 	val = 0x8;
 	val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
@@ -1220,211 +962,119 @@
 	VOP_CTRL_SET(vop, vact_st_end, val);
 	VOP_CTRL_SET(vop, vpost_st_end, val);
 
-	ret = vop_crtc_mode_set_base(crtc, x, y, fb);
-	if (ret)
-		goto out;
-
-	/*
-	 * reset dclk, take all mode config affect, so the clk would run in
-	 * correct frame.
-	 */
-	reset_control_assert(vop->dclk_rst);
-	usleep_range(10, 20);
-	reset_control_deassert(vop->dclk_rst);
-
 	clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
-out:
-	ret_clk = clk_enable(vop->dclk);
-	if (ret_clk < 0) {
-		dev_err(vop->dev, "failed to enable dclk - %d\n", ret_clk);
-		return ret_clk;
-	}
 
-	return ret;
+	VOP_CTRL_SET(vop, standby, 0);
 }
 
-static void vop_crtc_commit(struct drm_crtc *crtc)
+static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
+				  struct drm_crtc_state *old_crtc_state)
 {
+	struct vop *vop = to_vop(crtc);
+
+	if (WARN_ON(!vop->is_enabled))
+		return;
+
+	spin_lock(&vop->reg_lock);
+
+	vop_cfg_done(vop);
+
+	spin_unlock(&vop->reg_lock);
+}
+
+static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
+				  struct drm_crtc_state *old_crtc_state)
+{
+	struct vop *vop = to_vop(crtc);
+
+	if (crtc->state->event) {
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		vop->event = crtc->state->event;
+		crtc->state->event = NULL;
+	}
 }
 
 static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
-	.dpms = vop_crtc_dpms,
-	.prepare = vop_crtc_prepare,
+	.enable = vop_crtc_enable,
+	.disable = vop_crtc_disable,
 	.mode_fixup = vop_crtc_mode_fixup,
-	.mode_set = vop_crtc_mode_set,
-	.mode_set_base = vop_crtc_mode_set_base,
-	.commit = vop_crtc_commit,
+	.atomic_flush = vop_crtc_atomic_flush,
+	.atomic_begin = vop_crtc_atomic_begin,
 };
 
-static int vop_crtc_page_flip(struct drm_crtc *crtc,
-			      struct drm_framebuffer *fb,
-			      struct drm_pending_vblank_event *event,
-			      uint32_t page_flip_flags)
-{
-	struct vop *vop = to_vop(crtc);
-	struct drm_framebuffer *old_fb = crtc->primary->fb;
-	int ret;
-
-	/* when the page flip is requested, crtc should be on */
-	if (!vop->is_enabled) {
-		DRM_DEBUG("page flip request rejected because crtc is off.\n");
-		return 0;
-	}
-
-	crtc->primary->fb = fb;
-
-	ret = vop_update_primary_plane(crtc, event);
-	if (ret)
-		crtc->primary->fb = old_fb;
-
-	return ret;
-}
-
-static void vop_win_state_complete(struct vop_win *vop_win,
-				   struct vop_win_state *state)
-{
-	struct vop *vop = vop_win->vop;
-	struct drm_crtc *crtc = &vop->crtc;
-	struct drm_device *drm = crtc->dev;
-	unsigned long flags;
-
-	if (state->event) {
-		spin_lock_irqsave(&drm->event_lock, flags);
-		drm_crtc_send_vblank_event(crtc, state->event);
-		spin_unlock_irqrestore(&drm->event_lock, flags);
-	}
-
-	list_del(&state->head);
-	drm_vblank_put(crtc->dev, vop->pipe);
-}
-
 static void vop_crtc_destroy(struct drm_crtc *crtc)
 {
 	drm_crtc_cleanup(crtc);
 }
 
 static const struct drm_crtc_funcs vop_crtc_funcs = {
-	.set_config = drm_crtc_helper_set_config,
-	.page_flip = vop_crtc_page_flip,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
 	.destroy = vop_crtc_destroy,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
-static bool vop_win_state_is_active(struct vop_win *vop_win,
-				    struct vop_win_state *state)
+static bool vop_win_pending_is_complete(struct vop_win *vop_win)
 {
-	bool active = false;
+	struct drm_plane *plane = &vop_win->base;
+	struct vop_plane_state *state = to_vop_plane_state(plane->state);
+	dma_addr_t yrgb_mst;
 
-	if (state->fb) {
-		dma_addr_t yrgb_mst;
+	if (!state->enable)
+		return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
 
-		/* check yrgb_mst to tell if pending_fb is now front */
-		yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
+	yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
 
-		active = (yrgb_mst == state->yrgb_mst);
-	} else {
-		bool enabled;
+	return yrgb_mst == state->yrgb_mst;
+}
 
-		/* if enable bit is clear, plane is now disabled */
-		enabled = VOP_WIN_GET(vop_win->vop, vop_win->data, enable);
+static void vop_handle_vblank(struct vop *vop)
+{
+	struct drm_device *drm = vop->drm_dev;
+	struct drm_crtc *crtc = &vop->crtc;
+	unsigned long flags;
+	int i;
 
-		active = (enabled == 0);
+	for (i = 0; i < vop->data->win_size; i++) {
+		if (!vop_win_pending_is_complete(&vop->win[i]))
+			return;
 	}
 
-	return active;
-}
+	if (vop->event) {
+		spin_lock_irqsave(&drm->event_lock, flags);
 
-static void vop_win_state_destroy(struct vop_win_state *state)
-{
-	struct drm_framebuffer *fb = state->fb;
+		drm_crtc_send_vblank_event(crtc, vop->event);
+		drm_crtc_vblank_put(crtc);
+		vop->event = NULL;
 
-	if (fb)
-		drm_framebuffer_unreference(fb);
-
-	kfree(state);
-}
-
-static void vop_win_update_state(struct vop_win *vop_win)
-{
-	struct vop_win_state *state, *n, *new_active = NULL;
-
-	/* Check if any pending states are now active */
-	list_for_each_entry(state, &vop_win->pending, head)
-		if (vop_win_state_is_active(vop_win, state)) {
-			new_active = state;
-			break;
-		}
-
-	if (!new_active)
-		return;
-
-	/*
-	 * Destroy any 'skipped' pending states - states that were queued
-	 * before the newly active state.
-	 */
-	list_for_each_entry_safe(state, n, &vop_win->pending, head) {
-		if (state == new_active)
-			break;
-		vop_win_state_complete(vop_win, state);
-		vop_win_state_destroy(state);
+		spin_unlock_irqrestore(&drm->event_lock, flags);
 	}
-
-	vop_win_state_complete(vop_win, new_active);
-
-	if (vop_win->active)
-		vop_win_state_destroy(vop_win->active);
-	vop_win->active = new_active;
-}
-
-static bool vop_win_has_pending_state(struct vop_win *vop_win)
-{
-	return !list_empty(&vop_win->pending);
-}
-
-static irqreturn_t vop_isr_thread(int irq, void *data)
-{
-	struct vop *vop = data;
-	const struct vop_data *vop_data = vop->data;
-	unsigned int i;
-
-	mutex_lock(&vop->vsync_mutex);
-
-	if (!vop->vsync_work_pending)
-		goto done;
-
-	vop->vsync_work_pending = false;
-
-	for (i = 0; i < vop_data->win_size; i++) {
-		struct vop_win *vop_win = &vop->win[i];
-
-		vop_win_update_state(vop_win);
-		if (vop_win_has_pending_state(vop_win))
-			vop->vsync_work_pending = true;
-	}
-
-done:
-	mutex_unlock(&vop->vsync_mutex);
-
-	return IRQ_HANDLED;
+	if (!completion_done(&vop->wait_update_complete))
+		complete(&vop->wait_update_complete);
 }
 
 static irqreturn_t vop_isr(int irq, void *data)
 {
 	struct vop *vop = data;
-	uint32_t intr0_reg, active_irqs;
+	struct drm_crtc *crtc = &vop->crtc;
+	uint32_t active_irqs;
 	unsigned long flags;
 	int ret = IRQ_NONE;
 
 	/*
-	 * INTR_CTRL0 register has interrupt status, enable and clear bits, we
+	 * interrupt register has interrupt status, enable and clear bits, we
 	 * must hold irq_lock to avoid a race with enable/disable_vblank().
 	*/
 	spin_lock_irqsave(&vop->irq_lock, flags);
-	intr0_reg = vop_readl(vop, INTR_CTRL0);
-	active_irqs = intr0_reg & INTR_MASK;
+
+	active_irqs = VOP_INTR_GET_TYPE(vop, status, INTR_MASK);
 	/* Clear all active interrupt sources */
 	if (active_irqs)
-		vop_writel(vop, INTR_CTRL0,
-			   intr0_reg | (active_irqs << INTR_CLR_SHIFT));
+		VOP_INTR_SET_TYPE(vop, clear, active_irqs, 1);
+
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 
 	/* This is expected for vop iommu irqs, since the irq is shared */
@@ -1438,9 +1088,10 @@
 	}
 
 	if (active_irqs & FS_INTR) {
-		drm_handle_vblank(vop->drm_dev, vop->pipe);
+		drm_crtc_handle_vblank(crtc);
+		vop_handle_vblank(vop);
 		active_irqs &= ~FS_INTR;
-		ret = (vop->vsync_work_pending) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
+		ret = IRQ_HANDLED;
 	}
 
 	/* Unhandled irqs are spurious. */
@@ -1485,6 +1136,7 @@
 		}
 
 		plane = &vop_win->base;
+		drm_plane_helper_add(plane, &plane_helper_funcs);
 		if (plane->type == DRM_PLANE_TYPE_PRIMARY)
 			primary = plane;
 		else if (plane->type == DRM_PLANE_TYPE_CURSOR)
@@ -1520,6 +1172,7 @@
 			DRM_ERROR("failed to initialize overlay plane\n");
 			goto err_cleanup_crtc;
 		}
+		drm_plane_helper_add(&vop_win->base, &plane_helper_funcs);
 	}
 
 	port = of_get_child_by_name(dev->of_node, "port");
@@ -1530,9 +1183,9 @@
 	}
 
 	init_completion(&vop->dsp_hold_completion);
+	init_completion(&vop->wait_update_complete);
 	crtc->port = port;
-	vop->pipe = drm_crtc_index(crtc);
-	rockchip_register_crtc_funcs(drm_dev, &private_crtc_funcs, vop->pipe);
+	rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
 
 	return 0;
 
@@ -1548,7 +1201,7 @@
 {
 	struct drm_crtc *crtc = &vop->crtc;
 
-	rockchip_unregister_crtc_funcs(vop->drm_dev, vop->pipe);
+	rockchip_unregister_crtc_funcs(crtc);
 	of_node_put(crtc->port);
 	drm_crtc_cleanup(crtc);
 }
@@ -1664,14 +1317,12 @@
 
 		vop_win->data = win_data;
 		vop_win->vop = vop;
-		INIT_LIST_HEAD(&vop_win->pending);
 	}
 }
 
 static int vop_bind(struct device *dev, struct device *master, void *data)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	const struct of_device_id *of_id;
 	const struct vop_data *vop_data;
 	struct drm_device *drm_dev = data;
 	struct vop *vop;
@@ -1679,8 +1330,7 @@
 	size_t alloc_size;
 	int ret, irq;
 
-	of_id = of_match_device(vop_driver_dt_match, dev);
-	vop_data = of_id->data;
+	vop_data = of_device_get_match_data(dev);
 	if (!vop_data)
 		return -ENODEV;
 
@@ -1725,8 +1375,8 @@
 
 	mutex_init(&vop->vsync_mutex);
 
-	ret = devm_request_threaded_irq(dev, vop->irq, vop_isr, vop_isr_thread,
-					IRQF_SHARED, dev_name(dev), vop);
+	ret = devm_request_irq(dev, vop->irq, vop_isr,
+			       IRQF_SHARED, dev_name(dev), vop);
 	if (ret)
 		return ret;
 
@@ -1749,42 +1399,8 @@
 	vop_destroy_crtc(vop);
 }
 
-static const struct component_ops vop_component_ops = {
+const struct component_ops vop_component_ops = {
 	.bind = vop_bind,
 	.unbind = vop_unbind,
 };
-
-static int vop_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-
-	if (!dev->of_node) {
-		dev_err(dev, "can't find vop devices\n");
-		return -ENODEV;
-	}
-
-	return component_add(dev, &vop_component_ops);
-}
-
-static int vop_remove(struct platform_device *pdev)
-{
-	component_del(&pdev->dev, &vop_component_ops);
-
-	return 0;
-}
-
-struct platform_driver vop_platform_driver = {
-	.probe = vop_probe,
-	.remove = vop_remove,
-	.driver = {
-		.name = "rockchip-vop",
-		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(vop_driver_dt_match),
-	},
-};
-
-module_platform_driver(vop_platform_driver);
-
-MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
-MODULE_DESCRIPTION("ROCKCHIP VOP Driver");
-MODULE_LICENSE("GPL v2");
+EXPORT_SYMBOL_GPL(vop_component_ops);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index a2d4ddb..071ff0b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -15,111 +15,125 @@
 #ifndef _ROCKCHIP_DRM_VOP_H
 #define _ROCKCHIP_DRM_VOP_H
 
-/* register definition */
-#define REG_CFG_DONE			0x0000
-#define VERSION_INFO			0x0004
-#define SYS_CTRL			0x0008
-#define SYS_CTRL1			0x000c
-#define DSP_CTRL0			0x0010
-#define DSP_CTRL1			0x0014
-#define DSP_BG				0x0018
-#define MCU_CTRL			0x001c
-#define INTR_CTRL0			0x0020
-#define INTR_CTRL1			0x0024
-#define WIN0_CTRL0			0x0030
-#define WIN0_CTRL1			0x0034
-#define WIN0_COLOR_KEY			0x0038
-#define WIN0_VIR			0x003c
-#define WIN0_YRGB_MST			0x0040
-#define WIN0_CBR_MST			0x0044
-#define WIN0_ACT_INFO			0x0048
-#define WIN0_DSP_INFO			0x004c
-#define WIN0_DSP_ST			0x0050
-#define WIN0_SCL_FACTOR_YRGB		0x0054
-#define WIN0_SCL_FACTOR_CBR		0x0058
-#define WIN0_SCL_OFFSET			0x005c
-#define WIN0_SRC_ALPHA_CTRL		0x0060
-#define WIN0_DST_ALPHA_CTRL		0x0064
-#define WIN0_FADING_CTRL		0x0068
-/* win1 register */
-#define WIN1_CTRL0			0x0070
-#define WIN1_CTRL1			0x0074
-#define WIN1_COLOR_KEY			0x0078
-#define WIN1_VIR			0x007c
-#define WIN1_YRGB_MST			0x0080
-#define WIN1_CBR_MST			0x0084
-#define WIN1_ACT_INFO			0x0088
-#define WIN1_DSP_INFO			0x008c
-#define WIN1_DSP_ST			0x0090
-#define WIN1_SCL_FACTOR_YRGB		0x0094
-#define WIN1_SCL_FACTOR_CBR		0x0098
-#define WIN1_SCL_OFFSET			0x009c
-#define WIN1_SRC_ALPHA_CTRL		0x00a0
-#define WIN1_DST_ALPHA_CTRL		0x00a4
-#define WIN1_FADING_CTRL		0x00a8
-/* win2 register */
-#define WIN2_CTRL0			0x00b0
-#define WIN2_CTRL1			0x00b4
-#define WIN2_VIR0_1			0x00b8
-#define WIN2_VIR2_3			0x00bc
-#define WIN2_MST0			0x00c0
-#define WIN2_DSP_INFO0			0x00c4
-#define WIN2_DSP_ST0			0x00c8
-#define WIN2_COLOR_KEY			0x00cc
-#define WIN2_MST1			0x00d0
-#define WIN2_DSP_INFO1			0x00d4
-#define WIN2_DSP_ST1			0x00d8
-#define WIN2_SRC_ALPHA_CTRL		0x00dc
-#define WIN2_MST2			0x00e0
-#define WIN2_DSP_INFO2			0x00e4
-#define WIN2_DSP_ST2			0x00e8
-#define WIN2_DST_ALPHA_CTRL		0x00ec
-#define WIN2_MST3			0x00f0
-#define WIN2_DSP_INFO3			0x00f4
-#define WIN2_DSP_ST3			0x00f8
-#define WIN2_FADING_CTRL		0x00fc
-/* win3 register */
-#define WIN3_CTRL0			0x0100
-#define WIN3_CTRL1			0x0104
-#define WIN3_VIR0_1			0x0108
-#define WIN3_VIR2_3			0x010c
-#define WIN3_MST0			0x0110
-#define WIN3_DSP_INFO0			0x0114
-#define WIN3_DSP_ST0			0x0118
-#define WIN3_COLOR_KEY			0x011c
-#define WIN3_MST1			0x0120
-#define WIN3_DSP_INFO1			0x0124
-#define WIN3_DSP_ST1			0x0128
-#define WIN3_SRC_ALPHA_CTRL		0x012c
-#define WIN3_MST2			0x0130
-#define WIN3_DSP_INFO2			0x0134
-#define WIN3_DSP_ST2			0x0138
-#define WIN3_DST_ALPHA_CTRL		0x013c
-#define WIN3_MST3			0x0140
-#define WIN3_DSP_INFO3			0x0144
-#define WIN3_DSP_ST3			0x0148
-#define WIN3_FADING_CTRL		0x014c
-/* hwc register */
-#define HWC_CTRL0			0x0150
-#define HWC_CTRL1			0x0154
-#define HWC_MST				0x0158
-#define HWC_DSP_ST			0x015c
-#define HWC_SRC_ALPHA_CTRL		0x0160
-#define HWC_DST_ALPHA_CTRL		0x0164
-#define HWC_FADING_CTRL			0x0168
-/* post process register */
-#define POST_DSP_HACT_INFO		0x0170
-#define POST_DSP_VACT_INFO		0x0174
-#define POST_SCL_FACTOR_YRGB		0x0178
-#define POST_SCL_CTRL			0x0180
-#define POST_DSP_VACT_INFO_F1		0x0184
-#define DSP_HTOTAL_HS_END		0x0188
-#define DSP_HACT_ST_END			0x018c
-#define DSP_VTOTAL_VS_END		0x0190
-#define DSP_VACT_ST_END			0x0194
-#define DSP_VS_ST_END_F1		0x0198
-#define DSP_VACT_ST_END_F1		0x019c
-/* register definition end */
+enum vop_data_format {
+	VOP_FMT_ARGB8888 = 0,
+	VOP_FMT_RGB888,
+	VOP_FMT_RGB565,
+	VOP_FMT_YUV420SP = 4,
+	VOP_FMT_YUV422SP,
+	VOP_FMT_YUV444SP,
+};
+
+struct vop_reg_data {
+	uint32_t offset;
+	uint32_t value;
+};
+
+struct vop_reg {
+	uint32_t offset;
+	uint32_t shift;
+	uint32_t mask;
+};
+
+struct vop_ctrl {
+	struct vop_reg standby;
+	struct vop_reg data_blank;
+	struct vop_reg gate_en;
+	struct vop_reg mmu_en;
+	struct vop_reg rgb_en;
+	struct vop_reg edp_en;
+	struct vop_reg hdmi_en;
+	struct vop_reg mipi_en;
+	struct vop_reg out_mode;
+	struct vop_reg dither_down;
+	struct vop_reg dither_up;
+	struct vop_reg pin_pol;
+
+	struct vop_reg htotal_pw;
+	struct vop_reg hact_st_end;
+	struct vop_reg vtotal_pw;
+	struct vop_reg vact_st_end;
+	struct vop_reg hpost_st_end;
+	struct vop_reg vpost_st_end;
+
+	struct vop_reg cfg_done;
+};
+
+struct vop_intr {
+	const int *intrs;
+	uint32_t nintrs;
+	struct vop_reg enable;
+	struct vop_reg clear;
+	struct vop_reg status;
+};
+
+struct vop_scl_extension {
+	struct vop_reg cbcr_vsd_mode;
+	struct vop_reg cbcr_vsu_mode;
+	struct vop_reg cbcr_hsd_mode;
+	struct vop_reg cbcr_ver_scl_mode;
+	struct vop_reg cbcr_hor_scl_mode;
+	struct vop_reg yrgb_vsd_mode;
+	struct vop_reg yrgb_vsu_mode;
+	struct vop_reg yrgb_hsd_mode;
+	struct vop_reg yrgb_ver_scl_mode;
+	struct vop_reg yrgb_hor_scl_mode;
+	struct vop_reg line_load_mode;
+	struct vop_reg cbcr_axi_gather_num;
+	struct vop_reg yrgb_axi_gather_num;
+	struct vop_reg vsd_cbcr_gt2;
+	struct vop_reg vsd_cbcr_gt4;
+	struct vop_reg vsd_yrgb_gt2;
+	struct vop_reg vsd_yrgb_gt4;
+	struct vop_reg bic_coe_sel;
+	struct vop_reg cbcr_axi_gather_en;
+	struct vop_reg yrgb_axi_gather_en;
+	struct vop_reg lb_mode;
+};
+
+struct vop_scl_regs {
+	const struct vop_scl_extension *ext;
+
+	struct vop_reg scale_yrgb_x;
+	struct vop_reg scale_yrgb_y;
+	struct vop_reg scale_cbcr_x;
+	struct vop_reg scale_cbcr_y;
+};
+
+struct vop_win_phy {
+	const struct vop_scl_regs *scl;
+	const uint32_t *data_formats;
+	uint32_t nformats;
+
+	struct vop_reg enable;
+	struct vop_reg format;
+	struct vop_reg rb_swap;
+	struct vop_reg act_info;
+	struct vop_reg dsp_info;
+	struct vop_reg dsp_st;
+	struct vop_reg yrgb_mst;
+	struct vop_reg uv_mst;
+	struct vop_reg yrgb_vir;
+	struct vop_reg uv_vir;
+
+	struct vop_reg dst_alpha_ctl;
+	struct vop_reg src_alpha_ctl;
+};
+
+struct vop_win_data {
+	uint32_t base;
+	const struct vop_win_phy *phy;
+	enum drm_plane_type type;
+};
+
+struct vop_data {
+	const struct vop_reg_data *init_table;
+	unsigned int table_size;
+	const struct vop_ctrl *ctrl;
+	const struct vop_intr *intr;
+	const struct vop_win_data *win;
+	unsigned int win_size;
+};
 
 /* interrupt define */
 #define DSP_HOLD_VALID_INTR		(1 << 0)
@@ -233,6 +247,11 @@
 	return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
 }
 
+static inline uint16_t scl_cal_scale2(int src, int dst)
+{
+	return ((src - 1) << 12) / (dst - 1);
+}
+
 #define GET_SCL_FT_BILI_DN(src, dst)	scl_cal_scale(src, dst, 12)
 #define GET_SCL_FT_BILI_UP(src, dst)	scl_cal_scale(src, dst, 16)
 #define GET_SCL_FT_BIC(src, dst)	scl_cal_scale(src, dst, 16)
@@ -286,4 +305,5 @@
 	return lb_mode;
 }
 
+extern const struct component_ops vop_component_ops;
 #endif /* _ROCKCHIP_DRM_VOP_H */
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
new file mode 100644
index 0000000..3166b46
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author:Mark Yao <mark.yao@rock-chips.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+
+#include <linux/kernel.h>
+#include <linux/component.h>
+
+#include "rockchip_drm_vop.h"
+#include "rockchip_vop_reg.h"
+
+#define VOP_REG(off, _mask, s) \
+		{.offset = off, \
+		 .mask = _mask, \
+		 .shift = s,}
+
+static const uint32_t formats_win_full[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV24,
+};
+
+static const uint32_t formats_win_lite[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+};
+
+static const struct vop_scl_extension rk3288_win_full_scl_ext = {
+	.cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
+	.cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
+	.cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
+	.cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
+	.cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
+	.yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
+	.yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
+	.yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
+	.yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
+	.yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
+	.line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
+	.cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
+	.yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
+	.vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
+	.vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
+	.vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
+	.vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
+	.bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
+	.cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
+	.yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
+	.lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
+};
+
+static const struct vop_scl_regs rk3288_win_full_scl = {
+	.ext = &rk3288_win_full_scl_ext,
+	.scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
+};
+
+static const struct vop_win_phy rk3288_win01_data = {
+	.scl = &rk3288_win_full_scl,
+	.data_formats = formats_win_full,
+	.nformats = ARRAY_SIZE(formats_win_full),
+	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
+	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
+	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
+	.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
+	.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
+	.uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
+	.src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
+	.dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
+};
+
+static const struct vop_win_phy rk3288_win23_data = {
+	.data_formats = formats_win_lite,
+	.nformats = ARRAY_SIZE(formats_win_lite),
+	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
+	.format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
+	.rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
+	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
+	.src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
+	.dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
+};
+
+static const struct vop_ctrl rk3288_ctrl_data = {
+	.standby = VOP_REG(RK3288_SYS_CTRL, 0x1, 22),
+	.gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
+	.mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
+	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
+	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
+	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
+	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
+	.dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1),
+	.dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
+	.data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
+	.out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
+	.pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4),
+	.htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.cfg_done = VOP_REG(RK3288_REG_CFG_DONE, 0x1, 0),
+};
+
+static const struct vop_reg_data rk3288_init_reg_table[] = {
+	{RK3288_SYS_CTRL, 0x00c00000},
+	{RK3288_DSP_CTRL0, 0x00000000},
+	{RK3288_WIN0_CTRL0, 0x00000080},
+	{RK3288_WIN1_CTRL0, 0x00000080},
+	/* TODO: Win2/3 support multiple area function, but we haven't found
+	 * a suitable way to use it yet, so let's just use them as other windows
+	 * with only area 0 enabled.
+	 */
+	{RK3288_WIN2_CTRL0, 0x00000010},
+	{RK3288_WIN3_CTRL0, 0x00000010},
+};
+
+/*
+ * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
+ * special support to get alpha blending working.  For now, just use overlay
+ * window 3 for the drm cursor.
+ *
+ */
+static const struct vop_win_data rk3288_vop_win_data[] = {
+	{ .base = 0x00, .phy = &rk3288_win01_data,
+	  .type = DRM_PLANE_TYPE_PRIMARY },
+	{ .base = 0x40, .phy = &rk3288_win01_data,
+	  .type = DRM_PLANE_TYPE_OVERLAY },
+	{ .base = 0x00, .phy = &rk3288_win23_data,
+	  .type = DRM_PLANE_TYPE_OVERLAY },
+	{ .base = 0x50, .phy = &rk3288_win23_data,
+	  .type = DRM_PLANE_TYPE_CURSOR },
+};
+
+static const int rk3288_vop_intrs[] = {
+	DSP_HOLD_VALID_INTR,
+	FS_INTR,
+	LINE_FLAG_INTR,
+	BUS_ERROR_INTR,
+};
+
+static const struct vop_intr rk3288_vop_intr = {
+	.intrs = rk3288_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3288_vop_intrs),
+	.status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
+	.enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
+	.clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
+};
+
+static const struct vop_data rk3288_vop = {
+	.init_table = rk3288_init_reg_table,
+	.table_size = ARRAY_SIZE(rk3288_init_reg_table),
+	.intr = &rk3288_vop_intr,
+	.ctrl = &rk3288_ctrl_data,
+	.win = rk3288_vop_win_data,
+	.win_size = ARRAY_SIZE(rk3288_vop_win_data),
+};
+
+static const struct vop_scl_regs rk3066_win_scl = {
+	.scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
+};
+
+static const struct vop_win_phy rk3036_win0_data = {
+	.scl = &rk3066_win_scl,
+	.data_formats = formats_win_full,
+	.nformats = ARRAY_SIZE(formats_win_full),
+	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
+	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
+	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
+	.act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
+	.dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
+};
+
+static const struct vop_win_phy rk3036_win1_data = {
+	.data_formats = formats_win_lite,
+	.nformats = ARRAY_SIZE(formats_win_lite),
+	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
+	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
+	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
+	.act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
+	.dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
+};
+
+static const struct vop_win_data rk3036_vop_win_data[] = {
+	{ .base = 0x00, .phy = &rk3036_win0_data,
+	  .type = DRM_PLANE_TYPE_PRIMARY },
+	{ .base = 0x00, .phy = &rk3036_win1_data,
+	  .type = DRM_PLANE_TYPE_CURSOR },
+};
+
+static const int rk3036_vop_intrs[] = {
+	DSP_HOLD_VALID_INTR,
+	FS_INTR,
+	LINE_FLAG_INTR,
+	BUS_ERROR_INTR,
+};
+
+static const struct vop_intr rk3036_intr = {
+	.intrs = rk3036_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3036_vop_intrs),
+	.status = VOP_REG(RK3036_INT_STATUS, 0xf, 0),
+	.enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4),
+	.clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8),
+};
+
+static const struct vop_ctrl rk3036_ctrl_data = {
+	.standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30),
+	.out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
+	.pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
+	.htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0),
+};
+
+static const struct vop_reg_data rk3036_vop_init_reg_table[] = {
+	{RK3036_DSP_CTRL1, 0x00000000},
+};
+
+static const struct vop_data rk3036_vop = {
+	.init_table = rk3036_vop_init_reg_table,
+	.table_size = ARRAY_SIZE(rk3036_vop_init_reg_table),
+	.ctrl = &rk3036_ctrl_data,
+	.intr = &rk3036_intr,
+	.win = rk3036_vop_win_data,
+	.win_size = ARRAY_SIZE(rk3036_vop_win_data),
+};
+
+static const struct of_device_id vop_driver_dt_match[] = {
+	{ .compatible = "rockchip,rk3288-vop",
+	  .data = &rk3288_vop },
+	{ .compatible = "rockchip,rk3036-vop",
+	  .data = &rk3036_vop },
+	{},
+};
+MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
+
+static int vop_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	if (!dev->of_node) {
+		dev_err(dev, "can't find vop devices\n");
+		return -ENODEV;
+	}
+
+	return component_add(dev, &vop_component_ops);
+}
+
+static int vop_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &vop_component_ops);
+
+	return 0;
+}
+
+struct platform_driver vop_platform_driver = {
+	.probe = vop_probe,
+	.remove = vop_remove,
+	.driver = {
+		.name = "rockchip-vop",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(vop_driver_dt_match),
+	},
+};
+
+module_platform_driver(vop_platform_driver);
+
+MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
+MODULE_DESCRIPTION("ROCKCHIP VOP Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h
new file mode 100644
index 0000000..d4b46cb
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author:Mark Yao <mark.yao@rock-chips.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ROCKCHIP_VOP_REG_H
+#define _ROCKCHIP_VOP_REG_H
+
+/* rk3288 register definition */
+#define RK3288_REG_CFG_DONE			0x0000
+#define RK3288_VERSION_INFO			0x0004
+#define RK3288_SYS_CTRL				0x0008
+#define RK3288_SYS_CTRL1			0x000c
+#define RK3288_DSP_CTRL0			0x0010
+#define RK3288_DSP_CTRL1			0x0014
+#define RK3288_DSP_BG				0x0018
+#define RK3288_MCU_CTRL				0x001c
+#define RK3288_INTR_CTRL0			0x0020
+#define RK3288_INTR_CTRL1			0x0024
+#define RK3288_WIN0_CTRL0			0x0030
+#define RK3288_WIN0_CTRL1			0x0034
+#define RK3288_WIN0_COLOR_KEY			0x0038
+#define RK3288_WIN0_VIR				0x003c
+#define RK3288_WIN0_YRGB_MST			0x0040
+#define RK3288_WIN0_CBR_MST			0x0044
+#define RK3288_WIN0_ACT_INFO			0x0048
+#define RK3288_WIN0_DSP_INFO			0x004c
+#define RK3288_WIN0_DSP_ST			0x0050
+#define RK3288_WIN0_SCL_FACTOR_YRGB		0x0054
+#define RK3288_WIN0_SCL_FACTOR_CBR		0x0058
+#define RK3288_WIN0_SCL_OFFSET			0x005c
+#define RK3288_WIN0_SRC_ALPHA_CTRL		0x0060
+#define RK3288_WIN0_DST_ALPHA_CTRL		0x0064
+#define RK3288_WIN0_FADING_CTRL			0x0068
+
+/* win1 register */
+#define RK3288_WIN1_CTRL0			0x0070
+#define RK3288_WIN1_CTRL1			0x0074
+#define RK3288_WIN1_COLOR_KEY			0x0078
+#define RK3288_WIN1_VIR				0x007c
+#define RK3288_WIN1_YRGB_MST			0x0080
+#define RK3288_WIN1_CBR_MST			0x0084
+#define RK3288_WIN1_ACT_INFO			0x0088
+#define RK3288_WIN1_DSP_INFO			0x008c
+#define RK3288_WIN1_DSP_ST			0x0090
+#define RK3288_WIN1_SCL_FACTOR_YRGB		0x0094
+#define RK3288_WIN1_SCL_FACTOR_CBR		0x0098
+#define RK3288_WIN1_SCL_OFFSET			0x009c
+#define RK3288_WIN1_SRC_ALPHA_CTRL		0x00a0
+#define RK3288_WIN1_DST_ALPHA_CTRL		0x00a4
+#define RK3288_WIN1_FADING_CTRL			0x00a8
+/* win2 register */
+#define RK3288_WIN2_CTRL0			0x00b0
+#define RK3288_WIN2_CTRL1			0x00b4
+#define RK3288_WIN2_VIR0_1			0x00b8
+#define RK3288_WIN2_VIR2_3			0x00bc
+#define RK3288_WIN2_MST0			0x00c0
+#define RK3288_WIN2_DSP_INFO0			0x00c4
+#define RK3288_WIN2_DSP_ST0			0x00c8
+#define RK3288_WIN2_COLOR_KEY			0x00cc
+#define RK3288_WIN2_MST1			0x00d0
+#define RK3288_WIN2_DSP_INFO1			0x00d4
+#define RK3288_WIN2_DSP_ST1			0x00d8
+#define RK3288_WIN2_SRC_ALPHA_CTRL		0x00dc
+#define RK3288_WIN2_MST2			0x00e0
+#define RK3288_WIN2_DSP_INFO2			0x00e4
+#define RK3288_WIN2_DSP_ST2			0x00e8
+#define RK3288_WIN2_DST_ALPHA_CTRL		0x00ec
+#define RK3288_WIN2_MST3			0x00f0
+#define RK3288_WIN2_DSP_INFO3			0x00f4
+#define RK3288_WIN2_DSP_ST3			0x00f8
+#define RK3288_WIN2_FADING_CTRL			0x00fc
+/* win3 register */
+#define RK3288_WIN3_CTRL0			0x0100
+#define RK3288_WIN3_CTRL1			0x0104
+#define RK3288_WIN3_VIR0_1			0x0108
+#define RK3288_WIN3_VIR2_3			0x010c
+#define RK3288_WIN3_MST0			0x0110
+#define RK3288_WIN3_DSP_INFO0			0x0114
+#define RK3288_WIN3_DSP_ST0			0x0118
+#define RK3288_WIN3_COLOR_KEY			0x011c
+#define RK3288_WIN3_MST1			0x0120
+#define RK3288_WIN3_DSP_INFO1			0x0124
+#define RK3288_WIN3_DSP_ST1			0x0128
+#define RK3288_WIN3_SRC_ALPHA_CTRL		0x012c
+#define RK3288_WIN3_MST2			0x0130
+#define RK3288_WIN3_DSP_INFO2			0x0134
+#define RK3288_WIN3_DSP_ST2			0x0138
+#define RK3288_WIN3_DST_ALPHA_CTRL		0x013c
+#define RK3288_WIN3_MST3			0x0140
+#define RK3288_WIN3_DSP_INFO3			0x0144
+#define RK3288_WIN3_DSP_ST3			0x0148
+#define RK3288_WIN3_FADING_CTRL			0x014c
+/* hwc register */
+#define RK3288_HWC_CTRL0			0x0150
+#define RK3288_HWC_CTRL1			0x0154
+#define RK3288_HWC_MST				0x0158
+#define RK3288_HWC_DSP_ST			0x015c
+#define RK3288_HWC_SRC_ALPHA_CTRL		0x0160
+#define RK3288_HWC_DST_ALPHA_CTRL		0x0164
+#define RK3288_HWC_FADING_CTRL			0x0168
+/* post process register */
+#define RK3288_POST_DSP_HACT_INFO		0x0170
+#define RK3288_POST_DSP_VACT_INFO		0x0174
+#define RK3288_POST_SCL_FACTOR_YRGB		0x0178
+#define RK3288_POST_SCL_CTRL			0x0180
+#define RK3288_POST_DSP_VACT_INFO_F1		0x0184
+#define RK3288_DSP_HTOTAL_HS_END		0x0188
+#define RK3288_DSP_HACT_ST_END			0x018c
+#define RK3288_DSP_VTOTAL_VS_END		0x0190
+#define RK3288_DSP_VACT_ST_END			0x0194
+#define RK3288_DSP_VS_ST_END_F1			0x0198
+#define RK3288_DSP_VACT_ST_END_F1		0x019c
+/* register definition end */
+
+/* rk3036 register definition */
+#define RK3036_SYS_CTRL			0x00
+#define RK3036_DSP_CTRL0		0x04
+#define RK3036_DSP_CTRL1		0x08
+#define RK3036_INT_STATUS		0x10
+#define RK3036_ALPHA_CTRL		0x14
+#define RK3036_WIN0_COLOR_KEY		0x18
+#define RK3036_WIN1_COLOR_KEY		0x1c
+#define RK3036_WIN0_YRGB_MST		0x20
+#define RK3036_WIN0_CBR_MST		0x24
+#define RK3036_WIN1_VIR			0x28
+#define RK3036_AXI_BUS_CTRL		0x2c
+#define RK3036_WIN0_VIR			0x30
+#define RK3036_WIN0_ACT_INFO		0x34
+#define RK3036_WIN0_DSP_INFO		0x38
+#define RK3036_WIN0_DSP_ST		0x3c
+#define RK3036_WIN0_SCL_FACTOR_YRGB	0x40
+#define RK3036_WIN0_SCL_FACTOR_CBR	0x44
+#define RK3036_WIN0_SCL_OFFSET		0x48
+#define RK3036_HWC_MST			0x58
+#define RK3036_HWC_DSP_ST		0x5c
+#define RK3036_DSP_HTOTAL_HS_END	0x6c
+#define RK3036_DSP_HACT_ST_END		0x70
+#define RK3036_DSP_VTOTAL_VS_END	0x74
+#define RK3036_DSP_VACT_ST_END		0x78
+#define RK3036_DSP_VS_ST_END_F1		0x7c
+#define RK3036_DSP_VACT_ST_END_F1	0x80
+#define RK3036_GATHER_TRANSFER		0x84
+#define RK3036_VERSION_INFO		0x94
+#define RK3036_REG_CFG_DONE		0x90
+#define RK3036_WIN1_MST			0xa0
+#define RK3036_WIN1_ACT_INFO		0xb4
+#define RK3036_WIN1_DSP_INFO		0xb8
+#define RK3036_WIN1_DSP_ST		0xbc
+#define RK3036_WIN1_SCL_FACTOR_YRGB	0xc0
+#define RK3036_WIN1_SCL_OFFSET		0xc8
+#define RK3036_BCSH_CTRL		0xd0
+#define RK3036_BCSH_COLOR_BAR		0xd4
+#define RK3036_BCSH_BCS			0xd8
+#define RK3036_BCSH_H			0xdc
+#define RK3036_WIN1_LUT_ADDR		0x400
+#define RK3036_HWC_LUT_ADDR		0x800
+/* rk3036 register definition end */
+
+#endif /* _ROCKCHIP_VOP_REG_H */
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 1f5cb68..dde6f20 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1955,8 +1955,10 @@
 		 * cases where only a single display controller is used.
 		 */
 		for_each_matching_node(np, tegra_dc_of_match) {
-			if (np == dc->dev->of_node)
+			if (np == dc->dev->of_node) {
+				of_node_put(np);
 				break;
+			}
 
 			value++;
 		}
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index 6aecb66..b24a0f1 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -436,7 +436,7 @@
 	.remove = tegra_dpaux_remove,
 };
 
-struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np)
+struct drm_dp_aux *drm_dp_aux_find_by_of_node(struct device_node *np)
 {
 	struct tegra_dpaux *dpaux;
 
@@ -445,7 +445,7 @@
 	list_for_each_entry(dpaux, &dpaux_list, list)
 		if (np == dpaux->dev->of_node) {
 			mutex_unlock(&dpaux_lock);
-			return dpaux;
+			return &dpaux->aux;
 		}
 
 	mutex_unlock(&dpaux_lock);
@@ -453,8 +453,9 @@
 	return NULL;
 }
 
-int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output)
+int drm_dp_aux_attach(struct drm_dp_aux *aux, struct tegra_output *output)
 {
+	struct tegra_dpaux *dpaux = to_dpaux(aux);
 	unsigned long timeout;
 	int err;
 
@@ -470,7 +471,7 @@
 	while (time_before(jiffies, timeout)) {
 		enum drm_connector_status status;
 
-		status = tegra_dpaux_detect(dpaux);
+		status = drm_dp_aux_detect(aux);
 		if (status == connector_status_connected) {
 			enable_irq(dpaux->irq);
 			return 0;
@@ -482,8 +483,9 @@
 	return -ETIMEDOUT;
 }
 
-int tegra_dpaux_detach(struct tegra_dpaux *dpaux)
+int drm_dp_aux_detach(struct drm_dp_aux *aux)
 {
+	struct tegra_dpaux *dpaux = to_dpaux(aux);
 	unsigned long timeout;
 	int err;
 
@@ -498,7 +500,7 @@
 	while (time_before(jiffies, timeout)) {
 		enum drm_connector_status status;
 
-		status = tegra_dpaux_detect(dpaux);
+		status = drm_dp_aux_detect(aux);
 		if (status == connector_status_disconnected) {
 			dpaux->output = NULL;
 			return 0;
@@ -510,8 +512,9 @@
 	return -ETIMEDOUT;
 }
 
-enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux)
+enum drm_connector_status drm_dp_aux_detect(struct drm_dp_aux *aux)
 {
+	struct tegra_dpaux *dpaux = to_dpaux(aux);
 	u32 value;
 
 	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
@@ -522,8 +525,9 @@
 	return connector_status_disconnected;
 }
 
-int tegra_dpaux_enable(struct tegra_dpaux *dpaux)
+int drm_dp_aux_enable(struct drm_dp_aux *aux)
 {
+	struct tegra_dpaux *dpaux = to_dpaux(aux);
 	u32 value;
 
 	value = DPAUX_HYBRID_PADCTL_AUX_CMH(2) |
@@ -540,8 +544,9 @@
 	return 0;
 }
 
-int tegra_dpaux_disable(struct tegra_dpaux *dpaux)
+int drm_dp_aux_disable(struct drm_dp_aux *aux)
 {
+	struct tegra_dpaux *dpaux = to_dpaux(aux);
 	u32 value;
 
 	value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
@@ -551,11 +556,11 @@
 	return 0;
 }
 
-int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding)
+int drm_dp_aux_prepare(struct drm_dp_aux *aux, u8 encoding)
 {
 	int err;
 
-	err = drm_dp_dpcd_writeb(&dpaux->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
+	err = drm_dp_dpcd_writeb(aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
 				 encoding);
 	if (err < 0)
 		return err;
@@ -563,15 +568,15 @@
 	return 0;
 }
 
-int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
-		      u8 pattern)
+int drm_dp_aux_train(struct drm_dp_aux *aux, struct drm_dp_link *link,
+		     u8 pattern)
 {
 	u8 tp = pattern & DP_TRAINING_PATTERN_MASK;
 	u8 status[DP_LINK_STATUS_SIZE], values[4];
 	unsigned int i;
 	int err;
 
-	err = drm_dp_dpcd_writeb(&dpaux->aux, DP_TRAINING_PATTERN_SET, pattern);
+	err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET, pattern);
 	if (err < 0)
 		return err;
 
@@ -584,14 +589,14 @@
 			    DP_TRAIN_MAX_SWING_REACHED |
 			    DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
 
-	err = drm_dp_dpcd_write(&dpaux->aux, DP_TRAINING_LANE0_SET, values,
+	err = drm_dp_dpcd_write(aux, DP_TRAINING_LANE0_SET, values,
 				link->num_lanes);
 	if (err < 0)
 		return err;
 
 	usleep_range(500, 1000);
 
-	err = drm_dp_dpcd_read_link_status(&dpaux->aux, status);
+	err = drm_dp_dpcd_read_link_status(aux, status);
 	if (err < 0)
 		return err;
 
@@ -609,11 +614,11 @@
 		break;
 
 	default:
-		dev_err(dpaux->dev, "unsupported training pattern %u\n", tp);
+		dev_err(aux->dev, "unsupported training pattern %u\n", tp);
 		return -EINVAL;
 	}
 
-	err = drm_dp_dpcd_writeb(&dpaux->aux, DP_EDP_CONFIGURATION_SET, 0);
+	err = drm_dp_dpcd_writeb(aux, DP_EDP_CONFIGURATION_SET, 0);
 	if (err < 0)
 		return err;
 
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index ff948d2..c5c856a 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -137,8 +137,8 @@
 		start = geometry->aperture_start;
 		end = geometry->aperture_end;
 
-		DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n",
-			  start, end);
+		DRM_DEBUG_DRIVER("IOMMU aperture initialized (%#llx-%#llx)\n",
+				 start, end);
 		drm_mm_init(&tegra->mm, start, end - start + 1);
 	}
 
@@ -277,9 +277,7 @@
 	if (!gem)
 		return NULL;
 
-	mutex_lock(&drm->struct_mutex);
-	drm_gem_object_unreference(gem);
-	mutex_unlock(&drm->struct_mutex);
+	drm_gem_object_unreference_unlocked(gem);
 
 	bo = to_tegra_bo(gem);
 	return &bo->base;
@@ -473,7 +471,7 @@
 
 	args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
 
-	drm_gem_object_unreference(gem);
+	drm_gem_object_unreference_unlocked(gem);
 
 	return 0;
 }
@@ -683,7 +681,7 @@
 	bo->tiling.mode = mode;
 	bo->tiling.value = value;
 
-	drm_gem_object_unreference(gem);
+	drm_gem_object_unreference_unlocked(gem);
 
 	return 0;
 }
@@ -723,7 +721,7 @@
 		break;
 	}
 
-	drm_gem_object_unreference(gem);
+	drm_gem_object_unreference_unlocked(gem);
 
 	return err;
 }
@@ -748,7 +746,7 @@
 	if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
 		bo->flags |= TEGRA_BO_BOTTOM_UP;
 
-	drm_gem_object_unreference(gem);
+	drm_gem_object_unreference_unlocked(gem);
 
 	return 0;
 }
@@ -770,7 +768,7 @@
 	if (bo->flags & TEGRA_BO_BOTTOM_UP)
 		args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
 
-	drm_gem_object_unreference(gem);
+	drm_gem_object_unreference_unlocked(gem);
 
 	return 0;
 }
@@ -921,7 +919,8 @@
 #endif
 
 static struct drm_driver tegra_drm_driver = {
-	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
+	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
+			   DRIVER_ATOMIC,
 	.load = tegra_drm_load,
 	.unload = tegra_drm_unload,
 	.open = tegra_drm_open,
@@ -1022,8 +1021,17 @@
 static int host1x_drm_suspend(struct device *dev)
 {
 	struct drm_device *drm = dev_get_drvdata(dev);
+	struct tegra_drm *tegra = drm->dev_private;
 
 	drm_kms_helper_poll_disable(drm);
+	tegra_drm_fb_suspend(drm);
+
+	tegra->state = drm_atomic_helper_suspend(drm);
+	if (IS_ERR(tegra->state)) {
+		tegra_drm_fb_resume(drm);
+		drm_kms_helper_poll_enable(drm);
+		return PTR_ERR(tegra->state);
+	}
 
 	return 0;
 }
@@ -1031,7 +1039,10 @@
 static int host1x_drm_resume(struct device *dev)
 {
 	struct drm_device *drm = dev_get_drvdata(dev);
+	struct tegra_drm *tegra = drm->dev_private;
 
+	drm_atomic_helper_resume(drm, tegra->state);
+	tegra_drm_fb_resume(drm);
 	drm_kms_helper_poll_enable(drm);
 
 	return 0;
@@ -1075,6 +1086,16 @@
 	.subdevs = host1x_drm_subdevs,
 };
 
+static struct platform_driver * const drivers[] = {
+	&tegra_dc_driver,
+	&tegra_hdmi_driver,
+	&tegra_dsi_driver,
+	&tegra_dpaux_driver,
+	&tegra_sor_driver,
+	&tegra_gr2d_driver,
+	&tegra_gr3d_driver,
+};
+
 static int __init host1x_drm_init(void)
 {
 	int err;
@@ -1083,48 +1104,12 @@
 	if (err < 0)
 		return err;
 
-	err = platform_driver_register(&tegra_dc_driver);
+	err = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
 	if (err < 0)
 		goto unregister_host1x;
 
-	err = platform_driver_register(&tegra_dsi_driver);
-	if (err < 0)
-		goto unregister_dc;
-
-	err = platform_driver_register(&tegra_sor_driver);
-	if (err < 0)
-		goto unregister_dsi;
-
-	err = platform_driver_register(&tegra_hdmi_driver);
-	if (err < 0)
-		goto unregister_sor;
-
-	err = platform_driver_register(&tegra_dpaux_driver);
-	if (err < 0)
-		goto unregister_hdmi;
-
-	err = platform_driver_register(&tegra_gr2d_driver);
-	if (err < 0)
-		goto unregister_dpaux;
-
-	err = platform_driver_register(&tegra_gr3d_driver);
-	if (err < 0)
-		goto unregister_gr2d;
-
 	return 0;
 
-unregister_gr2d:
-	platform_driver_unregister(&tegra_gr2d_driver);
-unregister_dpaux:
-	platform_driver_unregister(&tegra_dpaux_driver);
-unregister_hdmi:
-	platform_driver_unregister(&tegra_hdmi_driver);
-unregister_sor:
-	platform_driver_unregister(&tegra_sor_driver);
-unregister_dsi:
-	platform_driver_unregister(&tegra_dsi_driver);
-unregister_dc:
-	platform_driver_unregister(&tegra_dc_driver);
 unregister_host1x:
 	host1x_driver_unregister(&host1x_drm_driver);
 	return err;
@@ -1133,13 +1118,7 @@
 
 static void __exit host1x_drm_exit(void)
 {
-	platform_driver_unregister(&tegra_gr3d_driver);
-	platform_driver_unregister(&tegra_gr2d_driver);
-	platform_driver_unregister(&tegra_dpaux_driver);
-	platform_driver_unregister(&tegra_hdmi_driver);
-	platform_driver_unregister(&tegra_sor_driver);
-	platform_driver_unregister(&tegra_dsi_driver);
-	platform_driver_unregister(&tegra_dc_driver);
+	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
 	host1x_driver_unregister(&host1x_drm_driver);
 }
 module_exit(host1x_drm_exit);
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index d88a2d1..c088f2f 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -57,6 +57,8 @@
 		struct work_struct work;
 		struct mutex lock;
 	} commit;
+
+	struct drm_atomic_state *state;
 };
 
 struct tegra_drm_client;
@@ -247,18 +249,17 @@
 void tegra_output_encoder_destroy(struct drm_encoder *encoder);
 
 /* from dpaux.c */
-struct tegra_dpaux;
 struct drm_dp_link;
 
-struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np);
-enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux);
-int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output);
-int tegra_dpaux_detach(struct tegra_dpaux *dpaux);
-int tegra_dpaux_enable(struct tegra_dpaux *dpaux);
-int tegra_dpaux_disable(struct tegra_dpaux *dpaux);
-int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding);
-int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
-		      u8 pattern);
+struct drm_dp_aux *drm_dp_aux_find_by_of_node(struct device_node *np);
+enum drm_connector_status drm_dp_aux_detect(struct drm_dp_aux *aux);
+int drm_dp_aux_attach(struct drm_dp_aux *aux, struct tegra_output *output);
+int drm_dp_aux_detach(struct drm_dp_aux *aux);
+int drm_dp_aux_enable(struct drm_dp_aux *aux);
+int drm_dp_aux_disable(struct drm_dp_aux *aux);
+int drm_dp_aux_prepare(struct drm_dp_aux *aux, u8 encoding);
+int drm_dp_aux_train(struct drm_dp_aux *aux, struct drm_dp_link *link,
+		     u8 pattern);
 
 /* from fb.c */
 struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
@@ -273,16 +274,18 @@
 void tegra_drm_fb_free(struct drm_device *drm);
 int tegra_drm_fb_init(struct drm_device *drm);
 void tegra_drm_fb_exit(struct drm_device *drm);
+void tegra_drm_fb_suspend(struct drm_device *drm);
+void tegra_drm_fb_resume(struct drm_device *drm);
 #ifdef CONFIG_DRM_FBDEV_EMULATION
 void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
 void tegra_fb_output_poll_changed(struct drm_device *drm);
 #endif
 
 extern struct platform_driver tegra_dc_driver;
-extern struct platform_driver tegra_dsi_driver;
-extern struct platform_driver tegra_sor_driver;
 extern struct platform_driver tegra_hdmi_driver;
+extern struct platform_driver tegra_dsi_driver;
 extern struct platform_driver tegra_dpaux_driver;
+extern struct platform_driver tegra_sor_driver;
 extern struct platform_driver tegra_gr2d_driver;
 extern struct platform_driver tegra_gr3d_driver;
 
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index a3515be..ca84de9 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/console.h>
+
 #include "drm.h"
 #include "gem.h"
 
@@ -413,3 +415,25 @@
 	tegra_fbdev_exit(tegra->fbdev);
 #endif
 }
+
+void tegra_drm_fb_suspend(struct drm_device *drm)
+{
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+	struct tegra_drm *tegra = drm->dev_private;
+
+	console_lock();
+	drm_fb_helper_set_suspend(&tegra->fbdev->base, 1);
+	console_unlock();
+#endif
+}
+
+void tegra_drm_fb_resume(struct drm_device *drm)
+{
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+	struct tegra_drm *tegra = drm->dev_private;
+
+	console_lock();
+	drm_fb_helper_set_suspend(&tegra->fbdev->base, 0);
+	console_unlock();
+#endif
+}
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index 01e16e1..33add93 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -28,11 +28,8 @@
 static void tegra_bo_put(struct host1x_bo *bo)
 {
 	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
-	struct drm_device *drm = obj->gem.dev;
 
-	mutex_lock(&drm->struct_mutex);
-	drm_gem_object_unreference(&obj->gem);
-	mutex_unlock(&drm->struct_mutex);
+	drm_gem_object_unreference_unlocked(&obj->gem);
 }
 
 static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt)
@@ -72,11 +69,8 @@
 static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
 {
 	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
-	struct drm_device *drm = obj->gem.dev;
 
-	mutex_lock(&drm->struct_mutex);
 	drm_gem_object_reference(&obj->gem);
-	mutex_unlock(&drm->struct_mutex);
 
 	return bo;
 }
@@ -408,12 +402,9 @@
 	struct drm_gem_object *gem;
 	struct tegra_bo *bo;
 
-	mutex_lock(&drm->struct_mutex);
-
 	gem = drm_gem_object_lookup(drm, file, handle);
 	if (!gem) {
 		dev_err(drm->dev, "failed to lookup GEM object\n");
-		mutex_unlock(&drm->struct_mutex);
 		return -EINVAL;
 	}
 
@@ -421,9 +412,7 @@
 
 	*offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
 
-	drm_gem_object_unreference(gem);
-
-	mutex_unlock(&drm->struct_mutex);
+	drm_gem_object_unreference_unlocked(gem);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 3e012ee..757c6e8 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -173,7 +173,7 @@
 	struct clk *clk_dp;
 	struct clk *clk;
 
-	struct tegra_dpaux *dpaux;
+	struct drm_dp_aux *aux;
 
 	struct drm_info_list *debugfs_files;
 	struct drm_minor *minor;
@@ -273,7 +273,7 @@
 		   SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0);
 	tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
 
-	err = tegra_dpaux_prepare(sor->dpaux, DP_SET_ANSI_8B10B);
+	err = drm_dp_aux_prepare(sor->aux, DP_SET_ANSI_8B10B);
 	if (err < 0)
 		return err;
 
@@ -288,7 +288,7 @@
 
 	pattern = DP_TRAINING_PATTERN_1;
 
-	err = tegra_dpaux_train(sor->dpaux, link, pattern);
+	err = drm_dp_aux_train(sor->aux, link, pattern);
 	if (err < 0)
 		return err;
 
@@ -309,7 +309,7 @@
 
 	pattern = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2;
 
-	err = tegra_dpaux_train(sor->dpaux, link, pattern);
+	err = drm_dp_aux_train(sor->aux, link, pattern);
 	if (err < 0)
 		return err;
 
@@ -324,7 +324,7 @@
 
 	pattern = DP_TRAINING_PATTERN_DISABLE;
 
-	err = tegra_dpaux_train(sor->dpaux, link, pattern);
+	err = drm_dp_aux_train(sor->aux, link, pattern);
 	if (err < 0)
 		return err;
 
@@ -1044,8 +1044,8 @@
 	struct tegra_output *output = connector_to_output(connector);
 	struct tegra_sor *sor = to_sor(output);
 
-	if (sor->dpaux)
-		return tegra_dpaux_detect(sor->dpaux);
+	if (sor->aux)
+		return drm_dp_aux_detect(sor->aux);
 
 	return tegra_output_connector_detect(connector, force);
 }
@@ -1066,13 +1066,13 @@
 	struct tegra_sor *sor = to_sor(output);
 	int err;
 
-	if (sor->dpaux)
-		tegra_dpaux_enable(sor->dpaux);
+	if (sor->aux)
+		drm_dp_aux_enable(sor->aux);
 
 	err = tegra_output_connector_get_modes(connector);
 
-	if (sor->dpaux)
-		tegra_dpaux_disable(sor->dpaux);
+	if (sor->aux)
+		drm_dp_aux_disable(sor->aux);
 
 	return err;
 }
@@ -1128,8 +1128,8 @@
 	if (err < 0)
 		dev_err(sor->dev, "failed to power down SOR: %d\n", err);
 
-	if (sor->dpaux) {
-		err = tegra_dpaux_disable(sor->dpaux);
+	if (sor->aux) {
+		err = drm_dp_aux_disable(sor->aux);
 		if (err < 0)
 			dev_err(sor->dev, "failed to disable DP: %d\n", err);
 	}
@@ -1196,7 +1196,7 @@
 	struct tegra_sor *sor = to_sor(output);
 	struct tegra_sor_config config;
 	struct drm_dp_link link;
-	struct drm_dp_aux *aux;
+	u8 rate, lanes;
 	int err = 0;
 	u32 value;
 
@@ -1209,20 +1209,14 @@
 	if (output->panel)
 		drm_panel_prepare(output->panel);
 
-	/* FIXME: properly convert to struct drm_dp_aux */
-	aux = (struct drm_dp_aux *)sor->dpaux;
+	err = drm_dp_aux_enable(sor->aux);
+	if (err < 0)
+		dev_err(sor->dev, "failed to enable DP: %d\n", err);
 
-	if (sor->dpaux) {
-		err = tegra_dpaux_enable(sor->dpaux);
-		if (err < 0)
-			dev_err(sor->dev, "failed to enable DP: %d\n", err);
-
-		err = drm_dp_link_probe(aux, &link);
-		if (err < 0) {
-			dev_err(sor->dev, "failed to probe eDP link: %d\n",
-				err);
-			return;
-		}
+	err = drm_dp_link_probe(sor->aux, &link);
+	if (err < 0) {
+		dev_err(sor->dev, "failed to probe eDP link: %d\n", err);
+		return;
 	}
 
 	err = clk_set_parent(sor->clk, sor->clk_safe);
@@ -1434,61 +1428,52 @@
 	value |= SOR_DP_PADCTL_PAD_CAL_PD;
 	tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
 
-	if (sor->dpaux) {
-		u8 rate, lanes;
+	err = drm_dp_link_probe(sor->aux, &link);
+	if (err < 0)
+		dev_err(sor->dev, "failed to probe eDP link: %d\n", err);
 
-		err = drm_dp_link_probe(aux, &link);
-		if (err < 0)
-			dev_err(sor->dev, "failed to probe eDP link: %d\n",
-				err);
+	err = drm_dp_link_power_up(sor->aux, &link);
+	if (err < 0)
+		dev_err(sor->dev, "failed to power up eDP link: %d\n", err);
 
-		err = drm_dp_link_power_up(aux, &link);
-		if (err < 0)
-			dev_err(sor->dev, "failed to power up eDP link: %d\n",
-				err);
+	err = drm_dp_link_configure(sor->aux, &link);
+	if (err < 0)
+		dev_err(sor->dev, "failed to configure eDP link: %d\n", err);
 
-		err = drm_dp_link_configure(aux, &link);
-		if (err < 0)
-			dev_err(sor->dev, "failed to configure eDP link: %d\n",
-				err);
+	rate = drm_dp_link_rate_to_bw_code(link.rate);
+	lanes = link.num_lanes;
 
-		rate = drm_dp_link_rate_to_bw_code(link.rate);
-		lanes = link.num_lanes;
+	value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
+	value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
+	value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
+	tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
 
-		value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
-		value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
-		value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
-		tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
+	value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
+	value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
+	value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
 
-		value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
-		value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
-		value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
+	if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
+		value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
 
-		if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
-			value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
+	tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
 
-		tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
+	/* disable training pattern generator */
 
-		/* disable training pattern generator */
-
-		for (i = 0; i < link.num_lanes; i++) {
-			unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
-					     SOR_DP_TPG_SCRAMBLER_GALIOS |
-					     SOR_DP_TPG_PATTERN_NONE;
-			value = (value << 8) | lane;
-		}
-
-		tegra_sor_writel(sor, value, SOR_DP_TPG);
-
-		err = tegra_sor_dp_train_fast(sor, &link);
-		if (err < 0) {
-			dev_err(sor->dev, "DP fast link training failed: %d\n",
-				err);
-		}
-
-		dev_dbg(sor->dev, "fast link training succeeded\n");
+	for (i = 0; i < link.num_lanes; i++) {
+		unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
+				     SOR_DP_TPG_SCRAMBLER_GALIOS |
+				     SOR_DP_TPG_PATTERN_NONE;
+		value = (value << 8) | lane;
 	}
 
+	tegra_sor_writel(sor, value, SOR_DP_TPG);
+
+	err = tegra_sor_dp_train_fast(sor, &link);
+	if (err < 0)
+		dev_err(sor->dev, "DP fast link training failed: %d\n", err);
+
+	dev_dbg(sor->dev, "fast link training succeeded\n");
+
 	err = tegra_sor_power_up(sor, 250);
 	if (err < 0)
 		dev_err(sor->dev, "failed to power up SOR: %d\n", err);
@@ -1961,9 +1946,9 @@
 
 	/* production settings */
 	settings = tegra_sor_hdmi_find_settings(sor, mode->clock * 1000);
-	if (IS_ERR(settings)) {
-		dev_err(sor->dev, "no settings for pixel clock %d Hz: %ld\n",
-			mode->clock * 1000, PTR_ERR(settings));
+	if (!settings) {
+		dev_err(sor->dev, "no settings for pixel clock %d Hz\n",
+			mode->clock * 1000);
 		return;
 	}
 
@@ -2148,7 +2133,7 @@
 	int encoder = DRM_MODE_ENCODER_NONE;
 	int err;
 
-	if (!sor->dpaux) {
+	if (!sor->aux) {
 		if (sor->soc->supports_hdmi) {
 			connector = DRM_MODE_CONNECTOR_HDMIA;
 			encoder = DRM_MODE_ENCODER_TMDS;
@@ -2199,8 +2184,8 @@
 			dev_err(sor->dev, "debugfs setup failed: %d\n", err);
 	}
 
-	if (sor->dpaux) {
-		err = tegra_dpaux_attach(sor->dpaux, &sor->output);
+	if (sor->aux) {
+		err = drm_dp_aux_attach(sor->aux, &sor->output);
 		if (err < 0) {
 			dev_err(sor->dev, "failed to attach DP: %d\n", err);
 			return err;
@@ -2249,8 +2234,8 @@
 
 	tegra_output_exit(&sor->output);
 
-	if (sor->dpaux) {
-		err = tegra_dpaux_detach(sor->dpaux);
+	if (sor->aux) {
+		err = drm_dp_aux_detach(sor->aux);
 		if (err < 0) {
 			dev_err(sor->dev, "failed to detach DP: %d\n", err);
 			return err;
@@ -2399,14 +2384,14 @@
 
 	np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0);
 	if (np) {
-		sor->dpaux = tegra_dpaux_find_by_of_node(np);
+		sor->aux = drm_dp_aux_find_by_of_node(np);
 		of_node_put(np);
 
-		if (!sor->dpaux)
+		if (!sor->aux)
 			return -EPROBE_DEFER;
 	}
 
-	if (!sor->dpaux) {
+	if (!sor->aux) {
 		if (sor->soc->supports_hdmi) {
 			sor->ops = &tegra_sor_hdmi_ops;
 		} else if (sor->soc->supports_lvds) {
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 745e996..4cbf265 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -176,7 +176,7 @@
 		list_add_tail(&bo->lru, &man->lru);
 		kref_get(&bo->list_kref);
 
-		if (bo->ttm != NULL) {
+		if (bo->ttm && !(bo->ttm->page_flags & TTM_PAGE_FLAG_SG)) {
 			list_add_tail(&bo->swap, &bo->glob->swap_lru);
 			kref_get(&bo->list_kref);
 		}
@@ -228,6 +228,27 @@
 }
 EXPORT_SYMBOL(ttm_bo_del_sub_from_lru);
 
+void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_mem_type_manager *man;
+
+	lockdep_assert_held(&bo->resv->lock.base);
+
+	if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT) {
+		list_del_init(&bo->swap);
+		list_del_init(&bo->lru);
+
+	} else {
+		if (bo->ttm && !(bo->ttm->page_flags & TTM_PAGE_FLAG_SG))
+			list_move_tail(&bo->swap, &bo->glob->swap_lru);
+
+		man = &bdev->man[bo->mem.mem_type];
+		list_move_tail(&bo->lru, &man->lru);
+	}
+}
+EXPORT_SYMBOL(ttm_bo_move_to_lru_tail);
+
 /*
  * Call bo->mutex locked.
  */
@@ -1170,9 +1191,15 @@
 	if (likely(!ret))
 		ret = ttm_bo_validate(bo, placement, interruptible, false);
 
-	if (!resv)
+	if (!resv) {
 		ttm_bo_unreserve(bo);
 
+	} else if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {
+		spin_lock(&bo->glob->lru_lock);
+		ttm_bo_add_to_lru(bo);
+		spin_unlock(&bo->glob->lru_lock);
+	}
+
 	if (unlikely(ret))
 		ttm_bo_unref(&bo);
 
diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/ttm/ttm_lock.c
index 6a95454..f154fb1 100644
--- a/drivers/gpu/drm/ttm/ttm_lock.c
+++ b/drivers/gpu/drm/ttm/ttm_lock.c
@@ -180,7 +180,7 @@
 			spin_unlock(&lock->lock);
 		}
 	} else
-		wait_event(lock->queue, __ttm_read_lock(lock));
+		wait_event(lock->queue, __ttm_write_lock(lock));
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index 39f29e7..48ce30a 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -71,7 +71,7 @@
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	unsigned long irqflags;
 	u32 i;
-	int ret;
+	int ret = 0;
 
 	spin_lock_irqsave(&vc4->job_lock, irqflags);
 	kernel_state = vc4->hang_state;
@@ -119,9 +119,11 @@
 		bo_state[i].size = vc4_bo->base.base.size;
 	}
 
-	ret = copy_to_user((void __user *)(uintptr_t)get_state->bo,
-			   bo_state,
-			   state->bo_count * sizeof(*bo_state));
+	if (copy_to_user((void __user *)(uintptr_t)get_state->bo,
+			 bo_state,
+			 state->bo_count * sizeof(*bo_state)))
+		ret = -EFAULT;
+
 	kfree(bo_state);
 
 err_free:
@@ -143,7 +145,7 @@
 	unsigned long irqflags;
 	unsigned int i, unref_list_count;
 
-	kernel_state = kcalloc(1, sizeof(*state), GFP_KERNEL);
+	kernel_state = kcalloc(1, sizeof(*kernel_state), GFP_KERNEL);
 	if (!kernel_state)
 		return;
 
@@ -554,34 +556,31 @@
 	exec->shader_state = temp + exec_size;
 	exec->shader_state_size = args->shader_rec_count;
 
-	ret = copy_from_user(bin,
-			     (void __user *)(uintptr_t)args->bin_cl,
-			     args->bin_cl_size);
-	if (ret) {
-		DRM_ERROR("Failed to copy in bin cl\n");
+	if (copy_from_user(bin,
+			   (void __user *)(uintptr_t)args->bin_cl,
+			   args->bin_cl_size)) {
+		ret = -EFAULT;
 		goto fail;
 	}
 
-	ret = copy_from_user(exec->shader_rec_u,
-			     (void __user *)(uintptr_t)args->shader_rec,
-			     args->shader_rec_size);
-	if (ret) {
-		DRM_ERROR("Failed to copy in shader recs\n");
+	if (copy_from_user(exec->shader_rec_u,
+			   (void __user *)(uintptr_t)args->shader_rec,
+			   args->shader_rec_size)) {
+		ret = -EFAULT;
 		goto fail;
 	}
 
-	ret = copy_from_user(exec->uniforms_u,
-			     (void __user *)(uintptr_t)args->uniforms,
-			     args->uniforms_size);
-	if (ret) {
-		DRM_ERROR("Failed to copy in uniforms cl\n");
+	if (copy_from_user(exec->uniforms_u,
+			   (void __user *)(uintptr_t)args->uniforms,
+			   args->uniforms_size)) {
+		ret = -EFAULT;
 		goto fail;
 	}
 
 	bo = vc4_bo_create(dev, exec_size, true);
 	if (!bo) {
 		DRM_ERROR("Couldn't allocate BO for binning\n");
-		ret = PTR_ERR(exec->exec_bo);
+		ret = -ENOMEM;
 		goto fail;
 	}
 	exec->exec_bo = &bo->base;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
index 6377e81..67cebb2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
@@ -247,7 +247,7 @@
 {
 	struct vmw_cmdbuf_man *man = header->man;
 
-	BUG_ON(!spin_is_locked(&man->lock));
+	lockdep_assert_held_once(&man->lock);
 
 	if (header->inline_space) {
 		vmw_cmdbuf_header_inline_free(header);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index a09cf85..c49812b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -1233,6 +1233,7 @@
 
 	vmw_fp->locked_master = drm_master_get(file_priv->master);
 	ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
+	vmw_kms_legacy_hotspot_clear(dev_priv);
 	if (unlikely((ret != 0))) {
 		DRM_ERROR("Unable to lock TTM at VT switch.\n");
 		drm_master_put(&vmw_fp->locked_master);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index a8ae9df..469cdd5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -925,6 +925,7 @@
 		    uint32_t num_clips);
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
+void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv);
 
 int vmw_dumb_create(struct drm_file *file_priv,
 		    struct drm_device *dev,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index a8baf5f..b6a0806 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -390,7 +390,7 @@
 	else if (ctx_id == SVGA3D_INVALID_ID)
 		ret = vmw_local_fifo_reserve(dev_priv, bytes);
 	else {
-		WARN_ON("Command buffer has not been allocated.\n");
+		WARN(1, "Command buffer has not been allocated.\n");
 		ret = NULL;
 	}
 	if (IS_ERR_OR_NULL(ret)) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 162f188..b221a8c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -133,13 +133,19 @@
 	vmw_mmio_write(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
 }
 
-int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
-			   uint32_t handle, uint32_t width, uint32_t height)
+
+/*
+ * vmw_du_crtc_cursor_set2 - Driver cursor_set2 callback.
+ */
+int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
+			    uint32_t handle, uint32_t width, uint32_t height,
+			    int32_t hot_x, int32_t hot_y)
 {
 	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
 	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
 	struct vmw_surface *surface = NULL;
 	struct vmw_dma_buffer *dmabuf = NULL;
+	s32 hotspot_x, hotspot_y;
 	int ret;
 
 	/*
@@ -151,6 +157,8 @@
 	 */
 	drm_modeset_unlock_crtc(crtc);
 	drm_modeset_lock_all(dev_priv->dev);
+	hotspot_x = hot_x + du->hotspot_x;
+	hotspot_y = hot_y + du->hotspot_y;
 
 	/* A lot of the code assumes this */
 	if (handle && (width != 64 || height != 64)) {
@@ -187,31 +195,34 @@
 		vmw_dmabuf_unreference(&du->cursor_dmabuf);
 
 	/* setup new image */
+	ret = 0;
 	if (surface) {
 		/* vmw_user_surface_lookup takes one reference */
 		du->cursor_surface = surface;
 
 		du->cursor_surface->snooper.crtc = crtc;
 		du->cursor_age = du->cursor_surface->snooper.age;
-		vmw_cursor_update_image(dev_priv, surface->snooper.image,
-					64, 64, du->hotspot_x, du->hotspot_y);
+		ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
+					      64, 64, hotspot_x, hotspot_y);
 	} else if (dmabuf) {
 		/* vmw_user_surface_lookup takes one reference */
 		du->cursor_dmabuf = dmabuf;
 
 		ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height,
-					       du->hotspot_x, du->hotspot_y);
+					       hotspot_x, hotspot_y);
 	} else {
 		vmw_cursor_update_position(dev_priv, false, 0, 0);
-		ret = 0;
 		goto out;
 	}
 
-	vmw_cursor_update_position(dev_priv, true,
-				   du->cursor_x + du->hotspot_x,
-				   du->cursor_y + du->hotspot_y);
+	if (!ret) {
+		vmw_cursor_update_position(dev_priv, true,
+					   du->cursor_x + hotspot_x,
+					   du->cursor_y + hotspot_y);
+		du->core_hotspot_x = hot_x;
+		du->core_hotspot_y = hot_y;
+	}
 
-	ret = 0;
 out:
 	drm_modeset_unlock_all(dev_priv->dev);
 	drm_modeset_lock_crtc(crtc, crtc->cursor);
@@ -239,8 +250,10 @@
 	drm_modeset_lock_all(dev_priv->dev);
 
 	vmw_cursor_update_position(dev_priv, shown,
-				   du->cursor_x + du->hotspot_x,
-				   du->cursor_y + du->hotspot_y);
+				   du->cursor_x + du->hotspot_x +
+				   du->core_hotspot_x,
+				   du->cursor_y + du->hotspot_y +
+				   du->core_hotspot_y);
 
 	drm_modeset_unlock_all(dev_priv->dev);
 	drm_modeset_lock_crtc(crtc, crtc->cursor);
@@ -334,6 +347,29 @@
 	ttm_bo_unreserve(bo);
 }
 
+/**
+ * vmw_kms_legacy_hotspot_clear - Clear legacy hotspots
+ *
+ * @dev_priv: Pointer to the device private struct.
+ *
+ * Clears all legacy hotspots.
+ */
+void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct vmw_display_unit *du;
+	struct drm_crtc *crtc;
+
+	drm_modeset_lock_all(dev);
+	drm_for_each_crtc(crtc, dev) {
+		du = vmw_crtc_to_du(crtc);
+
+		du->hotspot_x = 0;
+		du->hotspot_y = 0;
+	}
+	drm_modeset_unlock_all(dev);
+}
+
 void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
@@ -351,7 +387,9 @@
 		du->cursor_age = du->cursor_surface->snooper.age;
 		vmw_cursor_update_image(dev_priv,
 					du->cursor_surface->snooper.image,
-					64, 64, du->hotspot_x, du->hotspot_y);
+					64, 64,
+					du->hotspot_x + du->core_hotspot_x,
+					du->hotspot_y + du->core_hotspot_y);
 	}
 
 	mutex_unlock(&dev->mode_config.mutex);
@@ -725,21 +763,25 @@
 	uint32_t format;
 	struct drm_vmw_size content_base_size;
 	struct vmw_resource *res;
+	unsigned int bytes_pp;
 	int ret;
 
 	switch (mode_cmd->depth) {
 	case 32:
 	case 24:
 		format = SVGA3D_X8R8G8B8;
+		bytes_pp = 4;
 		break;
 
 	case 16:
 	case 15:
 		format = SVGA3D_R5G6B5;
+		bytes_pp = 2;
 		break;
 
 	case 8:
 		format = SVGA3D_P8;
+		bytes_pp = 1;
 		break;
 
 	default:
@@ -747,7 +789,7 @@
 		return -EINVAL;
 	}
 
-	content_base_size.width  = mode_cmd->width;
+	content_base_size.width  = mode_cmd->pitch / bytes_pp;
 	content_base_size.height = mode_cmd->height;
 	content_base_size.depth  = 1;
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 782df7c..edd8150 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -159,6 +159,8 @@
 
 	int hotspot_x;
 	int hotspot_y;
+	s32 core_hotspot_x;
+	s32 core_hotspot_y;
 
 	unsigned unit;
 
@@ -193,8 +195,9 @@
 void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
 			   u16 *r, u16 *g, u16 *b,
 			   uint32_t start, uint32_t size);
-int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
-			   uint32_t handle, uint32_t width, uint32_t height);
+int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
+			    uint32_t handle, uint32_t width, uint32_t height,
+			    int32_t hot_x, int32_t hot_y);
 int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
 int vmw_du_connector_dpms(struct drm_connector *connector, int mode);
 void vmw_du_connector_save(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 2def684..b6fa44f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -295,7 +295,7 @@
 }
 
 static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
-	.cursor_set = vmw_du_crtc_cursor_set,
+	.cursor_set2 = vmw_du_crtc_cursor_set2,
 	.cursor_move = vmw_du_crtc_cursor_move,
 	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_ldu_crtc_destroy,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index ecac70a..db082be 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -531,7 +531,7 @@
 }
 
 static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
-	.cursor_set = vmw_du_crtc_cursor_set,
+	.cursor_set2 = vmw_du_crtc_cursor_set2,
 	.cursor_move = vmw_du_crtc_cursor_move,
 	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_sou_crtc_destroy,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 87fc00a..4ef5ffd 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1041,7 +1041,7 @@
  *  Screen Target CRTC dispatch table
  */
 static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
-	.cursor_set = vmw_du_crtc_cursor_set,
+	.cursor_set2 = vmw_du_crtc_cursor_set2,
 	.cursor_move = vmw_du_crtc_cursor_move,
 	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_stdu_crtc_destroy,
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index c1189f0..a1d9974 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -10,6 +10,7 @@
 	mipi.o \
 	hw/host1x01.o \
 	hw/host1x02.o \
-	hw/host1x04.o
+	hw/host1x04.o \
+	hw/host1x05.o
 
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index 4a99c64..da462af 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -538,6 +538,8 @@
 
 void host1x_driver_unregister(struct host1x_driver *driver)
 {
+	driver_unregister(&driver->driver);
+
 	mutex_lock(&drivers_lock);
 	list_del_init(&driver->list);
 	mutex_unlock(&drivers_lock);
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 53d3d1d..314bf37 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -35,6 +35,7 @@
 #include "hw/host1x01.h"
 #include "hw/host1x02.h"
 #include "hw/host1x04.h"
+#include "hw/host1x05.h"
 
 void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
 {
@@ -87,7 +88,17 @@
 	.sync_offset = 0x2100,
 };
 
+static const struct host1x_info host1x05_info = {
+	.nb_channels = 14,
+	.nb_pts = 192,
+	.nb_mlocks = 16,
+	.nb_bases = 64,
+	.init = host1x05_init,
+	.sync_offset = 0x2100,
+};
+
 static struct of_device_id host1x_of_match[] = {
+	{ .compatible = "nvidia,tegra210-host1x", .data = &host1x05_info, },
 	{ .compatible = "nvidia,tegra124-host1x", .data = &host1x04_info, },
 	{ .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, },
 	{ .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, },
@@ -212,6 +223,11 @@
 	.remove = host1x_remove,
 };
 
+static struct platform_driver * const drivers[] = {
+	&tegra_host1x_driver,
+	&tegra_mipi_driver,
+};
+
 static int __init tegra_host1x_init(void)
 {
 	int err;
@@ -220,28 +236,17 @@
 	if (err < 0)
 		return err;
 
-	err = platform_driver_register(&tegra_host1x_driver);
+	err = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
 	if (err < 0)
-		goto unregister_bus;
+		bus_unregister(&host1x_bus_type);
 
-	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:
-	bus_unregister(&host1x_bus_type);
 	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);
+	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
 	bus_unregister(&host1x_bus_type);
 }
 module_exit(tegra_host1x_exit);
diff --git a/drivers/gpu/host1x/hw/host1x05.c b/drivers/gpu/host1x/hw/host1x05.c
new file mode 100644
index 0000000..047097c
--- /dev/null
+++ b/drivers/gpu/host1x/hw/host1x05.c
@@ -0,0 +1,42 @@
+/*
+ * Host1x init for Tegra210 SoCs
+ *
+ * Copyright (c) 2015 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 "host1x05.h"
+#include "host1x05_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 host1x05_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/host1x05.h b/drivers/gpu/host1x/hw/host1x05.h
new file mode 100644
index 0000000..a306d9c
--- /dev/null
+++ b/drivers/gpu/host1x/hw/host1x05.h
@@ -0,0 +1,26 @@
+/*
+ * Host1x init for Tegra210 SoCs
+ *
+ * Copyright (c) 2015 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_HOST1X05_H
+#define HOST1X_HOST1X05_H
+
+struct host1x;
+
+int host1x05_init(struct host1x *host);
+
+#endif
diff --git a/drivers/gpu/host1x/hw/host1x05_hardware.h b/drivers/gpu/host1x/hw/host1x05_hardware.h
new file mode 100644
index 0000000..2937ebb
--- /dev/null
+++ b/drivers/gpu/host1x/hw/host1x05_hardware.h
@@ -0,0 +1,142 @@
+/*
+ * Tegra host1x Register Offsets for Tegra210
+ *
+ * Copyright (c) 2015 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_HOST1X05_HARDWARE_H
+#define __HOST1X_HOST1X05_HARDWARE_H
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+#include "hw_host1x05_channel.h"
+#include "hw_host1x05_sync.h"
+#include "hw_host1x05_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/hw_host1x05_channel.h b/drivers/gpu/host1x/hw/hw_host1x05_channel.h
new file mode 100644
index 0000000..fce6e2c
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x05_channel.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015 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_HOST1X05_CHANNEL_H
+#define HOST1X_HW_HOST1X05_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_host1x05_sync.h b/drivers/gpu/host1x/hw/hw_host1x05_sync.h
new file mode 100644
index 0000000..ca10eee
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x05_sync.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2015 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_HOST1X05_SYNC_H
+#define HOST1X_HW_HOST1X05_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_v(u32 r)
+{
+	return (r >> 8) & 0xf;
+}
+#define HOST1X_SYNC_MLOCK_OWNER_CHID_V(v) \
+	host1x_sync_mlock_owner_chid_v(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_host1x05_uclass.h b/drivers/gpu/host1x/hw/hw_host1x05_uclass.h
new file mode 100644
index 0000000..0c411da
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x05_uclass.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015 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_HOST1X05_UCLASS_H
+#define HOST1X_HW_HOST1X05_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
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 3166e4b..9abcaa5 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -395,8 +395,10 @@
 		set_current_state(interruptible ?
 				  TASK_INTERRUPTIBLE :
 				  TASK_UNINTERRUPTIBLE);
-		if (signal_pending(current)) {
-			rc = -EINTR;
+		if (interruptible && signal_pending(current)) {
+			__set_current_state(TASK_RUNNING);
+			remove_wait_queue(&vga_wait_queue, &wait);
+			rc = -ERESTARTSYS;
 			break;
 		}
 		schedule();
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 9024a3d..8b78a7f 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -316,11 +316,6 @@
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001	0xa001
 
 #define USB_VENDOR_ID_ELAN		0x04f3
-#define USB_DEVICE_ID_ELAN_TOUCHSCREEN	0x0089
-#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B	0x009b
-#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103	0x0103
-#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c	0x010c
-#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F	0x016f
 
 #define USB_VENDOR_ID_ELECOM		0x056e
 #define USB_DEVICE_ID_ELECOM_BM084	0x0061
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 2324520..7dd0953 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -72,11 +72,7 @@
 	{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
 	{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL },
-	{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL },
-	{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL },
-	{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c, HID_QUIRK_ALWAYS_POLL },
-	{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL },
+	{ USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL },
 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
@@ -340,7 +336,8 @@
 
 	for (; hid_blacklist[n].idVendor; n++)
 		if (hid_blacklist[n].idVendor == idVendor &&
-				hid_blacklist[n].idProduct == idProduct)
+			(hid_blacklist[n].idProduct == (__u16) HID_ANY_ID ||
+				hid_blacklist[n].idProduct == idProduct))
 			bl_entry = &hid_blacklist[n];
 
 	if (bl_entry != NULL)
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 8f59f05..80a73bf 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1217,6 +1217,7 @@
 config SENSORS_SHT15
 	tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
 	depends on GPIOLIB || COMPILE_TEST
+	select BITREVERSE
 	help
 	  If you say yes here you get support for the Sensiron SHT10, SHT11,
 	  SHT15, SHT71, SHT75 humidity and temperature sensors.
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index 6548262..5289aa0 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -58,6 +58,7 @@
 	u16 config_orig;
 	unsigned long last_update;
 	int temp[3];
+	bool first_time;
 };
 
 /* convert left adjusted 13-bit TMP102 register value to milliCelsius */
@@ -93,6 +94,7 @@
 				tmp102->temp[i] = tmp102_reg_to_mC(status);
 		}
 		tmp102->last_update = jiffies;
+		tmp102->first_time = false;
 	}
 	mutex_unlock(&tmp102->lock);
 	return tmp102;
@@ -102,6 +104,12 @@
 {
 	struct tmp102 *tmp102 = tmp102_update_device(dev);
 
+	/* Is it too early even to return a conversion? */
+	if (tmp102->first_time) {
+		dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__);
+		return -EAGAIN;
+	}
+
 	*temp = tmp102->temp[0];
 
 	return 0;
@@ -114,6 +122,10 @@
 	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
 	struct tmp102 *tmp102 = tmp102_update_device(dev);
 
+	/* Is it too early even to return a read? */
+	if (tmp102->first_time)
+		return -EAGAIN;
+
 	return sprintf(buf, "%d\n", tmp102->temp[sda->index]);
 }
 
@@ -207,7 +219,9 @@
 		status = -ENODEV;
 		goto fail_restore_config;
 	}
-	tmp102->last_update = jiffies - HZ;
+	tmp102->last_update = jiffies;
+	/* Mark that we are not ready with data until conversion is complete */
+	tmp102->first_time = true;
 	mutex_init(&tmp102->lock);
 
 	hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index c5628a4..a8bdcb5 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -202,8 +202,15 @@
 	 * d is always 6 on Keystone I2C controller
 	 */
 
-	/* get minimum of 7 MHz clock, but max of 12 MHz */
-	psc = (input_clock / 7000000) - 1;
+	/*
+	 * Both Davinci and current Keystone User Guides recommend a value
+	 * between 7MHz and 12MHz. In reality 7MHz module clock doesn't
+	 * always produce enough margin between SDA and SCL transitions.
+	 * Measurements show that the higher the module clock is, the
+	 * bigger is the margin, providing more reliable communication.
+	 * So we better target for 12MHz.
+	 */
+	psc = (input_clock / 12000000) - 1;
 	if ((input_clock / (psc + 1)) > 12000000)
 		psc++;	/* better to run under spec than over */
 	d = (psc >= 2) ? 5 : 7 - psc;
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 8c48b27..de7fbbb 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -813,6 +813,12 @@
 tx_aborted:
 	if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
 		complete(&dev->cmd_complete);
+	else if (unlikely(dev->accessor_flags & ACCESS_INTR_MASK)) {
+		/* workaround to trigger pending interrupt */
+		stat = dw_readl(dev, DW_IC_INTR_MASK);
+		i2c_dw_disable_int(dev);
+		dw_writel(dev, stat, DW_IC_INTR_MASK);
+	}
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 1d50898..9ffb63a 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -111,6 +111,7 @@
 
 #define ACCESS_SWAP		0x00000001
 #define ACCESS_16BIT		0x00000002
+#define ACCESS_INTR_MASK	0x00000004
 
 extern int i2c_dw_init(struct dw_i2c_dev *dev);
 extern void i2c_dw_disable(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 809579e..6b00061c 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -93,6 +93,7 @@
 static int dw_i2c_acpi_configure(struct platform_device *pdev)
 {
 	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+	const struct acpi_device_id *id;
 
 	dev->adapter.nr = -1;
 	dev->tx_fifo_depth = 32;
@@ -106,6 +107,10 @@
 	dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
 			   &dev->sda_hold_time);
 
+	id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
+	if (id && id->driver_data)
+		dev->accessor_flags |= (u32)id->driver_data;
+
 	return 0;
 }
 
@@ -116,7 +121,7 @@
 	{ "INT3433", 0 },
 	{ "80860F41", 0 },
 	{ "808622C1", 0 },
-	{ "AMD0010", 0 },
+	{ "AMD0010", ACCESS_INTR_MASK },
 	{ }
 };
 MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
@@ -240,12 +245,10 @@
 	}
 
 	r = i2c_dw_probe(dev);
-	if (r) {
+	if (r && !dev->pm_runtime_disabled)
 		pm_runtime_disable(&pdev->dev);
-		return r;
-	}
 
-	return 0;
+	return r;
 }
 
 static int dw_i2c_plat_remove(struct platform_device *pdev)
@@ -260,7 +263,8 @@
 
 	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	pm_runtime_put_sync(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
+	if (!dev->pm_runtime_disabled)
+		pm_runtime_disable(&pdev->dev);
 
 	return 0;
 }
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 9bb0b05..d4d8536 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1119,6 +1119,8 @@
 			i2c_imx, IMX_I2C_I2CR);
 	imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
 
+	i2c_imx_init_recovery_info(i2c_imx, pdev);
+
 	/* Add I2C adapter */
 	ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
 	if (ret < 0) {
@@ -1126,8 +1128,6 @@
 		goto clk_disable;
 	}
 
-	i2c_imx_init_recovery_info(i2c_imx, pdev);
-
 	/* Set up platform driver data */
 	platform_set_drvdata(pdev, i2c_imx);
 	clk_disable_unprepare(i2c_imx->clk);
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 5801227..43207f5 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -146,6 +146,8 @@
 	bool			errata_delay;
 	struct reset_control	*rstc;
 	bool			irq_clear_inverted;
+	/* Clk div is 2 to the power n, not 2 to the power n + 1 */
+	bool			clk_n_base_0;
 };
 
 static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
@@ -757,25 +759,29 @@
 #ifdef CONFIG_OF
 #ifdef CONFIG_HAVE_CLK
 static int
-mv64xxx_calc_freq(const int tclk, const int n, const int m)
+mv64xxx_calc_freq(struct mv64xxx_i2c_data *drv_data,
+		  const int tclk, const int n, const int m)
 {
-	return tclk / (10 * (m + 1) * (2 << n));
+	if (drv_data->clk_n_base_0)
+		return tclk / (10 * (m + 1) * (1 << n));
+	else
+		return tclk / (10 * (m + 1) * (2 << n));
 }
 
 static bool
-mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n,
-			  u32 *best_m)
+mv64xxx_find_baud_factors(struct mv64xxx_i2c_data *drv_data,
+			  const u32 req_freq, const u32 tclk)
 {
 	int freq, delta, best_delta = INT_MAX;
 	int m, n;
 
 	for (n = 0; n <= 7; n++)
 		for (m = 0; m <= 15; m++) {
-			freq = mv64xxx_calc_freq(tclk, n, m);
+			freq = mv64xxx_calc_freq(drv_data, tclk, n, m);
 			delta = req_freq - freq;
 			if (delta >= 0 && delta < best_delta) {
-				*best_m = m;
-				*best_n = n;
+				drv_data->freq_m = m;
+				drv_data->freq_n = n;
 				best_delta = delta;
 			}
 			if (best_delta == 0)
@@ -813,8 +819,11 @@
 	if (of_property_read_u32(np, "clock-frequency", &bus_freq))
 		bus_freq = 100000; /* 100kHz by default */
 
-	if (!mv64xxx_find_baud_factors(bus_freq, tclk,
-				       &drv_data->freq_n, &drv_data->freq_m)) {
+	if (of_device_is_compatible(np, "allwinner,sun4i-a10-i2c") ||
+	    of_device_is_compatible(np, "allwinner,sun6i-a31-i2c"))
+		drv_data->clk_n_base_0 = true;
+
+	if (!mv64xxx_find_baud_factors(drv_data, bus_freq, tclk)) {
 		rc = -EINVAL;
 		goto out;
 	}
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index b0ae560..599c0d7 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -576,7 +576,7 @@
 	if (slave->flags & I2C_CLIENT_TEN)
 		return -EAFNOSUPPORT;
 
-	pm_runtime_forbid(rcar_i2c_priv_to_dev(priv));
+	pm_runtime_get_sync(rcar_i2c_priv_to_dev(priv));
 
 	priv->slave = slave;
 	rcar_i2c_write(priv, ICSAR, slave->addr);
@@ -598,7 +598,7 @@
 
 	priv->slave = NULL;
 
-	pm_runtime_allow(rcar_i2c_priv_to_dev(priv));
+	pm_runtime_put(rcar_i2c_priv_to_dev(priv));
 
 	return 0;
 }
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index c1935eb..9096d17 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -908,7 +908,7 @@
 				 &i2c->scl_fall_ns))
 		i2c->scl_fall_ns = 300;
 	if (of_property_read_u32(pdev->dev.of_node, "i2c-sda-falling-time-ns",
-				 &i2c->scl_fall_ns))
+				 &i2c->sda_fall_ns))
 		i2c->sda_fall_ns = i2c->scl_fall_ns;
 
 	strlcpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name));
diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c
index ea72dca..25020ec 100644
--- a/drivers/i2c/busses/i2c-st.c
+++ b/drivers/i2c/busses/i2c-st.c
@@ -822,7 +822,7 @@
 
 	adap = &i2c_dev->adap;
 	i2c_set_adapdata(adap, i2c_dev);
-	snprintf(adap->name, sizeof(adap->name), "ST I2C(0x%pa)", &res->start);
+	snprintf(adap->name, sizeof(adap->name), "ST I2C(%pa)", &res->start);
 	adap->owner = THIS_MODULE;
 	adap->timeout = 2 * HZ;
 	adap->retries = 0;
diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
index 0c4618b..c2babe5 100644
--- a/drivers/iio/adc/qcom-spmi-vadc.c
+++ b/drivers/iio/adc/qcom-spmi-vadc.c
@@ -839,8 +839,10 @@
 
 	for_each_available_child_of_node(node, child) {
 		ret = vadc_get_dt_channel_data(vadc->dev, &prop, child);
-		if (ret)
+		if (ret) {
+			of_node_put(child);
 			return ret;
+		}
 
 		vadc->chan_props[index] = prop;
 
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index d7e908a..0f6f63b 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -302,7 +302,7 @@
 	if (trialmask == NULL)
 		return -ENOMEM;
 	if (!indio_dev->masklength) {
-		WARN_ON("Trying to set scanmask prior to registering buffer\n");
+		WARN(1, "Trying to set scanmask prior to registering buffer\n");
 		goto err_invalid_mask;
 	}
 	bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 208358f..159ede6 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -655,7 +655,7 @@
 			break;
 		case IIO_SEPARATE:
 			if (!chan->indexed) {
-				WARN_ON("Differential channels must be indexed\n");
+				WARN(1, "Differential channels must be indexed\n");
 				ret = -EINVAL;
 				goto error_free_full_postfix;
 			}
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
index 7d269ef..f6a07dc 100644
--- a/drivers/iio/light/apds9960.c
+++ b/drivers/iio/light/apds9960.c
@@ -453,6 +453,7 @@
 			usleep_range(data->als_adc_int_us,
 				     APDS9960_MAX_INT_TIME_IN_US);
 	} else {
+		pm_runtime_mark_last_busy(dev);
 		ret = pm_runtime_put_autosuspend(dev);
 	}
 
diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
index 961f9f99..e544fcf 100644
--- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
+++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
@@ -130,10 +130,10 @@
 		if (ret < 0)
 			break;
 
-		/* return 0 since laser is likely pointed out of range */
+		/* return -EINVAL since laser is likely pointed out of range */
 		if (ret & LIDAR_REG_STATUS_INVALID) {
 			*reg = 0;
-			ret = 0;
+			ret = -EINVAL;
 			break;
 		}
 
@@ -197,7 +197,7 @@
 	if (!ret) {
 		iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
 						   iio_get_time_ns());
-	} else {
+	} else if (ret != -EINVAL) {
 		dev_err(&data->client->dev, "cannot read LIDAR measurement");
 	}
 
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 944cd90..d2d5d00 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1126,10 +1126,7 @@
 
 	rcu_read_lock();
 	err = fib_lookup(dev_net(net_dev), &fl4, &res, 0);
-	if (err)
-		return false;
-
-	ret = FIB_RES_DEV(res) == net_dev;
+	ret = err == 0 && FIB_RES_DEV(res) == net_dev;
 	rcu_read_unlock();
 
 	return ret;
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 8d8af7a..2281de1 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -1811,6 +1811,11 @@
 		if (qp_num == 0)
 			valid = 1;
 	} else {
+		/* CM attributes other than ClassPortInfo only use Send method */
+		if ((mad_hdr->mgmt_class == IB_MGMT_CLASS_CM) &&
+		    (mad_hdr->attr_id != IB_MGMT_CLASSPORTINFO_ATTR_ID) &&
+		    (mad_hdr->method != IB_MGMT_METHOD_SEND))
+			goto out;
 		/* Filter GSI packets sent to QP0 */
 		if (qp_num != 0)
 			valid = 1;
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 2aba774..a95a32b 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -512,7 +512,7 @@
 	return len;
 }
 
-static int ib_nl_send_msg(struct ib_sa_query *query)
+static int ib_nl_send_msg(struct ib_sa_query *query, gfp_t gfp_mask)
 {
 	struct sk_buff *skb = NULL;
 	struct nlmsghdr *nlh;
@@ -526,7 +526,7 @@
 	if (len <= 0)
 		return -EMSGSIZE;
 
-	skb = nlmsg_new(len, GFP_KERNEL);
+	skb = nlmsg_new(len, gfp_mask);
 	if (!skb)
 		return -ENOMEM;
 
@@ -544,7 +544,7 @@
 	/* Repair the nlmsg header length */
 	nlmsg_end(skb, nlh);
 
-	ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_LS, GFP_KERNEL);
+	ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_LS, gfp_mask);
 	if (!ret)
 		ret = len;
 	else
@@ -553,7 +553,7 @@
 	return ret;
 }
 
-static int ib_nl_make_request(struct ib_sa_query *query)
+static int ib_nl_make_request(struct ib_sa_query *query, gfp_t gfp_mask)
 {
 	unsigned long flags;
 	unsigned long delay;
@@ -562,25 +562,27 @@
 	INIT_LIST_HEAD(&query->list);
 	query->seq = (u32)atomic_inc_return(&ib_nl_sa_request_seq);
 
+	/* Put the request on the list first.*/
 	spin_lock_irqsave(&ib_nl_request_lock, flags);
-	ret = ib_nl_send_msg(query);
-	if (ret <= 0) {
-		ret = -EIO;
-		goto request_out;
-	} else {
-		ret = 0;
-	}
-
 	delay = msecs_to_jiffies(sa_local_svc_timeout_ms);
 	query->timeout = delay + jiffies;
 	list_add_tail(&query->list, &ib_nl_request_list);
 	/* Start the timeout if this is the only request */
 	if (ib_nl_request_list.next == &query->list)
 		queue_delayed_work(ib_nl_wq, &ib_nl_timed_work, delay);
-
-request_out:
 	spin_unlock_irqrestore(&ib_nl_request_lock, flags);
 
+	ret = ib_nl_send_msg(query, gfp_mask);
+	if (ret <= 0) {
+		ret = -EIO;
+		/* Remove the request */
+		spin_lock_irqsave(&ib_nl_request_lock, flags);
+		list_del(&query->list);
+		spin_unlock_irqrestore(&ib_nl_request_lock, flags);
+	} else {
+		ret = 0;
+	}
+
 	return ret;
 }
 
@@ -1108,7 +1110,7 @@
 
 	if (query->flags & IB_SA_ENABLE_LOCAL_SERVICE) {
 		if (!ibnl_chk_listeners(RDMA_NL_GROUP_LS)) {
-			if (!ib_nl_make_request(query))
+			if (!ib_nl_make_request(query, gfp_mask))
 				return id;
 		}
 		ib_sa_disable_local_svc(query);
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 94816ae..1c02dea 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -62,9 +62,11 @@
  * The ib_uobject locking scheme is as follows:
  *
  * - ib_uverbs_idr_lock protects the uverbs idrs themselves, so it
- *   needs to be held during all idr operations.  When an object is
+ *   needs to be held during all idr write operations.  When an object is
  *   looked up, a reference must be taken on the object's kref before
- *   dropping this lock.
+ *   dropping this lock.  For read operations, the rcu_read_lock()
+ *   and rcu_write_lock() but similarly the kref reference is grabbed
+ *   before the rcu_read_unlock().
  *
  * - Each object also has an rwsem.  This rwsem must be held for
  *   reading while an operation that uses the object is performed.
@@ -96,7 +98,7 @@
 
 static void release_uobj(struct kref *kref)
 {
-	kfree(container_of(kref, struct ib_uobject, ref));
+	kfree_rcu(container_of(kref, struct ib_uobject, ref), rcu);
 }
 
 static void put_uobj(struct ib_uobject *uobj)
@@ -145,7 +147,7 @@
 {
 	struct ib_uobject *uobj;
 
-	spin_lock(&ib_uverbs_idr_lock);
+	rcu_read_lock();
 	uobj = idr_find(idr, id);
 	if (uobj) {
 		if (uobj->context == context)
@@ -153,7 +155,7 @@
 		else
 			uobj = NULL;
 	}
-	spin_unlock(&ib_uverbs_idr_lock);
+	rcu_read_unlock();
 
 	return uobj;
 }
@@ -2446,6 +2448,7 @@
 	int                             i, sg_ind;
 	int				is_ud;
 	ssize_t                         ret = -EINVAL;
+	size_t                          next_size;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
@@ -2490,7 +2493,8 @@
 				goto out_put;
 			}
 
-			ud = alloc_wr(sizeof(*ud), user_wr->num_sge);
+			next_size = sizeof(*ud);
+			ud = alloc_wr(next_size, user_wr->num_sge);
 			if (!ud) {
 				ret = -ENOMEM;
 				goto out_put;
@@ -2511,7 +2515,8 @@
 			   user_wr->opcode == IB_WR_RDMA_READ) {
 			struct ib_rdma_wr *rdma;
 
-			rdma = alloc_wr(sizeof(*rdma), user_wr->num_sge);
+			next_size = sizeof(*rdma);
+			rdma = alloc_wr(next_size, user_wr->num_sge);
 			if (!rdma) {
 				ret = -ENOMEM;
 				goto out_put;
@@ -2525,7 +2530,8 @@
 			   user_wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) {
 			struct ib_atomic_wr *atomic;
 
-			atomic = alloc_wr(sizeof(*atomic), user_wr->num_sge);
+			next_size = sizeof(*atomic);
+			atomic = alloc_wr(next_size, user_wr->num_sge);
 			if (!atomic) {
 				ret = -ENOMEM;
 				goto out_put;
@@ -2540,7 +2546,8 @@
 		} else if (user_wr->opcode == IB_WR_SEND ||
 			   user_wr->opcode == IB_WR_SEND_WITH_IMM ||
 			   user_wr->opcode == IB_WR_SEND_WITH_INV) {
-			next = alloc_wr(sizeof(*next), user_wr->num_sge);
+			next_size = sizeof(*next);
+			next = alloc_wr(next_size, user_wr->num_sge);
 			if (!next) {
 				ret = -ENOMEM;
 				goto out_put;
@@ -2572,7 +2579,7 @@
 
 		if (next->num_sge) {
 			next->sg_list = (void *) next +
-				ALIGN(sizeof *next, sizeof (struct ib_sge));
+				ALIGN(next_size, sizeof(struct ib_sge));
 			if (copy_from_user(next->sg_list,
 					   buf + sizeof cmd +
 					   cmd.wr_count * cmd.wqe_size +
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 043a60e..545906d 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -1516,7 +1516,7 @@
  * @sg_nents:      number of entries in sg
  * @set_page:      driver page assignment function pointer
  *
- * Core service helper for drivers to covert the largest
+ * Core service helper for drivers to convert the largest
  * prefix of given sg list to a page vector. The sg list
  * prefix converted is the prefix that meet the requirements
  * of ib_map_mr_sg.
@@ -1533,7 +1533,7 @@
 	u64 last_end_dma_addr = 0, last_page_addr = 0;
 	unsigned int last_page_off = 0;
 	u64 page_mask = ~((u64)mr->page_size - 1);
-	int i;
+	int i, ret;
 
 	mr->iova = sg_dma_address(&sgl[0]);
 	mr->length = 0;
@@ -1544,27 +1544,29 @@
 		u64 end_dma_addr = dma_addr + dma_len;
 		u64 page_addr = dma_addr & page_mask;
 
-		if (i && page_addr != dma_addr) {
-			if (last_end_dma_addr != dma_addr) {
-				/* gap */
-				goto done;
+		/*
+		 * For the second and later elements, check whether either the
+		 * end of element i-1 or the start of element i is not aligned
+		 * on a page boundary.
+		 */
+		if (i && (last_page_off != 0 || page_addr != dma_addr)) {
+			/* Stop mapping if there is a gap. */
+			if (last_end_dma_addr != dma_addr)
+				break;
 
-			} else if (last_page_off + dma_len <= mr->page_size) {
-				/* chunk this fragment with the last */
-				mr->length += dma_len;
-				last_end_dma_addr += dma_len;
-				last_page_off += dma_len;
-				continue;
-			} else {
-				/* map starting from the next page */
-				page_addr = last_page_addr + mr->page_size;
-				dma_len -= mr->page_size - last_page_off;
-			}
+			/*
+			 * Coalesce this element with the last. If it is small
+			 * enough just update mr->length. Otherwise start
+			 * mapping from the next page.
+			 */
+			goto next_page;
 		}
 
 		do {
-			if (unlikely(set_page(mr, page_addr)))
-				goto done;
+			ret = set_page(mr, page_addr);
+			if (unlikely(ret < 0))
+				return i ? : ret;
+next_page:
 			page_addr += mr->page_size;
 		} while (page_addr < end_dma_addr);
 
@@ -1574,7 +1576,6 @@
 		last_page_off = end_dma_addr & ~page_mask;
 	}
 
-done:
 	return i;
 }
 EXPORT_SYMBOL(ib_sg_to_pages);
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index f567160..97d6878 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -456,7 +456,7 @@
 	props->max_qp_wr	   = dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE;
 	props->max_sge		   = min(dev->dev->caps.max_sq_sg,
 					 dev->dev->caps.max_rq_sg);
-	props->max_sge_rd = props->max_sge;
+	props->max_sge_rd	   = MLX4_MAX_SGE_RD;
 	props->max_cq		   = dev->dev->quotas.cq;
 	props->max_cqe		   = dev->dev->caps.max_cqes;
 	props->max_mr		   = dev->dev->quotas.mpt;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index a2e4ca5..13eaaf4 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -34,6 +34,7 @@
 #include <linux/log2.h>
 #include <linux/slab.h>
 #include <linux/netdevice.h>
+#include <linux/vmalloc.h>
 
 #include <rdma/ib_cache.h>
 #include <rdma/ib_pack.h>
@@ -795,8 +796,14 @@
 		if (err)
 			goto err_mtt;
 
-		qp->sq.wrid  = kmalloc(qp->sq.wqe_cnt * sizeof (u64), gfp);
-		qp->rq.wrid  = kmalloc(qp->rq.wqe_cnt * sizeof (u64), gfp);
+		qp->sq.wrid = kmalloc(qp->sq.wqe_cnt * sizeof(u64), gfp);
+		if (!qp->sq.wrid)
+			qp->sq.wrid = __vmalloc(qp->sq.wqe_cnt * sizeof(u64),
+						gfp, PAGE_KERNEL);
+		qp->rq.wrid = kmalloc(qp->rq.wqe_cnt * sizeof(u64), gfp);
+		if (!qp->rq.wrid)
+			qp->rq.wrid = __vmalloc(qp->rq.wqe_cnt * sizeof(u64),
+						gfp, PAGE_KERNEL);
 		if (!qp->sq.wrid || !qp->rq.wrid) {
 			err = -ENOMEM;
 			goto err_wrid;
@@ -886,8 +893,8 @@
 		if (qp_has_rq(init_attr))
 			mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db);
 	} else {
-		kfree(qp->sq.wrid);
-		kfree(qp->rq.wrid);
+		kvfree(qp->sq.wrid);
+		kvfree(qp->rq.wrid);
 	}
 
 err_mtt:
@@ -1062,8 +1069,8 @@
 					      &qp->db);
 		ib_umem_release(qp->umem);
 	} else {
-		kfree(qp->sq.wrid);
-		kfree(qp->rq.wrid);
+		kvfree(qp->sq.wrid);
+		kvfree(qp->rq.wrid);
 		if (qp->mlx4_ib_qp_type & (MLX4_IB_QPT_PROXY_SMI_OWNER |
 		    MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI))
 			free_proxy_bufs(&dev->ib_dev, qp);
diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
index dce5dfe..8d133c4 100644
--- a/drivers/infiniband/hw/mlx4/srq.c
+++ b/drivers/infiniband/hw/mlx4/srq.c
@@ -34,6 +34,7 @@
 #include <linux/mlx4/qp.h>
 #include <linux/mlx4/srq.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 #include "mlx4_ib.h"
 #include "user.h"
@@ -172,8 +173,12 @@
 
 		srq->wrid = kmalloc(srq->msrq.max * sizeof (u64), GFP_KERNEL);
 		if (!srq->wrid) {
-			err = -ENOMEM;
-			goto err_mtt;
+			srq->wrid = __vmalloc(srq->msrq.max * sizeof(u64),
+					      GFP_KERNEL, PAGE_KERNEL);
+			if (!srq->wrid) {
+				err = -ENOMEM;
+				goto err_mtt;
+			}
 		}
 	}
 
@@ -204,7 +209,7 @@
 	if (pd->uobject)
 		mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &srq->db);
 	else
-		kfree(srq->wrid);
+		kvfree(srq->wrid);
 
 err_mtt:
 	mlx4_mtt_cleanup(dev->dev, &srq->mtt);
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index ec8993a..6000f7a 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -381,7 +381,19 @@
 			}
 		}
 	} else if (ent->cur > 2 * ent->limit) {
-		if (!someone_adding(cache) &&
+		/*
+		 * The remove_keys() logic is performed as garbage collection
+		 * task. Such task is intended to be run when no other active
+		 * processes are running.
+		 *
+		 * The need_resched() will return TRUE if there are user tasks
+		 * to be activated in near future.
+		 *
+		 * In such case, we don't execute remove_keys() and postpone
+		 * the garbage collection work to try to run in next cycle,
+		 * in order to free CPU resources to other tasks.
+		 */
+		if (!need_resched() && !someone_adding(cache) &&
 		    time_after(jiffies, cache->last_add + 300 * HZ)) {
 			remove_keys(dev, i, 1);
 			if (ent->cur > ent->limit)
diff --git a/drivers/infiniband/hw/qib/qib_qsfp.c b/drivers/infiniband/hw/qib/qib_qsfp.c
index 5e27f76..4c7c3c8 100644
--- a/drivers/infiniband/hw/qib/qib_qsfp.c
+++ b/drivers/infiniband/hw/qib/qib_qsfp.c
@@ -292,7 +292,7 @@
 		qib_dev_porterr(ppd->dd, ppd->port,
 				"QSFP byte0 is 0x%02X, S/B 0x0C/D\n", peek[0]);
 
-	if ((peek[2] & 2) == 0) {
+	if ((peek[2] & 4) == 0) {
 		/*
 		 * If cable is paged, rather than "flat memory", we need to
 		 * set the page to zero, Even if it already appears to be zero.
@@ -538,7 +538,7 @@
 	sofar += scnprintf(buf + sofar, len - sofar, "Date:%.*s\n",
 			   QSFP_DATE_LEN, cd.date);
 	sofar += scnprintf(buf + sofar, len - sofar, "Lot:%.*s\n",
-			   QSFP_LOT_LEN, cd.date);
+			   QSFP_LOT_LEN, cd.lot);
 
 	while (bidx < QSFP_DEFAULT_HDR_CNT) {
 		int iidx;
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h
index 2baf5ad..bc803f3 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.h
+++ b/drivers/infiniband/hw/qib/qib_verbs.h
@@ -329,9 +329,9 @@
 struct qib_mr {
 	struct ib_mr ibmr;
 	struct ib_umem *umem;
-	struct qib_mregion mr;  /* must be last */
 	u64 *pages;
 	u32 npages;
+	struct qib_mregion mr;  /* must be last */
 };
 
 /*
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index a930702..42f4da6 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -1293,7 +1293,7 @@
 		if (mr_status.fail_status & IB_MR_CHECK_SIG_STATUS) {
 			sector_t sector_off = mr_status.sig_err.sig_err_offset;
 
-			do_div(sector_off, sector_size + 8);
+			sector_div(sector_off, sector_size + 8);
 			*sector = scsi_get_lba(iser_task->sc) + sector_off;
 
 			pr_err("PI error found type %d at sector %llx "
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index dfbbbb2..8a51c3b 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -157,16 +157,9 @@
 	attr.recv_cq = comp->cq;
 	attr.cap.max_send_wr = ISERT_QP_MAX_REQ_DTOS;
 	attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS + 1;
-	/*
-	 * FIXME: Use devattr.max_sge - 2 for max_send_sge as
-	 * work-around for RDMA_READs with ConnectX-2.
-	 *
-	 * Also, still make sure to have at least two SGEs for
-	 * outgoing control PDU responses.
-	 */
-	attr.cap.max_send_sge = max(2, device->dev_attr.max_sge - 2);
-	isert_conn->max_sge = attr.cap.max_send_sge;
-
+	attr.cap.max_send_sge = device->dev_attr.max_sge;
+	isert_conn->max_sge = min(device->dev_attr.max_sge,
+				  device->dev_attr.max_sge_rd);
 	attr.cap.max_recv_sge = 1;
 	attr.sq_sig_type = IB_SIGNAL_REQ_WR;
 	attr.qp_type = IB_QPT_RC;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 9909022..3db9a65 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -488,7 +488,7 @@
 	struct ib_qp *qp;
 	struct ib_fmr_pool *fmr_pool = NULL;
 	struct srp_fr_pool *fr_pool = NULL;
-	const int m = 1 + dev->use_fast_reg;
+	const int m = dev->use_fast_reg ? 3 : 1;
 	struct ib_cq_init_attr cq_attr = {};
 	int ret;
 
@@ -994,16 +994,16 @@
 
 	ret = srp_lookup_path(ch);
 	if (ret)
-		return ret;
+		goto out;
 
 	while (1) {
 		init_completion(&ch->done);
 		ret = srp_send_req(ch, multich);
 		if (ret)
-			return ret;
+			goto out;
 		ret = wait_for_completion_interruptible(&ch->done);
 		if (ret < 0)
-			return ret;
+			goto out;
 
 		/*
 		 * The CM event handling code will set status to
@@ -1011,15 +1011,16 @@
 		 * back, or SRP_DLID_REDIRECT if we get a lid/qp
 		 * redirect REJ back.
 		 */
-		switch (ch->status) {
+		ret = ch->status;
+		switch (ret) {
 		case 0:
 			ch->connected = true;
-			return 0;
+			goto out;
 
 		case SRP_PORT_REDIRECT:
 			ret = srp_lookup_path(ch);
 			if (ret)
-				return ret;
+				goto out;
 			break;
 
 		case SRP_DLID_REDIRECT:
@@ -1028,13 +1029,16 @@
 		case SRP_STALE_CONN:
 			shost_printk(KERN_ERR, target->scsi_host, PFX
 				     "giving up on stale connection\n");
-			ch->status = -ECONNRESET;
-			return ch->status;
+			ret = -ECONNRESET;
+			goto out;
 
 		default:
-			return ch->status;
+			goto out;
 		}
 	}
+
+out:
+	return ret <= 0 ? ret : -ENODEV;
 }
 
 static int srp_inv_rkey(struct srp_rdma_ch *ch, u32 rkey)
@@ -1309,7 +1313,7 @@
 }
 
 static int srp_map_finish_fr(struct srp_map_state *state,
-			     struct srp_rdma_ch *ch)
+			     struct srp_rdma_ch *ch, int sg_nents)
 {
 	struct srp_target_port *target = ch->target;
 	struct srp_device *dev = target->srp_host->srp_dev;
@@ -1324,10 +1328,10 @@
 
 	WARN_ON_ONCE(!dev->use_fast_reg);
 
-	if (state->sg_nents == 0)
+	if (sg_nents == 0)
 		return 0;
 
-	if (state->sg_nents == 1 && target->global_mr) {
+	if (sg_nents == 1 && target->global_mr) {
 		srp_map_desc(state, sg_dma_address(state->sg),
 			     sg_dma_len(state->sg),
 			     target->global_mr->rkey);
@@ -1341,8 +1345,7 @@
 	rkey = ib_inc_rkey(desc->mr->rkey);
 	ib_update_fast_reg_key(desc->mr, rkey);
 
-	n = ib_map_mr_sg(desc->mr, state->sg, state->sg_nents,
-			 dev->mr_page_size);
+	n = ib_map_mr_sg(desc->mr, state->sg, sg_nents, dev->mr_page_size);
 	if (unlikely(n < 0))
 		return n;
 
@@ -1448,16 +1451,15 @@
 	state->fr.next = req->fr_list;
 	state->fr.end = req->fr_list + ch->target->cmd_sg_cnt;
 	state->sg = scat;
-	state->sg_nents = scsi_sg_count(req->scmnd);
 
-	while (state->sg_nents) {
+	while (count) {
 		int i, n;
 
-		n = srp_map_finish_fr(state, ch);
+		n = srp_map_finish_fr(state, ch, count);
 		if (unlikely(n < 0))
 			return n;
 
-		state->sg_nents -= n;
+		count -= n;
 		for (i = 0; i < n; i++)
 			state->sg = sg_next(state->sg);
 	}
@@ -1517,10 +1519,12 @@
 
 	if (dev->use_fast_reg) {
 		state.sg = idb_sg;
-		state.sg_nents = 1;
 		sg_set_buf(idb_sg, req->indirect_desc, idb_len);
 		idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
-		ret = srp_map_finish_fr(&state, ch);
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+		idb_sg->dma_length = idb_sg->length;	      /* hack^2 */
+#endif
+		ret = srp_map_finish_fr(&state, ch, 1);
 		if (ret < 0)
 			return ret;
 	} else if (dev->use_fmr) {
@@ -1655,7 +1659,7 @@
 			return ret;
 		req->nmdesc++;
 	} else {
-		idb_rkey = target->global_mr->rkey;
+		idb_rkey = cpu_to_be32(target->global_mr->rkey);
 	}
 
 	indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 87a2a91..f6af531 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -300,10 +300,7 @@
 	dma_addr_t		base_dma_addr;
 	u32			dma_len;
 	u32			total_len;
-	union {
-		unsigned int	npages;
-		int		sg_nents;
-	};
+	unsigned int		npages;
 	unsigned int		nmdesc;
 	unsigned int		ndesc;
 };
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 932d073..da32609 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -592,6 +592,7 @@
 		return;
 	}
 
+	memset(&db9_parport_cb, 0, sizeof(db9_parport_cb));
 	db9_parport_cb.flags = PARPORT_FLAG_EXCL;
 
 	pd = parport_register_dev_model(pp, "db9", &db9_parport_cb, port_idx);
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 5a672dc..eae14d5 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -951,6 +951,7 @@
 	pads = gc_cfg[port_idx].args + 1;
 	n_pads = gc_cfg[port_idx].nargs - 1;
 
+	memset(&gc_parport_cb, 0, sizeof(gc_parport_cb));
 	gc_parport_cb.flags = PARPORT_FLAG_EXCL;
 
 	pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb,
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 9f5bca2..77f575d 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -181,6 +181,7 @@
 	n_buttons = tgfx_cfg[port_idx].args + 1;
 	n_devs = tgfx_cfg[port_idx].nargs - 1;
 
+	memset(&tgfx_parport_cb, 0, sizeof(tgfx_parport_cb));
 	tgfx_parport_cb.flags = PARPORT_FLAG_EXCL;
 
 	pd = parport_register_dev_model(pp, "turbografx", &tgfx_parport_cb,
diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c
index 9c07fe9..70a893a 100644
--- a/drivers/input/joystick/walkera0701.c
+++ b/drivers/input/joystick/walkera0701.c
@@ -218,6 +218,7 @@
 
 	w->parport = pp;
 
+	memset(&walkera0701_parport_cb, 0, sizeof(walkera0701_parport_cb));
 	walkera0701_parport_cb.flags = PARPORT_FLAG_EXCL;
 	walkera0701_parport_cb.irq_func = walkera0701_irq_handler;
 	walkera0701_parport_cb.private = w;
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
index 4bf6785..d5994a7 100644
--- a/drivers/input/misc/arizona-haptics.c
+++ b/drivers/input/misc/arizona-haptics.c
@@ -97,8 +97,7 @@
 
 		ret = regmap_update_bits(arizona->regmap,
 					 ARIZONA_HAPTICS_CONTROL_1,
-					 ARIZONA_HAP_CTRL_MASK,
-					 1 << ARIZONA_HAP_CTRL_SHIFT);
+					 ARIZONA_HAP_CTRL_MASK, 0);
 		if (ret != 0) {
 			dev_err(arizona->dev, "Failed to stop haptics: %d\n",
 				ret);
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 5e1665b..2f58985 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -41,6 +41,7 @@
 
 #define DRIVER_NAME		"elan_i2c"
 #define ELAN_DRIVER_VERSION	"1.6.1"
+#define ELAN_VENDOR_ID		0x04f3
 #define ETP_MAX_PRESSURE	255
 #define ETP_FWIDTH_REDUCE	90
 #define ETP_FINGER_WIDTH	15
@@ -914,6 +915,8 @@
 
 	input->name = "Elan Touchpad";
 	input->id.bustype = BUS_I2C;
+	input->id.vendor = ELAN_VENDOR_ID;
+	input->id.product = data->product_id;
 	input_set_drvdata(input, data);
 
 	error = input_mt_init_slots(input, ETP_MAX_FINGERS,
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
index 92c31b8..1edfac7 100644
--- a/drivers/input/serio/parkbd.c
+++ b/drivers/input/serio/parkbd.c
@@ -145,6 +145,7 @@
 {
 	struct pardev_cb parkbd_parport_cb;
 
+	memset(&parkbd_parport_cb, 0, sizeof(parkbd_parport_cb));
 	parkbd_parport_cb.irq_func = parkbd_interrupt;
 	parkbd_parport_cb.flags = PARPORT_FLAG_EXCL;
 
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index e7f966d..78ca448 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -1819,6 +1819,14 @@
 	input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
 	input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);
 
+	/* Verify that a device really has an endpoint */
+	if (intf->altsetting[0].desc.bNumEndpoints < 1) {
+		dev_err(&intf->dev,
+			"interface has %d endpoints, but must have minimum 1\n",
+			intf->altsetting[0].desc.bNumEndpoints);
+		err = -EINVAL;
+		goto fail3;
+	}
 	endpoint = &intf->altsetting[0].endpoint[0].desc;
 
 	/* Go set up our URB, which is called when the tablet receives
@@ -1861,6 +1869,7 @@
 	if (i == ARRAY_SIZE(speeds)) {
 		dev_info(&intf->dev,
 			 "Aiptek tried all speeds, no sane response\n");
+		err = -EINVAL;
 		goto fail3;
 	}
 
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index c562205..2d5794e 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2487,6 +2487,31 @@
 	{ }
 };
 
+static unsigned int chromebook_tp_buttons[] = {
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	BTN_LEFT
+};
+
+static struct mxt_acpi_platform_data chromebook_platform_data[] = {
+	{
+		/* Touchpad */
+		.hid	= "ATML0000",
+		.pdata	= {
+			.t19_num_keys	= ARRAY_SIZE(chromebook_tp_buttons),
+			.t19_keymap	= chromebook_tp_buttons,
+		},
+	},
+	{
+		/* Touchscreen */
+		.hid	= "ATML0001",
+	},
+	{ }
+};
+
 static const struct dmi_system_id mxt_dmi_table[] = {
 	{
 		/* 2015 Google Pixel */
@@ -2497,6 +2522,14 @@
 		},
 		.driver_data = samus_platform_data,
 	},
+	{
+		/* Other Google Chromebooks */
+		.ident = "Chromebook",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+		},
+		.driver_data = chromebook_platform_data,
+	},
 	{ }
 };
 
@@ -2701,6 +2734,7 @@
 	{ "qt602240_ts", 0 },
 	{ "atmel_mxt_ts", 0 },
 	{ "atmel_mxt_tp", 0 },
+	{ "maxtouch", 0 },
 	{ "mXT224", 0 },
 	{ }
 };
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index 17cc20e..ac09855 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -1316,7 +1316,13 @@
 
 	disable_irq(client->irq);
 
-	if (device_may_wakeup(dev) || ts->keep_power_in_suspend) {
+	if (device_may_wakeup(dev)) {
+		/*
+		 * The device will automatically enter idle mode
+		 * that has reduced power consumption.
+		 */
+		ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0);
+	} else if (ts->keep_power_in_suspend) {
 		for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
 			error = elants_i2c_send(client, set_sleep_cmd,
 						sizeof(set_sleep_cmd));
@@ -1326,10 +1332,6 @@
 			dev_err(&client->dev,
 				"suspend command failed: %d\n", error);
 		}
-
-		if (device_may_wakeup(dev))
-			ts->wake_irq_enabled =
-					(enable_irq_wake(client->irq) == 0);
 	} else {
 		elants_i2c_power_off(ts);
 	}
@@ -1345,10 +1347,11 @@
 	int retry_cnt;
 	int error;
 
-	if (device_may_wakeup(dev) && ts->wake_irq_enabled)
-		disable_irq_wake(client->irq);
-
-	if (ts->keep_power_in_suspend) {
+	if (device_may_wakeup(dev)) {
+		if (ts->wake_irq_enabled)
+			disable_irq_wake(client->irq);
+		elants_i2c_sw_reset(client);
+	} else if (ts->keep_power_in_suspend) {
 		for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
 			error = elants_i2c_send(client, set_active_cmd,
 						sizeof(set_active_cmd));
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index d21d4ed..7caf2fa 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -494,6 +494,22 @@
 	}
 }
 
+static bool access_error(struct vm_area_struct *vma, struct fault *fault)
+{
+	unsigned long requested = 0;
+
+	if (fault->flags & PPR_FAULT_EXEC)
+		requested |= VM_EXEC;
+
+	if (fault->flags & PPR_FAULT_READ)
+		requested |= VM_READ;
+
+	if (fault->flags & PPR_FAULT_WRITE)
+		requested |= VM_WRITE;
+
+	return (requested & ~vma->vm_flags) != 0;
+}
+
 static void do_fault(struct work_struct *work)
 {
 	struct fault *fault = container_of(work, struct fault, work);
@@ -516,8 +532,8 @@
 		goto out;
 	}
 
-	if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) {
-		/* handle_mm_fault would BUG_ON() */
+	/* Check if we have the right permissions on the vma */
+	if (access_error(vma, fault)) {
 		up_read(&mm->mmap_sem);
 		handle_fault_error(fault);
 		goto out;
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index f1042da..ac73876 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2159,7 +2159,7 @@
 			sg_res = aligned_nrpages(sg->offset, sg->length);
 			sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
 			sg->dma_length = sg->length;
-			pteval = (sg_phys(sg) & PAGE_MASK) | prot;
+			pteval = page_to_phys(sg_page(sg)) | prot;
 			phys_pfn = pteval >> VTD_PAGE_SHIFT;
 		}
 
@@ -3704,7 +3704,7 @@
 
 	for_each_sg(sglist, sg, nelems, i) {
 		BUG_ON(!sg_page(sg));
-		sg->dma_address = sg_phys(sg);
+		sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
 		sg->dma_length = sg->length;
 	}
 	return nelems;
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index c69e3f9..5046483 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -484,6 +484,23 @@
 };
 
 #define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10)
+
+static bool access_error(struct vm_area_struct *vma, struct page_req_dsc *req)
+{
+	unsigned long requested = 0;
+
+	if (req->exe_req)
+		requested |= VM_EXEC;
+
+	if (req->rd_req)
+		requested |= VM_READ;
+
+	if (req->wr_req)
+		requested |= VM_WRITE;
+
+	return (requested & ~vma->vm_flags) != 0;
+}
+
 static irqreturn_t prq_event_thread(int irq, void *d)
 {
 	struct intel_iommu *iommu = d;
@@ -539,6 +556,9 @@
 		if (!vma || address < vma->vm_start)
 			goto invalid;
 
+		if (access_error(vma, req))
+			goto invalid;
+
 		ret = handle_mm_fault(svm->mm, vma, address,
 				      req->wr_req ? FAULT_FLAG_WRITE : 0);
 		if (ret & VM_FAULT_ERROR)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index abae363..0e3b009 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1430,7 +1430,7 @@
 	min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap);
 
 	for_each_sg(sg, s, nents, i) {
-		phys_addr_t phys = sg_phys(s);
+		phys_addr_t phys = page_to_phys(sg_page(s)) + s->offset;
 
 		/*
 		 * We are mapping on IOMMU page boundaries, so offset within
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
index 598ab3f..cadf104 100644
--- a/drivers/irqchip/irq-versatile-fpga.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -210,7 +210,12 @@
 		parent_irq = -1;
 	}
 
+#ifdef CONFIG_ARCH_VERSATILE
+	fpga_irq_init(base, node->name, IRQ_SIC_START, parent_irq, valid_mask,
+				  node);
+#else
 	fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node);
+#endif
 
 	writel(clear_mask, base + IRQ_ENABLE_CLEAR);
 	writel(clear_mask, base + FIQ_ENABLE_CLEAR);
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index 375be50..2a506fe 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -67,8 +67,7 @@
 	struct sk_buff *skb = bcs->tx_skb;
 	int sent = -EOPNOTSUPP;
 
-	if (!tty || !tty->driver || !skb)
-		return -EINVAL;
+	WARN_ON(!tty || !tty->ops || !skb);
 
 	if (!skb->len) {
 		dev_kfree_skb_any(skb);
@@ -109,8 +108,7 @@
 	unsigned long flags;
 	int sent = 0;
 
-	if (!tty || !tty->driver)
-		return -EFAULT;
+	WARN_ON(!tty || !tty->ops);
 
 	cb = cs->cmdbuf;
 	if (!cb)
@@ -370,19 +368,18 @@
 	tasklet_kill(&cs->write_tasklet);
 	if (!cs->hw.ser)
 		return;
-	dev_set_drvdata(&cs->hw.ser->dev.dev, NULL);
 	platform_device_unregister(&cs->hw.ser->dev);
-	kfree(cs->hw.ser);
-	cs->hw.ser = NULL;
 }
 
 static void gigaset_device_release(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
+	struct cardstate *cs = dev_get_drvdata(dev);
 
-	/* adapted from platform_device_release() in drivers/base/platform.c */
-	kfree(dev->platform_data);
-	kfree(pdev->resource);
+	if (!cs)
+		return;
+	dev_set_drvdata(dev, NULL);
+	kfree(cs->hw.ser);
+	cs->hw.ser = NULL;
 }
 
 /*
@@ -432,7 +429,9 @@
 	struct tty_struct *tty = cs->hw.ser->tty;
 	unsigned int set, clear;
 
-	if (!tty || !tty->driver || !tty->ops->tiocmset)
+	WARN_ON(!tty || !tty->ops);
+	/* tiocmset is an optional tty driver method */
+	if (!tty->ops->tiocmset)
 		return -EINVAL;
 	set = new_state & ~old_state;
 	clear = old_state & ~new_state;
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index a77eea5..cb428b9 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -1170,7 +1170,7 @@
 
 	if (ipac->type & IPAC_TYPE_IPACX) {
 		ista = ReadIPAC(ipac, ISACX_ISTA);
-		while (ista && cnt--) {
+		while (ista && --cnt) {
 			pr_debug("%s: ISTA %02x\n", ipac->name, ista);
 			if (ista & IPACX__ICA)
 				ipac_irq(&ipac->hscx[0], ista);
@@ -1182,7 +1182,7 @@
 		}
 	} else if (ipac->type & IPAC_TYPE_IPAC) {
 		ista = ReadIPAC(ipac, IPAC_ISTA);
-		while (ista && cnt--) {
+		while (ista && --cnt) {
 			pr_debug("%s: ISTA %02x\n", ipac->name, ista);
 			if (ista & (IPAC__ICD | IPAC__EXD)) {
 				istad = ReadISAC(isac, ISAC_ISTA);
@@ -1200,7 +1200,7 @@
 			ista = ReadIPAC(ipac, IPAC_ISTA);
 		}
 	} else if (ipac->type & IPAC_TYPE_HSCX) {
-		while (cnt) {
+		while (--cnt) {
 			ista = ReadIPAC(ipac, IPAC_ISTAB + ipac->hscx[1].off);
 			pr_debug("%s: B2 ISTA %02x\n", ipac->name, ista);
 			if (ista)
@@ -1211,7 +1211,6 @@
 				mISDNisac_irq(isac, istad);
 			if (0 == (ista | istad))
 				break;
-			cnt--;
 		}
 	}
 	if (cnt > maxloop) /* only for ISAC/HSCX without PCI IRQ test */
diff --git a/drivers/lightnvm/Kconfig b/drivers/lightnvm/Kconfig
index a16bf56..85a3390 100644
--- a/drivers/lightnvm/Kconfig
+++ b/drivers/lightnvm/Kconfig
@@ -18,6 +18,7 @@
 
 config NVM_DEBUG
 	bool "Open-Channel SSD debugging support"
+	default n
 	---help---
 	Exposes a debug management interface to create/remove targets at:
 
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 86ce887..8f41b24 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -74,7 +74,7 @@
 void *nvm_dev_dma_alloc(struct nvm_dev *dev, gfp_t mem_flags,
 							dma_addr_t *dma_handler)
 {
-	return dev->ops->dev_dma_alloc(dev->q, dev->ppalist_pool, mem_flags,
+	return dev->ops->dev_dma_alloc(dev, dev->ppalist_pool, mem_flags,
 								dma_handler);
 }
 EXPORT_SYMBOL(nvm_dev_dma_alloc);
@@ -97,15 +97,47 @@
 	return NULL;
 }
 
+struct nvmm_type *nvm_init_mgr(struct nvm_dev *dev)
+{
+	struct nvmm_type *mt;
+	int ret;
+
+	lockdep_assert_held(&nvm_lock);
+
+	list_for_each_entry(mt, &nvm_mgrs, list) {
+		ret = mt->register_mgr(dev);
+		if (ret < 0) {
+			pr_err("nvm: media mgr failed to init (%d) on dev %s\n",
+								ret, dev->name);
+			return NULL; /* initialization failed */
+		} else if (ret > 0)
+			return mt;
+	}
+
+	return NULL;
+}
+
 int nvm_register_mgr(struct nvmm_type *mt)
 {
+	struct nvm_dev *dev;
 	int ret = 0;
 
 	down_write(&nvm_lock);
-	if (nvm_find_mgr_type(mt->name))
+	if (nvm_find_mgr_type(mt->name)) {
 		ret = -EEXIST;
-	else
+		goto finish;
+	} else {
 		list_add(&mt->list, &nvm_mgrs);
+	}
+
+	/* try to register media mgr if any device have none configured */
+	list_for_each_entry(dev, &nvm_devices, devices) {
+		if (dev->mt)
+			continue;
+
+		dev->mt = nvm_init_mgr(dev);
+	}
+finish:
 	up_write(&nvm_lock);
 
 	return ret;
@@ -123,26 +155,6 @@
 }
 EXPORT_SYMBOL(nvm_unregister_mgr);
 
-/* register with device with a supported manager */
-static int register_mgr(struct nvm_dev *dev)
-{
-	struct nvmm_type *mt;
-	int ret = 0;
-
-	list_for_each_entry(mt, &nvm_mgrs, list) {
-		ret = mt->register_mgr(dev);
-		if (ret > 0) {
-			dev->mt = mt;
-			break; /* successfully initialized */
-		}
-	}
-
-	if (!ret)
-		pr_info("nvm: no compatible nvm manager found.\n");
-
-	return ret;
-}
-
 static struct nvm_dev *nvm_find_nvm_dev(const char *name)
 {
 	struct nvm_dev *dev;
@@ -246,7 +258,7 @@
 	if (!dev->q || !dev->ops)
 		return ret;
 
-	if (dev->ops->identity(dev->q, &dev->identity)) {
+	if (dev->ops->identity(dev, &dev->identity)) {
 		pr_err("nvm: device could not be identified\n");
 		goto err;
 	}
@@ -271,14 +283,6 @@
 		goto err;
 	}
 
-	down_write(&nvm_lock);
-	ret = register_mgr(dev);
-	up_write(&nvm_lock);
-	if (ret < 0)
-		goto err;
-	if (!ret)
-		return 0;
-
 	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
 			dev->name, dev->sec_per_pg, dev->nr_planes,
 			dev->pgs_per_blk, dev->blks_per_lun, dev->nr_luns,
@@ -326,8 +330,7 @@
 	}
 
 	if (dev->ops->max_phys_sect > 1) {
-		dev->ppalist_pool = dev->ops->create_dma_pool(dev->q,
-								"ppalist");
+		dev->ppalist_pool = dev->ops->create_dma_pool(dev, "ppalist");
 		if (!dev->ppalist_pool) {
 			pr_err("nvm: could not create ppa pool\n");
 			ret = -ENOMEM;
@@ -335,7 +338,9 @@
 		}
 	}
 
+	/* register device with a supported media manager */
 	down_write(&nvm_lock);
+	dev->mt = nvm_init_mgr(dev);
 	list_add(&dev->devices, &nvm_devices);
 	up_write(&nvm_lock);
 
@@ -380,19 +385,13 @@
 	struct nvm_tgt_type *tt;
 	struct nvm_target *t;
 	void *targetdata;
-	int ret = 0;
 
-	down_write(&nvm_lock);
 	if (!dev->mt) {
-		ret = register_mgr(dev);
-		if (!ret)
-			ret = -ENODEV;
-		if (ret < 0) {
-			up_write(&nvm_lock);
-			return ret;
-		}
+		pr_info("nvm: device has no media manager registered.\n");
+		return -ENODEV;
 	}
 
+	down_write(&nvm_lock);
 	tt = nvm_find_target_type(create->tgttype);
 	if (!tt) {
 		pr_err("nvm: target type %s not found\n", create->tgttype);
diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c
index 35dde84..f434e89 100644
--- a/drivers/lightnvm/gennvm.c
+++ b/drivers/lightnvm/gennvm.c
@@ -195,7 +195,7 @@
 	}
 
 	if (dev->ops->get_l2p_tbl) {
-		ret = dev->ops->get_l2p_tbl(dev->q, 0, dev->total_pages,
+		ret = dev->ops->get_l2p_tbl(dev, 0, dev->total_pages,
 							gennvm_block_map, dev);
 		if (ret) {
 			pr_err("gennvm: could not read L2P table.\n");
@@ -219,6 +219,9 @@
 	struct gen_nvm *gn;
 	int ret;
 
+	if (!try_module_get(THIS_MODULE))
+		return -ENODEV;
+
 	gn = kzalloc(sizeof(struct gen_nvm), GFP_KERNEL);
 	if (!gn)
 		return -ENOMEM;
@@ -242,12 +245,14 @@
 	return 1;
 err:
 	gennvm_free(dev);
+	module_put(THIS_MODULE);
 	return ret;
 }
 
 static void gennvm_unregister(struct nvm_dev *dev)
 {
 	gennvm_free(dev);
+	module_put(THIS_MODULE);
 }
 
 static struct nvm_block *gennvm_get_blk(struct nvm_dev *dev,
@@ -262,14 +267,11 @@
 	if (list_empty(&lun->free_list)) {
 		pr_err_ratelimited("gennvm: lun %u have no free pages available",
 								lun->vlun.id);
-		spin_unlock(&vlun->lock);
 		goto out;
 	}
 
-	while (!is_gc && lun->vlun.nr_free_blocks < lun->reserved_blocks) {
-		spin_unlock(&vlun->lock);
+	if (!is_gc && lun->vlun.nr_free_blocks < lun->reserved_blocks)
 		goto out;
-	}
 
 	blk = list_first_entry(&lun->free_list, struct nvm_block, list);
 	list_move_tail(&blk->list, &lun->used_list);
@@ -278,8 +280,8 @@
 	lun->vlun.nr_free_blocks--;
 	lun->vlun.nr_inuse_blocks++;
 
-	spin_unlock(&vlun->lock);
 out:
+	spin_unlock(&vlun->lock);
 	return blk;
 }
 
@@ -349,7 +351,7 @@
 	gennvm_generic_to_addr_mode(dev, rqd);
 
 	rqd->dev = dev;
-	return dev->ops->submit_io(dev->q, rqd);
+	return dev->ops->submit_io(dev, rqd);
 }
 
 static void gennvm_blk_set_type(struct nvm_dev *dev, struct ppa_addr *ppa,
@@ -385,7 +387,7 @@
 	if (!dev->ops->set_bb_tbl)
 		return;
 
-	if (dev->ops->set_bb_tbl(dev->q, rqd, 1))
+	if (dev->ops->set_bb_tbl(dev, rqd, 1))
 		return;
 
 	gennvm_addr_to_generic_mode(dev, rqd);
@@ -453,7 +455,7 @@
 
 	gennvm_generic_to_addr_mode(dev, &rqd);
 
-	ret = dev->ops->erase_block(dev->q, &rqd);
+	ret = dev->ops->erase_block(dev, &rqd);
 
 	if (plane_cnt)
 		nvm_dev_dma_free(dev, rqd.ppa_list, rqd.dma_ppa_list);
diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
index 75e59c3..134e4fa 100644
--- a/drivers/lightnvm/rrpc.c
+++ b/drivers/lightnvm/rrpc.c
@@ -182,7 +182,7 @@
 	struct nvm_block *blk;
 	struct rrpc_block *rblk;
 
-	blk = nvm_get_blk(rrpc->dev, rlun->parent, 0);
+	blk = nvm_get_blk(rrpc->dev, rlun->parent, flags);
 	if (!blk)
 		return NULL;
 
@@ -202,6 +202,20 @@
 	nvm_put_blk(rrpc->dev, rblk->parent);
 }
 
+static void rrpc_put_blks(struct rrpc *rrpc)
+{
+	struct rrpc_lun *rlun;
+	int i;
+
+	for (i = 0; i < rrpc->nr_luns; i++) {
+		rlun = &rrpc->luns[i];
+		if (rlun->cur)
+			rrpc_put_blk(rrpc, rlun->cur);
+		if (rlun->gc_cur)
+			rrpc_put_blk(rrpc, rlun->gc_cur);
+	}
+}
+
 static struct rrpc_lun *get_next_lun(struct rrpc *rrpc)
 {
 	int next = atomic_inc_return(&rrpc->next_lun);
@@ -1002,7 +1016,7 @@
 		return 0;
 
 	/* Bring up the mapping table from device */
-	ret = dev->ops->get_l2p_tbl(dev->q, 0, dev->total_pages,
+	ret = dev->ops->get_l2p_tbl(dev, 0, dev->total_pages,
 							rrpc_l2p_update, rrpc);
 	if (ret) {
 		pr_err("nvm: rrpc: could not read L2P table.\n");
@@ -1224,18 +1238,21 @@
 
 		rblk = rrpc_get_blk(rrpc, rlun, 0);
 		if (!rblk)
-			return -EINVAL;
+			goto err;
 
 		rrpc_set_lun_cur(rlun, rblk);
 
 		/* Emergency gc block */
 		rblk = rrpc_get_blk(rrpc, rlun, 1);
 		if (!rblk)
-			return -EINVAL;
+			goto err;
 		rlun->gc_cur = rblk;
 	}
 
 	return 0;
+err:
+	rrpc_put_blks(rrpc);
+	return -EINVAL;
 }
 
 static struct nvm_tgt_type tt_rrpc;
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 1fa4569..c219a05 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1207,6 +1207,12 @@
 	dm_block_t held_root;
 
 	/*
+	 * We commit to ensure the btree roots which we increment in a
+	 * moment are up to date.
+	 */
+	__commit_transaction(pmd);
+
+	/*
 	 * Copy the superblock.
 	 */
 	dm_sm_inc_block(pmd->metadata_sm, THIN_SUPERBLOCK_LOCATION);
@@ -1538,7 +1544,7 @@
 static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_t end)
 {
 	int r;
-	unsigned count;
+	unsigned count, total_count = 0;
 	struct dm_pool_metadata *pmd = td->pmd;
 	dm_block_t keys[1] = { td->id };
 	__le64 value;
@@ -1561,11 +1567,29 @@
 	if (r)
 		return r;
 
-	r = dm_btree_remove_leaves(&pmd->bl_info, mapping_root, &begin, end, &mapping_root, &count);
-	if (r)
-		return r;
+	/*
+	 * Remove leaves stops at the first unmapped entry, so we have to
+	 * loop round finding mapped ranges.
+	 */
+	while (begin < end) {
+		r = dm_btree_lookup_next(&pmd->bl_info, mapping_root, &begin, &begin, &value);
+		if (r == -ENODATA)
+			break;
 
-	td->mapped_blocks -= count;
+		if (r)
+			return r;
+
+		if (begin >= end)
+			break;
+
+		r = dm_btree_remove_leaves(&pmd->bl_info, mapping_root, &begin, end, &mapping_root, &count);
+		if (r)
+			return r;
+
+		total_count += count;
+	}
+
+	td->mapped_blocks -= total_count;
 	td->changed = 1;
 
 	/*
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 807095f..dbedc58 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -314,8 +314,8 @@
  */
 void mddev_suspend(struct mddev *mddev)
 {
-	BUG_ON(mddev->suspended);
-	mddev->suspended = 1;
+	if (mddev->suspended++)
+		return;
 	synchronize_rcu();
 	wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);
 	mddev->pers->quiesce(mddev, 1);
@@ -326,7 +326,8 @@
 
 void mddev_resume(struct mddev *mddev)
 {
-	mddev->suspended = 0;
+	if (--mddev->suspended)
+		return;
 	wake_up(&mddev->sb_wait);
 	mddev->pers->quiesce(mddev, 0);
 
@@ -1652,7 +1653,7 @@
 			rdev->journal_tail = le64_to_cpu(sb->journal_tail);
 			if (mddev->recovery_cp == MaxSector)
 				set_bit(MD_JOURNAL_CLEAN, &mddev->flags);
-			rdev->raid_disk = mddev->raid_disks;
+			rdev->raid_disk = 0;
 			break;
 		default:
 			rdev->saved_raid_disk = role;
@@ -2773,6 +2774,7 @@
 		/* Activating a spare .. or possibly reactivating
 		 * if we ever get bitmaps working here.
 		 */
+		int err;
 
 		if (rdev->raid_disk != -1)
 			return -EBUSY;
@@ -2794,9 +2796,15 @@
 			rdev->saved_raid_disk = -1;
 		clear_bit(In_sync, &rdev->flags);
 		clear_bit(Bitmap_sync, &rdev->flags);
-		remove_and_add_spares(rdev->mddev, rdev);
-		if (rdev->raid_disk == -1)
-			return -EBUSY;
+		err = rdev->mddev->pers->
+			hot_add_disk(rdev->mddev, rdev);
+		if (err) {
+			rdev->raid_disk = -1;
+			return err;
+		} else
+			sysfs_notify_dirent_safe(rdev->sysfs_state);
+		if (sysfs_link_rdev(rdev->mddev, rdev))
+			/* failure here is OK */;
 		/* don't wakeup anyone, leave that to userspace. */
 	} else {
 		if (slot >= rdev->mddev->raid_disks &&
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 2bea51e..ca0b643 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -566,7 +566,9 @@
 static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char nm[20];
-	if (!test_bit(Replacement, &rdev->flags) && mddev->kobj.sd) {
+	if (!test_bit(Replacement, &rdev->flags) &&
+	    !test_bit(Journal, &rdev->flags) &&
+	    mddev->kobj.sd) {
 		sprintf(nm, "rd%d", rdev->raid_disk);
 		return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
 	} else
@@ -576,7 +578,9 @@
 static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev)
 {
 	char nm[20];
-	if (!test_bit(Replacement, &rdev->flags) && mddev->kobj.sd) {
+	if (!test_bit(Replacement, &rdev->flags) &&
+	    !test_bit(Journal, &rdev->flags) &&
+	    mddev->kobj.sd) {
 		sprintf(nm, "rd%d", rdev->raid_disk);
 		sysfs_remove_link(&mddev->kobj, nm);
 	}
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
index c573402..b1ced58 100644
--- a/drivers/md/persistent-data/dm-btree.c
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -63,6 +63,11 @@
 	return bsearch(n, key, 0);
 }
 
+static int upper_bound(struct btree_node *n, uint64_t key)
+{
+	return bsearch(n, key, 1);
+}
+
 void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
 		  struct dm_btree_value_type *vt)
 {
@@ -252,6 +257,16 @@
 	dm_tm_unlock(s->tm, f->b);
 }
 
+static void unlock_all_frames(struct del_stack *s)
+{
+	struct frame *f;
+
+	while (unprocessed_frames(s)) {
+		f = s->spine + s->top--;
+		dm_tm_unlock(s->tm, f->b);
+	}
+}
+
 int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
 {
 	int r;
@@ -308,9 +323,13 @@
 			pop_frame(s);
 		}
 	}
-
 out:
+	if (r) {
+		/* cleanup all frames of del_stack */
+		unlock_all_frames(s);
+	}
 	kfree(s);
+
 	return r;
 }
 EXPORT_SYMBOL_GPL(dm_btree_del);
@@ -392,6 +411,82 @@
 }
 EXPORT_SYMBOL_GPL(dm_btree_lookup);
 
+static int dm_btree_lookup_next_single(struct dm_btree_info *info, dm_block_t root,
+				       uint64_t key, uint64_t *rkey, void *value_le)
+{
+	int r, i;
+	uint32_t flags, nr_entries;
+	struct dm_block *node;
+	struct btree_node *n;
+
+	r = bn_read_lock(info, root, &node);
+	if (r)
+		return r;
+
+	n = dm_block_data(node);
+	flags = le32_to_cpu(n->header.flags);
+	nr_entries = le32_to_cpu(n->header.nr_entries);
+
+	if (flags & INTERNAL_NODE) {
+		i = lower_bound(n, key);
+		if (i < 0 || i >= nr_entries) {
+			r = -ENODATA;
+			goto out;
+		}
+
+		r = dm_btree_lookup_next_single(info, value64(n, i), key, rkey, value_le);
+		if (r == -ENODATA && i < (nr_entries - 1)) {
+			i++;
+			r = dm_btree_lookup_next_single(info, value64(n, i), key, rkey, value_le);
+		}
+
+	} else {
+		i = upper_bound(n, key);
+		if (i < 0 || i >= nr_entries) {
+			r = -ENODATA;
+			goto out;
+		}
+
+		*rkey = le64_to_cpu(n->keys[i]);
+		memcpy(value_le, value_ptr(n, i), info->value_type.size);
+	}
+out:
+	dm_tm_unlock(info->tm, node);
+	return r;
+}
+
+int dm_btree_lookup_next(struct dm_btree_info *info, dm_block_t root,
+			 uint64_t *keys, uint64_t *rkey, void *value_le)
+{
+	unsigned level;
+	int r = -ENODATA;
+	__le64 internal_value_le;
+	struct ro_spine spine;
+
+	init_ro_spine(&spine, info);
+	for (level = 0; level < info->levels - 1u; level++) {
+		r = btree_lookup_raw(&spine, root, keys[level],
+				     lower_bound, rkey,
+				     &internal_value_le, sizeof(uint64_t));
+		if (r)
+			goto out;
+
+		if (*rkey != keys[level]) {
+			r = -ENODATA;
+			goto out;
+		}
+
+		root = le64_to_cpu(internal_value_le);
+	}
+
+	r = dm_btree_lookup_next_single(info, root, keys[level], rkey, value_le);
+out:
+	exit_ro_spine(&spine);
+	return r;
+}
+
+EXPORT_SYMBOL_GPL(dm_btree_lookup_next);
+
 /*
  * Splits a node by creating a sibling node and shifting half the nodes
  * contents across.  Assumes there is a parent node, and it has room for
@@ -473,8 +568,10 @@
 
 	r = insert_at(sizeof(__le64), pn, parent_index + 1,
 		      le64_to_cpu(rn->keys[0]), &location);
-	if (r)
+	if (r) {
+		unlock_block(s->info, right);
 		return r;
+	}
 
 	if (key < le64_to_cpu(rn->keys[0])) {
 		unlock_block(s->info, right);
diff --git a/drivers/md/persistent-data/dm-btree.h b/drivers/md/persistent-data/dm-btree.h
index 11d8cf7..c74301f 100644
--- a/drivers/md/persistent-data/dm-btree.h
+++ b/drivers/md/persistent-data/dm-btree.h
@@ -110,6 +110,13 @@
 		    uint64_t *keys, void *value_le);
 
 /*
+ * Tries to find the first key where the bottom level key is >= to that
+ * given.  Useful for skipping empty sections of the btree.
+ */
+int dm_btree_lookup_next(struct dm_btree_info *info, dm_block_t root,
+			 uint64_t *keys, uint64_t *rkey, void *value_le);
+
+/*
  * Insertion (or overwrite an existing value).  O(ln(n))
  */
 int dm_btree_insert(struct dm_btree_info *info, dm_block_t root,
@@ -135,9 +142,10 @@
 		    uint64_t *keys, dm_block_t *new_root);
 
 /*
- * Removes values between 'keys' and keys2, where keys2 is keys with the
- * final key replaced with 'end_key'.  'end_key' is the one-past-the-end
- * value.  'keys' may be altered.
+ * Removes a _contiguous_ run of values starting from 'keys' and not
+ * reaching keys2 (where keys2 is keys with the final key replaced with
+ * 'end_key').  'end_key' is the one-past-the-end value.  'keys' may be
+ * altered.
  */
 int dm_btree_remove_leaves(struct dm_btree_info *info, dm_block_t root,
 			   uint64_t *keys, uint64_t end_key,
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c
index 5309129..fca6dbc 100644
--- a/drivers/md/persistent-data/dm-space-map-metadata.c
+++ b/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -136,7 +136,7 @@
 	return 0;
 }
 
-static int brb_pop(struct bop_ring_buffer *brb, struct block_op *result)
+static int brb_peek(struct bop_ring_buffer *brb, struct block_op *result)
 {
 	struct block_op *bop;
 
@@ -147,6 +147,17 @@
 	result->type = bop->type;
 	result->block = bop->block;
 
+	return 0;
+}
+
+static int brb_pop(struct bop_ring_buffer *brb)
+{
+	struct block_op *bop;
+
+	if (brb_empty(brb))
+		return -ENODATA;
+
+	bop = brb->bops + brb->begin;
 	brb->begin = brb_next(brb, brb->begin);
 
 	return 0;
@@ -211,7 +222,7 @@
 	while (!brb_empty(&smm->uncommitted)) {
 		struct block_op bop;
 
-		r = brb_pop(&smm->uncommitted, &bop);
+		r = brb_peek(&smm->uncommitted, &bop);
 		if (r) {
 			DMERR("bug in bop ring buffer");
 			break;
@@ -220,6 +231,8 @@
 		r = commit_bop(smm, &bop);
 		if (r)
 			break;
+
+		brb_pop(&smm->uncommitted);
 	}
 
 	return r;
@@ -683,7 +696,6 @@
 static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
 {
 	int r, i;
-	enum allocation_event ev;
 	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 	dm_block_t old_len = smm->ll.nr_blocks;
 
@@ -705,11 +717,12 @@
 	 * allocate any new blocks.
 	 */
 	do {
-		for (i = old_len; !r && i < smm->begin; i++) {
-			r = sm_ll_inc(&smm->ll, i, &ev);
-			if (r)
-				goto out;
-		}
+		for (i = old_len; !r && i < smm->begin; i++)
+			r = add_bop(smm, BOP_INC, i);
+
+		if (r)
+			goto out;
+
 		old_len = smm->begin;
 
 		r = apply_bops(smm);
@@ -754,7 +767,6 @@
 {
 	int r;
 	dm_block_t i;
-	enum allocation_event ev;
 	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
 	smm->begin = superblock + 1;
@@ -782,7 +794,7 @@
 	 * allocated blocks that they were built from.
 	 */
 	for (i = superblock; !r && i < smm->begin; i++)
-		r = sm_ll_inc(&smm->ll, i, &ev);
+		r = add_bop(smm, BOP_INC, i);
 
 	if (r)
 		return r;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 41d70bc..84e597e 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1946,6 +1946,8 @@
 
 	first = i;
 	fbio = r10_bio->devs[i].bio;
+	fbio->bi_iter.bi_size = r10_bio->sectors << 9;
+	fbio->bi_iter.bi_idx = 0;
 
 	vcnt = (r10_bio->sectors + (PAGE_SIZE >> 9) - 1) >> (PAGE_SHIFT - 9);
 	/* now find blocks with errors */
@@ -1989,7 +1991,7 @@
 		bio_reset(tbio);
 
 		tbio->bi_vcnt = vcnt;
-		tbio->bi_iter.bi_size = r10_bio->sectors << 9;
+		tbio->bi_iter.bi_size = fbio->bi_iter.bi_size;
 		tbio->bi_rw = WRITE;
 		tbio->bi_private = r10_bio;
 		tbio->bi_iter.bi_sector = r10_bio->devs[i].addr;
diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c
index 8616fa8..c2e60b4 100644
--- a/drivers/media/pci/ivtv/ivtv-driver.c
+++ b/drivers/media/pci/ivtv/ivtv-driver.c
@@ -805,11 +805,11 @@
 {
 	int i;
 
-	for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS - 1; i++)
+	for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++)
 		if (itv->card->video_inputs[i].video_type == 0)
 			break;
 	itv->nof_inputs = i;
-	for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS - 1; i++)
+	for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++)
 		if (itv->card->audio_inputs[i].audio_type == 0)
 			break;
 	itv->nof_audio_inputs = i;
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
index fcbb497..565a593 100644
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -134,7 +134,7 @@
 	int            urbs_submitted;
 
 	/* USB control message buffer */
-	#define BUF_SIZE 24
+	#define BUF_SIZE 128
 	u8 buf[BUF_SIZE];
 
 	/* Current configuration */
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index e05bfec..0fe5cb2 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -24,6 +24,15 @@
 #include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
 
+/*
+ * Used Avago MGA-81563 RF amplifier could be destroyed pretty easily with too
+ * strong signal or transmitting to bad antenna.
+ * Set RF gain control to 'grabbed' state by default for sure.
+ */
+static bool hackrf_enable_rf_gain_ctrl;
+module_param_named(enable_rf_gain_ctrl, hackrf_enable_rf_gain_ctrl, bool, 0644);
+MODULE_PARM_DESC(enable_rf_gain_ctrl, "enable RX/TX RF amplifier control (warn: could damage amplifier)");
+
 /* HackRF USB API commands (from HackRF Library) */
 enum {
 	CMD_SET_TRANSCEIVER_MODE           = 0x01,
@@ -1451,6 +1460,7 @@
 		dev_err(dev->dev, "Could not initialize controls\n");
 		goto err_v4l2_ctrl_handler_free_rx;
 	}
+	v4l2_ctrl_grab(dev->rx_rf_gain, !hackrf_enable_rf_gain_ctrl);
 	v4l2_ctrl_handler_setup(&dev->rx_ctrl_handler);
 
 	/* Register controls for transmitter */
@@ -1471,6 +1481,7 @@
 		dev_err(dev->dev, "Could not initialize controls\n");
 		goto err_v4l2_ctrl_handler_free_tx;
 	}
+	v4l2_ctrl_grab(dev->tx_rf_gain, !hackrf_enable_rf_gain_ctrl);
 	v4l2_ctrl_handler_setup(&dev->tx_ctrl_handler);
 
 	/* Register the v4l2_device structure */
@@ -1530,7 +1541,7 @@
 err_kfree:
 	kfree(dev);
 err:
-	dev_dbg(dev->dev, "failed=%d\n", ret);
+	dev_dbg(&intf->dev, "failed=%d\n", ret);
 	return ret;
 }
 
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index d2e75c8..f409097 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -497,6 +497,7 @@
 {
 	u64 sr = 0;
 
+	set_endian(sr);
 	if (ctx->master)
 		sr |= CXL_PSL_SR_An_MP;
 	if (mfspr(SPRN_LPCR) & LPCR_TC)
@@ -506,7 +507,6 @@
 		sr |= CXL_PSL_SR_An_HV;
 	} else {
 		sr |= CXL_PSL_SR_An_PR | CXL_PSL_SR_An_R;
-		set_endian(sr);
 		sr &= ~(CXL_PSL_SR_An_HV);
 		if (!test_tsk_thread_flag(current, TIF_32BIT))
 			sr |= CXL_PSL_SR_An_SF;
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 669c345..9ed6038 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -46,10 +46,18 @@
 
 	ofpart_node = of_get_child_by_name(mtd_node, "partitions");
 	if (!ofpart_node) {
-		pr_warn("%s: 'partitions' subnode not found on %s. Trying to parse direct subnodes as partitions.\n",
-			master->name, mtd_node->full_name);
+		/*
+		 * We might get here even when ofpart isn't used at all (e.g.,
+		 * when using another parser), so don't be louder than
+		 * KERN_DEBUG
+		 */
+		pr_debug("%s: 'partitions' subnode not found on %s. Trying to parse direct subnodes as partitions.\n",
+			 master->name, mtd_node->full_name);
 		ofpart_node = mtd_node;
 		dedicated = false;
+	} else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) {
+		/* The 'partitions' subnode might be used by another parser */
+		return 0;
 	}
 
 	/* First count the subnodes */
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 970781a..f6a7161 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1849,7 +1849,7 @@
 	usleep_range(10, 15);
 
 	/* Poll Until Poll Condition */
-	while (count-- && XGMAC_IOREAD_BITS(pdata, DMA_MR, SWR))
+	while (--count && XGMAC_IOREAD_BITS(pdata, DMA_MR, SWR))
 		usleep_range(500, 600);
 
 	if (!count)
@@ -1873,7 +1873,7 @@
 	/* Poll Until Poll Condition */
 	for (i = 0; i < pdata->tx_q_count; i++) {
 		count = 2000;
-		while (count-- && XGMAC_MTL_IOREAD_BITS(pdata, i,
+		while (--count && XGMAC_MTL_IOREAD_BITS(pdata, i,
 							MTL_Q_TQOMR, FTQ))
 			usleep_range(500, 600);
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 9147a01..d0ae1a6 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -289,6 +289,7 @@
 				    struct sk_buff *skb)
 {
 	struct device *dev = ndev_to_dev(tx_ring->ndev);
+	struct xgene_enet_pdata *pdata = netdev_priv(tx_ring->ndev);
 	struct xgene_enet_raw_desc *raw_desc;
 	__le64 *exp_desc = NULL, *exp_bufs = NULL;
 	dma_addr_t dma_addr, pbuf_addr, *frag_dma_addr;
@@ -419,6 +420,7 @@
 	raw_desc->m0 = cpu_to_le64(SET_VAL(LL, ll) | SET_VAL(NV, nv) |
 				   SET_VAL(USERINFO, tx_ring->tail));
 	tx_ring->cp_ring->cp_skb[tx_ring->tail] = skb;
+	pdata->tx_level += count;
 	tx_ring->tail = tail;
 
 	return count;
@@ -429,14 +431,13 @@
 {
 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 	struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring;
-	struct xgene_enet_desc_ring *cp_ring = tx_ring->cp_ring;
-	u32 tx_level, cq_level;
+	u32 tx_level = pdata->tx_level;
 	int count;
 
-	tx_level = pdata->ring_ops->len(tx_ring);
-	cq_level = pdata->ring_ops->len(cp_ring);
-	if (unlikely(tx_level > pdata->tx_qcnt_hi ||
-		     cq_level > pdata->cp_qcnt_hi)) {
+	if (tx_level < pdata->txc_level)
+		tx_level += ((typeof(pdata->tx_level))~0U);
+
+	if ((tx_level - pdata->txc_level) > pdata->tx_qcnt_hi) {
 		netif_stop_queue(ndev);
 		return NETDEV_TX_BUSY;
 	}
@@ -539,10 +540,13 @@
 	struct xgene_enet_raw_desc *raw_desc, *exp_desc;
 	u16 head = ring->head;
 	u16 slots = ring->slots - 1;
-	int ret, count = 0, processed = 0;
+	int ret, desc_count, count = 0, processed = 0;
+	bool is_completion;
 
 	do {
 		raw_desc = &ring->raw_desc[head];
+		desc_count = 0;
+		is_completion = false;
 		exp_desc = NULL;
 		if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc)))
 			break;
@@ -559,18 +563,24 @@
 			}
 			dma_rmb();
 			count++;
+			desc_count++;
 		}
-		if (is_rx_desc(raw_desc))
+		if (is_rx_desc(raw_desc)) {
 			ret = xgene_enet_rx_frame(ring, raw_desc);
-		else
+		} else {
 			ret = xgene_enet_tx_completion(ring, raw_desc);
+			is_completion = true;
+		}
 		xgene_enet_mark_desc_slot_empty(raw_desc);
 		if (exp_desc)
 			xgene_enet_mark_desc_slot_empty(exp_desc);
 
 		head = (head + 1) & slots;
 		count++;
+		desc_count++;
 		processed++;
+		if (is_completion)
+			pdata->txc_level += desc_count;
 
 		if (ret)
 			break;
@@ -580,10 +590,8 @@
 		pdata->ring_ops->wr_cmd(ring, -count);
 		ring->head = head;
 
-		if (netif_queue_stopped(ring->ndev)) {
-			if (pdata->ring_ops->len(ring) < pdata->cp_qcnt_low)
-				netif_wake_queue(ring->ndev);
-		}
+		if (netif_queue_stopped(ring->ndev))
+			netif_start_queue(ring->ndev);
 	}
 
 	return processed;
@@ -1033,9 +1041,7 @@
 	pdata->tx_ring->cp_ring = cp_ring;
 	pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring);
 
-	pdata->tx_qcnt_hi = pdata->tx_ring->slots / 2;
-	pdata->cp_qcnt_hi = pdata->rx_ring->slots / 2;
-	pdata->cp_qcnt_low = pdata->cp_qcnt_hi / 2;
+	pdata->tx_qcnt_hi = pdata->tx_ring->slots - 128;
 
 	return 0;
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index a6e56b8..1aa72c7 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -155,11 +155,11 @@
 	enum xgene_enet_id enet_id;
 	struct xgene_enet_desc_ring *tx_ring;
 	struct xgene_enet_desc_ring *rx_ring;
+	u16 tx_level;
+	u16 txc_level;
 	char *dev_name;
 	u32 rx_buff_cnt;
 	u32 tx_qcnt_hi;
-	u32 cp_qcnt_hi;
-	u32 cp_qcnt_low;
 	u32 rx_irq;
 	u32 txc_irq;
 	u8 cq_cnt;
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 2795d6d..8b5988e 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -1016,13 +1016,12 @@
 		sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
 		8 * 4;
 
-	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
-				&ring_header->dma);
+	ring_header->desc = dma_zalloc_coherent(&pdev->dev, ring_header->size,
+						&ring_header->dma, GFP_KERNEL);
 	if (unlikely(!ring_header->desc)) {
-		dev_err(&pdev->dev, "pci_alloc_consistend failed\n");
+		dev_err(&pdev->dev, "could not get memory for DMA buffer\n");
 		goto err_nomem;
 	}
-	memset(ring_header->desc, 0, ring_header->size);
 	/* init TPD ring */
 
 	tpd_ring[0].dma = roundup(ring_header->dma, 8);
diff --git a/drivers/net/ethernet/aurora/Kconfig b/drivers/net/ethernet/aurora/Kconfig
index a3c7106..8ba7f8f 100644
--- a/drivers/net/ethernet/aurora/Kconfig
+++ b/drivers/net/ethernet/aurora/Kconfig
@@ -13,6 +13,7 @@
 
 config AURORA_NB8800
 	tristate "Aurora AU-NB8800 support"
+	depends on HAS_DMA
 	select PHYLIB
 	help
 	 Support for the AU-NB8800 gigabit Ethernet controller.
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index bdf094f..07f5f23 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -2693,17 +2693,16 @@
 	req.ver_upd = DRV_VER_UPD;
 
 	if (BNXT_PF(bp)) {
-		unsigned long vf_req_snif_bmap[4];
+		DECLARE_BITMAP(vf_req_snif_bmap, 256);
 		u32 *data = (u32 *)vf_req_snif_bmap;
 
-		memset(vf_req_snif_bmap, 0, 32);
+		memset(vf_req_snif_bmap, 0, sizeof(vf_req_snif_bmap));
 		for (i = 0; i < ARRAY_SIZE(bnxt_vf_req_snif); i++)
 			__set_bit(bnxt_vf_req_snif[i], vf_req_snif_bmap);
 
-		for (i = 0; i < 8; i++) {
-			req.vf_req_fwd[i] = cpu_to_le32(*data);
-			data++;
-		}
+		for (i = 0; i < 8; i++)
+			req.vf_req_fwd[i] = cpu_to_le32(data[i]);
+
 		req.enables |=
 			cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_VF_REQ_FWD);
 	}
@@ -4603,7 +4602,7 @@
 			bp->nge_port_cnt = 1;
 	}
 
-	bp->state = BNXT_STATE_OPEN;
+	set_bit(BNXT_STATE_OPEN, &bp->state);
 	bnxt_enable_int(bp);
 	/* Enable TX queues */
 	bnxt_tx_enable(bp);
@@ -4679,8 +4678,10 @@
 	/* Change device state to avoid TX queue wake up's */
 	bnxt_tx_disable(bp);
 
-	bp->state = BNXT_STATE_CLOSED;
-	cancel_work_sync(&bp->sp_task);
+	clear_bit(BNXT_STATE_OPEN, &bp->state);
+	smp_mb__after_atomic();
+	while (test_bit(BNXT_STATE_IN_SP_TASK, &bp->state))
+		msleep(20);
 
 	/* Flush rings before disabling interrupts */
 	bnxt_shutdown_nic(bp, irq_re_init);
@@ -5030,8 +5031,10 @@
 static void bnxt_reset_task(struct bnxt *bp)
 {
 	bnxt_dbg_dump_states(bp);
-	if (netif_running(bp->dev))
-		bnxt_tx_disable(bp); /* prevent tx timout again */
+	if (netif_running(bp->dev)) {
+		bnxt_close_nic(bp, false, false);
+		bnxt_open_nic(bp, false, false);
+	}
 }
 
 static void bnxt_tx_timeout(struct net_device *dev)
@@ -5081,8 +5084,12 @@
 	struct bnxt *bp = container_of(work, struct bnxt, sp_task);
 	int rc;
 
-	if (bp->state != BNXT_STATE_OPEN)
+	set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+	smp_mb__after_atomic();
+	if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
+		clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
 		return;
+	}
 
 	if (test_and_clear_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event))
 		bnxt_cfg_rx_mode(bp);
@@ -5106,8 +5113,19 @@
 		bnxt_hwrm_tunnel_dst_port_free(
 			bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN);
 	}
-	if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
+	if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event)) {
+		/* bnxt_reset_task() calls bnxt_close_nic() which waits
+		 * for BNXT_STATE_IN_SP_TASK to clear.
+		 */
+		clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+		rtnl_lock();
 		bnxt_reset_task(bp);
+		set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+		rtnl_unlock();
+	}
+
+	smp_mb__before_atomic();
+	clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
 }
 
 static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev)
@@ -5186,7 +5204,7 @@
 	bp->timer.function = bnxt_timer;
 	bp->current_interval = BNXT_TIMER_INTERVAL;
 
-	bp->state = BNXT_STATE_CLOSED;
+	clear_bit(BNXT_STATE_OPEN, &bp->state);
 
 	return 0;
 
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 674bc51..f199f4c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -925,9 +925,9 @@
 
 	struct timer_list	timer;
 
-	int			state;
-#define BNXT_STATE_CLOSED	0
-#define BNXT_STATE_OPEN		1
+	unsigned long		state;
+#define BNXT_STATE_OPEN		0
+#define BNXT_STATE_IN_SP_TASK	1
 
 	struct bnxt_irq	*irq_tbl;
 	u8			mac_addr[ETH_ALEN];
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
index 7a9af28..ea044bb 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
@@ -21,7 +21,7 @@
 #ifdef CONFIG_BNXT_SRIOV
 static int bnxt_vf_ndo_prep(struct bnxt *bp, int vf_id)
 {
-	if (bp->state != BNXT_STATE_OPEN) {
+	if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
 		netdev_err(bp->dev, "vf ndo called though PF is down\n");
 		return -EINVAL;
 	}
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 4b7fd63..5f24d11 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -37,7 +37,6 @@
 #define	NIC_GET_BGX_FROM_VF_LMAC_MAP(map)	((map >> 4) & 0xF)
 #define	NIC_GET_LMAC_FROM_VF_LMAC_MAP(map)	(map & 0xF)
 	u8			vf_lmac_map[MAX_LMAC];
-	u8			lmac_cnt;
 	struct delayed_work     dwork;
 	struct workqueue_struct *check_link;
 	u8			link[MAX_LMAC];
@@ -280,7 +279,6 @@
 	u64 lmac_credit;
 
 	nic->num_vf_en = 0;
-	nic->lmac_cnt = 0;
 
 	for (bgx = 0; bgx < NIC_MAX_BGX; bgx++) {
 		if (!(bgx_map & (1 << bgx)))
@@ -290,7 +288,6 @@
 			nic->vf_lmac_map[next_bgx_lmac++] =
 						NIC_SET_VF_LMAC_MAP(bgx, lmac);
 		nic->num_vf_en += lmac_cnt;
-		nic->lmac_cnt += lmac_cnt;
 
 		/* Program LMAC credits */
 		lmac_credit = (1ull << 1); /* channel credit enable */
@@ -618,6 +615,21 @@
 	return 0;
 }
 
+static void nic_enable_vf(struct nicpf *nic, int vf, bool enable)
+{
+	int bgx, lmac;
+
+	nic->vf_enabled[vf] = enable;
+
+	if (vf >= nic->num_vf_en)
+		return;
+
+	bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+	lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+
+	bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, enable);
+}
+
 /* Interrupt handler to handle mailbox messages from VFs */
 static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
 {
@@ -717,29 +729,14 @@
 		break;
 	case NIC_MBOX_MSG_CFG_DONE:
 		/* Last message of VF config msg sequence */
-		nic->vf_enabled[vf] = true;
-		if (vf >= nic->lmac_cnt)
-			goto unlock;
-
-		bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-		lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-
-		bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, true);
+		nic_enable_vf(nic, vf, true);
 		goto unlock;
 	case NIC_MBOX_MSG_SHUTDOWN:
 		/* First msg in VF teardown sequence */
-		nic->vf_enabled[vf] = false;
 		if (vf >= nic->num_vf_en)
 			nic->sqs_used[vf - nic->num_vf_en] = false;
 		nic->pqs_vf[vf] = 0;
-
-		if (vf >= nic->lmac_cnt)
-			break;
-
-		bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-		lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-
-		bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, false);
+		nic_enable_vf(nic, vf, false);
 		break;
 	case NIC_MBOX_MSG_ALLOC_SQS:
 		nic_alloc_sqs(nic, &mbx.sqs_alloc);
@@ -958,7 +955,7 @@
 
 	mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
 
-	for (vf = 0; vf < nic->lmac_cnt; vf++) {
+	for (vf = 0; vf < nic->num_vf_en; vf++) {
 		/* Poll only if VF is UP */
 		if (!nic->vf_enabled[vf])
 			continue;
diff --git a/drivers/net/ethernet/ezchip/nps_enet.c b/drivers/net/ethernet/ezchip/nps_enet.c
index 63c2bcf..b102668 100644
--- a/drivers/net/ethernet/ezchip/nps_enet.c
+++ b/drivers/net/ethernet/ezchip/nps_enet.c
@@ -48,21 +48,15 @@
 			*reg = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF);
 	else { /* !dst_is_aligned */
 		for (i = 0; i < len; i++, reg++) {
-			u32 buf =
-				nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF);
-
-			/* to accommodate word-unaligned address of "reg"
-			 * we have to do memcpy_toio() instead of simple "=".
-			 */
-			memcpy_toio((void __iomem *)reg, &buf, sizeof(buf));
+			u32 buf = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF);
+			put_unaligned(buf, reg);
 		}
 	}
 
 	/* copy last bytes (if any) */
 	if (last) {
 		u32 buf = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF);
-
-		memcpy_toio((void __iomem *)reg, &buf, last);
+		memcpy((u8*)reg, &buf, last);
 	}
 }
 
@@ -367,7 +361,7 @@
 	struct nps_enet_tx_ctl tx_ctrl;
 	short length = skb->len;
 	u32 i, len = DIV_ROUND_UP(length, sizeof(u32));
-	u32 *src = (u32 *)virt_to_phys(skb->data);
+	u32 *src = (void *)skb->data;
 	bool src_is_aligned = IS_ALIGNED((unsigned long)src, sizeof(u32));
 
 	tx_ctrl.value = 0;
@@ -375,17 +369,11 @@
 	if (src_is_aligned)
 		for (i = 0; i < len; i++, src++)
 			nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF, *src);
-	else { /* !src_is_aligned */
-		for (i = 0; i < len; i++, src++) {
-			u32 buf;
+	else /* !src_is_aligned */
+		for (i = 0; i < len; i++, src++)
+			nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF,
+					 get_unaligned(src));
 
-			/* to accommodate word-unaligned address of "src"
-			 * we have to do memcpy_fromio() instead of simple "="
-			 */
-			memcpy_fromio(&buf, (void __iomem *)src, sizeof(buf));
-			nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF, buf);
-		}
-	}
 	/* Write the length of the Frame */
 	tx_ctrl.nt = length;
 
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
index 08f5b91..52e0091 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
@@ -552,7 +552,7 @@
 	cbd_t __iomem *prev_bd;
 	cbd_t __iomem *last_tx_bd;
 
-	last_tx_bd = fep->tx_bd_base + (fpi->tx_ring * sizeof(cbd_t));
+	last_tx_bd = fep->tx_bd_base + ((fpi->tx_ring - 1) * sizeof(cbd_t));
 
 	/* get the current bd held in TBPTR  and scan back from this point */
 	recheck_bd = curr_tbptr = (cbd_t __iomem *)
diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
index 55c3623..40071da 100644
--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
@@ -464,7 +464,7 @@
 			 * address). Print error message but continue anyway.
 			 */
 			if ((void *)tbipa > priv->map + resource_size(&res) - 4)
-				dev_err(&pdev->dev, "invalid register map (should be at least 0x%04x to contain TBI address)\n",
+				dev_err(&pdev->dev, "invalid register map (should be at least 0x%04zx to contain TBI address)\n",
 					((void *)tbipa - priv->map) + 4);
 
 			iowrite32be(be32_to_cpup(prop), tbipa);
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 7cf8984..3e233d9 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -894,7 +894,8 @@
 				     FSL_GIANFAR_DEV_HAS_VLAN |
 				     FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
 				     FSL_GIANFAR_DEV_HAS_EXTENDED_HASH |
-				     FSL_GIANFAR_DEV_HAS_TIMER;
+				     FSL_GIANFAR_DEV_HAS_TIMER |
+				     FSL_GIANFAR_DEV_HAS_RX_FILER;
 
 	err = of_property_read_string(np, "phy-connection-type", &ctype);
 
@@ -1396,8 +1397,9 @@
 		priv->rx_queue[i]->rxic = DEFAULT_RXIC;
 	}
 
-	/* always enable rx filer */
-	priv->rx_filer_enable = 1;
+	/* Always enable rx filer if available */
+	priv->rx_filer_enable =
+	    (priv->device_flags & FSL_GIANFAR_DEV_HAS_RX_FILER) ? 1 : 0;
 	/* Enable most messages by default */
 	priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
 	/* use pritority h/w tx queue scheduling for single queue devices */
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index f266b20..cb77667 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -923,6 +923,7 @@
 #define FSL_GIANFAR_DEV_HAS_BUF_STASHING	0x00000400
 #define FSL_GIANFAR_DEV_HAS_TIMER		0x00000800
 #define FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER	0x00001000
+#define FSL_GIANFAR_DEV_HAS_RX_FILER		0x00002000
 
 #if (MAXGROUPS == 2)
 #define DEFAULT_MAPPING 	0xAA
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 2a98eba..b674414 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -1259,12 +1259,8 @@
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
 	    MAC_IS_BROADCAST(mac_entry->addr) ||
 	    MAC_IS_MULTICAST(mac_entry->addr)) {
-		dev_err(dsaf_dev->dev,
-			"set_uc %s Mac %02x:%02x:%02x:%02x:%02x:%02x err!\n",
-			dsaf_dev->ae_dev.name, mac_entry->addr[0],
-			mac_entry->addr[1], mac_entry->addr[2],
-			mac_entry->addr[3], mac_entry->addr[4],
-			mac_entry->addr[5]);
+		dev_err(dsaf_dev->dev, "set_uc %s Mac %pM err!\n",
+			dsaf_dev->ae_dev.name, mac_entry->addr);
 		return -EINVAL;
 	}
 
@@ -1331,12 +1327,8 @@
 
 	/* mac addr check */
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
-		dev_err(dsaf_dev->dev,
-			"set uc %s Mac %02x:%02x:%02x:%02x:%02x:%02x err!\n",
-			dsaf_dev->ae_dev.name, mac_entry->addr[0],
-			mac_entry->addr[1], mac_entry->addr[2],
-			mac_entry->addr[3],
-			mac_entry->addr[4], mac_entry->addr[5]);
+		dev_err(dsaf_dev->dev, "set uc %s Mac %pM err!\n",
+			dsaf_dev->ae_dev.name, mac_entry->addr);
 		return -EINVAL;
 	}
 
@@ -1410,11 +1402,8 @@
 
 	/*chechk mac addr */
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
-		dev_err(dsaf_dev->dev,
-			"set_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x!\n",
-			mac_entry->addr[0], mac_entry->addr[1],
-			mac_entry->addr[2], mac_entry->addr[3],
-			mac_entry->addr[4], mac_entry->addr[5]);
+		dev_err(dsaf_dev->dev, "set_entry failed,addr %pM!\n",
+			mac_entry->addr);
 		return -EINVAL;
 	}
 
@@ -1497,9 +1486,8 @@
 
 	/*check mac addr */
 	if (MAC_IS_ALL_ZEROS(addr) || MAC_IS_BROADCAST(addr)) {
-		dev_err(dsaf_dev->dev,
-			"del_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x!\n",
-			addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+		dev_err(dsaf_dev->dev, "del_entry failed,addr %pM!\n",
+			addr);
 		return -EINVAL;
 	}
 
@@ -1563,11 +1551,8 @@
 
 	/*check mac addr */
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
-		dev_err(dsaf_dev->dev,
-			"del_port failed, addr %02x:%02x:%02x:%02x:%02x:%02x!\n",
-			mac_entry->addr[0], mac_entry->addr[1],
-			mac_entry->addr[2], mac_entry->addr[3],
-			mac_entry->addr[4], mac_entry->addr[5]);
+		dev_err(dsaf_dev->dev, "del_port failed, addr %pM!\n",
+			mac_entry->addr);
 		return -EINVAL;
 	}
 
@@ -1644,11 +1629,8 @@
 	/* check macaddr */
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
 	    MAC_IS_BROADCAST(mac_entry->addr)) {
-		dev_err(dsaf_dev->dev,
-			"get_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x\n",
-			mac_entry->addr[0], mac_entry->addr[1],
-			mac_entry->addr[2], mac_entry->addr[3],
-			mac_entry->addr[4], mac_entry->addr[5]);
+		dev_err(dsaf_dev->dev, "get_entry failed,addr %pM\n",
+			mac_entry->addr);
 		return -EINVAL;
 	}
 
@@ -1695,11 +1677,8 @@
 	/*check mac addr */
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
 	    MAC_IS_BROADCAST(mac_entry->addr)) {
-		dev_err(dsaf_dev->dev,
-			"get_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x\n",
-			mac_entry->addr[0], mac_entry->addr[1],
-			mac_entry->addr[2], mac_entry->addr[3],
-			mac_entry->addr[4], mac_entry->addr[5]);
+		dev_err(dsaf_dev->dev, "get_entry failed,addr %pM\n",
+			mac_entry->addr);
 		return -EINVAL;
 	}
 
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
index b475e1b..bdbd804 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
@@ -898,7 +898,7 @@
 #define XGMAC_PAUSE_CTL_RSP_MODE_B	2
 #define XGMAC_PAUSE_CTL_TX_XOFF_B	3
 
-static inline void dsaf_write_reg(void *base, u32 reg, u32 value)
+static inline void dsaf_write_reg(void __iomem *base, u32 reg, u32 value)
 {
 	u8 __iomem *reg_addr = ACCESS_ONCE(base);
 
@@ -908,7 +908,7 @@
 #define dsaf_write_dev(a, reg, value) \
 	dsaf_write_reg((a)->io_base, (reg), (value))
 
-static inline u32 dsaf_read_reg(u8 *base, u32 reg)
+static inline u32 dsaf_read_reg(u8 __iomem *base, u32 reg)
 {
 	u8 __iomem *reg_addr = ACCESS_ONCE(base);
 
@@ -927,8 +927,8 @@
 #define dsaf_set_bit(origin, shift, val) \
 	dsaf_set_field((origin), (1ull << (shift)), (shift), (val))
 
-static inline void dsaf_set_reg_field(void *base, u32 reg, u32 mask, u32 shift,
-				      u32 val)
+static inline void dsaf_set_reg_field(void __iomem *base, u32 reg, u32 mask,
+				      u32 shift, u32 val)
 {
 	u32 origin = dsaf_read_reg(base, reg);
 
@@ -947,7 +947,8 @@
 #define dsaf_get_bit(origin, shift) \
 	dsaf_get_field((origin), (1ull << (shift)), (shift))
 
-static inline u32 dsaf_get_reg_field(void *base, u32 reg, u32 mask, u32 shift)
+static inline u32 dsaf_get_reg_field(void __iomem *base, u32 reg, u32 mask,
+				     u32 shift)
 {
 	u32 origin;
 
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index 0ff8f01..1fd5ea8 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -567,10 +567,6 @@
 		goto init_adminq_exit;
 	}
 
-	/* initialize locks */
-	mutex_init(&hw->aq.asq_mutex);
-	mutex_init(&hw->aq.arq_mutex);
-
 	/* Set up register offsets */
 	i40e_adminq_init_regs(hw);
 
@@ -664,8 +660,6 @@
 	i40e_shutdown_asq(hw);
 	i40e_shutdown_arq(hw);
 
-	/* destroy the locks */
-
 	if (hw->nvm_buff.va)
 		i40e_free_virt_mem(hw, &hw->nvm_buff);
 
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index b825f97..4a9873ec 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -10295,6 +10295,12 @@
 	/* set up a default setting for link flow control */
 	pf->hw.fc.requested_mode = I40E_FC_NONE;
 
+	/* set up the locks for the AQ, do this only once in probe
+	 * and destroy them only once in remove
+	 */
+	mutex_init(&hw->aq.asq_mutex);
+	mutex_init(&hw->aq.arq_mutex);
+
 	err = i40e_init_adminq(hw);
 
 	/* provide nvm, fw, api versions */
@@ -10697,7 +10703,6 @@
 	set_bit(__I40E_DOWN, &pf->state);
 	del_timer_sync(&pf->service_timer);
 	cancel_work_sync(&pf->service_task);
-	i40e_fdir_teardown(pf);
 
 	if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
 		i40e_free_vfs(pf);
@@ -10740,6 +10745,10 @@
 			 "Failed to destroy the Admin Queue resources: %d\n",
 			 ret_code);
 
+	/* destroy the locks only once, here */
+	mutex_destroy(&hw->aq.arq_mutex);
+	mutex_destroy(&hw->aq.asq_mutex);
+
 	/* Clear all dynamic memory lists of rings, q_vectors, and VSIs */
 	i40e_clear_interrupt_scheme(pf);
 	for (i = 0; i < pf->num_alloc_vsi; i++) {
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
index fd123ca..3f65e39 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
@@ -551,10 +551,6 @@
 		goto init_adminq_exit;
 	}
 
-	/* initialize locks */
-	mutex_init(&hw->aq.asq_mutex);
-	mutex_init(&hw->aq.arq_mutex);
-
 	/* Set up register offsets */
 	i40e_adminq_init_regs(hw);
 
@@ -596,8 +592,6 @@
 	i40e_shutdown_asq(hw);
 	i40e_shutdown_arq(hw);
 
-	/* destroy the locks */
-
 	if (hw->nvm_buff.va)
 		i40e_free_virt_mem(hw, &hw->nvm_buff);
 
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index d962164..99d2cff 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -2476,6 +2476,12 @@
 	hw->bus.device = PCI_SLOT(pdev->devfn);
 	hw->bus.func = PCI_FUNC(pdev->devfn);
 
+	/* set up the locks for the AQ, do this only once in probe
+	 * and destroy them only once in remove
+	 */
+	mutex_init(&hw->aq.asq_mutex);
+	mutex_init(&hw->aq.arq_mutex);
+
 	INIT_LIST_HEAD(&adapter->mac_filter_list);
 	INIT_LIST_HEAD(&adapter->vlan_filter_list);
 
@@ -2629,6 +2635,10 @@
 	if (hw->aq.asq.count)
 		i40evf_shutdown_adminq(hw);
 
+	/* destroy the locks only once, here */
+	mutex_destroy(&hw->aq.arq_mutex);
+	mutex_destroy(&hw->aq.asq_mutex);
+
 	iounmap(hw->hw_addr);
 	pci_release_regions(pdev);
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 47395ff..aed8d02 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7920,6 +7920,9 @@
 	 */
 	if (netif_running(dev))
 		ixgbe_close(dev);
+	else
+		ixgbe_reset(adapter);
+
 	ixgbe_clear_interrupt_scheme(adapter);
 
 #ifdef CONFIG_IXGBE_DCB
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index d9884fd..a4beccf 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -3413,16 +3413,23 @@
 }
 
 /* Free all buffers from the pool */
-static void mvpp2_bm_bufs_free(struct mvpp2 *priv, struct mvpp2_bm_pool *bm_pool)
+static void mvpp2_bm_bufs_free(struct device *dev, struct mvpp2 *priv,
+			       struct mvpp2_bm_pool *bm_pool)
 {
 	int i;
 
 	for (i = 0; i < bm_pool->buf_num; i++) {
+		dma_addr_t buf_phys_addr;
 		u32 vaddr;
 
 		/* Get buffer virtual address (indirect access) */
-		mvpp2_read(priv, MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
+		buf_phys_addr = mvpp2_read(priv,
+					   MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
 		vaddr = mvpp2_read(priv, MVPP2_BM_VIRT_ALLOC_REG);
+
+		dma_unmap_single(dev, buf_phys_addr,
+				 bm_pool->buf_size, DMA_FROM_DEVICE);
+
 		if (!vaddr)
 			break;
 		dev_kfree_skb_any((struct sk_buff *)vaddr);
@@ -3439,7 +3446,7 @@
 {
 	u32 val;
 
-	mvpp2_bm_bufs_free(priv, bm_pool);
+	mvpp2_bm_bufs_free(&pdev->dev, priv, bm_pool);
 	if (bm_pool->buf_num) {
 		WARN(1, "cannot free all buffers in pool %d\n", bm_pool->id);
 		return 0;
@@ -3692,7 +3699,8 @@
 				   MVPP2_BM_LONG_BUF_NUM :
 				   MVPP2_BM_SHORT_BUF_NUM;
 		else
-			mvpp2_bm_bufs_free(port->priv, new_pool);
+			mvpp2_bm_bufs_free(port->dev->dev.parent,
+					   port->priv, new_pool);
 
 		new_pool->pkt_size = pkt_size;
 
@@ -3756,7 +3764,7 @@
 	int pkt_size = MVPP2_RX_PKT_SIZE(mtu);
 
 	/* Update BM pool with new buffer size */
-	mvpp2_bm_bufs_free(port->priv, port_pool);
+	mvpp2_bm_bufs_free(dev->dev.parent, port->priv, port_pool);
 	if (port_pool->buf_num) {
 		WARN(1, "cannot free all buffers in pool %d\n", port_pool->id);
 		return -EIO;
@@ -4401,11 +4409,10 @@
 
 		mvpp2_txq_inc_get(txq_pcpu);
 
-		if (!skb)
-			continue;
-
 		dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
 				 skb_headlen(skb), DMA_TO_DEVICE);
+		if (!skb)
+			continue;
 		dev_kfree_skb_any(skb);
 	}
 }
@@ -5092,7 +5099,8 @@
 		    struct mvpp2_rx_queue *rxq)
 {
 	struct net_device *dev = port->dev;
-	int rx_received, rx_filled, i;
+	int rx_received;
+	int rx_done = 0;
 	u32 rcvd_pkts = 0;
 	u32 rcvd_bytes = 0;
 
@@ -5101,17 +5109,18 @@
 	if (rx_todo > rx_received)
 		rx_todo = rx_received;
 
-	rx_filled = 0;
-	for (i = 0; i < rx_todo; i++) {
+	while (rx_done < rx_todo) {
 		struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
 		struct mvpp2_bm_pool *bm_pool;
 		struct sk_buff *skb;
+		dma_addr_t phys_addr;
 		u32 bm, rx_status;
 		int pool, rx_bytes, err;
 
-		rx_filled++;
+		rx_done++;
 		rx_status = rx_desc->status;
 		rx_bytes = rx_desc->data_size - MVPP2_MH_SIZE;
+		phys_addr = rx_desc->buf_phys_addr;
 
 		bm = mvpp2_bm_cookie_build(rx_desc);
 		pool = mvpp2_bm_cookie_pool_get(bm);
@@ -5128,8 +5137,10 @@
 		 * comprised by the RX descriptor.
 		 */
 		if (rx_status & MVPP2_RXD_ERR_SUMMARY) {
+		err_drop_frame:
 			dev->stats.rx_errors++;
 			mvpp2_rx_error(port, rx_desc);
+			/* Return the buffer to the pool */
 			mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
 					  rx_desc->buf_cookie);
 			continue;
@@ -5137,6 +5148,15 @@
 
 		skb = (struct sk_buff *)rx_desc->buf_cookie;
 
+		err = mvpp2_rx_refill(port, bm_pool, bm, 0);
+		if (err) {
+			netdev_err(port->dev, "failed to refill BM pools\n");
+			goto err_drop_frame;
+		}
+
+		dma_unmap_single(dev->dev.parent, phys_addr,
+				 bm_pool->buf_size, DMA_FROM_DEVICE);
+
 		rcvd_pkts++;
 		rcvd_bytes += rx_bytes;
 		atomic_inc(&bm_pool->in_use);
@@ -5147,12 +5167,6 @@
 		mvpp2_rx_csum(port, rx_status, skb);
 
 		napi_gro_receive(&port->napi, skb);
-
-		err = mvpp2_rx_refill(port, bm_pool, bm, 0);
-		if (err) {
-			netdev_err(port->dev, "failed to refill BM pools\n");
-			rx_filled--;
-		}
 	}
 
 	if (rcvd_pkts) {
@@ -5166,7 +5180,7 @@
 
 	/* Update Rx queue management counters */
 	wmb();
-	mvpp2_rxq_status_update(port, rxq->id, rx_todo, rx_filled);
+	mvpp2_rxq_status_update(port, rxq->id, rx_done, rx_done);
 
 	return rx_todo;
 }
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 2177e56..d48d579 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1010,7 +1010,7 @@
 		if (!(smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED &&
 		      smp->method == IB_MGMT_METHOD_GET) || network_view) {
 			mlx4_err(dev, "Unprivileged slave %d is trying to execute a Subnet MGMT MAD, class 0x%x, method 0x%x, view=%s for attr 0x%x. Rejecting\n",
-				 slave, smp->method, smp->mgmt_class,
+				 slave, smp->mgmt_class, smp->method,
 				 network_view ? "Network" : "Host",
 				 be16_to_cpu(smp->attr_id));
 			return -EPERM;
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 6fec3e9..cad6c44 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -4306,9 +4306,10 @@
 		return -EOPNOTSUPP;
 
 	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
-	ctrl->port = mlx4_slave_convert_port(dev, slave, ctrl->port);
-	if (ctrl->port <= 0)
+	err = mlx4_slave_convert_port(dev, slave, ctrl->port);
+	if (err <= 0)
 		return -EINVAL;
+	ctrl->port = err;
 	qpn = be32_to_cpu(ctrl->qpn) & 0xffffff;
 	err = get_res(dev, slave, qpn, RES_QP, &rqp);
 	if (err) {
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index ac17d86..1292c36 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -299,6 +299,7 @@
 
 	/* Flag indicating whether interrupts are enabled or not*/
 	bool				b_int_enabled;
+	bool				b_int_requested;
 
 	struct qed_mcp_info		*mcp_info;
 
@@ -491,6 +492,8 @@
 		   u32 input_len, u8 *input_buf,
 		   u32 max_size, u8 *unzip_buf);
 
+int qed_slowpath_irq_req(struct qed_hwfn *hwfn);
+
 #define QED_ETH_INTERFACE_VERSION       300
 
 #endif /* _QED_H */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 803b190..817bbd5 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -1385,52 +1385,63 @@
 	return rc;
 }
 
-static u32 qed_hw_bar_size(struct qed_dev *cdev,
-			   u8 bar_id)
+static u32 qed_hw_bar_size(struct qed_hwfn	*p_hwfn,
+			   u8			bar_id)
 {
-	u32 size = pci_resource_len(cdev->pdev, (bar_id > 0) ? 2 : 0);
+	u32 bar_reg = (bar_id == 0 ? PGLUE_B_REG_PF_BAR0_SIZE
+		       : PGLUE_B_REG_PF_BAR1_SIZE);
+	u32 val = qed_rd(p_hwfn, p_hwfn->p_main_ptt, bar_reg);
 
-	return size / cdev->num_hwfns;
+	/* Get the BAR size(in KB) from hardware given val */
+	return 1 << (val + 15);
 }
 
 int qed_hw_prepare(struct qed_dev *cdev,
 		   int personality)
 {
-	int rc, i;
+	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+	int rc;
 
 	/* Store the precompiled init data ptrs */
 	qed_init_iro_array(cdev);
 
 	/* Initialize the first hwfn - will learn number of hwfns */
-	rc = qed_hw_prepare_single(&cdev->hwfns[0], cdev->regview,
+	rc = qed_hw_prepare_single(p_hwfn,
+				   cdev->regview,
 				   cdev->doorbells, personality);
 	if (rc)
 		return rc;
 
-	personality = cdev->hwfns[0].hw_info.personality;
+	personality = p_hwfn->hw_info.personality;
 
 	/* Initialize the rest of the hwfns */
-	for (i = 1; i < cdev->num_hwfns; i++) {
+	if (cdev->num_hwfns > 1) {
 		void __iomem *p_regview, *p_doorbell;
+		u8 __iomem *addr;
 
-		p_regview =  cdev->regview +
-			     i * qed_hw_bar_size(cdev, 0);
-		p_doorbell = cdev->doorbells +
-			     i * qed_hw_bar_size(cdev, 1);
-		rc = qed_hw_prepare_single(&cdev->hwfns[i], p_regview,
+		/* adjust bar offset for second engine */
+		addr = cdev->regview + qed_hw_bar_size(p_hwfn, 0) / 2;
+		p_regview = addr;
+
+		/* adjust doorbell bar offset for second engine */
+		addr = cdev->doorbells + qed_hw_bar_size(p_hwfn, 1) / 2;
+		p_doorbell = addr;
+
+		/* prepare second hw function */
+		rc = qed_hw_prepare_single(&cdev->hwfns[1], p_regview,
 					   p_doorbell, personality);
+
+		/* in case of error, need to free the previously
+		 * initiliazed hwfn 0.
+		 */
 		if (rc) {
-			/* Cleanup previously initialized hwfns */
-			while (--i >= 0) {
-				qed_init_free(&cdev->hwfns[i]);
-				qed_mcp_free(&cdev->hwfns[i]);
-				qed_hw_hwfn_free(&cdev->hwfns[i]);
-			}
-			return rc;
+			qed_init_free(p_hwfn);
+			qed_mcp_free(p_hwfn);
+			qed_hw_hwfn_free(p_hwfn);
 		}
 	}
 
-	return 0;
+	return rc;
 }
 
 void qed_hw_remove(struct qed_dev *cdev)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c
index de50e84..9cc9d62 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -783,22 +783,16 @@
 	qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf);
 }
 
-void qed_int_igu_enable(struct qed_hwfn *p_hwfn,
-			struct qed_ptt *p_ptt,
-			enum qed_int_mode int_mode)
+int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+		       enum qed_int_mode int_mode)
 {
-	int i;
-
-	p_hwfn->b_int_enabled = 1;
+	int rc, i;
 
 	/* Mask non-link attentions */
 	for (i = 0; i < 9; i++)
 		qed_wr(p_hwfn, p_ptt,
 		       MISC_REG_AEU_ENABLE1_IGU_OUT_0 + (i << 2), 0);
 
-	/* Enable interrupt Generation */
-	qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode);
-
 	/* Configure AEU signal change to produce attentions for link */
 	qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0xfff);
 	qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0xfff);
@@ -808,6 +802,19 @@
 
 	/* Unmask AEU signals toward IGU */
 	qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_MASK_ATTN_IGU, 0xff);
+	if ((int_mode != QED_INT_MODE_INTA) || IS_LEAD_HWFN(p_hwfn)) {
+		rc = qed_slowpath_irq_req(p_hwfn);
+		if (rc != 0) {
+			DP_NOTICE(p_hwfn, "Slowpath IRQ request failed\n");
+			return -EINVAL;
+		}
+		p_hwfn->b_int_requested = true;
+	}
+	/* Enable interrupt Generation */
+	qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode);
+	p_hwfn->b_int_enabled = 1;
+
+	return rc;
 }
 
 void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn,
@@ -1127,3 +1134,11 @@
 
 	return info->igu_sb_cnt;
 }
+
+void qed_int_disable_post_isr_release(struct qed_dev *cdev)
+{
+	int i;
+
+	for_each_hwfn(cdev, i)
+		cdev->hwfns[i].b_int_requested = false;
+}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.h b/drivers/net/ethernet/qlogic/qed/qed_int.h
index 16b5751..51e0b09 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.h
@@ -169,10 +169,14 @@
 			int *p_iov_blks);
 
 /**
- * @file
+ * @brief qed_int_disable_post_isr_release - performs the cleanup post ISR
+ *        release. The API need to be called after releasing all slowpath IRQs
+ *        of the device.
  *
- * @brief Interrupt handler
+ * @param cdev
+ *
  */
+void qed_int_disable_post_isr_release(struct qed_dev *cdev);
 
 #define QED_CAU_DEF_RX_TIMER_RES 0
 #define QED_CAU_DEF_TX_TIMER_RES 0
@@ -366,10 +370,11 @@
  * @param p_hwfn
  * @param p_ptt
  * @param int_mode
+ *
+ * @return int
  */
-void qed_int_igu_enable(struct qed_hwfn *p_hwfn,
-			struct qed_ptt *p_ptt,
-			enum qed_int_mode int_mode);
+int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+		       enum qed_int_mode int_mode);
 
 /**
  * @brief - Initialize CAU status block entry
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 947c7af..174f734 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -476,41 +476,22 @@
 	return rc;
 }
 
-static int qed_slowpath_irq_req(struct qed_dev *cdev)
+int qed_slowpath_irq_req(struct qed_hwfn *hwfn)
 {
-	int i = 0, rc = 0;
+	struct qed_dev *cdev = hwfn->cdev;
+	int rc = 0;
+	u8 id;
 
 	if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
-		/* Request all the slowpath MSI-X vectors */
-		for (i = 0; i < cdev->num_hwfns; i++) {
-			snprintf(cdev->hwfns[i].name, NAME_SIZE,
-				 "sp-%d-%02x:%02x.%02x",
-				 i, cdev->pdev->bus->number,
-				 PCI_SLOT(cdev->pdev->devfn),
-				 cdev->hwfns[i].abs_pf_id);
-
-			rc = request_irq(cdev->int_params.msix_table[i].vector,
-					 qed_msix_sp_int, 0,
-					 cdev->hwfns[i].name,
-					 cdev->hwfns[i].sp_dpc);
-			if (rc)
-				break;
-
-			DP_VERBOSE(&cdev->hwfns[i],
-				   (NETIF_MSG_INTR | QED_MSG_SP),
+		id = hwfn->my_id;
+		snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x",
+			 id, cdev->pdev->bus->number,
+			 PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id);
+		rc = request_irq(cdev->int_params.msix_table[id].vector,
+				 qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc);
+		if (!rc)
+			DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP),
 				   "Requested slowpath MSI-X\n");
-		}
-
-		if (i != cdev->num_hwfns) {
-			/* Free already request MSI-X vectors */
-			for (i--; i >= 0; i--) {
-				unsigned int vec =
-					cdev->int_params.msix_table[i].vector;
-				synchronize_irq(vec);
-				free_irq(cdev->int_params.msix_table[i].vector,
-					 cdev->hwfns[i].sp_dpc);
-			}
-		}
 	} else {
 		unsigned long flags = 0;
 
@@ -534,13 +515,17 @@
 
 	if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
 		for_each_hwfn(cdev, i) {
+			if (!cdev->hwfns[i].b_int_requested)
+				break;
 			synchronize_irq(cdev->int_params.msix_table[i].vector);
 			free_irq(cdev->int_params.msix_table[i].vector,
 				 cdev->hwfns[i].sp_dpc);
 		}
 	} else {
-		free_irq(cdev->pdev->irq, cdev);
+		if (QED_LEADING_HWFN(cdev)->b_int_requested)
+			free_irq(cdev->pdev->irq, cdev);
 	}
+	qed_int_disable_post_isr_release(cdev);
 }
 
 static int qed_nic_stop(struct qed_dev *cdev)
@@ -765,16 +750,11 @@
 	if (rc)
 		goto err1;
 
-	/* Request the slowpath IRQ */
-	rc = qed_slowpath_irq_req(cdev);
-	if (rc)
-		goto err2;
-
 	/* Allocate stream for unzipping */
 	rc = qed_alloc_stream_mem(cdev);
 	if (rc) {
 		DP_NOTICE(cdev, "Failed to allocate stream memory\n");
-		goto err3;
+		goto err2;
 	}
 
 	/* Start the slowpath */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
index 7a5ce59..e8df123 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
@@ -363,4 +363,8 @@
 		0x7 << 0)
 #define  MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT \
 	0
+#define PGLUE_B_REG_PF_BAR0_SIZE \
+	0x2aae60UL
+#define PGLUE_B_REG_PF_BAR1_SIZE \
+	0x2aae64UL
 #endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h
index 31a1f1e..287fadf 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h
@@ -124,8 +124,12 @@
 	dma_addr_t		p_phys;
 	struct qed_spq_entry	*p_virt;
 
-	/* Used as index for completions (returns on EQ by FW) */
-	u16			echo_idx;
+#define SPQ_RING_SIZE \
+	(CORE_SPQE_PAGE_SIZE_BYTES / sizeof(struct slow_path_element))
+
+	/* Bitmap for handling out-of-order completions */
+	DECLARE_BITMAP(p_comp_bitmap, SPQ_RING_SIZE);
+	u8			comp_bitmap_idx;
 
 	/* Statistics */
 	u32			unlimited_pending_count;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c
index 7c0b845..3dd548a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -112,8 +112,6 @@
 qed_spq_fill_entry(struct qed_hwfn *p_hwfn,
 		   struct qed_spq_entry *p_ent)
 {
-	p_ent->elem.hdr.echo = 0;
-	p_hwfn->p_spq->echo_idx++;
 	p_ent->flags = 0;
 
 	switch (p_ent->comp_mode) {
@@ -195,10 +193,12 @@
 			   struct qed_spq *p_spq,
 			   struct qed_spq_entry *p_ent)
 {
-	struct qed_chain		*p_chain = &p_hwfn->p_spq->chain;
+	struct qed_chain *p_chain = &p_hwfn->p_spq->chain;
+	u16 echo = qed_chain_get_prod_idx(p_chain);
 	struct slow_path_element	*elem;
 	struct core_db_data		db;
 
+	p_ent->elem.hdr.echo	= cpu_to_le16(echo);
 	elem = qed_chain_produce(p_chain);
 	if (!elem) {
 		DP_NOTICE(p_hwfn, "Failed to produce from SPQ chain\n");
@@ -437,7 +437,9 @@
 	p_spq->comp_count		= 0;
 	p_spq->comp_sent_count		= 0;
 	p_spq->unlimited_pending_count	= 0;
-	p_spq->echo_idx			= 0;
+
+	bitmap_zero(p_spq->p_comp_bitmap, SPQ_RING_SIZE);
+	p_spq->comp_bitmap_idx = 0;
 
 	/* SPQ cid, cannot fail */
 	qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_CORE, &p_spq->cid);
@@ -582,26 +584,32 @@
 	struct qed_spq *p_spq = p_hwfn->p_spq;
 
 	if (p_ent->queue == &p_spq->unlimited_pending) {
-		struct qed_spq_entry *p_en2;
 
 		if (list_empty(&p_spq->free_pool)) {
 			list_add_tail(&p_ent->list, &p_spq->unlimited_pending);
 			p_spq->unlimited_pending_count++;
 
 			return 0;
+		} else {
+			struct qed_spq_entry *p_en2;
+
+			p_en2 = list_first_entry(&p_spq->free_pool,
+						 struct qed_spq_entry,
+						 list);
+			list_del(&p_en2->list);
+
+			/* Copy the ring element physical pointer to the new
+			 * entry, since we are about to override the entire ring
+			 * entry and don't want to lose the pointer.
+			 */
+			p_ent->elem.data_ptr = p_en2->elem.data_ptr;
+
+			*p_en2 = *p_ent;
+
+			kfree(p_ent);
+
+			p_ent = p_en2;
 		}
-
-		p_en2 = list_first_entry(&p_spq->free_pool,
-					 struct qed_spq_entry,
-					 list);
-		list_del(&p_en2->list);
-
-		/* Strcut assignment */
-		*p_en2 = *p_ent;
-
-		kfree(p_ent);
-
-		p_ent = p_en2;
 	}
 
 	/* entry is to be placed in 'pending' queue */
@@ -777,13 +785,38 @@
 	list_for_each_entry_safe(p_ent, tmp, &p_spq->completion_pending,
 				 list) {
 		if (p_ent->elem.hdr.echo == echo) {
+			u16 pos = le16_to_cpu(echo) % SPQ_RING_SIZE;
+
 			list_del(&p_ent->list);
 
-			qed_chain_return_produced(&p_spq->chain);
+			/* Avoid overriding of SPQ entries when getting
+			 * out-of-order completions, by marking the completions
+			 * in a bitmap and increasing the chain consumer only
+			 * for the first successive completed entries.
+			 */
+			bitmap_set(p_spq->p_comp_bitmap, pos, SPQ_RING_SIZE);
+
+			while (test_bit(p_spq->comp_bitmap_idx,
+					p_spq->p_comp_bitmap)) {
+				bitmap_clear(p_spq->p_comp_bitmap,
+					     p_spq->comp_bitmap_idx,
+					     SPQ_RING_SIZE);
+				p_spq->comp_bitmap_idx++;
+				qed_chain_return_produced(&p_spq->chain);
+			}
+
 			p_spq->comp_count++;
 			found = p_ent;
 			break;
 		}
+
+		/* This is relatively uncommon - depends on scenarios
+		 * which have mutliple per-PF sent ramrods.
+		 */
+		DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
+			   "Got completion for echo %04x - doesn't match echo %04x in completion pending list\n",
+			   le16_to_cpu(echo),
+			   le16_to_cpu(p_ent->elem.hdr.echo));
 	}
 
 	/* Release lock before callback, as callback may post
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
index be7d7a6..b1a452f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
@@ -246,7 +246,8 @@
 	u32 state;
 
 	state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
-	while (state != QLCNIC_DEV_NPAR_OPER && idc->vnic_wait_limit--) {
+	while (state != QLCNIC_DEV_NPAR_OPER && idc->vnic_wait_limit) {
+		idc->vnic_wait_limit--;
 		msleep(1000);
 		state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
 	}
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index 02b7115..9979764 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -4211,8 +4211,9 @@
 
 	/* Wait for an outstanding reset to complete. */
 	if (!test_bit(QL_ADAPTER_UP, &qdev->flags)) {
-		int i = 3;
-		while (i-- && !test_bit(QL_ADAPTER_UP, &qdev->flags)) {
+		int i = 4;
+
+		while (--i && !test_bit(QL_ADAPTER_UP, &qdev->flags)) {
 			netif_err(qdev, ifup, qdev->ndev,
 				  "Waiting for adapter UP...\n");
 			ssleep(1);
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
index ddb2c6c..689a4a5 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -736,9 +736,8 @@
 	netdev_info(qca->net_dev, "Transmit timeout at %ld, latency %ld\n",
 		    jiffies, jiffies - dev->trans_start);
 	qca->net_dev->stats.tx_errors++;
-	/* wake the queue if there is room */
-	if (qcaspi_tx_ring_has_space(&qca->txr))
-		netif_wake_queue(dev);
+	/* Trigger tx queue flush and QCA7000 reset */
+	qca->sync = QCASPI_SYNC_UNKNOWN;
 }
 
 static int
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index ed5da4d..467d416 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -905,6 +905,9 @@
 		netdev_info(ndev, "limited PHY to 100Mbit/s\n");
 	}
 
+	/* 10BASE is not supported */
+	phydev->supported &= ~PHY_10BT_FEATURES;
+
 	netdev_info(ndev, "attached PHY %d (IRQ %d) to driver %s\n",
 		    phydev->addr, phydev->irq, phydev->drv->name);
 
@@ -1037,7 +1040,7 @@
 	"rx_queue_1_mcast_packets",
 	"rx_queue_1_errors",
 	"rx_queue_1_crc_errors",
-	"rx_queue_1_frame_errors_",
+	"rx_queue_1_frame_errors",
 	"rx_queue_1_length_errors",
 	"rx_queue_1_missed_errors",
 	"rx_queue_1_over_errors",
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index e7bab79..a0eaf50 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -52,6 +52,8 @@
 		NETIF_MSG_RX_ERR| \
 		NETIF_MSG_TX_ERR)
 
+#define SH_ETH_OFFSET_INVALID	((u16)~0)
+
 #define SH_ETH_OFFSET_DEFAULTS			\
 	[0 ... SH_ETH_MAX_REGISTER_OFFSET - 1] = SH_ETH_OFFSET_INVALID
 
@@ -404,6 +406,28 @@
 static void sh_eth_rcv_snd_disable(struct net_device *ndev);
 static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev);
 
+static void sh_eth_write(struct net_device *ndev, u32 data, int enum_index)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u16 offset = mdp->reg_offset[enum_index];
+
+	if (WARN_ON(offset == SH_ETH_OFFSET_INVALID))
+		return;
+
+	iowrite32(data, mdp->addr + offset);
+}
+
+static u32 sh_eth_read(struct net_device *ndev, int enum_index)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u16 offset = mdp->reg_offset[enum_index];
+
+	if (WARN_ON(offset == SH_ETH_OFFSET_INVALID))
+		return ~0U;
+
+	return ioread32(mdp->addr + offset);
+}
+
 static bool sh_eth_is_gether(struct sh_eth_private *mdp)
 {
 	return mdp->reg_offset == sh_eth_offset_gigabit;
@@ -1172,7 +1196,7 @@
 			break;
 		}
 		mdp->rx_skbuff[i] = skb;
-		rxdesc->addr = dma_addr;
+		rxdesc->addr = cpu_to_edmac(mdp, dma_addr);
 		rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
 
 		/* Rx descriptor address set */
@@ -1403,7 +1427,8 @@
 			   entry, edmac_to_cpu(mdp, txdesc->status));
 		/* Free the original skb. */
 		if (mdp->tx_skbuff[entry]) {
-			dma_unmap_single(&ndev->dev, txdesc->addr,
+			dma_unmap_single(&ndev->dev,
+					 edmac_to_cpu(mdp, txdesc->addr),
 					 txdesc->buffer_length, DMA_TO_DEVICE);
 			dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
 			mdp->tx_skbuff[entry] = NULL;
@@ -1462,6 +1487,7 @@
 		if (mdp->cd->shift_rd0)
 			desc_status >>= 16;
 
+		skb = mdp->rx_skbuff[entry];
 		if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
 				   RD_RFS5 | RD_RFS6 | RD_RFS10)) {
 			ndev->stats.rx_errors++;
@@ -1477,16 +1503,16 @@
 				ndev->stats.rx_missed_errors++;
 			if (desc_status & RD_RFS10)
 				ndev->stats.rx_over_errors++;
-		} else {
+		} else	if (skb) {
+			dma_addr = edmac_to_cpu(mdp, rxdesc->addr);
 			if (!mdp->cd->hw_swap)
 				sh_eth_soft_swap(
-					phys_to_virt(ALIGN(rxdesc->addr, 4)),
+					phys_to_virt(ALIGN(dma_addr, 4)),
 					pkt_len + 2);
-			skb = mdp->rx_skbuff[entry];
 			mdp->rx_skbuff[entry] = NULL;
 			if (mdp->cd->rpadir)
 				skb_reserve(skb, NET_IP_ALIGN);
-			dma_unmap_single(&ndev->dev, rxdesc->addr,
+			dma_unmap_single(&ndev->dev, dma_addr,
 					 ALIGN(mdp->rx_buf_sz, 32),
 					 DMA_FROM_DEVICE);
 			skb_put(skb, pkt_len);
@@ -1523,7 +1549,7 @@
 			mdp->rx_skbuff[entry] = skb;
 
 			skb_checksum_none_assert(skb);
-			rxdesc->addr = dma_addr;
+			rxdesc->addr = cpu_to_edmac(mdp, dma_addr);
 		}
 		dma_wmb(); /* RACT bit must be set after all the above writes */
 		if (entry >= mdp->num_rx_ring - 1)
@@ -2331,8 +2357,8 @@
 	/* Free all the skbuffs in the Rx queue. */
 	for (i = 0; i < mdp->num_rx_ring; i++) {
 		rxdesc = &mdp->rx_ring[i];
-		rxdesc->status = 0;
-		rxdesc->addr = 0xBADF00D0;
+		rxdesc->status = cpu_to_edmac(mdp, 0);
+		rxdesc->addr = cpu_to_edmac(mdp, 0xBADF00D0);
 		dev_kfree_skb(mdp->rx_skbuff[i]);
 		mdp->rx_skbuff[i] = NULL;
 	}
@@ -2350,6 +2376,7 @@
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	struct sh_eth_txdesc *txdesc;
+	dma_addr_t dma_addr;
 	u32 entry;
 	unsigned long flags;
 
@@ -2372,14 +2399,14 @@
 	txdesc = &mdp->tx_ring[entry];
 	/* soft swap. */
 	if (!mdp->cd->hw_swap)
-		sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)),
-				 skb->len + 2);
-	txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
-				      DMA_TO_DEVICE);
-	if (dma_mapping_error(&ndev->dev, txdesc->addr)) {
+		sh_eth_soft_swap(PTR_ALIGN(skb->data, 4), skb->len + 2);
+	dma_addr = dma_map_single(&ndev->dev, skb->data, skb->len,
+				  DMA_TO_DEVICE);
+	if (dma_mapping_error(&ndev->dev, dma_addr)) {
 		kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
+	txdesc->addr = cpu_to_edmac(mdp, dma_addr);
 	txdesc->buffer_length = skb->len;
 
 	dma_wmb(); /* TACT bit must be set after all the above writes */
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 50382b1..26ad1cf 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -546,31 +546,6 @@
 #endif
 }
 
-#define SH_ETH_OFFSET_INVALID	((u16) ~0)
-
-static inline void sh_eth_write(struct net_device *ndev, u32 data,
-				int enum_index)
-{
-	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u16 offset = mdp->reg_offset[enum_index];
-
-	if (WARN_ON(offset == SH_ETH_OFFSET_INVALID))
-		return;
-
-	iowrite32(data, mdp->addr + offset);
-}
-
-static inline u32 sh_eth_read(struct net_device *ndev, int enum_index)
-{
-	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u16 offset = mdp->reg_offset[enum_index];
-
-	if (WARN_ON(offset == SH_ETH_OFFSET_INVALID))
-		return ~0U;
-
-	return ioread32(mdp->addr + offset);
-}
-
 static inline void *sh_eth_tsu_get_offset(struct sh_eth_private *mdp,
 					  int enum_index)
 {
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index bc6d21b..e6a084a 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -3299,7 +3299,8 @@
 
 		new_spec.priority = EFX_FILTER_PRI_AUTO;
 		new_spec.flags = (EFX_FILTER_FLAG_RX |
-				  EFX_FILTER_FLAG_RX_RSS);
+				  (efx_rss_enabled(efx) ?
+				   EFX_FILTER_FLAG_RX_RSS : 0));
 		new_spec.dmaq_id = 0;
 		new_spec.rss_context = EFX_FILTER_RSS_CONTEXT_DEFAULT;
 		rc = efx_ef10_filter_push(efx, &new_spec,
@@ -3921,6 +3922,7 @@
 {
 	struct efx_ef10_filter_table *table = efx->filter_state;
 	struct efx_ef10_dev_addr *addr_list;
+	enum efx_filter_flags filter_flags;
 	struct efx_filter_spec spec;
 	u8 baddr[ETH_ALEN];
 	unsigned int i, j;
@@ -3935,11 +3937,11 @@
 		addr_count = table->dev_uc_count;
 	}
 
+	filter_flags = efx_rss_enabled(efx) ? EFX_FILTER_FLAG_RX_RSS : 0;
+
 	/* Insert/renew filters */
 	for (i = 0; i < addr_count; i++) {
-		efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO,
-				   EFX_FILTER_FLAG_RX_RSS,
-				   0);
+		efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
 		efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC,
 					 addr_list[i].addr);
 		rc = efx_ef10_filter_insert(efx, &spec, true);
@@ -3968,9 +3970,7 @@
 
 	if (multicast && rollback) {
 		/* Also need an Ethernet broadcast filter */
-		efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO,
-				   EFX_FILTER_FLAG_RX_RSS,
-				   0);
+		efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
 		eth_broadcast_addr(baddr);
 		efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC, baddr);
 		rc = efx_ef10_filter_insert(efx, &spec, true);
@@ -4000,13 +4000,14 @@
 {
 	struct efx_ef10_filter_table *table = efx->filter_state;
 	struct efx_ef10_nic_data *nic_data = efx->nic_data;
+	enum efx_filter_flags filter_flags;
 	struct efx_filter_spec spec;
 	u8 baddr[ETH_ALEN];
 	int rc;
 
-	efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO,
-			   EFX_FILTER_FLAG_RX_RSS,
-			   0);
+	filter_flags = efx_rss_enabled(efx) ? EFX_FILTER_FLAG_RX_RSS : 0;
+
+	efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
 
 	if (multicast)
 		efx_filter_set_mc_def(&spec);
@@ -4023,8 +4024,7 @@
 		if (!nic_data->workaround_26807) {
 			/* Also need an Ethernet broadcast filter */
 			efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO,
-					   EFX_FILTER_FLAG_RX_RSS,
-					   0);
+					   filter_flags, 0);
 			eth_broadcast_addr(baddr);
 			efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC,
 						 baddr);
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index 1aaf76c..1082747 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -76,6 +76,11 @@
 #define EFX_TXQ_MAX_ENT(efx)	(EFX_WORKAROUND_35388(efx) ? \
 				 EFX_MAX_DMAQ_SIZE / 2 : EFX_MAX_DMAQ_SIZE)
 
+static inline bool efx_rss_enabled(struct efx_nic *efx)
+{
+	return efx->rss_spread > 1;
+}
+
 /* Filters */
 
 void efx_mac_reconfigure(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index 5a1c5a8..133e9e3 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -2242,7 +2242,7 @@
 	 */
 	spec->priority = EFX_FILTER_PRI_AUTO;
 	spec->flags = (EFX_FILTER_FLAG_RX |
-		       (efx->n_rx_channels > 1 ? EFX_FILTER_FLAG_RX_RSS : 0) |
+		       (efx_rss_enabled(efx) ? EFX_FILTER_FLAG_RX_RSS : 0) |
 		       (efx->rx_scatter ? EFX_FILTER_FLAG_RX_SCATTER : 0));
 	spec->dmaq_id = 0;
 }
diff --git a/drivers/net/ethernet/sfc/txc43128_phy.c b/drivers/net/ethernet/sfc/txc43128_phy.c
index 3d5ee32..194f67d 100644
--- a/drivers/net/ethernet/sfc/txc43128_phy.c
+++ b/drivers/net/ethernet/sfc/txc43128_phy.c
@@ -418,7 +418,7 @@
 
 	val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
 	efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, val);
-	while (tries--) {
+	while (--tries) {
 		val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
 		if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN)))
 			break;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
index 52b8ed9..adff463 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -153,7 +153,11 @@
 	if (ret)
 		return ret;
 
-	return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+	if (ret)
+		sun7i_gmac_exit(pdev, plat_dat->bsp_priv);
+
+	return ret;
 }
 
 static const struct of_device_id sun7i_dwmac_match[] = {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3c6549a..a5b869e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3046,8 +3046,6 @@
 	priv->hw->dma->stop_tx(priv->ioaddr);
 	priv->hw->dma->stop_rx(priv->ioaddr);
 
-	stmmac_clear_descriptors(priv);
-
 	/* Enable Power down mode by programming the PMT regs */
 	if (device_may_wakeup(priv->device)) {
 		priv->hw->mac->pmt(priv->hw, priv->wolopts);
@@ -3105,7 +3103,12 @@
 
 	netif_device_attach(ndev);
 
-	init_dma_desc_rings(ndev, GFP_ATOMIC);
+	priv->cur_rx = 0;
+	priv->dirty_rx = 0;
+	priv->dirty_tx = 0;
+	priv->cur_tx = 0;
+	stmmac_clear_descriptors(priv);
+
 	stmmac_hw_setup(ndev, false);
 	stmmac_init_tx_coalesce(priv);
 	stmmac_set_rx_mode(ndev);
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index de5c30c..c2b79f5 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -967,8 +967,6 @@
 	err = udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev,
 				   &fl6.saddr, &fl6.daddr, prio, ttl,
 				   sport, geneve->dst_port, !udp_csum);
-
-	iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
 	return NETDEV_TX_OK;
 
 tx_error:
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
index 908e8d4..7f8e766 100644
--- a/drivers/net/phy/mdio-mux.c
+++ b/drivers/net/phy/mdio-mux.c
@@ -149,9 +149,14 @@
 		}
 		cb->bus_number = v;
 		cb->parent = pb;
-		cb->mii_bus = mdiobus_alloc();
-		cb->mii_bus->priv = cb;
 
+		cb->mii_bus = mdiobus_alloc();
+		if (!cb->mii_bus) {
+			ret_val = -ENOMEM;
+			of_node_put(child_bus_node);
+			break;
+		}
+		cb->mii_bus->priv = cb;
 		cb->mii_bus->irq = cb->phy_irq;
 		cb->mii_bus->name = "mdio_mux";
 		snprintf(cb->mii_bus->id, MII_BUS_ID_SIZE, "%x.%x",
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index cf6312f..e13ad6c 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -339,9 +339,18 @@
 {
 	const struct device *dev = &phydev->dev;
 	const struct device_node *of_node = dev->of_node;
+	const struct device *dev_walker;
 
-	if (!of_node && dev->parent->of_node)
-		of_node = dev->parent->of_node;
+	/* The Micrel driver has a deprecated option to place phy OF
+	 * properties in the MAC node. Walk up the tree of devices to
+	 * find a device with an OF node.
+	 */
+	dev_walker = &phydev->dev;
+	do {
+		of_node = dev_walker->of_node;
+		dev_walker = dev_walker->parent;
+
+	} while (!of_node && dev_walker);
 
 	if (of_node) {
 		ksz9021_load_values_from_of(phydev, of_node,
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 5e0b432..0a37f84 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -568,6 +568,9 @@
 	sk->sk_family		= PF_PPPOX;
 	sk->sk_protocol		= PX_PROTO_OE;
 
+	INIT_WORK(&pppox_sk(sk)->proto.pppoe.padt_work,
+		  pppoe_unbind_sock_work);
+
 	return 0;
 }
 
@@ -632,8 +635,6 @@
 
 	lock_sock(sk);
 
-	INIT_WORK(&po->proto.pppoe.padt_work, pppoe_unbind_sock_work);
-
 	error = -EINVAL;
 	if (sp->sa_protocol != PX_PROTO_OE)
 		goto end;
@@ -663,8 +664,13 @@
 			po->pppoe_dev = NULL;
 		}
 
-		memset(sk_pppox(po) + 1, 0,
-		       sizeof(struct pppox_sock) - sizeof(struct sock));
+		po->pppoe_ifindex = 0;
+		memset(&po->pppoe_pa, 0, sizeof(po->pppoe_pa));
+		memset(&po->pppoe_relay, 0, sizeof(po->pppoe_relay));
+		memset(&po->chan, 0, sizeof(po->chan));
+		po->next = NULL;
+		po->num = 0;
+
 		sk->sk_state = PPPOX_NONE;
 	}
 
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index fc69e41..597c53e 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -419,6 +419,9 @@
 	struct pptp_opt *opt = &po->proto.pptp;
 	int error = 0;
 
+	if (sockaddr_len < sizeof(struct sockaddr_pppox))
+		return -EINVAL;
+
 	lock_sock(sk);
 
 	opt->src_addr = sp->sa_addr.pptp;
@@ -440,6 +443,9 @@
 	struct flowi4 fl4;
 	int error = 0;
 
+	if (sockaddr_len < sizeof(struct sockaddr_pppox))
+		return -EINVAL;
+
 	if (sp->sa_protocol != PX_PROTO_PPTP)
 		return -EINVAL;
 
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index bbde988..8973abd 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -158,7 +158,7 @@
 	if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
 		goto err;
 
-	ret = cdc_ncm_bind_common(dev, intf, data_altsetting, 0);
+	ret = cdc_ncm_bind_common(dev, intf, data_altsetting, dev->driver_info->data);
 	if (ret)
 		goto err;
 
@@ -582,6 +582,26 @@
 	.tx_fixup = cdc_mbim_tx_fixup,
 };
 
+/* The spefication explicitly allows NDPs to be placed anywhere in the
+ * frame, but some devices fail unless the NDP is placed after the IP
+ * packets.  Using the CDC_NCM_FLAG_NDP_TO_END flags to force this
+ * behaviour.
+ *
+ * Note: The current implementation of this feature restricts each NTB
+ * to a single NDP, implying that multiplexed sessions cannot share an
+ * NTB. This might affect performace for multiplexed sessions.
+ */
+static const struct driver_info cdc_mbim_info_ndp_to_end = {
+	.description = "CDC MBIM",
+	.flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN,
+	.bind = cdc_mbim_bind,
+	.unbind = cdc_mbim_unbind,
+	.manage_power = cdc_mbim_manage_power,
+	.rx_fixup = cdc_mbim_rx_fixup,
+	.tx_fixup = cdc_mbim_tx_fixup,
+	.data = CDC_NCM_FLAG_NDP_TO_END,
+};
+
 static const struct usb_device_id mbim_devs[] = {
 	/* This duplicate NCM entry is intentional. MBIM devices can
 	 * be disguised as NCM by default, and this is necessary to
@@ -597,6 +617,10 @@
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0bdb, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
 	  .driver_info = (unsigned long)&cdc_mbim_info,
 	},
+	/* Huawei E3372 fails unless NDP comes after the IP packets */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x12d1, 0x157d, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+	  .driver_info = (unsigned long)&cdc_mbim_info_ndp_to_end,
+	},
 	/* default entry */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
 	  .driver_info = (unsigned long)&cdc_mbim_info_zlp,
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 3b1ba82..1e9843a 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -955,10 +955,18 @@
 	* NTH16 header as we would normally do. NDP isn't written to the SKB yet, and
 	* the wNdpIndex field in the header is actually not consistent with reality. It will be later.
 	*/
-	if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
+	if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
 		if (ctx->delayed_ndp16->dwSignature == sign)
 			return ctx->delayed_ndp16;
 
+		/* We can only push a single NDP to the end. Return
+		 * NULL to send what we've already got and queue this
+		 * skb for later.
+		 */
+		else if (ctx->delayed_ndp16->dwSignature)
+			return NULL;
+	}
+
 	/* follow the chain of NDPs, looking for a match */
 	while (ndpoffset) {
 		ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index d9427ca..2e32c41 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -3067,17 +3067,6 @@
 
 	mutex_lock(&tp->control);
 
-	/* The WORK_ENABLE may be set when autoresume occurs */
-	if (test_bit(WORK_ENABLE, &tp->flags)) {
-		clear_bit(WORK_ENABLE, &tp->flags);
-		usb_kill_urb(tp->intr_urb);
-		cancel_delayed_work_sync(&tp->schedule);
-
-		/* disable the tx/rx, if the workqueue has enabled them. */
-		if (netif_carrier_ok(netdev))
-			tp->rtl_ops.disable(tp);
-	}
-
 	tp->rtl_ops.up(tp);
 
 	rtl8152_set_speed(tp, AUTONEG_ENABLE,
@@ -3124,12 +3113,6 @@
 	} else {
 		mutex_lock(&tp->control);
 
-		/* The autosuspend may have been enabled and wouldn't
-		 * be disable when autoresume occurs, because the
-		 * netif_running() would be false.
-		 */
-		rtl_runtime_suspend_enable(tp, false);
-
 		tp->rtl_ops.down(tp);
 
 		mutex_unlock(&tp->control);
@@ -3512,7 +3495,7 @@
 		netif_device_attach(tp->netdev);
 	}
 
-	if (netif_running(tp->netdev)) {
+	if (netif_running(tp->netdev) && tp->netdev->flags & IFF_UP) {
 		if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
 			rtl_runtime_suspend_enable(tp, false);
 			clear_bit(SELECTIVE_SUSPEND, &tp->flags);
@@ -3532,6 +3515,8 @@
 		}
 		usb_submit_urb(tp->intr_urb, GFP_KERNEL);
 	} else if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
+		if (tp->netdev->flags & IFF_UP)
+			rtl_runtime_suspend_enable(tp, false);
 		clear_bit(SELECTIVE_SUSPEND, &tp->flags);
 	}
 
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index d8838ded..f94ab78 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -140,6 +140,12 @@
 
 	/* CPU hot plug notifier */
 	struct notifier_block nb;
+
+	/* Control VQ buffers: protected by the rtnl lock */
+	struct virtio_net_ctrl_hdr ctrl_hdr;
+	virtio_net_ctrl_ack ctrl_status;
+	u8 ctrl_promisc;
+	u8 ctrl_allmulti;
 };
 
 struct padded_vnet_hdr {
@@ -976,31 +982,30 @@
 				 struct scatterlist *out)
 {
 	struct scatterlist *sgs[4], hdr, stat;
-	struct virtio_net_ctrl_hdr ctrl;
-	virtio_net_ctrl_ack status = ~0;
 	unsigned out_num = 0, tmp;
 
 	/* Caller should know better */
 	BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ));
 
-	ctrl.class = class;
-	ctrl.cmd = cmd;
+	vi->ctrl_status = ~0;
+	vi->ctrl_hdr.class = class;
+	vi->ctrl_hdr.cmd = cmd;
 	/* Add header */
-	sg_init_one(&hdr, &ctrl, sizeof(ctrl));
+	sg_init_one(&hdr, &vi->ctrl_hdr, sizeof(vi->ctrl_hdr));
 	sgs[out_num++] = &hdr;
 
 	if (out)
 		sgs[out_num++] = out;
 
 	/* Add return status. */
-	sg_init_one(&stat, &status, sizeof(status));
+	sg_init_one(&stat, &vi->ctrl_status, sizeof(vi->ctrl_status));
 	sgs[out_num] = &stat;
 
 	BUG_ON(out_num + 1 > ARRAY_SIZE(sgs));
 	virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC);
 
 	if (unlikely(!virtqueue_kick(vi->cvq)))
-		return status == VIRTIO_NET_OK;
+		return vi->ctrl_status == VIRTIO_NET_OK;
 
 	/* Spin for a response, the kick causes an ioport write, trapping
 	 * into the hypervisor, so the request should be handled immediately.
@@ -1009,7 +1014,7 @@
 	       !virtqueue_is_broken(vi->cvq))
 		cpu_relax();
 
-	return status == VIRTIO_NET_OK;
+	return vi->ctrl_status == VIRTIO_NET_OK;
 }
 
 static int virtnet_set_mac_address(struct net_device *dev, void *p)
@@ -1151,7 +1156,6 @@
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 	struct scatterlist sg[2];
-	u8 promisc, allmulti;
 	struct virtio_net_ctrl_mac *mac_data;
 	struct netdev_hw_addr *ha;
 	int uc_count;
@@ -1163,22 +1167,22 @@
 	if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX))
 		return;
 
-	promisc = ((dev->flags & IFF_PROMISC) != 0);
-	allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
+	vi->ctrl_promisc = ((dev->flags & IFF_PROMISC) != 0);
+	vi->ctrl_allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
 
-	sg_init_one(sg, &promisc, sizeof(promisc));
+	sg_init_one(sg, &vi->ctrl_promisc, sizeof(vi->ctrl_promisc));
 
 	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
 				  VIRTIO_NET_CTRL_RX_PROMISC, sg))
 		dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
-			 promisc ? "en" : "dis");
+			 vi->ctrl_promisc ? "en" : "dis");
 
-	sg_init_one(sg, &allmulti, sizeof(allmulti));
+	sg_init_one(sg, &vi->ctrl_allmulti, sizeof(vi->ctrl_allmulti));
 
 	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
 				  VIRTIO_NET_CTRL_RX_ALLMULTI, sg))
 		dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n",
-			 allmulti ? "en" : "dis");
+			 vi->ctrl_allmulti ? "en" : "dis");
 
 	uc_count = netdev_uc_count(dev);
 	mc_count = netdev_mc_count(dev);
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 6369a57..ba363ce 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1158,7 +1158,6 @@
 	struct pcpu_sw_netstats *stats;
 	union vxlan_addr saddr;
 	int err = 0;
-	union vxlan_addr *remote_ip;
 
 	/* For flow based devices, map all packets to VNI 0 */
 	if (vs->flags & VXLAN_F_COLLECT_METADATA)
@@ -1169,7 +1168,6 @@
 	if (!vxlan)
 		goto drop;
 
-	remote_ip = &vxlan->default_dst.remote_ip;
 	skb_reset_mac_header(skb);
 	skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev)));
 	skb->protocol = eth_type_trans(skb, vxlan->dev);
@@ -1179,8 +1177,8 @@
 	if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
 		goto drop;
 
-	/* Re-examine inner Ethernet packet */
-	if (remote_ip->sa.sa_family == AF_INET) {
+	/* Get data from the outer IP header */
+	if (vxlan_get_sk_family(vs) == AF_INET) {
 		oip = ip_hdr(skb);
 		saddr.sin.sin_addr.s_addr = oip->saddr;
 		saddr.sa.sa_family = AF_INET;
@@ -1848,6 +1846,34 @@
 				   !(vxflags & VXLAN_F_UDP_CSUM));
 }
 
+#if IS_ENABLED(CONFIG_IPV6)
+static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
+					  struct sk_buff *skb, int oif,
+					  const struct in6_addr *daddr,
+					  struct in6_addr *saddr)
+{
+	struct dst_entry *ndst;
+	struct flowi6 fl6;
+	int err;
+
+	memset(&fl6, 0, sizeof(fl6));
+	fl6.flowi6_oif = oif;
+	fl6.daddr = *daddr;
+	fl6.saddr = vxlan->cfg.saddr.sin6.sin6_addr;
+	fl6.flowi6_mark = skb->mark;
+	fl6.flowi6_proto = IPPROTO_UDP;
+
+	err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
+					 vxlan->vn6_sock->sock->sk,
+					 &ndst, &fl6);
+	if (err < 0)
+		return ERR_PTR(err);
+
+	*saddr = fl6.saddr;
+	return ndst;
+}
+#endif
+
 /* Bypass encapsulation if the destination is local */
 static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
 			       struct vxlan_dev *dst_vxlan)
@@ -2035,21 +2061,17 @@
 #if IS_ENABLED(CONFIG_IPV6)
 	} else {
 		struct dst_entry *ndst;
-		struct flowi6 fl6;
+		struct in6_addr saddr;
 		u32 rt6i_flags;
 
 		if (!vxlan->vn6_sock)
 			goto drop;
 		sk = vxlan->vn6_sock->sock->sk;
 
-		memset(&fl6, 0, sizeof(fl6));
-		fl6.flowi6_oif = rdst ? rdst->remote_ifindex : 0;
-		fl6.daddr = dst->sin6.sin6_addr;
-		fl6.saddr = vxlan->cfg.saddr.sin6.sin6_addr;
-		fl6.flowi6_mark = skb->mark;
-		fl6.flowi6_proto = IPPROTO_UDP;
-
-		if (ipv6_stub->ipv6_dst_lookup(vxlan->net, sk, &ndst, &fl6)) {
+		ndst = vxlan6_get_route(vxlan, skb,
+					rdst ? rdst->remote_ifindex : 0,
+					&dst->sin6.sin6_addr, &saddr);
+		if (IS_ERR(ndst)) {
 			netdev_dbg(dev, "no route to %pI6\n",
 				   &dst->sin6.sin6_addr);
 			dev->stats.tx_carrier_errors++;
@@ -2081,7 +2103,7 @@
 		}
 
 		ttl = ttl ? : ip6_dst_hoplimit(ndst);
-		err = vxlan6_xmit_skb(ndst, sk, skb, dev, &fl6.saddr, &fl6.daddr,
+		err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr,
 				      0, ttl, src_port, dst_port, htonl(vni << 8), md,
 				      !net_eq(vxlan->net, dev_net(vxlan->dev)),
 				      flags);
@@ -2395,9 +2417,30 @@
 				  vxlan->cfg.port_max, true);
 	dport = info->key.tp_dst ? : vxlan->cfg.dst_port;
 
-	if (ip_tunnel_info_af(info) == AF_INET)
+	if (ip_tunnel_info_af(info) == AF_INET) {
+		if (!vxlan->vn4_sock)
+			return -EINVAL;
 		return egress_ipv4_tun_info(dev, skb, info, sport, dport);
-	return -EINVAL;
+	} else {
+#if IS_ENABLED(CONFIG_IPV6)
+		struct dst_entry *ndst;
+
+		if (!vxlan->vn6_sock)
+			return -EINVAL;
+		ndst = vxlan6_get_route(vxlan, skb, 0,
+					&info->key.u.ipv6.dst,
+					&info->key.u.ipv6.src);
+		if (IS_ERR(ndst))
+			return PTR_ERR(ndst);
+		dst_release(ndst);
+
+		info->key.tp_src = sport;
+		info->key.tp_dst = dport;
+#else /* !CONFIG_IPV6 */
+		return -EPFNOSUPPORT;
+#endif
+	}
+	return 0;
 }
 
 static const struct net_device_ops vxlan_netdev_ops = {
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index e481f37..1049c34 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -258,18 +258,18 @@
 						 struct netrx_pending_operations *npo)
 {
 	struct xenvif_rx_meta *meta;
-	struct xen_netif_rx_request *req;
+	struct xen_netif_rx_request req;
 
-	req = RING_GET_REQUEST(&queue->rx, queue->rx.req_cons++);
+	RING_COPY_REQUEST(&queue->rx, queue->rx.req_cons++, &req);
 
 	meta = npo->meta + npo->meta_prod++;
 	meta->gso_type = XEN_NETIF_GSO_TYPE_NONE;
 	meta->gso_size = 0;
 	meta->size = 0;
-	meta->id = req->id;
+	meta->id = req.id;
 
 	npo->copy_off = 0;
-	npo->copy_gref = req->gref;
+	npo->copy_gref = req.gref;
 
 	return meta;
 }
@@ -424,7 +424,7 @@
 	struct xenvif *vif = netdev_priv(skb->dev);
 	int nr_frags = skb_shinfo(skb)->nr_frags;
 	int i;
-	struct xen_netif_rx_request *req;
+	struct xen_netif_rx_request req;
 	struct xenvif_rx_meta *meta;
 	unsigned char *data;
 	int head = 1;
@@ -443,15 +443,15 @@
 
 	/* Set up a GSO prefix descriptor, if necessary */
 	if ((1 << gso_type) & vif->gso_prefix_mask) {
-		req = RING_GET_REQUEST(&queue->rx, queue->rx.req_cons++);
+		RING_COPY_REQUEST(&queue->rx, queue->rx.req_cons++, &req);
 		meta = npo->meta + npo->meta_prod++;
 		meta->gso_type = gso_type;
 		meta->gso_size = skb_shinfo(skb)->gso_size;
 		meta->size = 0;
-		meta->id = req->id;
+		meta->id = req.id;
 	}
 
-	req = RING_GET_REQUEST(&queue->rx, queue->rx.req_cons++);
+	RING_COPY_REQUEST(&queue->rx, queue->rx.req_cons++, &req);
 	meta = npo->meta + npo->meta_prod++;
 
 	if ((1 << gso_type) & vif->gso_mask) {
@@ -463,9 +463,9 @@
 	}
 
 	meta->size = 0;
-	meta->id = req->id;
+	meta->id = req.id;
 	npo->copy_off = 0;
-	npo->copy_gref = req->gref;
+	npo->copy_gref = req.gref;
 
 	data = skb->data;
 	while (data < skb_tail_pointer(skb)) {
@@ -679,9 +679,7 @@
 	 * Allow a burst big enough to transmit a jumbo packet of up to 128kB.
 	 * Otherwise the interface can seize up due to insufficient credit.
 	 */
-	max_burst = RING_GET_REQUEST(&queue->tx, queue->tx.req_cons)->size;
-	max_burst = min(max_burst, 131072UL);
-	max_burst = max(max_burst, queue->credit_bytes);
+	max_burst = max(131072UL, queue->credit_bytes);
 
 	/* Take care that adding a new chunk of credit doesn't wrap to zero. */
 	max_credit = queue->remaining_credit + queue->credit_bytes;
@@ -711,7 +709,7 @@
 		spin_unlock_irqrestore(&queue->response_lock, flags);
 		if (cons == end)
 			break;
-		txp = RING_GET_REQUEST(&queue->tx, cons++);
+		RING_COPY_REQUEST(&queue->tx, cons++, txp);
 	} while (1);
 	queue->tx.req_cons = cons;
 }
@@ -778,8 +776,7 @@
 		if (drop_err)
 			txp = &dropped_tx;
 
-		memcpy(txp, RING_GET_REQUEST(&queue->tx, cons + slots),
-		       sizeof(*txp));
+		RING_COPY_REQUEST(&queue->tx, cons + slots, txp);
 
 		/* If the guest submitted a frame >= 64 KiB then
 		 * first->size overflowed and following slots will
@@ -1112,8 +1109,7 @@
 			return -EBADR;
 		}
 
-		memcpy(&extra, RING_GET_REQUEST(&queue->tx, cons),
-		       sizeof(extra));
+		RING_COPY_REQUEST(&queue->tx, cons, &extra);
 		if (unlikely(!extra.type ||
 			     extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
 			queue->tx.req_cons = ++cons;
@@ -1322,7 +1318,7 @@
 
 		idx = queue->tx.req_cons;
 		rmb(); /* Ensure that we see the request before we copy it. */
-		memcpy(&txreq, RING_GET_REQUEST(&queue->tx, idx), sizeof(txreq));
+		RING_COPY_REQUEST(&queue->tx, idx, &txreq);
 
 		/* Credit-based scheduling. */
 		if (txreq.size > queue->remaining_credit &&
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 06c3364..15f2acb 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -271,9 +271,9 @@
 	return 0;
 }
 
-static int nvme_nvm_identity(struct request_queue *q, struct nvm_id *nvm_id)
+static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
 {
-	struct nvme_ns *ns = q->queuedata;
+	struct nvme_ns *ns = nvmdev->q->queuedata;
 	struct nvme_dev *dev = ns->dev;
 	struct nvme_nvm_id *nvme_nvm_id;
 	struct nvme_nvm_command c = {};
@@ -308,10 +308,10 @@
 	return ret;
 }
 
-static int nvme_nvm_get_l2p_tbl(struct request_queue *q, u64 slba, u32 nlb,
+static int nvme_nvm_get_l2p_tbl(struct nvm_dev *nvmdev, u64 slba, u32 nlb,
 				nvm_l2p_update_fn *update_l2p, void *priv)
 {
-	struct nvme_ns *ns = q->queuedata;
+	struct nvme_ns *ns = nvmdev->q->queuedata;
 	struct nvme_dev *dev = ns->dev;
 	struct nvme_nvm_command c = {};
 	u32 len = queue_max_hw_sectors(dev->admin_q) << 9;
@@ -415,10 +415,10 @@
 	return ret;
 }
 
-static int nvme_nvm_set_bb_tbl(struct request_queue *q, struct nvm_rq *rqd,
+static int nvme_nvm_set_bb_tbl(struct nvm_dev *nvmdev, struct nvm_rq *rqd,
 								int type)
 {
-	struct nvme_ns *ns = q->queuedata;
+	struct nvme_ns *ns = nvmdev->q->queuedata;
 	struct nvme_dev *dev = ns->dev;
 	struct nvme_nvm_command c = {};
 	int ret = 0;
@@ -455,7 +455,7 @@
 	struct nvm_rq *rqd = rq->end_io_data;
 	struct nvm_dev *dev = rqd->dev;
 
-	if (dev->mt->end_io(rqd, error))
+	if (dev->mt && dev->mt->end_io(rqd, error))
 		pr_err("nvme: err status: %x result: %lx\n",
 				rq->errors, (unsigned long)rq->special);
 
@@ -463,8 +463,9 @@
 	blk_mq_free_request(rq);
 }
 
-static int nvme_nvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
+static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
 {
+	struct request_queue *q = dev->q;
 	struct nvme_ns *ns = q->queuedata;
 	struct request *rq;
 	struct bio *bio = rqd->bio;
@@ -502,8 +503,9 @@
 	return 0;
 }
 
-static int nvme_nvm_erase_block(struct request_queue *q, struct nvm_rq *rqd)
+static int nvme_nvm_erase_block(struct nvm_dev *dev, struct nvm_rq *rqd)
 {
+	struct request_queue *q = dev->q;
 	struct nvme_ns *ns = q->queuedata;
 	struct nvme_nvm_command c = {};
 
@@ -515,9 +517,9 @@
 	return nvme_submit_sync_cmd(q, (struct nvme_command *)&c, NULL, 0);
 }
 
-static void *nvme_nvm_create_dma_pool(struct request_queue *q, char *name)
+static void *nvme_nvm_create_dma_pool(struct nvm_dev *nvmdev, char *name)
 {
-	struct nvme_ns *ns = q->queuedata;
+	struct nvme_ns *ns = nvmdev->q->queuedata;
 	struct nvme_dev *dev = ns->dev;
 
 	return dma_pool_create(name, dev->dev, PAGE_SIZE, PAGE_SIZE, 0);
@@ -530,7 +532,7 @@
 	dma_pool_destroy(dma_pool);
 }
 
-static void *nvme_nvm_dev_dma_alloc(struct request_queue *q, void *pool,
+static void *nvme_nvm_dev_dma_alloc(struct nvm_dev *dev, void *pool,
 				    gfp_t mem_flags, dma_addr_t *dma_handler)
 {
 	return dma_pool_alloc(pool, mem_flags, dma_handler);
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 9e294ff..0c67b57 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -2540,8 +2540,17 @@
 {
 	bool kill = nvme_io_incapable(ns->dev) && !blk_queue_dying(ns->queue);
 
-	if (kill)
+	if (kill) {
 		blk_set_queue_dying(ns->queue);
+
+		/*
+		 * The controller was shutdown first if we got here through
+		 * device removal. The shutdown may requeue outstanding
+		 * requests. These need to be aborted immediately so
+		 * del_gendisk doesn't block indefinitely for their completion.
+		 */
+		blk_mq_abort_requeue_list(ns->queue);
+	}
 	if (ns->disk->flags & GENHD_FL_UP)
 		del_gendisk(ns->disk);
 	if (kill || !blk_queue_dying(ns->queue)) {
@@ -2977,6 +2986,15 @@
 {
 	struct nvme_ns *ns, *next;
 
+	if (nvme_io_incapable(dev)) {
+		/*
+		 * If the device is not capable of IO (surprise hot-removal,
+		 * for example), we need to quiesce prior to deleting the
+		 * namespaces. This will end outstanding requests and prevent
+		 * attempts to sync dirty data.
+		 */
+		nvme_dev_shutdown(dev);
+	}
 	list_for_each_entry_safe(ns, next, &dev->namespaces, list)
 		nvme_ns_remove(ns);
 }
diff --git a/drivers/of/address.c b/drivers/of/address.c
index cd53fe4..9582c57 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -485,9 +485,10 @@
 	int rone;
 	u64 offset = OF_BAD_ADDR;
 
-	/* Normally, an absence of a "ranges" property means we are
+	/*
+	 * Normally, an absence of a "ranges" property means we are
 	 * crossing a non-translatable boundary, and thus the addresses
-	 * below the current not cannot be converted to CPU physical ones.
+	 * below the current cannot be converted to CPU physical ones.
 	 * Unfortunately, while this is very clear in the spec, it's not
 	 * what Apple understood, and they do have things like /uni-n or
 	 * /ht nodes with no "ranges" property and a lot of perfectly
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index d243029..655f79d 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/initrd.h>
 #include <linux/memblock.h>
+#include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/of_reserved_mem.h>
@@ -436,6 +437,8 @@
 	return kzalloc(size, GFP_KERNEL);
 }
 
+static DEFINE_MUTEX(of_fdt_unflatten_mutex);
+
 /**
  * of_fdt_unflatten_tree - create tree of device_nodes from flat blob
  *
@@ -447,7 +450,9 @@
 void of_fdt_unflatten_tree(const unsigned long *blob,
 			struct device_node **mynodes)
 {
+	mutex_lock(&of_fdt_unflatten_mutex);
 	__unflatten_device_tree(blob, mynodes, &kernel_tree_alloc);
+	mutex_unlock(&of_fdt_unflatten_mutex);
 }
 EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
 
@@ -1041,7 +1046,7 @@
 int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
 					phys_addr_t size, bool nomap)
 {
-	pr_err("Reserved memory not supported, ignoring range 0x%pa - 0x%pa%s\n",
+	pr_err("Reserved memory not supported, ignoring range %pa - %pa%s\n",
 		  &base, &size, nomap ? " (nomap)" : "");
 	return -ENOSYS;
 }
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 902b89b..4fa916d 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -53,7 +53,7 @@
  * Returns a pointer to the interrupt parent node, or NULL if the interrupt
  * parent could not be determined.
  */
-static struct device_node *of_irq_find_parent(struct device_node *child)
+struct device_node *of_irq_find_parent(struct device_node *child)
 {
 	struct device_node *p;
 	const __be32 *parp;
@@ -77,6 +77,7 @@
 
 	return p;
 }
+EXPORT_SYMBOL_GPL(of_irq_find_parent);
 
 /**
  * of_irq_parse_raw - Low level interrupt tree parsing
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index be77e75..1a3556a 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -206,7 +206,13 @@
 {
 	const struct reserved_mem *ra = a, *rb = b;
 
-	return ra->base - rb->base;
+	if (ra->base < rb->base)
+		return -1;
+
+	if (ra->base > rb->base)
+		return 1;
+
+	return 0;
 }
 
 static void __init __rmem_check_for_overlap(void)
diff --git a/drivers/parisc/iommu-helpers.h b/drivers/parisc/iommu-helpers.h
index 761e77b..e56f156 100644
--- a/drivers/parisc/iommu-helpers.h
+++ b/drivers/parisc/iommu-helpers.h
@@ -104,7 +104,11 @@
 	struct scatterlist *contig_sg;	   /* contig chunk head */
 	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
 	unsigned int n_mappings = 0;
-	unsigned int max_seg_size = dma_get_max_seg_size(dev);
+	unsigned int max_seg_size = min(dma_get_max_seg_size(dev),
+					(unsigned)DMA_CHUNK_SIZE);
+	unsigned int max_seg_boundary = dma_get_seg_boundary(dev) + 1;
+	if (max_seg_boundary)	/* check if the addition above didn't overflow */
+		max_seg_size = min(max_seg_size, max_seg_boundary);
 
 	while (nents > 0) {
 
@@ -138,14 +142,11 @@
 
 			/*
 			** First make sure current dma stream won't
-			** exceed DMA_CHUNK_SIZE if we coalesce the
+			** exceed max_seg_size if we coalesce the
 			** next entry.
 			*/   
-			if(unlikely(ALIGN(dma_len + dma_offset + startsg->length,
-					    IOVP_SIZE) > DMA_CHUNK_SIZE))
-				break;
-
-			if (startsg->length + dma_len > max_seg_size)
+			if (unlikely(ALIGN(dma_len + dma_offset + startsg->length, IOVP_SIZE) >
+				     max_seg_size))
 				break;
 
 			/*
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c
index e5dda38..99da549 100644
--- a/drivers/pci/host/pcie-altera.c
+++ b/drivers/pci/host/pcie-altera.c
@@ -55,8 +55,10 @@
 #define TLP_CFG_DW2(bus, devfn, offset)	\
 				(((bus) << 24) | ((devfn) << 16) | (offset))
 #define TLP_REQ_ID(bus, devfn)		(((bus) << 8) | (devfn))
+#define TLP_COMP_STATUS(s)		(((s) >> 12) & 7)
 #define TLP_HDR_SIZE			3
 #define TLP_LOOP			500
+#define RP_DEVFN			0
 
 #define INTX_NUM			4
 
@@ -166,34 +168,41 @@
 
 static int tlp_read_packet(struct altera_pcie *pcie, u32 *value)
 {
-	u8 loop;
+	int i;
 	bool sop = 0;
 	u32 ctrl;
 	u32 reg0, reg1;
+	u32 comp_status = 1;
 
 	/*
 	 * Minimum 2 loops to read TLP headers and 1 loop to read data
 	 * payload.
 	 */
-	for (loop = 0; loop < TLP_LOOP; loop++) {
+	for (i = 0; i < TLP_LOOP; i++) {
 		ctrl = cra_readl(pcie, RP_RXCPL_STATUS);
 		if ((ctrl & RP_RXCPL_SOP) || (ctrl & RP_RXCPL_EOP) || sop) {
 			reg0 = cra_readl(pcie, RP_RXCPL_REG0);
 			reg1 = cra_readl(pcie, RP_RXCPL_REG1);
 
-			if (ctrl & RP_RXCPL_SOP)
+			if (ctrl & RP_RXCPL_SOP) {
 				sop = true;
+				comp_status = TLP_COMP_STATUS(reg1);
+			}
 
 			if (ctrl & RP_RXCPL_EOP) {
+				if (comp_status)
+					return PCIBIOS_DEVICE_NOT_FOUND;
+
 				if (value)
 					*value = reg0;
+
 				return PCIBIOS_SUCCESSFUL;
 			}
 		}
 		udelay(5);
 	}
 
-	return -ENOENT;
+	return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
 static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers,
@@ -233,7 +242,7 @@
 	else
 		headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGRD1);
 
-	headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn),
+	headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN),
 					TLP_READ_TAG, byte_en);
 	headers[2] = TLP_CFG_DW2(bus, devfn, where);
 
@@ -253,7 +262,7 @@
 	else
 		headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGWR1);
 
-	headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn),
+	headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN),
 					TLP_WRITE_TAG, byte_en);
 	headers[2] = TLP_CFG_DW2(bus, devfn, where);
 
@@ -458,7 +467,7 @@
 	struct device_node *node = dev->of_node;
 
 	/* Setup INTx */
-	pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM,
+	pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM + 1,
 					&intx_domain_ops, pcie);
 	if (!pcie->irq_domain) {
 		dev_err(dev, "Failed to get a INTx IRQ domain\n");
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 53e4632..7eaa4c8 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -54,7 +54,7 @@
 	struct irq_domain *domain;
 
 	domain = pci_msi_get_domain(dev);
-	if (domain)
+	if (domain && irq_domain_is_hierarchy(domain))
 		return pci_msi_domain_alloc_irqs(domain, dev, nvec, type);
 
 	return arch_setup_msi_irqs(dev, nvec, type);
@@ -65,7 +65,7 @@
 	struct irq_domain *domain;
 
 	domain = pci_msi_get_domain(dev);
-	if (domain)
+	if (domain && irq_domain_is_hierarchy(domain))
 		pci_msi_domain_free_irqs(domain, dev);
 	else
 		arch_teardown_msi_irqs(dev);
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 7eb5859d..03cb3ea 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -233,6 +233,7 @@
 	tristate "Allwinner sun9i SoC USB PHY driver"
 	depends on ARCH_SUNXI && HAS_IOMEM && OF
 	depends on RESET_CONTROLLER
+	depends on USB_COMMON
 	select GENERIC_PHY
 	help
 	  Enable this to support the transceiver that is part of Allwinner
diff --git a/drivers/phy/phy-bcm-cygnus-pcie.c b/drivers/phy/phy-bcm-cygnus-pcie.c
index 7ad72b7..082c03f 100644
--- a/drivers/phy/phy-bcm-cygnus-pcie.c
+++ b/drivers/phy/phy-bcm-cygnus-pcie.c
@@ -128,6 +128,7 @@
 	struct phy_provider *provider;
 	struct resource *res;
 	unsigned cnt = 0;
+	int ret;
 
 	if (of_get_child_count(node) == 0) {
 		dev_err(dev, "PHY no child node\n");
@@ -154,24 +155,28 @@
 		if (of_property_read_u32(child, "reg", &id)) {
 			dev_err(dev, "missing reg property for %s\n",
 				child->name);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto put_child;
 		}
 
 		if (id >= MAX_NUM_PHYS) {
 			dev_err(dev, "invalid PHY id: %u\n", id);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto put_child;
 		}
 
 		if (core->phys[id].phy) {
 			dev_err(dev, "duplicated PHY id: %u\n", id);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto put_child;
 		}
 
 		p = &core->phys[id];
 		p->phy = devm_phy_create(dev, child, &cygnus_pcie_phy_ops);
 		if (IS_ERR(p->phy)) {
 			dev_err(dev, "failed to create PHY\n");
-			return PTR_ERR(p->phy);
+			ret = PTR_ERR(p->phy);
+			goto put_child;
 		}
 
 		p->core = core;
@@ -191,6 +196,9 @@
 	dev_dbg(dev, "registered %u PCIe PHY(s)\n", cnt);
 
 	return 0;
+put_child:
+	of_node_put(child);
+	return ret;
 }
 
 static const struct of_device_id cygnus_pcie_phy_match_table[] = {
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
index 77a2e05..f84a33a 100644
--- a/drivers/phy/phy-berlin-sata.c
+++ b/drivers/phy/phy-berlin-sata.c
@@ -195,7 +195,7 @@
 	struct phy_provider *phy_provider;
 	struct phy_berlin_priv *priv;
 	struct resource *res;
-	int i = 0;
+	int ret, i = 0;
 	u32 phy_id;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -237,22 +237,27 @@
 		if (of_property_read_u32(child, "reg", &phy_id)) {
 			dev_err(dev, "missing reg property in node %s\n",
 				child->name);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto put_child;
 		}
 
 		if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
 			dev_err(dev, "invalid reg in node %s\n", child->name);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto put_child;
 		}
 
 		phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
-		if (!phy_desc)
-			return -ENOMEM;
+		if (!phy_desc) {
+			ret = -ENOMEM;
+			goto put_child;
+		}
 
 		phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "failed to create PHY %d\n", phy_id);
-			return PTR_ERR(phy);
+			ret = PTR_ERR(phy);
+			goto put_child;
 		}
 
 		phy_desc->phy = phy;
@@ -269,6 +274,9 @@
 	phy_provider =
 		devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
 	return PTR_ERR_OR_ZERO(phy_provider);
+put_child:
+	of_node_put(child);
+	return ret;
 }
 
 static const struct of_device_id phy_berlin_sata_of_match[] = {
diff --git a/drivers/phy/phy-brcmstb-sata.c b/drivers/phy/phy-brcmstb-sata.c
index 8a2cb16..cd9dba8 100644
--- a/drivers/phy/phy-brcmstb-sata.c
+++ b/drivers/phy/phy-brcmstb-sata.c
@@ -140,7 +140,7 @@
 	struct brcm_sata_phy *priv;
 	struct resource *res;
 	struct phy_provider *provider;
-	int count = 0;
+	int ret, count = 0;
 
 	if (of_get_child_count(dn) == 0)
 		return -ENODEV;
@@ -163,16 +163,19 @@
 		if (of_property_read_u32(child, "reg", &id)) {
 			dev_err(dev, "missing reg property in node %s\n",
 					child->name);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto put_child;
 		}
 
 		if (id >= MAX_PORTS) {
 			dev_err(dev, "invalid reg: %u\n", id);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto put_child;
 		}
 		if (priv->phys[id].phy) {
 			dev_err(dev, "already registered port %u\n", id);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto put_child;
 		}
 
 		port = &priv->phys[id];
@@ -182,7 +185,8 @@
 		port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
 		if (IS_ERR(port->phy)) {
 			dev_err(dev, "failed to create PHY\n");
-			return PTR_ERR(port->phy);
+			ret = PTR_ERR(port->phy);
+			goto put_child;
 		}
 
 		phy_set_drvdata(port->phy, port);
@@ -198,6 +202,9 @@
 	dev_info(dev, "registered %d port(s)\n", count);
 
 	return 0;
+put_child:
+	of_node_put(child);
+	return ret;
 }
 
 static struct platform_driver brcm_sata_phy_driver = {
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index fc48fac..8c7f27d 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -636,8 +636,9 @@
  * @np: node containing the phy
  * @index: index of the phy
  *
- * Gets the phy using _of_phy_get(), and associates a device with it using
- * devres. On driver detach, release function is invoked on the devres data,
+ * Gets the phy using _of_phy_get(), then gets a refcount to it,
+ * and associates a device with it using devres. On driver detach,
+ * release function is invoked on the devres data,
  * then, devres data is freed.
  *
  */
@@ -651,13 +652,21 @@
 		return ERR_PTR(-ENOMEM);
 
 	phy = _of_phy_get(np, index);
-	if (!IS_ERR(phy)) {
-		*ptr = phy;
-		devres_add(dev, ptr);
-	} else {
+	if (IS_ERR(phy)) {
 		devres_free(ptr);
+		return phy;
 	}
 
+	if (!try_module_get(phy->ops->owner)) {
+		devres_free(ptr);
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	get_device(&phy->dev);
+
+	*ptr = phy;
+	devres_add(dev, ptr);
+
 	return phy;
 }
 EXPORT_SYMBOL_GPL(devm_of_phy_get_by_index);
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
index c47b56b..3acd2a1 100644
--- a/drivers/phy/phy-miphy28lp.c
+++ b/drivers/phy/phy-miphy28lp.c
@@ -1226,15 +1226,18 @@
 
 		miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
 					 GFP_KERNEL);
-		if (!miphy_phy)
-			return -ENOMEM;
+		if (!miphy_phy) {
+			ret = -ENOMEM;
+			goto put_child;
+		}
 
 		miphy_dev->phys[port] = miphy_phy;
 
 		phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops);
 		if (IS_ERR(phy)) {
 			dev_err(&pdev->dev, "failed to create PHY\n");
-			return PTR_ERR(phy);
+			ret = PTR_ERR(phy);
+			goto put_child;
 		}
 
 		miphy_dev->phys[port]->phy = phy;
@@ -1242,11 +1245,11 @@
 
 		ret = miphy28lp_of_probe(child, miphy_phy);
 		if (ret)
-			return ret;
+			goto put_child;
 
 		ret = miphy28lp_probe_resets(child, miphy_dev->phys[port]);
 		if (ret)
-			return ret;
+			goto put_child;
 
 		phy_set_drvdata(phy, miphy_dev->phys[port]);
 		port++;
@@ -1255,6 +1258,9 @@
 
 	provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);
 	return PTR_ERR_OR_ZERO(provider);
+put_child:
+	of_node_put(child);
+	return ret;
 }
 
 static const struct of_device_id miphy28lp_of_match[] = {
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
index 00a686a..e661f3b 100644
--- a/drivers/phy/phy-miphy365x.c
+++ b/drivers/phy/phy-miphy365x.c
@@ -566,22 +566,25 @@
 
 		miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
 					 GFP_KERNEL);
-		if (!miphy_phy)
-			return -ENOMEM;
+		if (!miphy_phy) {
+			ret = -ENOMEM;
+			goto put_child;
+		}
 
 		miphy_dev->phys[port] = miphy_phy;
 
 		phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops);
 		if (IS_ERR(phy)) {
 			dev_err(&pdev->dev, "failed to create PHY\n");
-			return PTR_ERR(phy);
+			ret = PTR_ERR(phy);
+			goto put_child;
 		}
 
 		miphy_dev->phys[port]->phy = phy;
 
 		ret = miphy365x_of_probe(child, miphy_phy);
 		if (ret)
-			return ret;
+			goto put_child;
 
 		phy_set_drvdata(phy, miphy_dev->phys[port]);
 
@@ -591,12 +594,15 @@
 					&miphy_phy->ctrlreg);
 		if (ret) {
 			dev_err(&pdev->dev, "No sysconfig offset found\n");
-			return ret;
+			goto put_child;
 		}
 	}
 
 	provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate);
 	return PTR_ERR_OR_ZERO(provider);
+put_child:
+	of_node_put(child);
+	return ret;
 }
 
 static const struct of_device_id miphy365x_of_match[] = {
diff --git a/drivers/phy/phy-mt65xx-usb3.c b/drivers/phy/phy-mt65xx-usb3.c
index f30b28b..e427c3b 100644
--- a/drivers/phy/phy-mt65xx-usb3.c
+++ b/drivers/phy/phy-mt65xx-usb3.c
@@ -415,7 +415,7 @@
 	struct resource *sif_res;
 	struct mt65xx_u3phy *u3phy;
 	struct resource res;
-	int port;
+	int port, retval;
 
 	u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL);
 	if (!u3phy)
@@ -447,31 +447,34 @@
 	for_each_child_of_node(np, child_np) {
 		struct mt65xx_phy_instance *instance;
 		struct phy *phy;
-		int retval;
 
 		instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
-		if (!instance)
-			return -ENOMEM;
+		if (!instance) {
+			retval = -ENOMEM;
+			goto put_child;
+		}
 
 		u3phy->phys[port] = instance;
 
 		phy = devm_phy_create(dev, child_np, &mt65xx_u3phy_ops);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "failed to create phy\n");
-			return PTR_ERR(phy);
+			retval = PTR_ERR(phy);
+			goto put_child;
 		}
 
 		retval = of_address_to_resource(child_np, 0, &res);
 		if (retval) {
 			dev_err(dev, "failed to get address resource(id-%d)\n",
 				port);
-			return retval;
+			goto put_child;
 		}
 
 		instance->port_base = devm_ioremap_resource(&phy->dev, &res);
 		if (IS_ERR(instance->port_base)) {
 			dev_err(dev, "failed to remap phy regs\n");
-			return PTR_ERR(instance->port_base);
+			retval = PTR_ERR(instance->port_base);
+			goto put_child;
 		}
 
 		instance->phy = phy;
@@ -483,6 +486,9 @@
 	provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate);
 
 	return PTR_ERR_OR_ZERO(provider);
+put_child:
+	of_node_put(child_np);
+	return retval;
 }
 
 static const struct of_device_id mt65xx_u3phy_id_table[] = {
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 91d6f34..62c43c4 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -108,13 +108,16 @@
 
 	for_each_available_child_of_node(dev->of_node, child) {
 		rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
-		if (!rk_phy)
-			return -ENOMEM;
+		if (!rk_phy) {
+			err = -ENOMEM;
+			goto put_child;
+		}
 
 		if (of_property_read_u32(child, "reg", &reg_offset)) {
 			dev_err(dev, "missing reg property in node %s\n",
 				child->name);
-			return -EINVAL;
+			err = -EINVAL;
+			goto put_child;
 		}
 
 		rk_phy->reg_offset = reg_offset;
@@ -127,18 +130,22 @@
 		rk_phy->phy = devm_phy_create(dev, child, &ops);
 		if (IS_ERR(rk_phy->phy)) {
 			dev_err(dev, "failed to create PHY\n");
-			return PTR_ERR(rk_phy->phy);
+			err = PTR_ERR(rk_phy->phy);
+			goto put_child;
 		}
 		phy_set_drvdata(rk_phy->phy, rk_phy);
 
 		/* only power up usb phy when it use, so disable it when init*/
 		err = rockchip_usb_phy_power(rk_phy, 1);
 		if (err)
-			return err;
+			goto put_child;
 	}
 
 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 	return PTR_ERR_OR_ZERO(phy_provider);
+put_child:
+	of_node_put(child);
+	return err;
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index a1ea565..2e6ca69 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -342,12 +342,6 @@
 	return bcm2835_gpio_get_bit(pc, GPLEV0, offset);
 }
 
-static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
-		unsigned offset, int value)
-{
-	return pinctrl_gpio_direction_output(chip->base + offset);
-}
-
 static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
@@ -355,6 +349,13 @@
 	bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset);
 }
 
+static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
+		unsigned offset, int value)
+{
+	bcm2835_gpio_set(chip, offset, value);
+	return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
 static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
diff --git a/drivers/pinctrl/freescale/pinctrl-vf610.c b/drivers/pinctrl/freescale/pinctrl-vf610.c
index 37a0375..587d1ff 100644
--- a/drivers/pinctrl/freescale/pinctrl-vf610.c
+++ b/drivers/pinctrl/freescale/pinctrl-vf610.c
@@ -299,7 +299,7 @@
 static struct imx_pinctrl_soc_info vf610_pinctrl_info = {
 	.pins = vf610_pinctrl_pads,
 	.npins = ARRAY_SIZE(vf610_pinctrl_pads),
-	.flags = SHARE_MUX_CONF_REG,
+	.flags = SHARE_MUX_CONF_REG | ZERO_OFFSET_VALID,
 };
 
 static const struct of_device_id vf610_pinctrl_of_match[] = {
diff --git a/drivers/pinctrl/intel/pinctrl-broxton.c b/drivers/pinctrl/intel/pinctrl-broxton.c
index e42d5d4..5979d38 100644
--- a/drivers/pinctrl/intel/pinctrl-broxton.c
+++ b/drivers/pinctrl/intel/pinctrl-broxton.c
@@ -28,6 +28,7 @@
 		.padcfglock_offset = BXT_PADCFGLOCK,	\
 		.hostown_offset = BXT_HOSTSW_OWN,	\
 		.ie_offset = BXT_GPI_IE,		\
+		.gpp_size = 32,                         \
 		.pin_base = (s),			\
 		.npins = ((e) - (s) + 1),		\
 	}
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 392e28d..26f6b6f 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -25,9 +25,6 @@
 
 #include "pinctrl-intel.h"
 
-/* Maximum number of pads in each group */
-#define NPADS_IN_GPP			24
-
 /* Offset from regs */
 #define PADBAR				0x00c
 #define GPI_IS				0x100
@@ -37,6 +34,7 @@
 #define PADOWN_BITS			4
 #define PADOWN_SHIFT(p)			((p) % 8 * PADOWN_BITS)
 #define PADOWN_MASK(p)			(0xf << PADOWN_SHIFT(p))
+#define PADOWN_GPP(p)			((p) / 8)
 
 /* Offset from pad_regs */
 #define PADCFG0				0x000
@@ -142,7 +140,7 @@
 static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
 {
 	const struct intel_community *community;
-	unsigned padno, gpp, gpp_offset, offset;
+	unsigned padno, gpp, offset, group;
 	void __iomem *padown;
 
 	community = intel_get_community(pctrl, pin);
@@ -152,9 +150,9 @@
 		return true;
 
 	padno = pin_to_padno(community, pin);
-	gpp = padno / NPADS_IN_GPP;
-	gpp_offset = padno % NPADS_IN_GPP;
-	offset = community->padown_offset + gpp * 16 + (gpp_offset / 8) * 4;
+	group = padno / community->gpp_size;
+	gpp = PADOWN_GPP(padno % community->gpp_size);
+	offset = community->padown_offset + 0x10 * group + gpp * 4;
 	padown = community->regs + offset;
 
 	return !(readl(padown) & PADOWN_MASK(padno));
@@ -173,11 +171,11 @@
 		return false;
 
 	padno = pin_to_padno(community, pin);
-	gpp = padno / NPADS_IN_GPP;
+	gpp = padno / community->gpp_size;
 	offset = community->hostown_offset + gpp * 4;
 	hostown = community->regs + offset;
 
-	return !(readl(hostown) & BIT(padno % NPADS_IN_GPP));
+	return !(readl(hostown) & BIT(padno % community->gpp_size));
 }
 
 static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
@@ -193,7 +191,7 @@
 		return false;
 
 	padno = pin_to_padno(community, pin);
-	gpp = padno / NPADS_IN_GPP;
+	gpp = padno / community->gpp_size;
 
 	/*
 	 * If PADCFGLOCK and PADCFGLOCKTX bits are both clear for this pad,
@@ -202,12 +200,12 @@
 	 */
 	offset = community->padcfglock_offset + gpp * 8;
 	value = readl(community->regs + offset);
-	if (value & BIT(pin % NPADS_IN_GPP))
+	if (value & BIT(pin % community->gpp_size))
 		return true;
 
 	offset = community->padcfglock_offset + 4 + gpp * 8;
 	value = readl(community->regs + offset);
-	if (value & BIT(pin % NPADS_IN_GPP))
+	if (value & BIT(pin % community->gpp_size))
 		return true;
 
 	return false;
@@ -663,8 +661,8 @@
 	community = intel_get_community(pctrl, pin);
 	if (community) {
 		unsigned padno = pin_to_padno(community, pin);
-		unsigned gpp_offset = padno % NPADS_IN_GPP;
-		unsigned gpp = padno / NPADS_IN_GPP;
+		unsigned gpp_offset = padno % community->gpp_size;
+		unsigned gpp = padno / community->gpp_size;
 
 		writel(BIT(gpp_offset), community->regs + GPI_IS + gpp * 4);
 	}
@@ -685,8 +683,8 @@
 	community = intel_get_community(pctrl, pin);
 	if (community) {
 		unsigned padno = pin_to_padno(community, pin);
-		unsigned gpp_offset = padno % NPADS_IN_GPP;
-		unsigned gpp = padno / NPADS_IN_GPP;
+		unsigned gpp_offset = padno % community->gpp_size;
+		unsigned gpp = padno / community->gpp_size;
 		void __iomem *reg;
 		u32 value;
 
@@ -780,8 +778,8 @@
 		return -EINVAL;
 
 	padno = pin_to_padno(community, pin);
-	gpp = padno / NPADS_IN_GPP;
-	gpp_offset = padno % NPADS_IN_GPP;
+	gpp = padno / community->gpp_size;
+	gpp_offset = padno % community->gpp_size;
 
 	/* Clear the existing wake status */
 	writel(BIT(gpp_offset), community->regs + GPI_GPE_STS + gpp * 4);
@@ -819,14 +817,14 @@
 		/* Only interrupts that are enabled */
 		pending &= enabled;
 
-		for_each_set_bit(gpp_offset, &pending, NPADS_IN_GPP) {
+		for_each_set_bit(gpp_offset, &pending, community->gpp_size) {
 			unsigned padno, irq;
 
 			/*
 			 * The last group in community can have less pins
 			 * than NPADS_IN_GPP.
 			 */
-			padno = gpp_offset + gpp * NPADS_IN_GPP;
+			padno = gpp_offset + gpp * community->gpp_size;
 			if (padno >= community->npins)
 				break;
 
@@ -1002,7 +1000,8 @@
 
 		community->regs = regs;
 		community->pad_regs = regs + padbar;
-		community->ngpps = DIV_ROUND_UP(community->npins, NPADS_IN_GPP);
+		community->ngpps = DIV_ROUND_UP(community->npins,
+						community->gpp_size);
 	}
 
 	irq = platform_get_irq(pdev, 0);
diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h
index 4ec8b57..b602157 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.h
+++ b/drivers/pinctrl/intel/pinctrl-intel.h
@@ -55,6 +55,8 @@
  *                  ACPI).
  * @ie_offset: Register offset of GPI_IE from @regs.
  * @pin_base: Starting pin of pins in this community
+ * @gpp_size: Maximum number of pads in each group, such as PADCFGLOCK,
+ *            HOSTSW_OWN,  GPI_IS, GPI_IE, etc.
  * @npins: Number of pins in this community
  * @regs: Community specific common registers (reserved for core driver)
  * @pad_regs: Community specific pad registers (reserved for core driver)
@@ -68,6 +70,7 @@
 	unsigned hostown_offset;
 	unsigned ie_offset;
 	unsigned pin_base;
+	unsigned gpp_size;
 	size_t npins;
 	void __iomem *regs;
 	void __iomem *pad_regs;
diff --git a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
index 1de9ae5..c725a53 100644
--- a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
+++ b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
@@ -30,6 +30,7 @@
 		.padcfglock_offset = SPT_PADCFGLOCK,	\
 		.hostown_offset = SPT_HOSTSW_OWN,	\
 		.ie_offset = SPT_GPI_IE,		\
+		.gpp_size = 24,				\
 		.pin_base = (s),			\
 		.npins = ((e) - (s) + 1),		\
 	}
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index cc97f08..48747c2 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -1341,10 +1341,13 @@
 
 	for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
 		/* check if the domain is locked by BIOS */
-		if (rapl_read_data_raw(rd, FW_LOCK, false, &locked)) {
+		ret = rapl_read_data_raw(rd, FW_LOCK, false, &locked);
+		if (ret)
+			return ret;
+		if (locked) {
 			pr_info("RAPL package %d domain %s locked by BIOS\n",
 				rp->id, rd->name);
-				rd->state |= DOMAIN_STATE_BIOS_LOCKED;
+			rd->state |= DOMAIN_STATE_BIOS_LOCKED;
 		}
 	}
 
diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c
index 284b587..d6c853b 100644
--- a/drivers/rtc/rtc-da9063.c
+++ b/drivers/rtc/rtc-da9063.c
@@ -483,17 +483,6 @@
 
 	platform_set_drvdata(pdev, rtc);
 
-	irq_alarm = platform_get_irq_byname(pdev, "ALARM");
-	ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL,
-					da9063_alarm_event,
-					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-					"ALARM", rtc);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n",
-			irq_alarm, ret);
-		return ret;
-	}
-
 	rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC,
 					   &da9063_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc_dev))
@@ -501,6 +490,16 @@
 
 	da9063_data_to_tm(data, &rtc->alarm_time, rtc);
 	rtc->rtc_sync = false;
+
+	irq_alarm = platform_get_irq_byname(pdev, "ALARM");
+	ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL,
+					da9063_alarm_event,
+					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+					"ALARM", rtc);
+	if (ret)
+		dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n",
+			irq_alarm, ret);
+
 	return ret;
 }
 
diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c
index 91ca0bc..35c9aad 100644
--- a/drivers/rtc/rtc-rk808.c
+++ b/drivers/rtc/rtc-rk808.c
@@ -56,6 +56,42 @@
 	int irq;
 };
 
+/*
+ * The Rockchip calendar used by the RK808 counts November with 31 days. We use
+ * these translation functions to convert its dates to/from the Gregorian
+ * calendar used by the rest of the world. We arbitrarily define Jan 1st, 2016
+ * as the day when both calendars were in sync, and treat all other dates
+ * relative to that.
+ * NOTE: Other system software (e.g. firmware) that reads the same hardware must
+ * implement this exact same conversion algorithm, with the same anchor date.
+ */
+static time64_t nov2dec_transitions(struct rtc_time *tm)
+{
+	return (tm->tm_year + 1900) - 2016 + (tm->tm_mon + 1 > 11 ? 1 : 0);
+}
+
+static void rockchip_to_gregorian(struct rtc_time *tm)
+{
+	/* If it's Nov 31st, rtc_tm_to_time64() will count that like Dec 1st */
+	time64_t time = rtc_tm_to_time64(tm);
+	rtc_time64_to_tm(time + nov2dec_transitions(tm) * 86400, tm);
+}
+
+static void gregorian_to_rockchip(struct rtc_time *tm)
+{
+	time64_t extra_days = nov2dec_transitions(tm);
+	time64_t time = rtc_tm_to_time64(tm);
+	rtc_time64_to_tm(time - extra_days * 86400, tm);
+
+	/* Compensate if we went back over Nov 31st (will work up to 2381) */
+	if (nov2dec_transitions(tm) < extra_days) {
+		if (tm->tm_mon + 1 == 11)
+			tm->tm_mday++;	/* This may result in 31! */
+		else
+			rtc_time64_to_tm(time - (extra_days - 1) * 86400, tm);
+	}
+}
+
 /* Read current time and date in RTC */
 static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
 {
@@ -101,9 +137,10 @@
 	tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1;
 	tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100;
 	tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK);
+	rockchip_to_gregorian(tm);
 	dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
 		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
-		tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
+		tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
 
 	return ret;
 }
@@ -116,6 +153,10 @@
 	u8 rtc_data[NUM_TIME_REGS];
 	int ret;
 
+	dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+		tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
+	gregorian_to_rockchip(tm);
 	rtc_data[0] = bin2bcd(tm->tm_sec);
 	rtc_data[1] = bin2bcd(tm->tm_min);
 	rtc_data[2] = bin2bcd(tm->tm_hour);
@@ -123,9 +164,6 @@
 	rtc_data[4] = bin2bcd(tm->tm_mon + 1);
 	rtc_data[5] = bin2bcd(tm->tm_year - 100);
 	rtc_data[6] = bin2bcd(tm->tm_wday);
-	dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
-		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
-		tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
 
 	/* Stop RTC while updating the RTC registers */
 	ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
@@ -170,6 +208,7 @@
 	alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK);
 	alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1;
 	alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100;
+	rockchip_to_gregorian(&alrm->time);
 
 	ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg);
 	if (ret) {
@@ -227,6 +266,7 @@
 		alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
 		alrm->time.tm_min, alrm->time.tm_sec);
 
+	gregorian_to_rockchip(&alrm->time);
 	alrm_data[0] = bin2bcd(alrm->time.tm_sec);
 	alrm_data[1] = bin2bcd(alrm->time.tm_min);
 	alrm_data[2] = bin2bcd(alrm->time.tm_hour);
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 61f7685..24ec282 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -599,8 +599,10 @@
 	status = ap_sm_recv(ap_dev);
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
-		if (ap_dev->queue_count > 0)
+		if (ap_dev->queue_count > 0) {
+			ap_dev->state = AP_STATE_WORKING;
 			return AP_WAIT_AGAIN;
+		}
 		ap_dev->state = AP_STATE_IDLE;
 		return AP_WAIT_NONE;
 	case AP_RESPONSE_NO_PENDING_REPLY:
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index b2a1a81..1b83159 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -984,32 +984,9 @@
 	return vq;
 }
 
-static void virtio_ccw_int_handler(struct ccw_device *cdev,
-				   unsigned long intparm,
-				   struct irb *irb)
+static void virtio_ccw_check_activity(struct virtio_ccw_device *vcdev,
+				      __u32 activity)
 {
-	__u32 activity = intparm & VIRTIO_CCW_INTPARM_MASK;
-	struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev);
-	int i;
-	struct virtqueue *vq;
-
-	if (!vcdev)
-		return;
-	/* Check if it's a notification from the host. */
-	if ((intparm == 0) &&
-	    (scsw_stctl(&irb->scsw) ==
-	     (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))) {
-		/* OK */
-	}
-	if (irb_is_error(irb)) {
-		/* Command reject? */
-		if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) &&
-		    (irb->ecw[0] & SNS0_CMD_REJECT))
-			vcdev->err = -EOPNOTSUPP;
-		else
-			/* Map everything else to -EIO. */
-			vcdev->err = -EIO;
-	}
 	if (vcdev->curr_io & activity) {
 		switch (activity) {
 		case VIRTIO_CCW_DOING_READ_FEAT:
@@ -1029,12 +1006,47 @@
 			break;
 		default:
 			/* don't know what to do... */
-			dev_warn(&cdev->dev, "Suspicious activity '%08x'\n",
-				 activity);
+			dev_warn(&vcdev->cdev->dev,
+				 "Suspicious activity '%08x'\n", activity);
 			WARN_ON(1);
 			break;
 		}
 	}
+}
+
+static void virtio_ccw_int_handler(struct ccw_device *cdev,
+				   unsigned long intparm,
+				   struct irb *irb)
+{
+	__u32 activity = intparm & VIRTIO_CCW_INTPARM_MASK;
+	struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev);
+	int i;
+	struct virtqueue *vq;
+
+	if (!vcdev)
+		return;
+	if (IS_ERR(irb)) {
+		vcdev->err = PTR_ERR(irb);
+		virtio_ccw_check_activity(vcdev, activity);
+		/* Don't poke around indicators, something's wrong. */
+		return;
+	}
+	/* Check if it's a notification from the host. */
+	if ((intparm == 0) &&
+	    (scsw_stctl(&irb->scsw) ==
+	     (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))) {
+		/* OK */
+	}
+	if (irb_is_error(irb)) {
+		/* Command reject? */
+		if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) &&
+		    (irb->ecw[0] & SNS0_CMD_REJECT))
+			vcdev->err = -EOPNOTSUPP;
+		else
+			/* Map everything else to -EIO. */
+			vcdev->err = -EIO;
+	}
+	virtio_ccw_check_activity(vcdev, activity);
 	for_each_set_bit(i, &vcdev->indicators,
 			 sizeof(vcdev->indicators) * BITS_PER_BYTE) {
 		/* The bit clear must happen before the vring kick. */
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index e4b7998..459abe1 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -219,13 +219,13 @@
 	struct scsi_device *sdev = to_scsi_device(dev);
 	int err = 0;
 
-	if (pm && pm->runtime_suspend) {
-		err = blk_pre_runtime_suspend(sdev->request_queue);
-		if (err)
-			return err;
+	err = blk_pre_runtime_suspend(sdev->request_queue);
+	if (err)
+		return err;
+	if (pm && pm->runtime_suspend)
 		err = pm->runtime_suspend(dev);
-		blk_post_runtime_suspend(sdev->request_queue, err);
-	}
+	blk_post_runtime_suspend(sdev->request_queue, err);
+
 	return err;
 }
 
@@ -248,11 +248,11 @@
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	int err = 0;
 
-	if (pm && pm->runtime_resume) {
-		blk_pre_runtime_resume(sdev->request_queue);
+	blk_pre_runtime_resume(sdev->request_queue);
+	if (pm && pm->runtime_resume)
 		err = pm->runtime_resume(dev);
-		blk_post_runtime_resume(sdev->request_queue, err);
-	}
+	blk_post_runtime_resume(sdev->request_queue, err);
+
 	return err;
 }
 
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index dcb0d76..044d064 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -84,6 +84,7 @@
 static int ses_recv_diag(struct scsi_device *sdev, int page_code,
 			 void *buf, int bufflen)
 {
+	int ret;
 	unsigned char cmd[] = {
 		RECEIVE_DIAGNOSTIC,
 		1,		/* Set PCV bit */
@@ -92,9 +93,26 @@
 		bufflen & 0xff,
 		0
 	};
+	unsigned char recv_page_code;
 
-	return scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
+	ret =  scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
 				NULL, SES_TIMEOUT, SES_RETRIES, NULL);
+	if (unlikely(!ret))
+		return ret;
+
+	recv_page_code = ((unsigned char *)buf)[0];
+
+	if (likely(recv_page_code == page_code))
+		return ret;
+
+	/* successful diagnostic but wrong page code.  This happens to some
+	 * USB devices, just print a message and pretend there was an error */
+
+	sdev_printk(KERN_ERR, sdev,
+		    "Wrong diagnostic page; asked for %d got %u\n",
+		    page_code, recv_page_code);
+
+	return -EINVAL;
 }
 
 static int ses_send_diag(struct scsi_device *sdev, int page_code,
@@ -541,7 +559,15 @@
 			if (desc_ptr)
 				desc_ptr += len;
 
-			if (addl_desc_ptr)
+			if (addl_desc_ptr &&
+			    /* only find additional descriptions for specific devices */
+			    (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
+			     type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE ||
+			     type_ptr[0] == ENCLOSURE_COMPONENT_SAS_EXPANDER ||
+			     /* these elements are optional */
+			     type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_TARGET_PORT ||
+			     type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT ||
+			     type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS))
 				addl_desc_ptr += addl_desc_ptr[1] + 2;
 
 		}
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 59a1143..39412c9 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -167,7 +167,7 @@
 {
 	unsigned int val;
 
-	regmap_read(dspi->regmap, SPI_CTAR(dspi->cs), &val);
+	regmap_read(dspi->regmap, SPI_CTAR(0), &val);
 
 	return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1;
 }
@@ -257,7 +257,7 @@
 
 	return	SPI_PUSHR_TXDATA(d16) |
 		SPI_PUSHR_PCS(dspi->cs) |
-		SPI_PUSHR_CTAS(dspi->cs) |
+		SPI_PUSHR_CTAS(0) |
 		SPI_PUSHR_CONT;
 }
 
@@ -290,7 +290,7 @@
 		 */
 		if (tx_word && (dspi->len == 1)) {
 			dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
-			regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
+			regmap_update_bits(dspi->regmap, SPI_CTAR(0),
 					SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
 			tx_word = 0;
 		}
@@ -339,7 +339,7 @@
 
 	if (tx_word && (dspi->len == 1)) {
 		dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
-		regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
+		regmap_update_bits(dspi->regmap, SPI_CTAR(0),
 				SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
 		tx_word = 0;
 	}
@@ -407,7 +407,7 @@
 		regmap_update_bits(dspi->regmap, SPI_MCR,
 				SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF,
 				SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF);
-		regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
+		regmap_write(dspi->regmap, SPI_CTAR(0),
 				dspi->cur_chip->ctar_val);
 
 		trans_mode = dspi->devtype_data->trans_mode;
@@ -566,7 +566,7 @@
 		if (!dspi->len) {
 			if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) {
 				regmap_update_bits(dspi->regmap,
-						   SPI_CTAR(dspi->cs),
+						   SPI_CTAR(0),
 						   SPI_FRAME_BITS_MASK,
 						   SPI_FRAME_BITS(16));
 				dspi->dataflags &= ~TRAN_STATE_WORD_ODD_NUM;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 2b0a8ec..dee1cb8 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1705,7 +1705,7 @@
 	master->bus_num = -1;
 	master->num_chipselect = 1;
 	master->dev.class = &spi_master_class;
-	master->dev.parent = get_device(dev);
+	master->dev.parent = dev;
 	spi_master_set_devdata(master, &master[1]);
 
 	return master;
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 91a0fcd..d0e7dfc 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -651,11 +651,11 @@
 		kfree(spidev->rx_buffer);
 		spidev->rx_buffer = NULL;
 
+		spin_lock_irq(&spidev->spi_lock);
 		if (spidev->spi)
 			spidev->speed_hz = spidev->spi->max_speed_hz;
 
 		/* ... after we unbound from the underlying device? */
-		spin_lock_irq(&spidev->spi_lock);
 		dofree = (spidev->spi == NULL);
 		spin_unlock_irq(&spidev->spi_lock);
 
diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c
index 195c41d..0813163 100644
--- a/drivers/staging/android/ion/ion_chunk_heap.c
+++ b/drivers/staging/android/ion/ion_chunk_heap.c
@@ -81,7 +81,7 @@
 err:
 	sg = table->sgl;
 	for (i -= 1; i >= 0; i--) {
-		gen_pool_free(chunk_heap->pool, sg_phys(sg) & PAGE_MASK,
+		gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
 			      sg->length);
 		sg = sg_next(sg);
 	}
@@ -109,7 +109,7 @@
 							DMA_BIDIRECTIONAL);
 
 	for_each_sg(table->sgl, sg, table->nents, i) {
-		gen_pool_free(chunk_heap->pool, sg_phys(sg) & PAGE_MASK,
+		gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
 			      sg->length);
 	}
 	chunk_heap->allocated -= allocated_size;
diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c
index bfbf1c5..6eb600f 100644
--- a/drivers/staging/iio/iio_simple_dummy_events.c
+++ b/drivers/staging/iio/iio_simple_dummy_events.c
@@ -159,7 +159,7 @@
 	struct iio_dummy_state *st = iio_priv(indio_dev);
 
 	st->event_timestamp = iio_get_time_ns();
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 
 /**
diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c
index f61ef66..a4a9a76 100644
--- a/drivers/staging/lustre/lustre/obdecho/echo_client.c
+++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c
@@ -1270,6 +1270,7 @@
 echo_copyout_lsm(struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob)
 {
 	struct lov_stripe_md *ulsm = _ulsm;
+	struct lov_oinfo **p;
 	int nob, i;
 
 	nob = offsetof(struct lov_stripe_md, lsm_oinfo[lsm->lsm_stripe_count]);
@@ -1279,9 +1280,10 @@
 	if (copy_to_user(ulsm, lsm, sizeof(*ulsm)))
 		return -EFAULT;
 
-	for (i = 0; i < lsm->lsm_stripe_count; i++) {
-		if (copy_to_user(ulsm->lsm_oinfo[i], lsm->lsm_oinfo[i],
-				      sizeof(lsm->lsm_oinfo[0])))
+	for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) {
+		struct lov_oinfo __user *up;
+		if (get_user(up, ulsm->lsm_oinfo + i) ||
+		    copy_to_user(up, *p, sizeof(struct lov_oinfo)))
 			return -EFAULT;
 	}
 	return 0;
@@ -1289,9 +1291,10 @@
 
 static int
 echo_copyin_lsm(struct echo_device *ed, struct lov_stripe_md *lsm,
-		 void *ulsm, int ulsm_nob)
+		struct lov_stripe_md __user *ulsm, int ulsm_nob)
 {
 	struct echo_client_obd *ec = ed->ed_ec;
+	struct lov_oinfo **p;
 	int		     i;
 
 	if (ulsm_nob < sizeof(*lsm))
@@ -1306,11 +1309,10 @@
 	    ((__u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count > ~0UL))
 		return -EINVAL;
 
-	for (i = 0; i < lsm->lsm_stripe_count; i++) {
-		if (copy_from_user(lsm->lsm_oinfo[i],
-				       ((struct lov_stripe_md *)ulsm)-> \
-				       lsm_oinfo[i],
-				       sizeof(lsm->lsm_oinfo[0])))
+	for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) {
+		struct lov_oinfo __user *up;
+		if (get_user(up, ulsm->lsm_oinfo + i) ||
+		    copy_from_user(*p, up, sizeof(struct lov_oinfo)))
 			return -EFAULT;
 	}
 	return 0;
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index ed77614..e49c2bce 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -2054,13 +2054,13 @@
 	size_t eol;
 	size_t tail;
 	int ret, found = 0;
-	bool eof_push = 0;
 
 	/* N.B. avoid overrun if nr == 0 */
-	n = min(*nr, smp_load_acquire(&ldata->canon_head) - ldata->read_tail);
-	if (!n)
+	if (!*nr)
 		return 0;
 
+	n = min(*nr + 1, smp_load_acquire(&ldata->canon_head) - ldata->read_tail);
+
 	tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1);
 	size = min_t(size_t, tail + n, N_TTY_BUF_SIZE);
 
@@ -2081,12 +2081,11 @@
 	n = eol - tail;
 	if (n > N_TTY_BUF_SIZE)
 		n += N_TTY_BUF_SIZE;
-	n += found;
-	c = n;
+	c = n + found;
 
-	if (found && !ldata->push && read_buf(ldata, eol) == __DISABLED_CHAR) {
-		n--;
-		eof_push = !n && ldata->read_tail != ldata->line_start;
+	if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) {
+		c = min(*nr, c);
+		n = c;
 	}
 
 	n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n",
@@ -2116,7 +2115,7 @@
 			ldata->push = 0;
 		tty_audit_push(tty);
 	}
-	return eof_push ? -EAGAIN : 0;
+	return 0;
 }
 
 extern ssize_t redirected_tty_write(struct file *, const char __user *,
@@ -2273,10 +2272,7 @@
 
 		if (ldata->icanon && !L_EXTPROC(tty)) {
 			retval = canon_copy_from_read_buf(tty, &b, &nr);
-			if (retval == -EAGAIN) {
-				retval = 0;
-				continue;
-			} else if (retval)
+			if (retval)
 				break;
 		} else {
 			int uncopied;
diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c
index d11621e..245edbb 100644
--- a/drivers/tty/serial/8250/8250_uniphier.c
+++ b/drivers/tty/serial/8250/8250_uniphier.c
@@ -115,12 +115,16 @@
  */
 static int uniphier_serial_dl_read(struct uart_8250_port *up)
 {
-	return readl(up->port.membase + UNIPHIER_UART_DLR);
+	int offset = UNIPHIER_UART_DLR << up->port.regshift;
+
+	return readl(up->port.membase + offset);
 }
 
 static void uniphier_serial_dl_write(struct uart_8250_port *up, int value)
 {
-	writel(value, up->port.membase + UNIPHIER_UART_DLR);
+	int offset = UNIPHIER_UART_DLR << up->port.regshift;
+
+	writel(value, up->port.membase + offset);
 }
 
 static int uniphier_of_serial_setup(struct device *dev, struct uart_port *port,
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index f096360..b5b2f2b 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -115,6 +115,7 @@
 	if (buf && !parse_options(&early_console_dev, buf))
 		buf = NULL;
 
+	spin_lock_init(&port->lock);
 	port->uartclk = BASE_BAUD * 16;
 	if (port->mapbase)
 		port->membase = earlycon_map(port->mapbase, 64);
@@ -202,6 +203,7 @@
 	int err;
 	struct uart_port *port = &early_console_dev.port;
 
+	spin_lock_init(&port->lock);
 	port->iotype = UPIO_MEM;
 	port->mapbase = addr;
 	port->uartclk = BASE_BAUD * 16;
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 960e50a..51c7507 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1437,7 +1437,7 @@
 			sg_init_table(sg, 1);
 			s->rx_buf[i] = buf;
 			sg_dma_address(sg) = dma;
-			sg->length = s->buf_len_rx;
+			sg_dma_len(sg) = s->buf_len_rx;
 
 			buf += s->buf_len_rx;
 			dma += s->buf_len_rx;
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 9a479e6..3cd31e0 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -450,7 +450,7 @@
 		count = disc->ops->receive_buf2(tty, p, f, count);
 	else {
 		count = min_t(int, count, tty->receive_room);
-		if (count)
+		if (count && disc->ops->receive_buf)
 			disc->ops->receive_buf(tty, p, f, count);
 	}
 	return count;
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index b30e742..26ca4f9 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1838,6 +1838,11 @@
 	},
 #endif
 
+	/* Exclude Infineon Flash Loader utility */
+	{ USB_DEVICE(0x058b, 0x0041),
+	.driver_info = IGNORE_DEVICE,
+	},
+
 	/* control interfaces without any protocol set */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_PROTO_NONE) },
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 7caff02..5050760 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -115,7 +115,8 @@
 		   USB_SS_MULT(desc->bmAttributes) > 3) {
 		dev_warn(ddev, "Isoc endpoint has Mult of %d in "
 				"config %d interface %d altsetting %d ep %d: "
-				"setting to 3\n", desc->bmAttributes + 1,
+				"setting to 3\n",
+				USB_SS_MULT(desc->bmAttributes),
 				cfgno, inum, asnum, ep->desc.bEndpointAddress);
 		ep->ss_ep_comp.bmAttributes = 2;
 	}
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index bdeadc1..ddbf32d 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -124,6 +124,10 @@
 
 int usb_device_supports_lpm(struct usb_device *udev)
 {
+	/* Some devices have trouble with LPM */
+	if (udev->quirks & USB_QUIRK_NO_LPM)
+		return 0;
+
 	/* USB 2.1 (and greater) devices indicate LPM support through
 	 * their USB 2.0 Extended Capabilities BOS descriptor.
 	 */
@@ -1031,10 +1035,20 @@
 	unsigned delay;
 
 	/* Continue a partial initialization */
-	if (type == HUB_INIT2)
-		goto init2;
-	if (type == HUB_INIT3)
+	if (type == HUB_INIT2 || type == HUB_INIT3) {
+		device_lock(hub->intfdev);
+
+		/* Was the hub disconnected while we were waiting? */
+		if (hub->disconnected) {
+			device_unlock(hub->intfdev);
+			kref_put(&hub->kref, hub_release);
+			return;
+		}
+		if (type == HUB_INIT2)
+			goto init2;
 		goto init3;
+	}
+	kref_get(&hub->kref);
 
 	/* The superspeed hub except for root hub has to use Hub Depth
 	 * value as an offset into the route string to locate the bits
@@ -1232,6 +1246,7 @@
 			queue_delayed_work(system_power_efficient_wq,
 					&hub->init_work,
 					msecs_to_jiffies(delay));
+			device_unlock(hub->intfdev);
 			return;		/* Continues at init3: below */
 		} else {
 			msleep(delay);
@@ -1253,6 +1268,11 @@
 	/* Allow autosuspend if it was suppressed */
 	if (type <= HUB_INIT3)
 		usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
+
+	if (type == HUB_INIT2 || type == HUB_INIT3)
+		device_unlock(hub->intfdev);
+
+	kref_put(&hub->kref, hub_release);
 }
 
 /* Implement the continuations for the delays above */
@@ -4512,6 +4532,8 @@
 		goto fail;
 	}
 
+	usb_detect_quirks(udev);
+
 	if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) {
 		retval = usb_get_bos_descriptor(udev);
 		if (!retval) {
@@ -4710,7 +4732,6 @@
 		if (status < 0)
 			goto loop;
 
-		usb_detect_quirks(udev);
 		if (udev->quirks & USB_QUIRK_DELAY_INIT)
 			msleep(1000);
 
@@ -5326,9 +5347,6 @@
 	if (udev->usb2_hw_lpm_enabled == 1)
 		usb_set_usb2_hardware_lpm(udev, 0);
 
-	bos = udev->bos;
-	udev->bos = NULL;
-
 	/* Disable LPM and LTM while we reset the device and reinstall the alt
 	 * settings.  Device-initiated LPM settings, and system exit latency
 	 * settings are cleared when the device is reset, so we have to set
@@ -5337,15 +5355,18 @@
 	ret = usb_unlocked_disable_lpm(udev);
 	if (ret) {
 		dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__);
-		goto re_enumerate;
+		goto re_enumerate_no_bos;
 	}
 	ret = usb_disable_ltm(udev);
 	if (ret) {
 		dev_err(&udev->dev, "%s Failed to disable LTM\n.",
 				__func__);
-		goto re_enumerate;
+		goto re_enumerate_no_bos;
 	}
 
+	bos = udev->bos;
+	udev->bos = NULL;
+
 	for (i = 0; i < SET_CONFIG_TRIES; ++i) {
 
 		/* ep0 maxpacket size may change; let the HCD know about it.
@@ -5442,10 +5463,11 @@
 	return 0;
 
 re_enumerate:
-	/* LPM state doesn't matter when we're about to destroy the device. */
-	hub_port_logical_disconnect(parent_hub, port1);
 	usb_release_bos_descriptor(udev);
 	udev->bos = bos;
+re_enumerate_no_bos:
+	/* LPM state doesn't matter when we're about to destroy the device. */
+	hub_port_logical_disconnect(parent_hub, port1);
 	return -ENODEV;
 }
 
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index 2106183..5487fe308 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -206,7 +206,7 @@
 		else
 			method = "default";
 
-		pr_warn("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n",
+		pr_debug("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n",
 			dev_name(&left->dev), dev_name(&right->dev), method,
 			dev_name(&left->dev),
 			lpeer ? dev_name(&lpeer->dev) : "none",
@@ -265,7 +265,7 @@
 	if (rc == 0) {
 		dev_dbg(&left->dev, "peered to %s\n", dev_name(&right->dev));
 	} else {
-		dev_warn(&left->dev, "failed to peer to %s (%d)\n",
+		dev_dbg(&left->dev, "failed to peer to %s (%d)\n",
 				dev_name(&right->dev), rc);
 		pr_warn_once("usb: port power management may be unreliable\n");
 		usb_port_block_power_off = 1;
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index f5a3819..6dc810b 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -125,6 +125,9 @@
 	{ USB_DEVICE(0x04f3, 0x016f), .driver_info =
 			USB_QUIRK_DEVICE_QUALIFIER },
 
+	{ USB_DEVICE(0x04f3, 0x21b8), .driver_info =
+			USB_QUIRK_DEVICE_QUALIFIER },
+
 	/* Roland SC-8820 */
 	{ USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -199,6 +202,12 @@
 	{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =
 			USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
 
+	/* Blackmagic Design Intensity Shuttle */
+	{ USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM },
+
+	/* Blackmagic Design UltraStudio SDI */
+	{ USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },
+
 	{ }  /* terminating entry must be last */
 };
 
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index e61d773..39c1cbf 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -125,9 +125,11 @@
 	if (ret)
 		return ret;
 
-	ret = clk_prepare_enable(hsotg->clk);
-	if (ret)
-		return ret;
+	if (hsotg->clk) {
+		ret = clk_prepare_enable(hsotg->clk);
+		if (ret)
+			return ret;
+	}
 
 	if (hsotg->uphy)
 		ret = usb_phy_init(hsotg->uphy);
@@ -175,7 +177,8 @@
 	if (ret)
 		return ret;
 
-	clk_disable_unprepare(hsotg->clk);
+	if (hsotg->clk)
+		clk_disable_unprepare(hsotg->clk);
 
 	ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
 				     hsotg->supplies);
@@ -212,14 +215,41 @@
 	 */
 	hsotg->phy = devm_phy_get(hsotg->dev, "usb2-phy");
 	if (IS_ERR(hsotg->phy)) {
-		hsotg->phy = NULL;
-		hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2);
-		if (IS_ERR(hsotg->uphy))
-			hsotg->uphy = NULL;
-		else
-			hsotg->plat = dev_get_platdata(hsotg->dev);
+		ret = PTR_ERR(hsotg->phy);
+		switch (ret) {
+		case -ENODEV:
+		case -ENOSYS:
+			hsotg->phy = NULL;
+			break;
+		case -EPROBE_DEFER:
+			return ret;
+		default:
+			dev_err(hsotg->dev, "error getting phy %d\n", ret);
+			return ret;
+		}
 	}
 
+	if (!hsotg->phy) {
+		hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2);
+		if (IS_ERR(hsotg->uphy)) {
+			ret = PTR_ERR(hsotg->uphy);
+			switch (ret) {
+			case -ENODEV:
+			case -ENXIO:
+				hsotg->uphy = NULL;
+				break;
+			case -EPROBE_DEFER:
+				return ret;
+			default:
+				dev_err(hsotg->dev, "error getting usb phy %d\n",
+					ret);
+				return ret;
+			}
+		}
+	}
+
+	hsotg->plat = dev_get_platdata(hsotg->dev);
+
 	if (hsotg->phy) {
 		/*
 		 * If using the generic PHY framework, check if the PHY bus
@@ -229,11 +259,6 @@
 			hsotg->phyif = GUSBCFG_PHYIF8;
 	}
 
-	if (!hsotg->phy && !hsotg->uphy && !hsotg->plat) {
-		dev_err(hsotg->dev, "no platform data or transceiver defined\n");
-		return -EPROBE_DEFER;
-	}
-
 	/* Clock */
 	hsotg->clk = devm_clk_get(hsotg->dev, "otg");
 	if (IS_ERR(hsotg->clk)) {
@@ -342,20 +367,6 @@
 	if (retval)
 		return retval;
 
-	irq = platform_get_irq(dev, 0);
-	if (irq < 0) {
-		dev_err(&dev->dev, "missing IRQ resource\n");
-		return irq;
-	}
-
-	dev_dbg(hsotg->dev, "registering common handler for irq%d\n",
-		irq);
-	retval = devm_request_irq(hsotg->dev, irq,
-				  dwc2_handle_common_intr, IRQF_SHARED,
-				  dev_name(hsotg->dev), hsotg);
-	if (retval)
-		return retval;
-
 	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	hsotg->regs = devm_ioremap_resource(&dev->dev, res);
 	if (IS_ERR(hsotg->regs))
@@ -390,6 +401,20 @@
 
 	dwc2_set_all_params(hsotg->core_params, -1);
 
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		dev_err(&dev->dev, "missing IRQ resource\n");
+		return irq;
+	}
+
+	dev_dbg(hsotg->dev, "registering common handler for irq%d\n",
+		irq);
+	retval = devm_request_irq(hsotg->dev, irq,
+				  dwc2_handle_common_intr, IRQF_SHARED,
+				  dev_name(hsotg->dev), hsotg);
+	if (retval)
+		return retval;
+
 	retval = dwc2_lowlevel_hw_enable(hsotg);
 	if (retval)
 		return retval;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index e24a01c..a58376f 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1078,6 +1078,7 @@
 	 * little bit faster.
 	 */
 	if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+			!usb_endpoint_xfer_int(dep->endpoint.desc) &&
 			!(dep->flags & DWC3_EP_BUSY)) {
 		ret = __dwc3_gadget_kick_transfer(dep, 0, true);
 		goto out;
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index adc6d52..cf43e9e 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -423,7 +423,7 @@
 	spin_unlock_irq(&ffs->ev.waitq.lock);
 	mutex_unlock(&ffs->mutex);
 
-	return unlikely(__copy_to_user(buf, events, size)) ? -EFAULT : size;
+	return unlikely(copy_to_user(buf, events, size)) ? -EFAULT : size;
 }
 
 static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
@@ -513,7 +513,7 @@
 
 		/* unlocks spinlock */
 		ret = __ffs_ep0_queue_wait(ffs, data, len);
-		if (likely(ret > 0) && unlikely(__copy_to_user(buf, data, len)))
+		if (likely(ret > 0) && unlikely(copy_to_user(buf, data, len)))
 			ret = -EFAULT;
 		goto done_mutex;
 
@@ -3493,7 +3493,7 @@
 	if (unlikely(!data))
 		return ERR_PTR(-ENOMEM);
 
-	if (unlikely(__copy_from_user(data, buf, len))) {
+	if (unlikely(copy_from_user(data, buf, len))) {
 		kfree(data);
 		return ERR_PTR(-EFAULT);
 	}
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 42acb45..898a570 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -370,6 +370,7 @@
 		if (err) {
 			ERROR(midi, "%s queue req: %d\n",
 				    midi->out_ep->name, err);
+			free_ep_req(midi->out_ep, req);
 		}
 	}
 
@@ -545,7 +546,7 @@
 		}
 	}
 
-	if (req->length > 0) {
+	if (req->length > 0 && ep->enabled) {
 		int err;
 
 		err = usb_ep_queue(ep, req, GFP_ATOMIC);
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 289ebca..ad8c9b0 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -20,7 +20,7 @@
 #define UVC_ATTR(prefix, cname, aname) \
 static struct configfs_attribute prefix##attr_##cname = { \
 	.ca_name	= __stringify(aname),				\
-	.ca_mode	= S_IRUGO,					\
+	.ca_mode	= S_IRUGO | S_IWUGO,				\
 	.ca_owner	= THIS_MODULE,					\
 	.show		= prefix##cname##_show,				\
 	.store		= prefix##cname##_store,			\
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
index 670ac0b..001a3b7 100644
--- a/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -2536,6 +2536,9 @@
 	udc->pullup_resume = udc->pullup_on;
 	dplus_pullup(udc, 0);
 
+	if (udc->driver)
+		udc->driver->disconnect(&udc->gadget);
+
 	return 0;
 }
 
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 342ffd1..8c6e15b 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -473,6 +473,8 @@
 	if (!pdata)
 		return -ENOMEM;
 
+	pdev->dev.platform_data = pdata;
+
 	if (!of_property_read_u32(np, "num-ports", &ports))
 		pdata->ports = ports;
 
@@ -483,6 +485,7 @@
 		 */
 		if (i >= pdata->ports) {
 			pdata->vbus_pin[i] = -EINVAL;
+			pdata->overcurrent_pin[i] = -EINVAL;
 			continue;
 		}
 
@@ -513,10 +516,8 @@
 	}
 
 	at91_for_each_port(i) {
-		if (i >= pdata->ports) {
-			pdata->overcurrent_pin[i] = -EINVAL;
-			continue;
-		}
+		if (i >= pdata->ports)
+			break;
 
 		pdata->overcurrent_pin[i] =
 			of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
@@ -552,8 +553,6 @@
 		}
 	}
 
-	pdev->dev.platform_data = pdata;
-
 	device_init_wakeup(&pdev->dev, 1);
 	return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
 }
diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c
index dc31c42..9f1c053 100644
--- a/drivers/usb/host/whci/qset.c
+++ b/drivers/usb/host/whci/qset.c
@@ -377,6 +377,10 @@
 	if (std->pl_virt == NULL)
 		return -ENOMEM;
 	std->dma_addr = dma_map_single(whc->wusbhc.dev, std->pl_virt, pl_len, DMA_TO_DEVICE);
+	if (dma_mapping_error(whc->wusbhc.dev, std->dma_addr)) {
+		kfree(std->pl_virt);
+		return -EFAULT;
+	}
 
 	for (p = 0; p < std->num_pointers; p++) {
 		std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr);
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 0230965..f980c23 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -733,8 +733,30 @@
 		if ((raw_port_status & PORT_RESET) ||
 				!(raw_port_status & PORT_PE))
 			return 0xffffffff;
-		if (time_after_eq(jiffies,
-					bus_state->resume_done[wIndex])) {
+		/* did port event handler already start resume timing? */
+		if (!bus_state->resume_done[wIndex]) {
+			/* If not, maybe we are in a host initated resume? */
+			if (test_bit(wIndex, &bus_state->resuming_ports)) {
+				/* Host initated resume doesn't time the resume
+				 * signalling using resume_done[].
+				 * It manually sets RESUME state, sleeps 20ms
+				 * and sets U0 state. This should probably be
+				 * changed, but not right now.
+				 */
+			} else {
+				/* port resume was discovered now and here,
+				 * start resume timing
+				 */
+				unsigned long timeout = jiffies +
+					msecs_to_jiffies(USB_RESUME_TIMEOUT);
+
+				set_bit(wIndex, &bus_state->resuming_ports);
+				bus_state->resume_done[wIndex] = timeout;
+				mod_timer(&hcd->rh_timer, timeout);
+			}
+		/* Has resume been signalled for USB_RESUME_TIME yet? */
+		} else if (time_after_eq(jiffies,
+					 bus_state->resume_done[wIndex])) {
 			int time_left;
 
 			xhci_dbg(xhci, "Resume USB2 port %d\n",
@@ -775,13 +797,26 @@
 		} else {
 			/*
 			 * The resume has been signaling for less than
-			 * 20ms. Report the port status as SUSPEND,
-			 * let the usbcore check port status again
-			 * and clear resume signaling later.
+			 * USB_RESUME_TIME. Report the port status as SUSPEND,
+			 * let the usbcore check port status again and clear
+			 * resume signaling later.
 			 */
 			status |= USB_PORT_STAT_SUSPEND;
 		}
 	}
+	/*
+	 * Clear stale usb2 resume signalling variables in case port changed
+	 * state during resume signalling. For example on error
+	 */
+	if ((bus_state->resume_done[wIndex] ||
+	     test_bit(wIndex, &bus_state->resuming_ports)) &&
+	    (raw_port_status & PORT_PLS_MASK) != XDEV_U3 &&
+	    (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) {
+		bus_state->resume_done[wIndex] = 0;
+		clear_bit(wIndex, &bus_state->resuming_ports);
+	}
+
+
 	if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 &&
 	    (raw_port_status & PORT_POWER)) {
 		if (bus_state->suspended_ports & (1 << wIndex)) {
@@ -1115,6 +1150,7 @@
 				if ((temp & PORT_PE) == 0)
 					goto error;
 
+				set_bit(wIndex, &bus_state->resuming_ports);
 				xhci_set_link_state(xhci, port_array, wIndex,
 							XDEV_RESUME);
 				spin_unlock_irqrestore(&xhci->lock, flags);
@@ -1122,6 +1158,7 @@
 				spin_lock_irqsave(&xhci->lock, flags);
 				xhci_set_link_state(xhci, port_array, wIndex,
 							XDEV_U0);
+				clear_bit(wIndex, &bus_state->resuming_ports);
 			}
 			bus_state->port_c_suspend |= 1 << wIndex;
 
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 17f6897..c621090 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -188,10 +188,14 @@
 		0xb7, 0x0c, 0x34, 0xac,	0x01, 0xe9, 0xbf, 0x45,
 		0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23,
 	};
-	acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1, NULL);
+	union acpi_object *obj;
+
+	obj = acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1,
+				NULL);
+	ACPI_FREE(obj);
 }
 #else
-	static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
+static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
 #endif /* CONFIG_ACPI */
 
 /* called during probe() after chip reset completes */
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 6c5e813..eeaa6c6 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1583,7 +1583,8 @@
 			 */
 			bogus_port_status = true;
 			goto cleanup;
-		} else {
+		} else if (!test_bit(faked_port_index,
+				     &bus_state->resuming_ports)) {
 			xhci_dbg(xhci, "resume HS port %d\n", port_id);
 			bus_state->resume_done[faked_port_index] = jiffies +
 				msecs_to_jiffies(USB_RESUME_TIMEOUT);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index dfa44d3..3f91270 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4778,8 +4778,16 @@
 	ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
 	slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx);
 	slot_ctx->dev_info |= cpu_to_le32(DEV_HUB);
+	/*
+	 * refer to section 6.2.2: MTT should be 0 for full speed hub,
+	 * but it may be already set to 1 when setup an xHCI virtual
+	 * device, so clear it anyway.
+	 */
 	if (tt->multi)
 		slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
+	else if (hdev->speed == USB_SPEED_FULL)
+		slot_ctx->dev_info &= cpu_to_le32(~DEV_MTT);
+
 	if (xhci->hci_version > 0x95) {
 		xhci_dbg(xhci, "xHCI version %x needs hub "
 				"TT think time and number of ports\n",
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 1f2037b..45c83ba 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -159,7 +159,7 @@
 
 config USB_TI_CPPI41_DMA
 	bool 'TI CPPI 4.1 (AM335x)'
-	depends on ARCH_OMAP
+	depends on ARCH_OMAP && DMADEVICES
 	select TI_CPPI41
 
 config USB_TUSB_OMAP_DMA
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 18cfc0a..ee9ff70 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2017,7 +2017,6 @@
 	/* We need musb_read/write functions initialized for PM */
 	pm_runtime_use_autosuspend(musb->controller);
 	pm_runtime_set_autosuspend_delay(musb->controller, 200);
-	pm_runtime_irq_safe(musb->controller);
 	pm_runtime_enable(musb->controller);
 
 	/* The musb_platform_init() call:
@@ -2095,6 +2094,7 @@
 #ifndef CONFIG_MUSB_PIO_ONLY
 	if (!musb->ops->dma_init || !musb->ops->dma_exit) {
 		dev_err(dev, "DMA controller not set\n");
+		status = -ENODEV;
 		goto fail2;
 	}
 	musb_dma_controller_create = musb->ops->dma_init;
@@ -2218,6 +2218,12 @@
 
 	pm_runtime_put(musb->controller);
 
+	/*
+	 * For why this is currently needed, see commit 3e43a0725637
+	 * ("usb: musb: core: add pm_runtime_irq_safe()")
+	 */
+	pm_runtime_irq_safe(musb->controller);
+
 	return 0;
 
 fail5:
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index 80eb991..0d19a6d 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -1506,7 +1506,6 @@
 {
 	struct msm_otg_platform_data *pdata;
 	struct extcon_dev *ext_id, *ext_vbus;
-	const struct of_device_id *id;
 	struct device_node *node = pdev->dev.of_node;
 	struct property *prop;
 	int len, ret, words;
@@ -1518,8 +1517,9 @@
 
 	motg->pdata = pdata;
 
-	id = of_match_device(msm_otg_dt_match, &pdev->dev);
-	pdata->phy_type = (enum msm_usb_phy_type) id->data;
+	pdata->phy_type = (enum msm_usb_phy_type)of_device_get_match_data(&pdev->dev);
+	if (!pdata->phy_type)
+		return 1;
 
 	motg->link_rst = devm_reset_control_get(&pdev->dev, "link");
 	if (IS_ERR(motg->link_rst))
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index b7536af..c2936dc 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -143,12 +143,17 @@
 	.flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
 };
 
+static const struct mxs_phy_data imx6ul_phy_data = {
+	.flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
+};
+
 static const struct of_device_id mxs_phy_dt_ids[] = {
 	{ .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, },
 	{ .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
 	{ .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
 	{ .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
 	{ .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, },
+	{ .compatible = "fsl,imx6ul-usbphy", .data = &imx6ul_phy_data, },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index de4f97d..8f7a78e 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -131,7 +131,8 @@
 	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
 	struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
 
-	dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe));
+	if (pipe)
+		dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe));
 
 	ureq->req.status = status;
 	spin_unlock(usbhs_priv_to_lock(priv));
@@ -685,7 +686,13 @@
 	struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
 	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
 
-	usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
+	if (pipe)
+		usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
+
+	/*
+	 * To dequeue a request, this driver should call the usbhsg_queue_pop()
+	 * even if the pipe is NULL.
+	 */
 	usbhsg_queue_pop(uep, ureq, -ECONNRESET);
 
 	return 0;
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index eac7cca..7d4f51a 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -132,7 +132,6 @@
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
-	{ USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
 	{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
 	{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index f51a5d5..ec1b8f2 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -531,7 +531,8 @@
 	 * through. Since this has a reasonably high failure rate, we retry
 	 * several times.
 	 */
-	while (retries--) {
+	while (retries) {
+		retries--;
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
 				0x1, 0, NULL, 0, 100);
diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c
index 3658662..a204782 100644
--- a/drivers/usb/serial/usb-serial-simple.c
+++ b/drivers/usb/serial/usb-serial-simple.c
@@ -53,6 +53,7 @@
 
 /* Infineon Flashloader driver */
 #define FLASHLOADER_IDS()		\
+	{ USB_DEVICE_INTERFACE_CLASS(0x058b, 0x0041, USB_CLASS_CDC_DATA) }, \
 	{ USB_DEVICE(0x8087, 0x0716) }
 DEVICE(flashloader, FLASHLOADER_IDS);
 
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index e691516..5c66d3f 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -796,6 +796,10 @@
 	if (devinfo->flags & US_FL_NO_REPORT_OPCODES)
 		sdev->no_report_opcodes = 1;
 
+	/* A few buggy USB-ATA bridges don't understand FUA */
+	if (devinfo->flags & US_FL_BROKEN_FUA)
+		sdev->broken_fua = 1;
+
 	scsi_change_queue_depth(sdev, devinfo->qdepth - 2);
 	return 0;
 }
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 6b24791..7ffe420 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1987,7 +1987,7 @@
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Michael Büsch <m@bues.ch> */
-UNUSUAL_DEV(  0x152d, 0x0567, 0x0114, 0x0114,
+UNUSUAL_DEV(  0x152d, 0x0567, 0x0114, 0x0116,
 		"JMicron",
 		"USB to ATA/ATAPI Bridge",
 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h
index c85ea53..ccc113e 100644
--- a/drivers/usb/storage/unusual_uas.h
+++ b/drivers/usb/storage/unusual_uas.h
@@ -132,7 +132,7 @@
 		"JMicron",
 		"JMS567",
 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
-		US_FL_NO_REPORT_OPCODES),
+		US_FL_BROKEN_FUA | US_FL_NO_REPORT_OPCODES),
 
 /* Reported-by: Hans de Goede <hdegoede@redhat.com> */
 UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999,
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index da6e2ce..850d86c 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -31,21 +31,6 @@
 
 	  If you don't know what to do here, say N.
 
-menuconfig VFIO_NOIOMMU
-	bool "VFIO No-IOMMU support"
-	depends on VFIO
-	help
-	  VFIO is built on the ability to isolate devices using the IOMMU.
-	  Only with an IOMMU can userspace access to DMA capable devices be
-	  considered secure.  VFIO No-IOMMU mode enables IOMMU groups for
-	  devices without IOMMU backing for the purpose of re-using the VFIO
-	  infrastructure in a non-secure mode.  Use of this mode will result
-	  in an unsupportable kernel and will therefore taint the kernel.
-	  Device assignment to virtual machines is also not possible with
-	  this mode since there is no IOMMU to provide DMA translation.
-
-	  If you don't know what to do here, say N.
-
 source "drivers/vfio/pci/Kconfig"
 source "drivers/vfio/platform/Kconfig"
 source "virt/lib/Kconfig"
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 32b88bd..56bf6db 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -940,13 +940,13 @@
 	if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
 		return -EINVAL;
 
-	group = vfio_iommu_group_get(&pdev->dev);
+	group = iommu_group_get(&pdev->dev);
 	if (!group)
 		return -EINVAL;
 
 	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
 	if (!vdev) {
-		vfio_iommu_group_put(group, &pdev->dev);
+		iommu_group_put(group);
 		return -ENOMEM;
 	}
 
@@ -957,7 +957,7 @@
 
 	ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
 	if (ret) {
-		vfio_iommu_group_put(group, &pdev->dev);
+		iommu_group_put(group);
 		kfree(vdev);
 		return ret;
 	}
@@ -993,7 +993,7 @@
 	if (!vdev)
 		return;
 
-	vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
+	iommu_group_put(pdev->dev.iommu_group);
 	kfree(vdev);
 
 	if (vfio_pci_is_vga(pdev)) {
@@ -1035,7 +1035,7 @@
 	return PCI_ERS_RESULT_CAN_RECOVER;
 }
 
-static struct pci_error_handlers vfio_err_handlers = {
+static const struct pci_error_handlers vfio_err_handlers = {
 	.error_detected = vfio_pci_aer_err_detected,
 };
 
diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
index f1625dc..b1cc3a7 100644
--- a/drivers/vfio/platform/vfio_platform.c
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -92,7 +92,6 @@
 	.remove		= vfio_platform_remove,
 	.driver	= {
 		.name	= "vfio-platform",
-		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index a1c50d6..418cdd9 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -51,13 +51,10 @@
 
 static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
-	char modname[256];
-
 	vdev->reset = vfio_platform_lookup_reset(vdev->compat,
 						&vdev->reset_module);
 	if (!vdev->reset) {
-		snprintf(modname, 256, "vfio-reset:%s", vdev->compat);
-		request_module(modname);
+		request_module("vfio-reset:%s", vdev->compat);
 		vdev->reset = vfio_platform_lookup_reset(vdev->compat,
 							 &vdev->reset_module);
 	}
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index de632da..6070b79 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -62,7 +62,6 @@
 	struct rw_semaphore		group_lock;
 	struct vfio_iommu_driver	*iommu_driver;
 	void				*iommu_data;
-	bool				noiommu;
 };
 
 struct vfio_unbound_dev {
@@ -85,7 +84,6 @@
 	struct list_head		unbound_list;
 	struct mutex			unbound_lock;
 	atomic_t			opened;
-	bool				noiommu;
 };
 
 struct vfio_device {
@@ -97,147 +95,6 @@
 	void				*device_data;
 };
 
-#ifdef CONFIG_VFIO_NOIOMMU
-static bool noiommu __read_mostly;
-module_param_named(enable_unsafe_noiommu_support,
-		   noiommu, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode.  This mode provides no device isolation, no DMA translation, no host kernel protection, cannot be used for device assignment to virtual machines, requires RAWIO permissions, and will taint the kernel.  If you do not know what this is for, step away. (default: false)");
-#endif
-
-/*
- * vfio_iommu_group_{get,put} are only intended for VFIO bus driver probe
- * and remove functions, any use cases other than acquiring the first
- * reference for the purpose of calling vfio_add_group_dev() or removing
- * that symmetric reference after vfio_del_group_dev() should use the raw
- * iommu_group_{get,put} functions.  In particular, vfio_iommu_group_put()
- * removes the device from the dummy group and cannot be nested.
- */
-struct iommu_group *vfio_iommu_group_get(struct device *dev)
-{
-	struct iommu_group *group;
-	int __maybe_unused ret;
-
-	group = iommu_group_get(dev);
-
-#ifdef CONFIG_VFIO_NOIOMMU
-	/*
-	 * With noiommu enabled, an IOMMU group will be created for a device
-	 * that doesn't already have one and doesn't have an iommu_ops on their
-	 * bus.  We use iommu_present() again in the main code to detect these
-	 * fake groups.
-	 */
-	if (group || !noiommu || iommu_present(dev->bus))
-		return group;
-
-	group = iommu_group_alloc();
-	if (IS_ERR(group))
-		return NULL;
-
-	iommu_group_set_name(group, "vfio-noiommu");
-	ret = iommu_group_add_device(group, dev);
-	iommu_group_put(group);
-	if (ret)
-		return NULL;
-
-	/*
-	 * Where to taint?  At this point we've added an IOMMU group for a
-	 * device that is not backed by iommu_ops, therefore any iommu_
-	 * callback using iommu_ops can legitimately Oops.  So, while we may
-	 * be about to give a DMA capable device to a user without IOMMU
-	 * protection, which is clearly taint-worthy, let's go ahead and do
-	 * it here.
-	 */
-	add_taint(TAINT_USER, LOCKDEP_STILL_OK);
-	dev_warn(dev, "Adding kernel taint for vfio-noiommu group on device\n");
-#endif
-
-	return group;
-}
-EXPORT_SYMBOL_GPL(vfio_iommu_group_get);
-
-void vfio_iommu_group_put(struct iommu_group *group, struct device *dev)
-{
-#ifdef CONFIG_VFIO_NOIOMMU
-	if (!iommu_present(dev->bus))
-		iommu_group_remove_device(dev);
-#endif
-
-	iommu_group_put(group);
-}
-EXPORT_SYMBOL_GPL(vfio_iommu_group_put);
-
-#ifdef CONFIG_VFIO_NOIOMMU
-static void *vfio_noiommu_open(unsigned long arg)
-{
-	if (arg != VFIO_NOIOMMU_IOMMU)
-		return ERR_PTR(-EINVAL);
-	if (!capable(CAP_SYS_RAWIO))
-		return ERR_PTR(-EPERM);
-
-	return NULL;
-}
-
-static void vfio_noiommu_release(void *iommu_data)
-{
-}
-
-static long vfio_noiommu_ioctl(void *iommu_data,
-			       unsigned int cmd, unsigned long arg)
-{
-	if (cmd == VFIO_CHECK_EXTENSION)
-		return arg == VFIO_NOIOMMU_IOMMU ? 1 : 0;
-
-	return -ENOTTY;
-}
-
-static int vfio_iommu_present(struct device *dev, void *unused)
-{
-	return iommu_present(dev->bus) ? 1 : 0;
-}
-
-static int vfio_noiommu_attach_group(void *iommu_data,
-				     struct iommu_group *iommu_group)
-{
-	return iommu_group_for_each_dev(iommu_group, NULL,
-					vfio_iommu_present) ? -EINVAL : 0;
-}
-
-static void vfio_noiommu_detach_group(void *iommu_data,
-				      struct iommu_group *iommu_group)
-{
-}
-
-static struct vfio_iommu_driver_ops vfio_noiommu_ops = {
-	.name = "vfio-noiommu",
-	.owner = THIS_MODULE,
-	.open = vfio_noiommu_open,
-	.release = vfio_noiommu_release,
-	.ioctl = vfio_noiommu_ioctl,
-	.attach_group = vfio_noiommu_attach_group,
-	.detach_group = vfio_noiommu_detach_group,
-};
-
-static struct vfio_iommu_driver vfio_noiommu_driver = {
-	.ops = &vfio_noiommu_ops,
-};
-
-/*
- * Wrap IOMMU drivers, the noiommu driver is the one and only driver for
- * noiommu groups (and thus containers) and not available for normal groups.
- */
-#define vfio_for_each_iommu_driver(con, pos)				\
-	for (pos = con->noiommu ? &vfio_noiommu_driver :		\
-	     list_first_entry(&vfio.iommu_drivers_list,			\
-			      struct vfio_iommu_driver, vfio_next);	\
-	     (con->noiommu ? pos != NULL :				\
-			&pos->vfio_next != &vfio.iommu_drivers_list);	\
-	      pos = con->noiommu ? NULL : list_next_entry(pos, vfio_next))
-#else
-#define vfio_for_each_iommu_driver(con, pos)				\
-	list_for_each_entry(pos, &vfio.iommu_drivers_list, vfio_next)
-#endif
-
-
 /**
  * IOMMU driver registration
  */
@@ -342,8 +199,7 @@
 /**
  * Group objects - create, release, get, put, search
  */
-static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
-					    bool noiommu)
+static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
 {
 	struct vfio_group *group, *tmp;
 	struct device *dev;
@@ -361,7 +217,6 @@
 	atomic_set(&group->container_users, 0);
 	atomic_set(&group->opened, 0);
 	group->iommu_group = iommu_group;
-	group->noiommu = noiommu;
 
 	group->nb.notifier_call = vfio_iommu_group_notifier;
 
@@ -397,8 +252,7 @@
 
 	dev = device_create(vfio.class, NULL,
 			    MKDEV(MAJOR(vfio.group_devt), minor),
-			    group, "%s%d", noiommu ? "noiommu-" : "",
-			    iommu_group_id(iommu_group));
+			    group, "%d", iommu_group_id(iommu_group));
 	if (IS_ERR(dev)) {
 		vfio_free_group_minor(minor);
 		vfio_group_unlock_and_free(group);
@@ -682,7 +536,7 @@
 		return 0;
 
 	/* TODO Prevent device auto probing */
-	WARN("Device %s added to live group %d!\n", dev_name(dev),
+	WARN(1, "Device %s added to live group %d!\n", dev_name(dev),
 	     iommu_group_id(group->iommu_group));
 
 	return 0;
@@ -786,8 +640,7 @@
 
 	group = vfio_group_get_from_iommu(iommu_group);
 	if (!group) {
-		group = vfio_create_group(iommu_group,
-					  !iommu_present(dev->bus));
+		group = vfio_create_group(iommu_group);
 		if (IS_ERR(group)) {
 			iommu_group_put(iommu_group);
 			return PTR_ERR(group);
@@ -999,7 +852,8 @@
 		 */
 		if (!driver) {
 			mutex_lock(&vfio.iommu_drivers_lock);
-			vfio_for_each_iommu_driver(container, driver) {
+			list_for_each_entry(driver, &vfio.iommu_drivers_list,
+					    vfio_next) {
 				if (!try_module_get(driver->ops->owner))
 					continue;
 
@@ -1068,7 +922,7 @@
 	}
 
 	mutex_lock(&vfio.iommu_drivers_lock);
-	vfio_for_each_iommu_driver(container, driver) {
+	list_for_each_entry(driver, &vfio.iommu_drivers_list, vfio_next) {
 		void *data;
 
 		if (!try_module_get(driver->ops->owner))
@@ -1333,9 +1187,6 @@
 	if (atomic_read(&group->container_users))
 		return -EINVAL;
 
-	if (group->noiommu && !capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
 	f = fdget(container_fd);
 	if (!f.file)
 		return -EBADF;
@@ -1351,13 +1202,6 @@
 
 	down_write(&container->group_lock);
 
-	/* Real groups and fake groups cannot mix */
-	if (!list_empty(&container->group_list) &&
-	    container->noiommu != group->noiommu) {
-		ret = -EPERM;
-		goto unlock_out;
-	}
-
 	driver = container->iommu_driver;
 	if (driver) {
 		ret = driver->ops->attach_group(container->iommu_data,
@@ -1367,7 +1211,6 @@
 	}
 
 	group->container = container;
-	container->noiommu = group->noiommu;
 	list_add(&group->container_next, &container->group_list);
 
 	/* Get a reference on the container and mark a user within the group */
@@ -1398,9 +1241,6 @@
 	    !group->container->iommu_driver || !vfio_group_viable(group))
 		return -EINVAL;
 
-	if (group->noiommu && !capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
 	device = vfio_device_get_from_name(group, buf);
 	if (!device)
 		return -ENODEV;
@@ -1443,10 +1283,6 @@
 
 	fd_install(ret, filep);
 
-	if (group->noiommu)
-		dev_warn(device->dev, "vfio-noiommu device opened by user "
-			 "(%s:%d)\n", current->comm, task_pid_nr(current));
-
 	return ret;
 }
 
@@ -1535,11 +1371,6 @@
 	if (!group)
 		return -ENODEV;
 
-	if (group->noiommu && !capable(CAP_SYS_RAWIO)) {
-		vfio_group_put(group);
-		return -EPERM;
-	}
-
 	/* Do we need multiple instances of the group open?  Seems not. */
 	opened = atomic_cmpxchg(&group->opened, 0, 1);
 	if (opened) {
@@ -1702,11 +1533,6 @@
 	if (!atomic_inc_not_zero(&group->container_users))
 		return ERR_PTR(-EINVAL);
 
-	if (group->noiommu) {
-		atomic_dec(&group->container_users);
-		return ERR_PTR(-EPERM);
-	}
-
 	if (!group->container->iommu_driver ||
 			!vfio_group_viable(group)) {
 		atomic_dec(&group->container_users);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index eec2f11..ad2146a 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -819,7 +819,7 @@
 		BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE);
 		if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) ||
 		    (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) ||
-		    (a.log_guest_addr & (sizeof(u64) - 1))) {
+		    (a.log_guest_addr & (VRING_USED_ALIGN_SIZE - 1))) {
 			r = -EINVAL;
 			break;
 		}
@@ -1369,7 +1369,7 @@
 	/* Grab the next descriptor number they're advertising, and increment
 	 * the index we've seen. */
 	if (unlikely(__get_user(ring_head,
-				&vq->avail->ring[last_avail_idx % vq->num]))) {
+				&vq->avail->ring[last_avail_idx & (vq->num - 1)]))) {
 		vq_err(vq, "Failed to read head: idx %d address %p\n",
 		       last_avail_idx,
 		       &vq->avail->ring[last_avail_idx % vq->num]);
@@ -1489,7 +1489,7 @@
 	u16 old, new;
 	int start;
 
-	start = vq->last_used_idx % vq->num;
+	start = vq->last_used_idx & (vq->num - 1);
 	used = vq->used->ring + start;
 	if (count == 1) {
 		if (__put_user(heads[0].id, &used->id)) {
@@ -1531,7 +1531,7 @@
 {
 	int start, n, r;
 
-	start = vq->last_used_idx % vq->num;
+	start = vq->last_used_idx & (vq->num - 1);
 	n = vq->num - start;
 	if (n < count) {
 		r = __vhost_add_used_n(vq, heads, n);
diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c
index b335c1a..fe00a07 100644
--- a/drivers/video/fbdev/fsl-diu-fb.c
+++ b/drivers/video/fbdev/fsl-diu-fb.c
@@ -479,7 +479,10 @@
 			port = FSL_DIU_PORT_DLVDS;
 	}
 
-	return diu_ops.valid_monitor_port(port);
+	if (diu_ops.valid_monitor_port)
+		port = diu_ops.valid_monitor_port(port);
+
+	return port;
 }
 
 /*
@@ -1915,6 +1918,14 @@
 #else
 	monitor_port = fsl_diu_name_to_port(monitor_string);
 #endif
+
+	/*
+	 * Must to verify set_pixel_clock. If not implement on platform,
+	 * then that means that there is no platform support for the DIU.
+	 */
+	if (!diu_ops.set_pixel_clock)
+		return -ENODEV;
+
 	pr_info("Freescale Display Interface Unit (DIU) framebuffer driver\n");
 
 #ifdef CONFIG_NOT_COHERENT_CACHE
diff --git a/drivers/video/fbdev/omap2/dss/venc.c b/drivers/video/fbdev/omap2/dss/venc.c
index 99ca268..d05a549 100644
--- a/drivers/video/fbdev/omap2/dss/venc.c
+++ b/drivers/video/fbdev/omap2/dss/venc.c
@@ -275,6 +275,12 @@
 	.vbp		= 41,
 
 	.interlace	= true,
+
+	.hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+	.vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+	.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
+	.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
 };
 EXPORT_SYMBOL(omap_dss_pal_timings);
 
@@ -290,6 +296,12 @@
 	.vbp		= 31,
 
 	.interlace	= true,
+
+	.hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+	.vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+	.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
+	.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
 };
 EXPORT_SYMBOL(omap_dss_ntsc_timings);
 
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index b1877d7..7062bb0 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -412,6 +412,7 @@
 static void __exit virtio_exit(void)
 {
 	bus_unregister(&virtio_bus);
+	ida_destroy(&virtio_index_ida);
 }
 core_initcall(virtio_init);
 module_exit(virtio_exit);
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 096b857..ee663c4 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -80,6 +80,12 @@
 	/* Last used index we've seen. */
 	u16 last_used_idx;
 
+	/* Last written value to avail->flags */
+	u16 avail_flags_shadow;
+
+	/* Last written value to avail->idx in guest byte order */
+	u16 avail_idx_shadow;
+
 	/* How to notify other side. FIXME: commonalize hcalls! */
 	bool (*notify)(struct virtqueue *vq);
 
@@ -109,7 +115,7 @@
 	 * otherwise virt_to_phys will give us bogus addresses in the
 	 * virtqueue.
 	 */
-	gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH);
+	gfp &= ~__GFP_HIGHMEM;
 
 	desc = kmalloc(total_sg * sizeof(struct vring_desc), gfp);
 	if (!desc)
@@ -235,13 +241,14 @@
 
 	/* Put entry in available array (but don't update avail->idx until they
 	 * do sync). */
-	avail = virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) & (vq->vring.num - 1);
+	avail = vq->avail_idx_shadow & (vq->vring.num - 1);
 	vq->vring.avail->ring[avail] = cpu_to_virtio16(_vq->vdev, head);
 
 	/* Descriptors and available array need to be set before we expose the
 	 * new available array entries. */
 	virtio_wmb(vq->weak_barriers);
-	vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) + 1);
+	vq->avail_idx_shadow++;
+	vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow);
 	vq->num_added++;
 
 	pr_debug("Added buffer head %i to %p\n", head, vq);
@@ -354,8 +361,8 @@
 	 * event. */
 	virtio_mb(vq->weak_barriers);
 
-	old = virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) - vq->num_added;
-	new = virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx);
+	old = vq->avail_idx_shadow - vq->num_added;
+	new = vq->avail_idx_shadow;
 	vq->num_added = 0;
 
 #ifdef DEBUG
@@ -510,7 +517,7 @@
 	/* If we expect an interrupt for the next entry, tell host
 	 * by writing event index and flush out the write before
 	 * the read in the next get_buf call. */
-	if (!(vq->vring.avail->flags & cpu_to_virtio16(_vq->vdev, VRING_AVAIL_F_NO_INTERRUPT))) {
+	if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) {
 		vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx);
 		virtio_mb(vq->weak_barriers);
 	}
@@ -537,7 +544,11 @@
 {
 	struct vring_virtqueue *vq = to_vvq(_vq);
 
-	vq->vring.avail->flags |= cpu_to_virtio16(_vq->vdev, VRING_AVAIL_F_NO_INTERRUPT);
+	if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) {
+		vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
+		vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
+	}
+
 }
 EXPORT_SYMBOL_GPL(virtqueue_disable_cb);
 
@@ -565,7 +576,10 @@
 	/* Depending on the VIRTIO_RING_F_EVENT_IDX feature, we need to
 	 * either clear the flags bit or point the event index at the next
 	 * entry. Always do both to keep code simple. */
-	vq->vring.avail->flags &= cpu_to_virtio16(_vq->vdev, ~VRING_AVAIL_F_NO_INTERRUPT);
+	if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) {
+		vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT;
+		vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
+	}
 	vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx);
 	END_USE(vq);
 	return last_used_idx;
@@ -633,9 +647,12 @@
 	/* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to
 	 * either clear the flags bit or point the event index at the next
 	 * entry. Always do both to keep code simple. */
-	vq->vring.avail->flags &= cpu_to_virtio16(_vq->vdev, ~VRING_AVAIL_F_NO_INTERRUPT);
+	if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) {
+		vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT;
+		vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
+	}
 	/* TODO: tune this threshold */
-	bufs = (u16)(virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) - vq->last_used_idx) * 3 / 4;
+	bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4;
 	vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx + bufs);
 	virtio_mb(vq->weak_barriers);
 	if (unlikely((u16)(virtio16_to_cpu(_vq->vdev, vq->vring.used->idx) - vq->last_used_idx) > bufs)) {
@@ -670,7 +687,8 @@
 		/* detach_buf clears data, so grab it now. */
 		buf = vq->data[i];
 		detach_buf(vq, i);
-		vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) - 1);
+		vq->avail_idx_shadow--;
+		vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow);
 		END_USE(vq);
 		return buf;
 	}
@@ -735,6 +753,8 @@
 	vq->weak_barriers = weak_barriers;
 	vq->broken = false;
 	vq->last_used_idx = 0;
+	vq->avail_flags_shadow = 0;
+	vq->avail_idx_shadow = 0;
 	vq->num_added = 0;
 	list_add_tail(&vq->vq.list, &vdev->vqs);
 #ifdef DEBUG
@@ -746,8 +766,10 @@
 	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
 	/* No callback?  Tell other side not to bother us. */
-	if (!callback)
-		vq->vring.avail->flags |= cpu_to_virtio16(vdev, VRING_AVAIL_F_NO_INTERRUPT);
+	if (!callback) {
+		vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
+		vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow);
+	}
 
 	/* Put everything in free lists. */
 	vq->free_head = 0;
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c
index e3e9e3d..96a1b8d 100644
--- a/drivers/xen/events/events_fifo.c
+++ b/drivers/xen/events/events_fifo.c
@@ -281,7 +281,8 @@
 
 static void consume_one_event(unsigned cpu,
 			      struct evtchn_fifo_control_block *control_block,
-			      unsigned priority, unsigned long *ready)
+			      unsigned priority, unsigned long *ready,
+			      bool drop)
 {
 	struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
 	uint32_t head;
@@ -313,13 +314,17 @@
 	if (head == 0)
 		clear_bit(priority, ready);
 
-	if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port))
-		handle_irq_for_port(port);
+	if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) {
+		if (unlikely(drop))
+			pr_warn("Dropping pending event for port %u\n", port);
+		else
+			handle_irq_for_port(port);
+	}
 
 	q->head[priority] = head;
 }
 
-static void evtchn_fifo_handle_events(unsigned cpu)
+static void __evtchn_fifo_handle_events(unsigned cpu, bool drop)
 {
 	struct evtchn_fifo_control_block *control_block;
 	unsigned long ready;
@@ -331,11 +336,16 @@
 
 	while (ready) {
 		q = find_first_bit(&ready, EVTCHN_FIFO_MAX_QUEUES);
-		consume_one_event(cpu, control_block, q, &ready);
+		consume_one_event(cpu, control_block, q, &ready, drop);
 		ready |= xchg(&control_block->ready, 0);
 	}
 }
 
+static void evtchn_fifo_handle_events(unsigned cpu)
+{
+	__evtchn_fifo_handle_events(cpu, false);
+}
+
 static void evtchn_fifo_resume(void)
 {
 	unsigned cpu;
@@ -420,6 +430,9 @@
 		if (!per_cpu(cpu_control_block, cpu))
 			ret = evtchn_fifo_alloc_control_block(cpu);
 		break;
+	case CPU_DEAD:
+		__evtchn_fifo_handle_events(cpu, true);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h
index 58e38d5..4d529f3 100644
--- a/drivers/xen/xen-pciback/pciback.h
+++ b/drivers/xen/xen-pciback/pciback.h
@@ -37,6 +37,7 @@
 	struct xen_pci_sharedinfo *sh_info;
 	unsigned long flags;
 	struct work_struct op_work;
+	struct xen_pci_op op;
 };
 
 struct xen_pcibk_dev_data {
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
index c4a0666..73dafdc 100644
--- a/drivers/xen/xen-pciback/pciback_ops.c
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -70,6 +70,13 @@
 		enable ? "enable" : "disable");
 
 	if (enable) {
+		/*
+		 * The MSI or MSI-X should not have an IRQ handler. Otherwise
+		 * if the guest terminates we BUG_ON in free_msi_irqs.
+		 */
+		if (dev->msi_enabled || dev->msix_enabled)
+			goto out;
+
 		rc = request_irq(dev_data->irq,
 				xen_pcibk_guest_interrupt, IRQF_SHARED,
 				dev_data->irq_name, dev);
@@ -144,7 +151,12 @@
 	if (unlikely(verbose_request))
 		printk(KERN_DEBUG DRV_NAME ": %s: enable MSI\n", pci_name(dev));
 
-	status = pci_enable_msi(dev);
+	if (dev->msi_enabled)
+		status = -EALREADY;
+	else if (dev->msix_enabled)
+		status = -ENXIO;
+	else
+		status = pci_enable_msi(dev);
 
 	if (status) {
 		pr_warn_ratelimited("%s: error enabling MSI for guest %u: err %d\n",
@@ -173,20 +185,23 @@
 int xen_pcibk_disable_msi(struct xen_pcibk_device *pdev,
 			  struct pci_dev *dev, struct xen_pci_op *op)
 {
-	struct xen_pcibk_dev_data *dev_data;
-
 	if (unlikely(verbose_request))
 		printk(KERN_DEBUG DRV_NAME ": %s: disable MSI\n",
 		       pci_name(dev));
-	pci_disable_msi(dev);
 
+	if (dev->msi_enabled) {
+		struct xen_pcibk_dev_data *dev_data;
+
+		pci_disable_msi(dev);
+
+		dev_data = pci_get_drvdata(dev);
+		if (dev_data)
+			dev_data->ack_intr = 1;
+	}
 	op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
 	if (unlikely(verbose_request))
 		printk(KERN_DEBUG DRV_NAME ": %s: MSI: %d\n", pci_name(dev),
 			op->value);
-	dev_data = pci_get_drvdata(dev);
-	if (dev_data)
-		dev_data->ack_intr = 1;
 	return 0;
 }
 
@@ -197,13 +212,26 @@
 	struct xen_pcibk_dev_data *dev_data;
 	int i, result;
 	struct msix_entry *entries;
+	u16 cmd;
 
 	if (unlikely(verbose_request))
 		printk(KERN_DEBUG DRV_NAME ": %s: enable MSI-X\n",
 		       pci_name(dev));
+
 	if (op->value > SH_INFO_MAX_VEC)
 		return -EINVAL;
 
+	if (dev->msix_enabled)
+		return -EALREADY;
+
+	/*
+	 * PCI_COMMAND_MEMORY must be enabled, otherwise we may not be able
+	 * to access the BARs where the MSI-X entries reside.
+	 */
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY))
+		return -ENXIO;
+
 	entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
 	if (entries == NULL)
 		return -ENOMEM;
@@ -245,23 +273,27 @@
 int xen_pcibk_disable_msix(struct xen_pcibk_device *pdev,
 			   struct pci_dev *dev, struct xen_pci_op *op)
 {
-	struct xen_pcibk_dev_data *dev_data;
 	if (unlikely(verbose_request))
 		printk(KERN_DEBUG DRV_NAME ": %s: disable MSI-X\n",
 			pci_name(dev));
-	pci_disable_msix(dev);
 
+	if (dev->msix_enabled) {
+		struct xen_pcibk_dev_data *dev_data;
+
+		pci_disable_msix(dev);
+
+		dev_data = pci_get_drvdata(dev);
+		if (dev_data)
+			dev_data->ack_intr = 1;
+	}
 	/*
 	 * SR-IOV devices (which don't have any legacy IRQ) have
 	 * an undefined IRQ value of zero.
 	 */
 	op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
 	if (unlikely(verbose_request))
-		printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n", pci_name(dev),
-			op->value);
-	dev_data = pci_get_drvdata(dev);
-	if (dev_data)
-		dev_data->ack_intr = 1;
+		printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n",
+		       pci_name(dev), op->value);
 	return 0;
 }
 #endif
@@ -298,9 +330,11 @@
 		container_of(data, struct xen_pcibk_device, op_work);
 	struct pci_dev *dev;
 	struct xen_pcibk_dev_data *dev_data = NULL;
-	struct xen_pci_op *op = &pdev->sh_info->op;
+	struct xen_pci_op *op = &pdev->op;
 	int test_intx = 0;
 
+	*op = pdev->sh_info->op;
+	barrier();
 	dev = xen_pcibk_get_pci_dev(pdev, op->domain, op->bus, op->devfn);
 
 	if (dev == NULL)
@@ -342,6 +376,17 @@
 		if ((dev_data->enable_intx != test_intx))
 			xen_pcibk_control_isr(dev, 0 /* no reset */);
 	}
+	pdev->sh_info->op.err = op->err;
+	pdev->sh_info->op.value = op->value;
+#ifdef CONFIG_PCI_MSI
+	if (op->cmd == XEN_PCI_OP_enable_msix && op->err == 0) {
+		unsigned int i;
+
+		for (i = 0; i < op->value; i++)
+			pdev->sh_info->op.msix_entries[i].vector =
+				op->msix_entries[i].vector;
+	}
+#endif
 	/* Tell the driver domain that we're done. */
 	wmb();
 	clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
index 98bc345..4843741 100644
--- a/drivers/xen/xen-pciback/xenbus.c
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -44,7 +44,6 @@
 	dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
 
 	pdev->xdev = xdev;
-	dev_set_drvdata(&xdev->dev, pdev);
 
 	mutex_init(&pdev->dev_lock);
 
@@ -58,6 +57,9 @@
 		kfree(pdev);
 		pdev = NULL;
 	}
+
+	dev_set_drvdata(&xdev->dev, pdev);
+
 out:
 	return pdev;
 }
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index 43bcae8..ad4eb10 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -726,7 +726,7 @@
 		if (!pending_req)
 			return 1;
 
-		ring_req = *RING_GET_REQUEST(ring, rc);
+		RING_COPY_REQUEST(ring, rc, &ring_req);
 		ring->req_cons = ++rc;
 
 		err = prepare_pending_reqs(info, &ring_req, pending_req);
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 699941e..5110785 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -451,9 +451,9 @@
 {
 	struct v9fs_inode *v9inode = V9FS_I(inode);
 
-	truncate_inode_pages_final(inode->i_mapping);
+	truncate_inode_pages_final(&inode->i_data);
 	clear_inode(inode);
-	filemap_fdatawrite(inode->i_mapping);
+	filemap_fdatawrite(&inode->i_data);
 
 	v9fs_cache_inode_put_cookie(inode);
 	/* clunk the fid stashed in writeback_fid */
diff --git a/fs/block_dev.c b/fs/block_dev.c
index c25639e..44d4a1e 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1523,11 +1523,14 @@
 		WARN_ON_ONCE(bdev->bd_holders);
 		sync_blockdev(bdev);
 		kill_bdev(bdev);
-		/*
-		 * ->release can cause the queue to disappear, so flush all
-		 * dirty data before.
-		 */
+
 		bdev_write_inode(bdev);
+		/*
+		 * Detaching bdev inode from its wb in __destroy_inode()
+		 * is too late: the queue which embeds its bdi (along with
+		 * root wb) can be gone as soon as we put_disk() below.
+		 */
+		inode_detach_wb(bdev->bd_inode);
 	}
 	if (bdev->bd_contains == bdev) {
 		if (disk->fops->release)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 4b89680a..c4661db 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -10480,11 +10480,15 @@
 		 * until transaction commit to do the actual discard.
 		 */
 		if (trimming) {
-			WARN_ON(!list_empty(&block_group->bg_list));
-			spin_lock(&trans->transaction->deleted_bgs_lock);
+			spin_lock(&fs_info->unused_bgs_lock);
+			/*
+			 * A concurrent scrub might have added us to the list
+			 * fs_info->unused_bgs, so use a list_move operation
+			 * to add the block group to the deleted_bgs list.
+			 */
 			list_move(&block_group->bg_list,
 				  &trans->transaction->deleted_bgs);
-			spin_unlock(&trans->transaction->deleted_bgs_lock);
+			spin_unlock(&fs_info->unused_bgs_lock);
 			btrfs_get_block_group(block_group);
 		}
 end_trans:
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 72e7346..0f09526 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1291,7 +1291,8 @@
  * on error we return an unlocked page and the error value
  * on success we return a locked page and 0
  */
-static int prepare_uptodate_page(struct page *page, u64 pos,
+static int prepare_uptodate_page(struct inode *inode,
+				 struct page *page, u64 pos,
 				 bool force_uptodate)
 {
 	int ret = 0;
@@ -1306,6 +1307,10 @@
 			unlock_page(page);
 			return -EIO;
 		}
+		if (page->mapping != inode->i_mapping) {
+			unlock_page(page);
+			return -EAGAIN;
+		}
 	}
 	return 0;
 }
@@ -1324,6 +1329,7 @@
 	int faili;
 
 	for (i = 0; i < num_pages; i++) {
+again:
 		pages[i] = find_or_create_page(inode->i_mapping, index + i,
 					       mask | __GFP_WRITE);
 		if (!pages[i]) {
@@ -1333,13 +1339,17 @@
 		}
 
 		if (i == 0)
-			err = prepare_uptodate_page(pages[i], pos,
+			err = prepare_uptodate_page(inode, pages[i], pos,
 						    force_uptodate);
-		if (i == num_pages - 1)
-			err = prepare_uptodate_page(pages[i],
+		if (!err && i == num_pages - 1)
+			err = prepare_uptodate_page(inode, pages[i],
 						    pos + write_bytes, false);
 		if (err) {
 			page_cache_release(pages[i]);
+			if (err == -EAGAIN) {
+				err = 0;
+				goto again;
+			}
 			faili = i - 1;
 			goto fail;
 		}
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 85a1f86..cfe99be 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -891,7 +891,7 @@
 		spin_unlock(&block_group->lock);
 		ret = 0;
 
-		btrfs_warn(fs_info, "failed to load free space cache for block group %llu, rebuild it now",
+		btrfs_warn(fs_info, "failed to load free space cache for block group %llu, rebuilding it now",
 			block_group->key.objectid);
 	}
 
@@ -2972,7 +2972,7 @@
 		     u64 cont1_bytes, u64 min_bytes)
 {
 	struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
-	struct btrfs_free_space *entry;
+	struct btrfs_free_space *entry = NULL;
 	int ret = -ENOSPC;
 	u64 bitmap_offset = offset_to_bitmap(ctl, offset);
 
@@ -2983,8 +2983,10 @@
 	 * The bitmap that covers offset won't be in the list unless offset
 	 * is just its start offset.
 	 */
-	entry = list_first_entry(bitmaps, struct btrfs_free_space, list);
-	if (entry->offset != bitmap_offset) {
+	if (!list_empty(bitmaps))
+		entry = list_first_entry(bitmaps, struct btrfs_free_space, list);
+
+	if (!entry || entry->offset != bitmap_offset) {
 		entry = tree_search_offset(ctl, bitmap_offset, 1, 0);
 		if (entry && list_empty(&entry->list))
 			list_add(&entry->list, bitmaps);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 3367a3c..be8eae8 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -274,7 +274,6 @@
 	cur_trans->num_dirty_bgs = 0;
 	spin_lock_init(&cur_trans->dirty_bgs_lock);
 	INIT_LIST_HEAD(&cur_trans->deleted_bgs);
-	spin_lock_init(&cur_trans->deleted_bgs_lock);
 	spin_lock_init(&cur_trans->dropped_roots_lock);
 	list_add_tail(&cur_trans->list, &fs_info->trans_list);
 	extent_io_tree_init(&cur_trans->dirty_pages,
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 0da21ca..64c8221 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -77,8 +77,8 @@
 	 */
 	struct mutex cache_write_mutex;
 	spinlock_t dirty_bgs_lock;
+	/* Protected by spin lock fs_info->unused_bgs_lock. */
 	struct list_head deleted_bgs;
-	spinlock_t deleted_bgs_lock;
 	spinlock_t dropped_roots_lock;
 	struct btrfs_delayed_ref_root delayed_refs;
 	int aborted;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 4564522..a23399e 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3548,12 +3548,11 @@
 
 			ret = btrfs_force_chunk_alloc(trans, chunk_root,
 						      BTRFS_BLOCK_GROUP_DATA);
+			btrfs_end_transaction(trans, chunk_root);
 			if (ret < 0) {
 				mutex_unlock(&fs_info->delete_unused_bgs_mutex);
 				goto error;
 			}
-
-			btrfs_end_transaction(trans, chunk_root);
 			chunk_reserved = 1;
 		}
 
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 6b66dd5..a329f5b 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1831,11 +1831,11 @@
  * @word: long word containing the bit lock
  */
 static int
-cifs_wait_bit_killable(struct wait_bit_key *key)
+cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
 {
-	if (fatal_signal_pending(current))
-		return -ERESTARTSYS;
 	freezable_schedule_unsafe();
+	if (signal_pending_state(mode, current))
+		return -ERESTARTSYS;
 	return 0;
 }
 
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 1c75a3a..602e844 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -1175,6 +1175,7 @@
 		if (dio->flags & DIO_LOCKING)
 			mutex_unlock(&inode->i_mutex);
 		kmem_cache_free(dio_cache, dio);
+		retval = 0;
 		goto out;
 	}
 
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 73c64da..60f03b7 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -592,10 +592,7 @@
 			}
 			unlock_page(page);
 		}
-		if (PageDirty(page) || PageWriteback(page))
-			*uptodate = true;
-		else
-			*uptodate = PageUptodate(page);
+		*uptodate = PageUptodate(page);
 		EXOFS_DBGMSG2("index=0x%lx uptodate=%d\n", index, *uptodate);
 		return page;
 	} else {
diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
index af06830..1a08350 100644
--- a/fs/ext4/crypto.c
+++ b/fs/ext4/crypto.c
@@ -389,7 +389,7 @@
 	struct ext4_crypto_ctx	*ctx;
 	struct page		*ciphertext_page = NULL;
 	struct bio		*bio;
-	ext4_lblk_t		lblk = ex->ee_block;
+	ext4_lblk_t		lblk = le32_to_cpu(ex->ee_block);
 	ext4_fsblk_t		pblk = ext4_ext_pblock(ex);
 	unsigned int		len = ext4_ext_get_actual_len(ex);
 	int			ret, err = 0;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 750063f..cc7ca4e 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -26,6 +26,7 @@
 #include <linux/seqlock.h>
 #include <linux/mutex.h>
 #include <linux/timer.h>
+#include <linux/version.h>
 #include <linux/wait.h>
 #include <linux/blockgroup_lock.h>
 #include <linux/percpu_counter.h>
@@ -727,19 +728,55 @@
 	<= (EXT4_GOOD_OLD_INODE_SIZE +			\
 	    (einode)->i_extra_isize))			\
 
+/*
+ * We use an encoding that preserves the times for extra epoch "00":
+ *
+ * extra  msb of                         adjust for signed
+ * epoch  32-bit                         32-bit tv_sec to
+ * bits   time    decoded 64-bit tv_sec  64-bit tv_sec      valid time range
+ * 0 0    1    -0x80000000..-0x00000001  0x000000000 1901-12-13..1969-12-31
+ * 0 0    0    0x000000000..0x07fffffff  0x000000000 1970-01-01..2038-01-19
+ * 0 1    1    0x080000000..0x0ffffffff  0x100000000 2038-01-19..2106-02-07
+ * 0 1    0    0x100000000..0x17fffffff  0x100000000 2106-02-07..2174-02-25
+ * 1 0    1    0x180000000..0x1ffffffff  0x200000000 2174-02-25..2242-03-16
+ * 1 0    0    0x200000000..0x27fffffff  0x200000000 2242-03-16..2310-04-04
+ * 1 1    1    0x280000000..0x2ffffffff  0x300000000 2310-04-04..2378-04-22
+ * 1 1    0    0x300000000..0x37fffffff  0x300000000 2378-04-22..2446-05-10
+ *
+ * Note that previous versions of the kernel on 64-bit systems would
+ * incorrectly use extra epoch bits 1,1 for dates between 1901 and
+ * 1970.  e2fsck will correct this, assuming that it is run on the
+ * affected filesystem before 2242.
+ */
+
 static inline __le32 ext4_encode_extra_time(struct timespec *time)
 {
-       return cpu_to_le32((sizeof(time->tv_sec) > 4 ?
-			   (time->tv_sec >> 32) & EXT4_EPOCH_MASK : 0) |
-                          ((time->tv_nsec << EXT4_EPOCH_BITS) & EXT4_NSEC_MASK));
+	u32 extra = sizeof(time->tv_sec) > 4 ?
+		((time->tv_sec - (s32)time->tv_sec) >> 32) & EXT4_EPOCH_MASK : 0;
+	return cpu_to_le32(extra | (time->tv_nsec << EXT4_EPOCH_BITS));
 }
 
 static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
 {
-       if (sizeof(time->tv_sec) > 4)
-	       time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
-			       << 32;
-       time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
+	if (unlikely(sizeof(time->tv_sec) > 4 &&
+			(extra & cpu_to_le32(EXT4_EPOCH_MASK)))) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
+		/* Handle legacy encoding of pre-1970 dates with epoch
+		 * bits 1,1.  We assume that by kernel version 4.20,
+		 * everyone will have run fsck over the affected
+		 * filesystems to correct the problem.  (This
+		 * backwards compatibility may be removed before this
+		 * time, at the discretion of the ext4 developers.)
+		 */
+		u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK;
+		if (extra_bits == 3 && ((time->tv_sec) & 0x80000000) != 0)
+			extra_bits = 0;
+		time->tv_sec += extra_bits << 32;
+#else
+		time->tv_sec += (u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32;
+#endif
+	}
+	time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
 }
 
 #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode)			       \
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index abe2401..e8e7af6 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -52,7 +52,7 @@
 	/* Symlink is encrypted */
 	sd = (struct ext4_encrypted_symlink_data *)caddr;
 	cstr.name = sd->encrypted_path;
-	cstr.len  = le32_to_cpu(sd->len);
+	cstr.len  = le16_to_cpu(sd->len);
 	if ((cstr.len +
 	     sizeof(struct ext4_encrypted_symlink_data) - 1) >
 	    max_size) {
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
index 1b57c72..1420a3c 100644
--- a/fs/ext4/sysfs.c
+++ b/fs/ext4/sysfs.c
@@ -358,7 +358,7 @@
 	return single_open(file, ext4_seq_##name##_show, PDE_DATA(inode)); \
 } \
 \
-const struct file_operations ext4_seq_##name##_fops = { \
+static const struct file_operations ext4_seq_##name##_fops = { \
 	.owner		= THIS_MODULE, \
 	.open		= name##_open, \
 	.read		= seq_read, \
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index eae2c11..8e3ee19 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -549,6 +549,8 @@
 		unregister_chrdev_region(cc->cdev->dev, 1);
 		cdev_del(cc->cdev);
 	}
+	/* Base reference is now owned by "fud" */
+	fuse_conn_put(&cc->fc);
 
 	rc = fuse_dev_release(inode, file);	/* puts the base reference */
 
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index e0faf8f..570ca40 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1049,6 +1049,7 @@
 		tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
 		flush_dcache_page(page);
 
+		iov_iter_advance(ii, tmp);
 		if (!tmp) {
 			unlock_page(page);
 			page_cache_release(page);
@@ -1061,7 +1062,6 @@
 		req->page_descs[req->num_pages].length = tmp;
 		req->num_pages++;
 
-		iov_iter_advance(ii, tmp);
 		count += tmp;
 		pos += tmp;
 		offset += tmp;
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 89463ee..ca181e8 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -1009,7 +1009,8 @@
 }
 
 /* Fast check whether buffer is already attached to the required transaction */
-static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh)
+static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh,
+							bool undo)
 {
 	struct journal_head *jh;
 	bool ret = false;
@@ -1036,6 +1037,9 @@
 	jh = READ_ONCE(bh->b_private);
 	if (!jh)
 		goto out;
+	/* For undo access buffer must have data copied */
+	if (undo && !jh->b_committed_data)
+		goto out;
 	if (jh->b_transaction != handle->h_transaction &&
 	    jh->b_next_transaction != handle->h_transaction)
 		goto out;
@@ -1073,7 +1077,7 @@
 	struct journal_head *jh;
 	int rc;
 
-	if (jbd2_write_access_granted(handle, bh))
+	if (jbd2_write_access_granted(handle, bh, false))
 		return 0;
 
 	jh = jbd2_journal_add_journal_head(bh);
@@ -1210,7 +1214,7 @@
 	char *committed_data = NULL;
 
 	JBUFFER_TRACE(jh, "entry");
-	if (jbd2_write_access_granted(handle, bh))
+	if (jbd2_write_access_granted(handle, bh, true))
 		return 0;
 
 	jh = jbd2_journal_add_journal_head(bh);
@@ -2152,6 +2156,7 @@
 
 		if (!buffer_dirty(bh)) {
 			/* bdflush has written it.  We can drop it now */
+			__jbd2_journal_remove_checkpoint(jh);
 			goto zap_buffer;
 		}
 
@@ -2181,6 +2186,7 @@
 				/* The orphan record's transaction has
 				 * committed.  We can cleanse this buffer */
 				clear_buffer_jbddirty(bh);
+				__jbd2_journal_remove_checkpoint(jh);
 				goto zap_buffer;
 			}
 		}
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index beac58b..646cdac 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -78,8 +78,7 @@
 
 	p = xdr_inline_decode(xdr, nbytes);
 	if (unlikely(p == NULL))
-		printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed "
-							"or truncated request.\n");
+		printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed!\n");
 	return p;
 }
 
@@ -890,7 +889,6 @@
 	struct cb_compound_hdr_arg hdr_arg = { 0 };
 	struct cb_compound_hdr_res hdr_res = { NULL };
 	struct xdr_stream xdr_in, xdr_out;
-	struct xdr_buf *rq_arg = &rqstp->rq_arg;
 	__be32 *p, status;
 	struct cb_process_state cps = {
 		.drc_status = 0,
@@ -902,8 +900,7 @@
 
 	dprintk("%s: start\n", __func__);
 
-	rq_arg->len = rq_arg->head[0].iov_len + rq_arg->page_len;
-	xdr_init_decode(&xdr_in, rq_arg, rq_arg->head[0].iov_base);
+	xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
 
 	p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
 	xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 31b0a52..c7e8b87 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -75,11 +75,11 @@
  * nfs_wait_bit_killable - helper for functions that are sleeping on bit locks
  * @word: long word containing the bit lock
  */
-int nfs_wait_bit_killable(struct wait_bit_key *key)
+int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
 {
-	if (fatal_signal_pending(current))
-		return -ERESTARTSYS;
 	freezable_schedule_unsafe();
+	if (signal_pending_state(mode, current))
+		return -ERESTARTSYS;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 56cfde2..9dea85f 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -379,7 +379,7 @@
 extern void nfs_clear_inode(struct inode *);
 extern void nfs_evict_inode(struct inode *);
 void nfs_zap_acl_cache(struct inode *inode);
-extern int nfs_wait_bit_killable(struct wait_bit_key *key);
+extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
 
 /* super.c */
 extern const struct super_operations nfs_sops;
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
index 5c0c6b5..9aebffb 100644
--- a/fs/nfs/objlayout/objio_osd.c
+++ b/fs/nfs/objlayout/objio_osd.c
@@ -476,10 +476,7 @@
 		}
 		unlock_page(page);
 	}
-	if (PageDirty(page) || PageWriteback(page))
-		*uptodate = true;
-	else
-		*uptodate = PageUptodate(page);
+	*uptodate = PageUptodate(page);
 	dprintk("%s: index=0x%lx uptodate=%d\n", __func__, index, *uptodate);
 	return page;
 }
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index fe3ddd2..452a011 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -129,7 +129,7 @@
 		set_bit(NFS_IO_INPROGRESS, &c->flags);
 		if (atomic_read(&c->io_count) == 0)
 			break;
-		ret = nfs_wait_bit_killable(&q.key);
+		ret = nfs_wait_bit_killable(&q.key, TASK_KILLABLE);
 	} while (atomic_read(&c->io_count) != 0 && !ret);
 	finish_wait(wq, &q.wait);
 	return ret;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 5a8ae21..bec0384 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1466,11 +1466,11 @@
 }
 
 /* stop waiting if someone clears NFS_LAYOUT_RETRY_LAYOUTGET bit. */
-static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key)
+static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key, int mode)
 {
 	if (!test_bit(NFS_LAYOUT_RETRY_LAYOUTGET, key->flags))
 		return 1;
-	return nfs_wait_bit_killable(key);
+	return nfs_wait_bit_killable(key, mode);
 }
 
 static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo)
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index 9ffef06..c9d6c71 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -616,6 +616,7 @@
 
 	mutex_lock(&ls->ls_mutex);
 	nfs4_inc_and_copy_stateid(&ls->ls_recall_sid, &ls->ls_stid);
+	mutex_unlock(&ls->ls_mutex);
 }
 
 static int
@@ -659,7 +660,6 @@
 
 	trace_layout_recall_release(&ls->ls_stid.sc_stateid);
 
-	mutex_unlock(&ls->ls_mutex);
 	nfsd4_return_all_layouts(ls, &reaplist);
 	nfsd4_free_layouts(&reaplist);
 	nfs4_put_stid(&ls->ls_stid);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index a03f6f4..3123408 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -367,13 +367,11 @@
 		goto leave;
 	}
 
-	status = posix_acl_create(dir, &mode, &default_acl, &acl);
+	status = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
 	if (status) {
 		mlog_errno(status);
 		goto leave;
 	}
-	/* update inode->i_mode after mask with "umask". */
-	inode->i_mode = mode;
 
 	handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb,
 							    S_ISDIR(mode),
diff --git a/fs/proc/base.c b/fs/proc/base.c
index bd3e9e6..4bd5d31 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2494,6 +2494,7 @@
 	mm = get_task_mm(task);
 	if (!mm)
 		goto out_no_mm;
+	ret = 0;
 
 	for (i = 0, mask = 1; i < MMF_DUMP_FILTER_BITS; i++, mask <<= 1) {
 		if (val & mask)
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index db284bf..9dbb739 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -5,7 +5,7 @@
  * Copyright 2001 Red Hat, Inc.
  * Based on code from mm/memory.c Copyright Linus Torvalds and others.
  *
- * Copyright 2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright 2011 Red Hat, Inc., Peter Zijlstra
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 04caa8f..d7162cf 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1117,6 +1117,7 @@
 #define DRM_PCIE_SPEED_80 4
 
 extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
+extern int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw);
 
 /* platform section */
 extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device);
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 1666371..24ab178 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -94,6 +94,7 @@
 	struct drm_dp_mst_topology_mgr *mgr;
 
 	struct edid *cached_edid; /* for DP logical ports - make tiling work */
+	bool has_audio;
 };
 
 /**
@@ -215,13 +216,13 @@
 	struct drm_dp_sideband_msg_hdr initial_hdr;
 };
 
-
+#define DRM_DP_MAX_SDP_STREAMS 16
 struct drm_dp_allocate_payload {
 	u8 port_number;
 	u8 number_sdp_streams;
 	u8 vcpi;
 	u16 pbn;
-	u8 sdp_stream_sink[8];
+	u8 sdp_stream_sink[DRM_DP_MAX_SDP_STREAMS];
 };
 
 struct drm_dp_allocate_payload_ack_reply {
@@ -450,9 +451,7 @@
 	   the mstb tx_slots and txmsg->state once they are queued */
 	struct mutex qlock;
 	struct list_head tx_msg_downq;
-	struct list_head tx_msg_upq;
 	bool tx_down_in_progress;
-	bool tx_up_in_progress;
 
 	/* payload info + lock for it */
 	struct mutex payload_lock;
@@ -484,6 +483,8 @@
 
 enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
 
+bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr,
+					struct drm_dp_mst_port *port);
 struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
 
 
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index f1d8d0d..1b3b1f8 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -163,9 +163,36 @@
 	return container_of(dev, struct mipi_dsi_device, dev);
 }
 
+/**
+ * mipi_dsi_pixel_format_to_bpp - obtain the number of bits per pixel for any
+ *                                given pixel format defined by the MIPI DSI
+ *                                specification
+ * @fmt: MIPI DSI pixel format
+ *
+ * Returns: The number of bits per pixel of the given pixel format.
+ */
+static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
+{
+	switch (fmt) {
+	case MIPI_DSI_FMT_RGB888:
+	case MIPI_DSI_FMT_RGB666:
+		return 24;
+
+	case MIPI_DSI_FMT_RGB666_PACKED:
+		return 18;
+
+	case MIPI_DSI_FMT_RGB565:
+		return 16;
+	}
+
+	return -EINVAL;
+}
+
 struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np);
 int mipi_dsi_attach(struct mipi_dsi_device *dsi);
 int mipi_dsi_detach(struct mipi_dsi_device *dsi);
+int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi);
+int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
 int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
 					    u16 value);
 
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
index fab1385..b46fa0e 100644
--- a/include/drm/i915_component.h
+++ b/include/drm/i915_component.h
@@ -65,6 +65,20 @@
 	 * sample rate, it will call this function to set n/cts
 	 */
 	int (*sync_audio_rate)(struct device *, int port, int rate);
+	/**
+	 * @get_eld: fill the audio state and ELD bytes for the given port
+	 *
+	 * Called from audio driver to get the HDMI/DP audio state of the given
+	 * digital port, and also fetch ELD bytes to the given pointer.
+	 *
+	 * It returns the byte size of the original ELD (not the actually
+	 * copied size), zero for an invalid ELD, or a negative error code.
+	 *
+	 * Note that the returned size may be over @max_bytes.  Then it
+	 * implies that only a part of ELD has been copied to the buffer.
+	 */
+	int (*get_eld)(struct device *, int port, bool *enabled,
+		       unsigned char *buf, int max_bytes);
 };
 
 /**
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index c768ddf..afae231 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -383,6 +383,16 @@
  */
 extern int ttm_bo_del_from_lru(struct ttm_buffer_object *bo);
 
+/**
+ * ttm_bo_move_to_lru_tail
+ *
+ * @bo: The buffer object.
+ *
+ * Move this BO to the tail of all lru lists used to lookup and reserve an
+ * object. This function must be called with struct ttm_bo_global::lru_lock
+ * held, and is used to make a BO less likely to be considered for eviction.
+ */
+extern void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo);
 
 /**
  * ttm_bo_lock_delayed_workqueue
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 2b8ed12..defeaac 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -107,7 +107,7 @@
  */
 static inline __u32 rol32(__u32 word, unsigned int shift)
 {
-	return (word << shift) | (word >> (32 - shift));
+	return (word << shift) | (word >> ((-shift) & 31));
 }
 
 /**
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 60d44b2..06b77f9d 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -90,7 +90,6 @@
  */
 struct cgroup_file {
 	/* do not access any fields from outside cgroup core */
-	struct list_head node;			/* anchored at css->files */
 	struct kernfs_node *kn;
 };
 
@@ -134,9 +133,6 @@
 	 */
 	u64 serial_nr;
 
-	/* all cgroup_files associated with this css */
-	struct list_head files;
-
 	/* percpu_ref killing and RCU release */
 	struct rcu_head rcu_head;
 	struct work_struct destroy_work;
@@ -426,12 +422,9 @@
 	void (*css_reset)(struct cgroup_subsys_state *css);
 	void (*css_e_css_changed)(struct cgroup_subsys_state *css);
 
-	int (*can_attach)(struct cgroup_subsys_state *css,
-			  struct cgroup_taskset *tset);
-	void (*cancel_attach)(struct cgroup_subsys_state *css,
-			      struct cgroup_taskset *tset);
-	void (*attach)(struct cgroup_subsys_state *css,
-		       struct cgroup_taskset *tset);
+	int (*can_attach)(struct cgroup_taskset *tset);
+	void (*cancel_attach)(struct cgroup_taskset *tset);
+	void (*attach)(struct cgroup_taskset *tset);
 	int (*can_fork)(struct task_struct *task, void **priv_p);
 	void (*cancel_fork)(struct task_struct *task, void *priv);
 	void (*fork)(struct task_struct *task, void *priv);
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 22e3754..cb91b44 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -88,6 +88,7 @@
 int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
 int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
 int cgroup_rm_cftypes(struct cftype *cfts);
+void cgroup_file_notify(struct cgroup_file *cfile);
 
 char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
 int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry);
@@ -119,8 +120,10 @@
 struct cgroup_subsys_state *css_next_descendant_post(struct cgroup_subsys_state *pos,
 						     struct cgroup_subsys_state *css);
 
-struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset);
-struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset);
+struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset,
+					 struct cgroup_subsys_state **dst_cssp);
+struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset,
+					struct cgroup_subsys_state **dst_cssp);
 
 void css_task_iter_start(struct cgroup_subsys_state *css,
 			 struct css_task_iter *it);
@@ -235,30 +238,39 @@
 /**
  * cgroup_taskset_for_each - iterate cgroup_taskset
  * @task: the loop cursor
+ * @dst_css: the destination css
  * @tset: taskset to iterate
  *
  * @tset may contain multiple tasks and they may belong to multiple
- * processes.  When there are multiple tasks in @tset, if a task of a
- * process is in @tset, all tasks of the process are in @tset.  Also, all
- * are guaranteed to share the same source and destination csses.
+ * processes.
+ *
+ * On the v2 hierarchy, there may be tasks from multiple processes and they
+ * may not share the source or destination csses.
+ *
+ * On traditional hierarchies, when there are multiple tasks in @tset, if a
+ * task of a process is in @tset, all tasks of the process are in @tset.
+ * Also, all are guaranteed to share the same source and destination csses.
  *
  * Iteration is not in any specific order.
  */
-#define cgroup_taskset_for_each(task, tset)				\
-	for ((task) = cgroup_taskset_first((tset)); (task);		\
-	     (task) = cgroup_taskset_next((tset)))
+#define cgroup_taskset_for_each(task, dst_css, tset)			\
+	for ((task) = cgroup_taskset_first((tset), &(dst_css));		\
+	     (task);							\
+	     (task) = cgroup_taskset_next((tset), &(dst_css)))
 
 /**
  * cgroup_taskset_for_each_leader - iterate group leaders in a cgroup_taskset
  * @leader: the loop cursor
+ * @dst_css: the destination css
  * @tset: takset to iterate
  *
  * Iterate threadgroup leaders of @tset.  For single-task migrations, @tset
  * may not contain any.
  */
-#define cgroup_taskset_for_each_leader(leader, tset)			\
-	for ((leader) = cgroup_taskset_first((tset)); (leader);		\
-	     (leader) = cgroup_taskset_next((tset)))			\
+#define cgroup_taskset_for_each_leader(leader, dst_css, tset)		\
+	for ((leader) = cgroup_taskset_first((tset), &(dst_css));	\
+	     (leader);							\
+	     (leader) = cgroup_taskset_next((tset), &(dst_css)))	\
 		if ((leader) != (leader)->group_leader)			\
 			;						\
 		else
@@ -516,19 +528,6 @@
 	pr_cont_kernfs_path(cgrp->kn);
 }
 
-/**
- * cgroup_file_notify - generate a file modified event for a cgroup_file
- * @cfile: target cgroup_file
- *
- * @cfile must have been obtained by setting cftype->file_offset.
- */
-static inline void cgroup_file_notify(struct cgroup_file *cfile)
-{
-	/* might not have been created due to one of the CFTYPE selector flags */
-	if (cfile->kn)
-		kernfs_notify(cfile->kn);
-}
-
 #else /* !CONFIG_CGROUPS */
 
 struct cgroup_subsys_state;
diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
index 7be22da..a4cf57c 100644
--- a/include/linux/enclosure.h
+++ b/include/linux/enclosure.h
@@ -29,7 +29,11 @@
 /* A few generic types ... taken from ses-2 */
 enum enclosure_component_type {
 	ENCLOSURE_COMPONENT_DEVICE = 0x01,
+	ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS = 0x07,
+	ENCLOSURE_COMPONENT_SCSI_TARGET_PORT = 0x14,
+	ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT = 0x15,
 	ENCLOSURE_COMPONENT_ARRAY_DEVICE = 0x17,
+	ENCLOSURE_COMPONENT_SAS_EXPANDER = 0x18,
 };
 
 /* ses-2 common element status */
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index c9ae0c6..d5d798b 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -330,6 +330,7 @@
 };
 
 struct irq_domain;
+struct device_node;
 int its_cpu_init(void);
 int its_init(struct device_node *node, struct rdists *rdists,
 	     struct irq_domain *domain);
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 8dde559..0536524 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -5,7 +5,7 @@
  * Jump label support
  *
  * Copyright (C) 2009-2012 Jason Baron <jbaron@redhat.com>
- * Copyright (C) 2011-2012 Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra
  *
  * DEPRECATED API:
  *
diff --git a/include/linux/kmemleak.h b/include/linux/kmemleak.h
index d0a1f99..4894c68 100644
--- a/include/linux/kmemleak.h
+++ b/include/linux/kmemleak.h
@@ -25,7 +25,7 @@
 
 #ifdef CONFIG_DEBUG_KMEMLEAK
 
-extern void kmemleak_init(void) __ref;
+extern void kmemleak_init(void) __init;
 extern void kmemleak_alloc(const void *ptr, size_t size, int min_count,
 			   gfp_t gfp) __ref;
 extern void kmemleak_alloc_percpu(const void __percpu *ptr, size_t size,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 83577f8..600c1e0 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -210,6 +210,7 @@
 	ATA_FLAG_SLAVE_POSS	= (1 << 0), /* host supports slave dev */
 					    /* (doesn't imply presence) */
 	ATA_FLAG_SATA		= (1 << 1),
+	ATA_FLAG_NO_LOG_PAGE	= (1 << 5), /* do not issue log page read */
 	ATA_FLAG_NO_ATAPI	= (1 << 6), /* No ATAPI support */
 	ATA_FLAG_PIO_DMA	= (1 << 7), /* PIO cmds via DMA */
 	ATA_FLAG_PIO_LBA48	= (1 << 8), /* Host DMA engine is LBA28 only */
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
index c6916ae..034117b 100644
--- a/include/linux/lightnvm.h
+++ b/include/linux/lightnvm.h
@@ -50,9 +50,16 @@
 	NVM_IO_DUAL_ACCESS	= 0x1,
 	NVM_IO_QUAD_ACCESS	= 0x2,
 
+	/* NAND Access Modes */
 	NVM_IO_SUSPEND		= 0x80,
 	NVM_IO_SLC_MODE		= 0x100,
 	NVM_IO_SCRAMBLE_DISABLE	= 0x200,
+
+	/* Block Types */
+	NVM_BLK_T_FREE		= 0x0,
+	NVM_BLK_T_BAD		= 0x1,
+	NVM_BLK_T_DEV		= 0x2,
+	NVM_BLK_T_HOST		= 0x4,
 };
 
 struct nvm_id_group {
@@ -176,17 +183,17 @@
 
 typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *);
 typedef int (nvm_bb_update_fn)(struct ppa_addr, int, u8 *, void *);
-typedef int (nvm_id_fn)(struct request_queue *, struct nvm_id *);
-typedef int (nvm_get_l2p_tbl_fn)(struct request_queue *, u64, u32,
+typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
+typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32,
 				nvm_l2p_update_fn *, void *);
 typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, int,
 				nvm_bb_update_fn *, void *);
-typedef int (nvm_op_set_bb_fn)(struct request_queue *, struct nvm_rq *, int);
-typedef int (nvm_submit_io_fn)(struct request_queue *, struct nvm_rq *);
-typedef int (nvm_erase_blk_fn)(struct request_queue *, struct nvm_rq *);
-typedef void *(nvm_create_dma_pool_fn)(struct request_queue *, char *);
+typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int);
+typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
+typedef int (nvm_erase_blk_fn)(struct nvm_dev *, struct nvm_rq *);
+typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *);
 typedef void (nvm_destroy_dma_pool_fn)(void *);
-typedef void *(nvm_dev_dma_alloc_fn)(struct request_queue *, void *, gfp_t,
+typedef void *(nvm_dev_dma_alloc_fn)(struct nvm_dev *, void *, gfp_t,
 								dma_addr_t *);
 typedef void (nvm_dev_dma_free_fn)(void *, void*, dma_addr_t);
 
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 70400dc..c57e424 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -2,7 +2,7 @@
  * Runtime locking correctness validator
  *
  *  Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * see Documentation/locking/lockdep-design.txt for more details.
  */
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 7501626..d3133be 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -427,6 +427,17 @@
 };
 
 enum {
+	/*
+	 * Max wqe size for rdma read is 512 bytes, so this
+	 * limits our max_sge_rd as the wqe needs to fit:
+	 * - ctrl segment (16 bytes)
+	 * - rdma segment (16 bytes)
+	 * - scatter elements (16 bytes each)
+	 */
+	MLX4_MAX_SGE_RD	= (512 - 16 - 16) / 16
+};
+
+enum {
 	MLX4_DEV_PMC_SUBTYPE_GUID_INFO	 = 0x14,
 	MLX4_DEV_PMC_SUBTYPE_PORT_INFO	 = 0x15,
 	MLX4_DEV_PMC_SUBTYPE_PKEY_TABLE	 = 0x16,
diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h
index 877ef22..772362a 100644
--- a/include/linux/mmdebug.h
+++ b/include/linux/mmdebug.h
@@ -1,6 +1,7 @@
 #ifndef LINUX_MM_DEBUG_H
 #define LINUX_MM_DEBUG_H 1
 
+#include <linux/bug.h>
 #include <linux/stringify.h>
 
 struct page;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3b5d134..3143c84 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2084,7 +2084,7 @@
 })
 
 #define netdev_alloc_pcpu_stats(type)					\
-	__netdev_alloc_pcpu_stats(type, GFP_KERNEL);
+	__netdev_alloc_pcpu_stats(type, GFP_KERNEL)
 
 #include <linux/notifier.h>
 
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 249d1bb..5646b24 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -14,7 +14,7 @@
 	int (*call_rcu)(struct sock *nl, struct sk_buff *skb, 
 		    const struct nlmsghdr *nlh,
 		    const struct nlattr * const cda[]);
-	int (*call_batch)(struct sock *nl, struct sk_buff *skb,
+	int (*call_batch)(struct net *net, struct sock *nl, struct sk_buff *skb,
 			  const struct nlmsghdr *nlh,
 			  const struct nlattr * const cda[]);
 	const struct nla_policy *policy;	/* netlink attribute policy */
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 039f2ee..1e0deb8 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -46,12 +46,14 @@
 extern int of_irq_get_byname(struct device_node *dev, const char *name);
 extern int of_irq_to_resource_table(struct device_node *dev,
 		struct resource *res, int nr_irqs);
+extern struct device_node *of_irq_find_parent(struct device_node *child);
 extern struct irq_domain *of_msi_get_domain(struct device *dev,
 					    struct device_node *np,
 					    enum irq_domain_bus_token token);
 extern struct irq_domain *of_msi_map_get_device_domain(struct device *dev,
 						       u32 rid);
 extern void of_msi_configure(struct device *dev, struct device_node *np);
+u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
 #else
 static inline int of_irq_count(struct device_node *dev)
 {
@@ -70,6 +72,11 @@
 {
 	return 0;
 }
+static inline void *of_irq_find_parent(struct device_node *child)
+{
+	return NULL;
+}
+
 static inline struct irq_domain *of_msi_get_domain(struct device *dev,
 						   struct device_node *np,
 						   enum irq_domain_bus_token token)
@@ -84,6 +91,11 @@
 static inline void of_msi_configure(struct device *dev, struct device_node *np)
 {
 }
+static inline u32 of_msi_map_rid(struct device *dev,
+				 struct device_node *msi_np, u32 rid_in)
+{
+	return rid_in;
+}
 #endif
 
 #if defined(CONFIG_OF_IRQ) || defined(CONFIG_SPARC)
@@ -93,7 +105,6 @@
  * so declare it here regardless of the CONFIG_OF_IRQ setting.
  */
 extern unsigned int irq_of_parse_and_map(struct device_node *node, int index);
-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
 
 #else /* !CONFIG_OF && !CONFIG_SPARC */
 static inline unsigned int irq_of_parse_and_map(struct device_node *dev,
@@ -101,12 +112,6 @@
 {
 	return 0;
 }
-
-static inline u32 of_msi_map_rid(struct device *dev,
-				 struct device_node *msi_np, u32 rid_in)
-{
-	return rid_in;
-}
 #endif /* !CONFIG_OF */
 
 #endif /* __OF_IRQ_H */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index d841d33..f9828a4 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -697,9 +697,11 @@
  * if there is no cgroup event for the current CPU context.
  */
 static inline struct perf_cgroup *
-perf_cgroup_from_task(struct task_struct *task)
+perf_cgroup_from_task(struct task_struct *task, struct perf_event_context *ctx)
 {
-	return container_of(task_css(task, perf_event_cgrp_id),
+	return container_of(task_css_check(task, perf_event_cgrp_id,
+					   ctx ? lockdep_is_held(&ctx->lock)
+					       : true),
 			    struct perf_cgroup, css);
 }
 #endif /* CONFIG_CGROUP_PERF */
diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
index e2878ba..4299f4b 100644
--- a/include/linux/platform_data/edma.h
+++ b/include/linux/platform_data/edma.h
@@ -72,7 +72,7 @@
 	struct edma_rsv_info	*rsv;
 
 	/* List of channels allocated for memcpy, terminated with -1 */
-	s16			*memcpy_channels;
+	s32			*memcpy_channels;
 
 	s8	(*queue_priority_mapping)[2];
 	const s16	(*xbar_chans)[2];
diff --git a/include/linux/proportions.h b/include/linux/proportions.h
index 5440f64..2122133 100644
--- a/include/linux/proportions.h
+++ b/include/linux/proportions.h
@@ -1,7 +1,7 @@
 /*
  * FLoating proportions
  *
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * This file contains the public data structure and API definitions.
  */
diff --git a/include/linux/qed/common_hsi.h b/include/linux/qed/common_hsi.h
index 6a43476..1d1ba2c 100644
--- a/include/linux/qed/common_hsi.h
+++ b/include/linux/qed/common_hsi.h
@@ -9,6 +9,8 @@
 #ifndef __COMMON_HSI__
 #define __COMMON_HSI__
 
+#define CORE_SPQE_PAGE_SIZE_BYTES                       4096
+
 #define FW_MAJOR_VERSION	8
 #define FW_MINOR_VERSION	4
 #define FW_REVISION_VERSION	2
diff --git a/include/linux/qed/qed_chain.h b/include/linux/qed/qed_chain.h
index b920c36..41b9049 100644
--- a/include/linux/qed/qed_chain.h
+++ b/include/linux/qed/qed_chain.h
@@ -111,7 +111,8 @@
 	used = ((u32)0x10000u + (u32)(p_chain->prod_idx)) -
 		(u32)p_chain->cons_idx;
 	if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR)
-		used -= (used / p_chain->elem_per_page);
+		used -= p_chain->prod_idx / p_chain->elem_per_page -
+			p_chain->cons_idx / p_chain->elem_per_page;
 
 	return p_chain->capacity - used;
 }
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 843ceca..e50b31d 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -19,6 +19,7 @@
 
 #include <linux/atomic.h>
 #include <linux/compiler.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/jhash.h>
 #include <linux/list_nulls.h>
@@ -339,10 +340,11 @@
 int rhashtable_init(struct rhashtable *ht,
 		    const struct rhashtable_params *params);
 
-int rhashtable_insert_slow(struct rhashtable *ht, const void *key,
-			   struct rhash_head *obj,
-			   struct bucket_table *old_tbl);
-int rhashtable_insert_rehash(struct rhashtable *ht);
+struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
+					    const void *key,
+					    struct rhash_head *obj,
+					    struct bucket_table *old_tbl);
+int rhashtable_insert_rehash(struct rhashtable *ht, struct bucket_table *tbl);
 
 int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter);
 void rhashtable_walk_exit(struct rhashtable_iter *iter);
@@ -598,9 +600,11 @@
 
 	new_tbl = rht_dereference_rcu(tbl->future_tbl, ht);
 	if (unlikely(new_tbl)) {
-		err = rhashtable_insert_slow(ht, key, obj, new_tbl);
-		if (err == -EAGAIN)
+		tbl = rhashtable_insert_slow(ht, key, obj, new_tbl);
+		if (!IS_ERR_OR_NULL(tbl))
 			goto slow_path;
+
+		err = PTR_ERR(tbl);
 		goto out;
 	}
 
@@ -611,7 +615,7 @@
 	if (unlikely(rht_grow_above_100(ht, tbl))) {
 slow_path:
 		spin_unlock_bh(lock);
-		err = rhashtable_insert_rehash(ht);
+		err = rhashtable_insert_rehash(ht, tbl);
 		rcu_read_unlock();
 		if (err)
 			return err;
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 0adedca..0e1b154 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -99,7 +99,7 @@
  * grabbing every spinlock (and more).  So the "read" side to such a
  * lock is anything which disables preemption.
  */
-#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP)
+#if defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU)
 
 /**
  * stop_machine: freeze the machine on all CPUs and run this function
@@ -118,7 +118,7 @@
 
 int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
 				   const struct cpumask *cpus);
-#else	 /* CONFIG_STOP_MACHINE && CONFIG_SMP */
+#else	/* CONFIG_SMP || CONFIG_HOTPLUG_CPU */
 
 static inline int stop_machine(cpu_stop_fn_t fn, void *data,
 				 const struct cpumask *cpus)
@@ -137,5 +137,5 @@
 	return stop_machine(fn, data, cpus);
 }
 
-#endif	/* CONFIG_STOP_MACHINE && CONFIG_SMP */
+#endif	/* CONFIG_SMP || CONFIG_HOTPLUG_CPU */
 #endif	/* _LINUX_STOP_MACHINE */
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index 0bdc72f..4a29c75 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -21,7 +21,7 @@
  * Authors:
  *	Srikar Dronamraju
  *	Jim Keniston
- * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra
  */
 
 #include <linux/errno.h>
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index 9948c87..1d0043d 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -47,4 +47,7 @@
 /* device generates spurious wakeup, ignore remote wakeup capability */
 #define USB_QUIRK_IGNORE_REMOTE_WAKEUP		BIT(9)
 
+/* device can't handle Link Power Management */
+#define USB_QUIRK_NO_LPM			BIT(10)
+
 #endif /* __LINUX_USB_QUIRKS_H */
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 610a86a..ddb4409 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -44,9 +44,6 @@
 	void	(*request)(void *device_data, unsigned int count);
 };
 
-extern struct iommu_group *vfio_iommu_group_get(struct device *dev);
-extern void vfio_iommu_group_put(struct iommu_group *group, struct device *dev);
-
 extern int vfio_add_group_dev(struct device *dev,
 			      const struct vfio_device_ops *ops,
 			      void *device_data);
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 1e1bf9f..513b36f 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -145,7 +145,7 @@
 	list_del(&old->task_list);
 }
 
-typedef int wait_bit_action_f(struct wait_bit_key *);
+typedef int wait_bit_action_f(struct wait_bit_key *, int mode);
 void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
 void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key);
 void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
@@ -960,10 +960,10 @@
 	} while (0)
 
 
-extern int bit_wait(struct wait_bit_key *);
-extern int bit_wait_io(struct wait_bit_key *);
-extern int bit_wait_timeout(struct wait_bit_key *);
-extern int bit_wait_io_timeout(struct wait_bit_key *);
+extern int bit_wait(struct wait_bit_key *, int);
+extern int bit_wait_io(struct wait_bit_key *, int);
+extern int bit_wait_timeout(struct wait_bit_key *, int);
+extern int bit_wait_io_timeout(struct wait_bit_key *, int);
 
 /**
  * wait_on_bit - wait for a bit to be cleared
diff --git a/include/net/dst.h b/include/net/dst.h
index 1279f9b..c7329dc 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -322,6 +322,39 @@
 	}
 }
 
+/**
+ * dst_hold_safe - Take a reference on a dst if possible
+ * @dst: pointer to dst entry
+ *
+ * This helper returns false if it could not safely
+ * take a reference on a dst.
+ */
+static inline bool dst_hold_safe(struct dst_entry *dst)
+{
+	if (dst->flags & DST_NOCACHE)
+		return atomic_inc_not_zero(&dst->__refcnt);
+	dst_hold(dst);
+	return true;
+}
+
+/**
+ * skb_dst_force_safe - makes sure skb dst is refcounted
+ * @skb: buffer
+ *
+ * If dst is not yet refcounted and not destroyed, grab a ref on it.
+ */
+static inline void skb_dst_force_safe(struct sk_buff *skb)
+{
+	if (skb_dst_is_noref(skb)) {
+		struct dst_entry *dst = skb_dst(skb);
+
+		if (!dst_hold_safe(dst))
+			dst = NULL;
+
+		skb->_skb_refdst = (unsigned long)dst;
+	}
+}
+
 
 /**
  *	__skb_tunnel_rx - prepare skb for rx reinsert
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 2134e6d..625bdf9 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -210,18 +210,37 @@
 #define IP_CMSG_ORIGDSTADDR	BIT(6)
 #define IP_CMSG_CHECKSUM	BIT(7)
 
-/* SYNACK messages might be attached to request sockets.
+/**
+ * sk_to_full_sk - Access to a full socket
+ * @sk: pointer to a socket
+ *
+ * SYNACK messages might be attached to request sockets.
  * Some places want to reach the listener in this case.
  */
-static inline struct sock *skb_to_full_sk(const struct sk_buff *skb)
+static inline struct sock *sk_to_full_sk(struct sock *sk)
 {
-	struct sock *sk = skb->sk;
-
+#ifdef CONFIG_INET
 	if (sk && sk->sk_state == TCP_NEW_SYN_RECV)
 		sk = inet_reqsk(sk)->rsk_listener;
+#endif
 	return sk;
 }
 
+/* sk_to_full_sk() variant with a const argument */
+static inline const struct sock *sk_const_to_full_sk(const struct sock *sk)
+{
+#ifdef CONFIG_INET
+	if (sk && sk->sk_state == TCP_NEW_SYN_RECV)
+		sk = ((const struct request_sock *)sk)->rsk_listener;
+#endif
+	return sk;
+}
+
+static inline struct sock *skb_to_full_sk(const struct sk_buff *skb)
+{
+	return sk_to_full_sk(skb->sk);
+}
+
 static inline struct inet_sock *inet_sk(const struct sock *sk)
 {
 	return (struct inet_sock *)sk;
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 4a6009d..235c781 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -78,6 +78,7 @@
 static inline void inetpeer_set_addr_v4(struct inetpeer_addr *iaddr, __be32 ip)
 {
 	iaddr->a4.addr = ip;
+	iaddr->a4.vif = 0;
 	iaddr->family = AF_INET;
 }
 
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7bbb710..eea9bde 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1493,7 +1493,8 @@
 		 *             : SACK's are not delayed (see Section 6).
 		 */
 		__u8    sack_needed:1,     /* Do we need to sack the peer? */
-			sack_generation:1;
+			sack_generation:1,
+			zero_window_announced:1;
 		__u32	sack_cnt;
 
 		__u32   adaptation_ind;	 /* Adaptation Code point. */
diff --git a/include/net/sock.h b/include/net/sock.h
index 52d27ee..14d3c07 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -388,7 +388,7 @@
 		struct socket_wq	*sk_wq_raw;
 	};
 #ifdef CONFIG_XFRM
-	struct xfrm_policy	*sk_policy[2];
+	struct xfrm_policy __rcu *sk_policy[2];
 #endif
 	struct dst_entry	*sk_rx_dst;
 	struct dst_entry __rcu	*sk_dst_cache;
@@ -404,6 +404,7 @@
 				sk_userlocks : 4,
 				sk_protocol  : 8,
 				sk_type      : 16;
+#define SK_PROTOCOL_MAX U8_MAX
 	kmemcheck_bitfield_end(flags);
 	int			sk_wmem_queued;
 	gfp_t			sk_allocation;
@@ -740,6 +741,8 @@
 	SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */
 };
 
+#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
+
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
 {
 	nsk->sk_flags = osk->sk_flags;
@@ -814,7 +817,7 @@
 static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
 	/* dont let skb dst not refcounted, we are going to leave rcu lock */
-	skb_dst_force(skb);
+	skb_dst_force_safe(skb);
 
 	if (!sk->sk_backlog.tail)
 		sk->sk_backlog.head = skb;
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index c1c899c..e289ada 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -79,7 +79,7 @@
 };
 
 /* VXLAN header flags. */
-#define VXLAN_HF_RCO BIT(24)
+#define VXLAN_HF_RCO BIT(21)
 #define VXLAN_HF_VNI BIT(27)
 #define VXLAN_HF_GBP BIT(31)
 
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 4a9c21f..d6f6e50 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -548,6 +548,7 @@
 	u16			family;
 	struct xfrm_sec_ctx	*security;
 	struct xfrm_tmpl       	xfrm_vec[XFRM_MAX_DEPTH];
+	struct rcu_head		rcu;
 };
 
 static inline struct net *xp_net(const struct xfrm_policy *xp)
@@ -1141,12 +1142,14 @@
 	return xfrm_route_forward(skb, AF_INET6);
 }
 
-int __xfrm_sk_clone_policy(struct sock *sk);
+int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk);
 
-static inline int xfrm_sk_clone_policy(struct sock *sk)
+static inline int xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk)
 {
-	if (unlikely(sk->sk_policy[0] || sk->sk_policy[1]))
-		return __xfrm_sk_clone_policy(sk);
+	sk->sk_policy[0] = NULL;
+	sk->sk_policy[1] = NULL;
+	if (unlikely(osk->sk_policy[0] || osk->sk_policy[1]))
+		return __xfrm_sk_clone_policy(sk, osk);
 	return 0;
 }
 
@@ -1154,12 +1157,16 @@
 
 static inline void xfrm_sk_free_policy(struct sock *sk)
 {
-	if (unlikely(sk->sk_policy[0] != NULL)) {
-		xfrm_policy_delete(sk->sk_policy[0], XFRM_POLICY_MAX);
+	struct xfrm_policy *pol;
+
+	pol = rcu_dereference_protected(sk->sk_policy[0], 1);
+	if (unlikely(pol != NULL)) {
+		xfrm_policy_delete(pol, XFRM_POLICY_MAX);
 		sk->sk_policy[0] = NULL;
 	}
-	if (unlikely(sk->sk_policy[1] != NULL)) {
-		xfrm_policy_delete(sk->sk_policy[1], XFRM_POLICY_MAX+1);
+	pol = rcu_dereference_protected(sk->sk_policy[1], 1);
+	if (unlikely(pol != NULL)) {
+		xfrm_policy_delete(pol, XFRM_POLICY_MAX+1);
 		sk->sk_policy[1] = NULL;
 	}
 }
@@ -1169,7 +1176,7 @@
 #else
 
 static inline void xfrm_sk_free_policy(struct sock *sk) {}
-static inline int xfrm_sk_clone_policy(struct sock *sk) { return 0; }
+static inline int xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk) { return 0; }
 static inline int xfrm6_route_forward(struct sk_buff *skb) { return 1; }  
 static inline int xfrm4_route_forward(struct sk_buff *skb) { return 1; } 
 static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index 188df91..ec9b44d 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -237,6 +237,8 @@
 	u8			data[IB_MGMT_VENDOR_DATA];
 };
 
+#define IB_MGMT_CLASSPORTINFO_ATTR_ID	cpu_to_be16(0x0001)
+
 struct ib_class_port_info {
 	u8			base_version;
 	u8			class_version;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 9a68a19..120da1d 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1271,6 +1271,7 @@
 	int			id;		/* index into kernel idr */
 	struct kref		ref;
 	struct rw_semaphore	mutex;		/* protects .live */
+	struct rcu_head		rcu;		/* kfree_rcu() overhead */
 	int			live;
 };
 
diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h
index 2ae8812..94dc6a9 100644
--- a/include/sound/hda_register.h
+++ b/include/sound/hda_register.h
@@ -93,6 +93,9 @@
 #define AZX_REG_HSW_EM4			0x100c
 #define AZX_REG_HSW_EM5			0x1010
 
+/* Skylake/Broxton display HD-A controller Extended Mode registers */
+#define AZX_REG_SKL_EM4L		0x1040
+
 /* PCI space */
 #define AZX_PCIREG_TCSEL		0x44
 
diff --git a/include/uapi/drm/etnaviv_drm.h b/include/uapi/drm/etnaviv_drm.h
new file mode 100644
index 0000000..4cc989a
--- /dev/null
+++ b/include/uapi/drm/etnaviv_drm.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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 __ETNAVIV_DRM_H__
+#define __ETNAVIV_DRM_H__
+
+#include "drm.h"
+
+/* Please note that modifications to all structs defined here are
+ * subject to backwards-compatibility constraints:
+ *  1) Do not use pointers, use __u64 instead for 32 bit / 64 bit
+ *     user/kernel compatibility
+ *  2) Keep fields aligned to their size
+ *  3) Because of how drm_ioctl() works, we can add new fields at
+ *     the end of an ioctl if some care is taken: drm_ioctl() will
+ *     zero out the new fields at the tail of the ioctl, so a zero
+ *     value should have a backwards compatible meaning.  And for
+ *     output params, userspace won't see the newly added output
+ *     fields.. so that has to be somehow ok.
+ */
+
+/* timeouts are specified in clock-monotonic absolute times (to simplify
+ * restarting interrupted ioctls).  The following struct is logically the
+ * same as 'struct timespec' but 32/64b ABI safe.
+ */
+struct drm_etnaviv_timespec {
+	__s64 tv_sec;          /* seconds */
+	__s64 tv_nsec;         /* nanoseconds */
+};
+
+#define ETNAVIV_PARAM_GPU_MODEL                     0x01
+#define ETNAVIV_PARAM_GPU_REVISION                  0x02
+#define ETNAVIV_PARAM_GPU_FEATURES_0                0x03
+#define ETNAVIV_PARAM_GPU_FEATURES_1                0x04
+#define ETNAVIV_PARAM_GPU_FEATURES_2                0x05
+#define ETNAVIV_PARAM_GPU_FEATURES_3                0x06
+#define ETNAVIV_PARAM_GPU_FEATURES_4                0x07
+
+#define ETNAVIV_PARAM_GPU_STREAM_COUNT              0x10
+#define ETNAVIV_PARAM_GPU_REGISTER_MAX              0x11
+#define ETNAVIV_PARAM_GPU_THREAD_COUNT              0x12
+#define ETNAVIV_PARAM_GPU_VERTEX_CACHE_SIZE         0x13
+#define ETNAVIV_PARAM_GPU_SHADER_CORE_COUNT         0x14
+#define ETNAVIV_PARAM_GPU_PIXEL_PIPES               0x15
+#define ETNAVIV_PARAM_GPU_VERTEX_OUTPUT_BUFFER_SIZE 0x16
+#define ETNAVIV_PARAM_GPU_BUFFER_SIZE               0x17
+#define ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT         0x18
+#define ETNAVIV_PARAM_GPU_NUM_CONSTANTS             0x19
+
+#define ETNA_MAX_PIPES 4
+
+struct drm_etnaviv_param {
+	__u32 pipe;           /* in */
+	__u32 param;          /* in, ETNAVIV_PARAM_x */
+	__u64 value;          /* out (get_param) or in (set_param) */
+};
+
+/*
+ * GEM buffers:
+ */
+
+#define ETNA_BO_CACHE_MASK   0x000f0000
+/* cache modes */
+#define ETNA_BO_CACHED       0x00010000
+#define ETNA_BO_WC           0x00020000
+#define ETNA_BO_UNCACHED     0x00040000
+/* map flags */
+#define ETNA_BO_FORCE_MMU    0x00100000
+
+struct drm_etnaviv_gem_new {
+	__u64 size;           /* in */
+	__u32 flags;          /* in, mask of ETNA_BO_x */
+	__u32 handle;         /* out */
+};
+
+struct drm_etnaviv_gem_info {
+	__u32 handle;         /* in */
+	__u32 pad;
+	__u64 offset;         /* out, offset to pass to mmap() */
+};
+
+#define ETNA_PREP_READ        0x01
+#define ETNA_PREP_WRITE       0x02
+#define ETNA_PREP_NOSYNC      0x04
+
+struct drm_etnaviv_gem_cpu_prep {
+	__u32 handle;         /* in */
+	__u32 op;             /* in, mask of ETNA_PREP_x */
+	struct drm_etnaviv_timespec timeout;   /* in */
+};
+
+struct drm_etnaviv_gem_cpu_fini {
+	__u32 handle;         /* in */
+	__u32 flags;          /* in, placeholder for now, no defined values */
+};
+
+/*
+ * Cmdstream Submission:
+ */
+
+/* The value written into the cmdstream is logically:
+ * relocbuf->gpuaddr + reloc_offset
+ *
+ * NOTE that reloc's must be sorted by order of increasing submit_offset,
+ * otherwise EINVAL.
+ */
+struct drm_etnaviv_gem_submit_reloc {
+	__u32 submit_offset;  /* in, offset from submit_bo */
+	__u32 reloc_idx;      /* in, index of reloc_bo buffer */
+	__u64 reloc_offset;   /* in, offset from start of reloc_bo */
+	__u32 flags;          /* in, placeholder for now, no defined values */
+};
+
+/* Each buffer referenced elsewhere in the cmdstream submit (ie. the
+ * cmdstream buffer(s) themselves or reloc entries) has one (and only
+ * one) entry in the submit->bos[] table.
+ *
+ * As a optimization, the current buffer (gpu virtual address) can be
+ * passed back through the 'presumed' field.  If on a subsequent reloc,
+ * userspace passes back a 'presumed' address that is still valid,
+ * then patching the cmdstream for this entry is skipped.  This can
+ * avoid kernel needing to map/access the cmdstream bo in the common
+ * case.
+ */
+#define ETNA_SUBMIT_BO_READ             0x0001
+#define ETNA_SUBMIT_BO_WRITE            0x0002
+struct drm_etnaviv_gem_submit_bo {
+	__u32 flags;          /* in, mask of ETNA_SUBMIT_BO_x */
+	__u32 handle;         /* in, GEM handle */
+	__u64 presumed;       /* in/out, presumed buffer address */
+};
+
+/* Each cmdstream submit consists of a table of buffers involved, and
+ * one or more cmdstream buffers.  This allows for conditional execution
+ * (context-restore), and IB buffers needed for per tile/bin draw cmds.
+ */
+#define ETNA_PIPE_3D      0x00
+#define ETNA_PIPE_2D      0x01
+#define ETNA_PIPE_VG      0x02
+struct drm_etnaviv_gem_submit {
+	__u32 fence;          /* out */
+	__u32 pipe;           /* in */
+	__u32 exec_state;     /* in, initial execution state (ETNA_PIPE_x) */
+	__u32 nr_bos;         /* in, number of submit_bo's */
+	__u32 nr_relocs;      /* in, number of submit_reloc's */
+	__u32 stream_size;    /* in, cmdstream size */
+	__u64 bos;            /* in, ptr to array of submit_bo's */
+	__u64 relocs;         /* in, ptr to array of submit_reloc's */
+	__u64 stream;         /* in, ptr to cmdstream */
+};
+
+/* The normal way to synchronize with the GPU is just to CPU_PREP on
+ * a buffer if you need to access it from the CPU (other cmdstream
+ * submission from same or other contexts, PAGE_FLIP ioctl, etc, all
+ * handle the required synchronization under the hood).  This ioctl
+ * mainly just exists as a way to implement the gallium pipe_fence
+ * APIs without requiring a dummy bo to synchronize on.
+ */
+#define ETNA_WAIT_NONBLOCK      0x01
+struct drm_etnaviv_wait_fence {
+	__u32 pipe;           /* in */
+	__u32 fence;          /* in */
+	__u32 flags;          /* in, mask of ETNA_WAIT_x */
+	__u32 pad;
+	struct drm_etnaviv_timespec timeout;   /* in */
+};
+
+#define ETNA_USERPTR_READ	0x01
+#define ETNA_USERPTR_WRITE	0x02
+struct drm_etnaviv_gem_userptr {
+	__u64 user_ptr;	/* in, page aligned user pointer */
+	__u64 user_size;	/* in, page aligned user size */
+	__u32 flags;		/* in, flags */
+	__u32 handle;	/* out, non-zero handle */
+};
+
+struct drm_etnaviv_gem_wait {
+	__u32 pipe;				/* in */
+	__u32 handle;				/* in, bo to be waited for */
+	__u32 flags;				/* in, mask of ETNA_WAIT_x  */
+	__u32 pad;
+	struct drm_etnaviv_timespec timeout;	/* in */
+};
+
+#define DRM_ETNAVIV_GET_PARAM          0x00
+/* placeholder:
+#define DRM_ETNAVIV_SET_PARAM          0x01
+ */
+#define DRM_ETNAVIV_GEM_NEW            0x02
+#define DRM_ETNAVIV_GEM_INFO           0x03
+#define DRM_ETNAVIV_GEM_CPU_PREP       0x04
+#define DRM_ETNAVIV_GEM_CPU_FINI       0x05
+#define DRM_ETNAVIV_GEM_SUBMIT         0x06
+#define DRM_ETNAVIV_WAIT_FENCE         0x07
+#define DRM_ETNAVIV_GEM_USERPTR        0x08
+#define DRM_ETNAVIV_GEM_WAIT           0x09
+#define DRM_ETNAVIV_NUM_IOCTLS         0x0a
+
+#define DRM_IOCTL_ETNAVIV_GET_PARAM    DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GET_PARAM, struct drm_etnaviv_param)
+#define DRM_IOCTL_ETNAVIV_GEM_NEW      DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_NEW, struct drm_etnaviv_gem_new)
+#define DRM_IOCTL_ETNAVIV_GEM_INFO     DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_INFO, struct drm_etnaviv_gem_info)
+#define DRM_IOCTL_ETNAVIV_GEM_CPU_PREP DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_CPU_PREP, struct drm_etnaviv_gem_cpu_prep)
+#define DRM_IOCTL_ETNAVIV_GEM_CPU_FINI DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_CPU_FINI, struct drm_etnaviv_gem_cpu_fini)
+#define DRM_IOCTL_ETNAVIV_GEM_SUBMIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_SUBMIT, struct drm_etnaviv_gem_submit)
+#define DRM_IOCTL_ETNAVIV_WAIT_FENCE   DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence)
+#define DRM_IOCTL_ETNAVIV_GEM_USERPTR  DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_USERPTR, struct drm_etnaviv_gem_userptr)
+#define DRM_IOCTL_ETNAVIV_GEM_WAIT     DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_WAIT, struct drm_etnaviv_gem_wait)
+
+#endif /* __ETNAVIV_DRM_H__ */
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index c937a36..acf2102 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -356,6 +356,7 @@
 #define I915_PARAM_EU_TOTAL		 34
 #define I915_PARAM_HAS_GPU_RESET	 35
 #define I915_PARAM_HAS_RESOURCE_STREAMER 36
+#define I915_PARAM_HAS_EXEC_SOFTPIN	 37
 
 typedef struct drm_i915_getparam {
 	__s32 param;
@@ -682,8 +683,12 @@
 	__u64 alignment;
 
 	/**
-	 * Returned value of the updated offset of the object, for future
-	 * presumed_offset writes.
+	 * When the EXEC_OBJECT_PINNED flag is specified this is populated by
+	 * the user with the GTT offset at which this object will be pinned.
+	 * When the I915_EXEC_NO_RELOC flag is specified this must contain the
+	 * presumed_offset of the object.
+	 * During execbuffer2 the kernel populates it with the value of the
+	 * current GTT offset of the object, for future presumed_offset writes.
 	 */
 	__u64 offset;
 
@@ -691,7 +696,8 @@
 #define EXEC_OBJECT_NEEDS_GTT	(1<<1)
 #define EXEC_OBJECT_WRITE	(1<<2)
 #define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3)
-#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_SUPPORTS_48B_ADDRESS<<1)
+#define EXEC_OBJECT_PINNED	(1<<4)
+#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_PINNED<<1)
 	__u64 flags;
 
 	__u64 rsvd1;
diff --git a/include/uapi/drm/omap_drm.h b/include/uapi/drm/omap_drm.h
index 0750c01..38a3bd8 100644
--- a/include/uapi/drm/omap_drm.h
+++ b/include/uapi/drm/omap_drm.h
@@ -101,9 +101,6 @@
 
 #define DRM_OMAP_GET_PARAM		0x00
 #define DRM_OMAP_SET_PARAM		0x01
-/* placeholder for plugin-api
-#define DRM_OMAP_GET_BASE		0x02
-*/
 #define DRM_OMAP_GEM_NEW		0x03
 #define DRM_OMAP_GEM_CPU_PREP		0x04
 #define DRM_OMAP_GEM_CPU_FINI		0x05
@@ -112,9 +109,6 @@
 
 #define DRM_IOCTL_OMAP_GET_PARAM	DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GET_PARAM, struct drm_omap_param)
 #define DRM_IOCTL_OMAP_SET_PARAM	DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_SET_PARAM, struct drm_omap_param)
-/* placeholder for plugin-api
-#define DRM_IOCTL_OMAP_GET_BASE		DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GET_BASE, struct drm_omap_get_base)
-*/
 #define DRM_IOCTL_OMAP_GEM_NEW		DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GEM_NEW, struct drm_omap_gem_new)
 #define DRM_IOCTL_OMAP_GEM_CPU_PREP	DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_GEM_CPU_PREP, struct drm_omap_gem_cpu_prep)
 #define DRM_IOCTL_OMAP_GEM_CPU_FINI	DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_GEM_CPU_FINI, struct drm_omap_gem_cpu_fini)
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 628e6e6..c2e5d6c 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -186,6 +186,7 @@
 header-y += if_vlan.h
 header-y += if_x25.h
 header-y += igmp.h
+header-y += ila.h
 header-y += in6.h
 header-y += inet_diag.h
 header-y += in.h
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 28ccedd..a27222d 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -628,7 +628,7 @@
  * @OVS_CT_ATTR_MARK: u32 value followed by u32 mask. For each bit set in the
  * mask, the corresponding bit in the value is copied to the connection
  * tracking mark field in the connection.
- * @OVS_CT_ATTR_LABEL: %OVS_CT_LABELS_LEN value followed by %OVS_CT_LABELS_LEN
+ * @OVS_CT_ATTR_LABELS: %OVS_CT_LABELS_LEN value followed by %OVS_CT_LABELS_LEN
  * mask. For each bit set in the mask, the corresponding bit in the value is
  * copied to the connection tracking label field in the connection.
  * @OVS_CT_ATTR_HELPER: variable length string defining conntrack ALG.
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 751b69f..9fd7b5d 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -39,13 +39,6 @@
 #define VFIO_SPAPR_TCE_v2_IOMMU		7
 
 /*
- * The No-IOMMU IOMMU offers no translation or isolation for devices and
- * supports no ioctls outside of VFIO_CHECK_EXTENSION.  Use of VFIO's No-IOMMU
- * code will taint the host kernel and should be used with extreme caution.
- */
-#define VFIO_NOIOMMU_IOMMU		8
-
-/*
  * The IOCTL interface is designed for extensibility by embedding the
  * structure length (argsz) and flags into structures passed between
  * kernel and userspace.  We therefore use the _IO() macro for these
diff --git a/include/xen/interface/io/ring.h b/include/xen/interface/io/ring.h
index 7d28aff..7dc685b 100644
--- a/include/xen/interface/io/ring.h
+++ b/include/xen/interface/io/ring.h
@@ -181,6 +181,20 @@
 #define RING_GET_REQUEST(_r, _idx)					\
     (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
 
+/*
+ * Get a local copy of a request.
+ *
+ * Use this in preference to RING_GET_REQUEST() so all processing is
+ * done on a local copy that cannot be modified by the other end.
+ *
+ * Note that https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 may cause this
+ * to be ineffective where _req is a struct which consists of only bitfields.
+ */
+#define RING_COPY_REQUEST(_r, _idx, _req) do {				\
+	/* Use volatile to force the copy into _req. */			\
+	*(_req) = *(volatile typeof(_req))RING_GET_REQUEST(_r, _idx);	\
+} while (0)
+
 #define RING_GET_RESPONSE(_r, _idx)					\
     (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
 
diff --git a/init/Kconfig b/init/Kconfig
index c24b6f7..235c7a2 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2030,13 +2030,6 @@
 	  it was better to provide this option than to break all the archs
 	  and have several arch maintainers pursuing me down dark alleys.
 
-config STOP_MACHINE
-	bool
-	default y
-	depends on (SMP && MODULE_UNLOAD) || HOTPLUG_CPU
-	help
-	  Need stop_machine() primitive.
-
 source "block/Kconfig"
 
 config PREEMPT_NOTIFIERS
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index f1603c1..470f653 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -98,6 +98,12 @@
 static DEFINE_SPINLOCK(cgroup_idr_lock);
 
 /*
+ * Protects cgroup_file->kn for !self csses.  It synchronizes notifications
+ * against file removal/re-creation across css hiding.
+ */
+static DEFINE_SPINLOCK(cgroup_file_kn_lock);
+
+/*
  * Protects cgroup_subsys->release_agent_path.  Modifying it also requires
  * cgroup_mutex.  Reading requires either cgroup_mutex or this spinlock.
  */
@@ -754,9 +760,11 @@
 	if (!atomic_dec_and_test(&cset->refcount))
 		return;
 
-	/* This css_set is dead. unlink it and release cgroup refcounts */
-	for_each_subsys(ss, ssid)
+	/* This css_set is dead. unlink it and release cgroup and css refs */
+	for_each_subsys(ss, ssid) {
 		list_del(&cset->e_cset_node[ssid]);
+		css_put(cset->subsys[ssid]);
+	}
 	hash_del(&cset->hlist);
 	css_set_count--;
 
@@ -1056,9 +1064,13 @@
 	key = css_set_hash(cset->subsys);
 	hash_add(css_set_table, &cset->hlist, key);
 
-	for_each_subsys(ss, ssid)
+	for_each_subsys(ss, ssid) {
+		struct cgroup_subsys_state *css = cset->subsys[ssid];
+
 		list_add_tail(&cset->e_cset_node[ssid],
-			      &cset->subsys[ssid]->cgroup->e_csets[ssid]);
+			      &css->cgroup->e_csets[ssid]);
+		css_get(css);
+	}
 
 	spin_unlock_bh(&css_set_lock);
 
@@ -1393,6 +1405,16 @@
 	char name[CGROUP_FILE_NAME_MAX];
 
 	lockdep_assert_held(&cgroup_mutex);
+
+	if (cft->file_offset) {
+		struct cgroup_subsys_state *css = cgroup_css(cgrp, cft->ss);
+		struct cgroup_file *cfile = (void *)css + cft->file_offset;
+
+		spin_lock_irq(&cgroup_file_kn_lock);
+		cfile->kn = NULL;
+		spin_unlock_irq(&cgroup_file_kn_lock);
+	}
+
 	kernfs_remove_by_name(cgrp->kn, cgroup_file_name(cgrp, cft, name));
 }
 
@@ -1856,7 +1878,6 @@
 
 	INIT_LIST_HEAD(&cgrp->self.sibling);
 	INIT_LIST_HEAD(&cgrp->self.children);
-	INIT_LIST_HEAD(&cgrp->self.files);
 	INIT_LIST_HEAD(&cgrp->cset_links);
 	INIT_LIST_HEAD(&cgrp->pidlists);
 	mutex_init(&cgrp->pidlist_mutex);
@@ -2216,6 +2237,9 @@
 	struct list_head	src_csets;
 	struct list_head	dst_csets;
 
+	/* the subsys currently being processed */
+	int			ssid;
+
 	/*
 	 * Fields for cgroup_taskset_*() iteration.
 	 *
@@ -2278,25 +2302,29 @@
 /**
  * cgroup_taskset_first - reset taskset and return the first task
  * @tset: taskset of interest
+ * @dst_cssp: output variable for the destination css
  *
  * @tset iteration is initialized and the first task is returned.
  */
-struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset)
+struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset,
+					 struct cgroup_subsys_state **dst_cssp)
 {
 	tset->cur_cset = list_first_entry(tset->csets, struct css_set, mg_node);
 	tset->cur_task = NULL;
 
-	return cgroup_taskset_next(tset);
+	return cgroup_taskset_next(tset, dst_cssp);
 }
 
 /**
  * cgroup_taskset_next - iterate to the next task in taskset
  * @tset: taskset of interest
+ * @dst_cssp: output variable for the destination css
  *
  * Return the next task in @tset.  Iteration must have been initialized
  * with cgroup_taskset_first().
  */
-struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset)
+struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset,
+					struct cgroup_subsys_state **dst_cssp)
 {
 	struct css_set *cset = tset->cur_cset;
 	struct task_struct *task = tset->cur_task;
@@ -2311,6 +2339,18 @@
 		if (&task->cg_list != &cset->mg_tasks) {
 			tset->cur_cset = cset;
 			tset->cur_task = task;
+
+			/*
+			 * This function may be called both before and
+			 * after cgroup_taskset_migrate().  The two cases
+			 * can be distinguished by looking at whether @cset
+			 * has its ->mg_dst_cset set.
+			 */
+			if (cset->mg_dst_cset)
+				*dst_cssp = cset->mg_dst_cset->subsys[tset->ssid];
+			else
+				*dst_cssp = cset->subsys[tset->ssid];
+
 			return task;
 		}
 
@@ -2346,7 +2386,8 @@
 	/* check that we can legitimately attach to the cgroup */
 	for_each_e_css(css, i, dst_cgrp) {
 		if (css->ss->can_attach) {
-			ret = css->ss->can_attach(css, tset);
+			tset->ssid = i;
+			ret = css->ss->can_attach(tset);
 			if (ret) {
 				failed_css = css;
 				goto out_cancel_attach;
@@ -2379,9 +2420,12 @@
 	 */
 	tset->csets = &tset->dst_csets;
 
-	for_each_e_css(css, i, dst_cgrp)
-		if (css->ss->attach)
-			css->ss->attach(css, tset);
+	for_each_e_css(css, i, dst_cgrp) {
+		if (css->ss->attach) {
+			tset->ssid = i;
+			css->ss->attach(tset);
+		}
+	}
 
 	ret = 0;
 	goto out_release_tset;
@@ -2390,8 +2434,10 @@
 	for_each_e_css(css, i, dst_cgrp) {
 		if (css == failed_css)
 			break;
-		if (css->ss->cancel_attach)
-			css->ss->cancel_attach(css, tset);
+		if (css->ss->cancel_attach) {
+			tset->ssid = i;
+			css->ss->cancel_attach(tset);
+		}
 	}
 out_release_tset:
 	spin_lock_bh(&css_set_lock);
@@ -3313,9 +3359,9 @@
 	if (cft->file_offset) {
 		struct cgroup_file *cfile = (void *)css + cft->file_offset;
 
-		kernfs_get(kn);
+		spin_lock_irq(&cgroup_file_kn_lock);
 		cfile->kn = kn;
-		list_add(&cfile->node, &css->files);
+		spin_unlock_irq(&cgroup_file_kn_lock);
 	}
 
 	return 0;
@@ -3553,6 +3599,22 @@
 }
 
 /**
+ * cgroup_file_notify - generate a file modified event for a cgroup_file
+ * @cfile: target cgroup_file
+ *
+ * @cfile must have been obtained by setting cftype->file_offset.
+ */
+void cgroup_file_notify(struct cgroup_file *cfile)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cgroup_file_kn_lock, flags);
+	if (cfile->kn)
+		kernfs_notify(cfile->kn);
+	spin_unlock_irqrestore(&cgroup_file_kn_lock, flags);
+}
+
+/**
  * cgroup_task_count - count the number of tasks in a cgroup.
  * @cgrp: the cgroup in question
  *
@@ -4613,13 +4675,9 @@
 		container_of(work, struct cgroup_subsys_state, destroy_work);
 	struct cgroup_subsys *ss = css->ss;
 	struct cgroup *cgrp = css->cgroup;
-	struct cgroup_file *cfile;
 
 	percpu_ref_exit(&css->refcnt);
 
-	list_for_each_entry(cfile, &css->files, node)
-		kernfs_put(cfile->kn);
-
 	if (ss) {
 		/* css free path */
 		int id = css->id;
@@ -4724,7 +4782,6 @@
 	css->ss = ss;
 	INIT_LIST_HEAD(&css->sibling);
 	INIT_LIST_HEAD(&css->children);
-	INIT_LIST_HEAD(&css->files);
 	css->serial_nr = css_serial_nr_next++;
 
 	if (cgroup_parent(cgrp)) {
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index f1b30ad..2d3df82 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -155,12 +155,10 @@
  * @freezer->lock.  freezer_attach() makes the new tasks conform to the
  * current state and all following state changes can see the new tasks.
  */
-static void freezer_attach(struct cgroup_subsys_state *new_css,
-			   struct cgroup_taskset *tset)
+static void freezer_attach(struct cgroup_taskset *tset)
 {
-	struct freezer *freezer = css_freezer(new_css);
 	struct task_struct *task;
-	bool clear_frozen = false;
+	struct cgroup_subsys_state *new_css;
 
 	mutex_lock(&freezer_mutex);
 
@@ -174,22 +172,21 @@
 	 * current state before executing the following - !frozen tasks may
 	 * be visible in a FROZEN cgroup and frozen tasks in a THAWED one.
 	 */
-	cgroup_taskset_for_each(task, tset) {
+	cgroup_taskset_for_each(task, new_css, tset) {
+		struct freezer *freezer = css_freezer(new_css);
+
 		if (!(freezer->state & CGROUP_FREEZING)) {
 			__thaw_task(task);
 		} else {
 			freeze_task(task);
-			freezer->state &= ~CGROUP_FROZEN;
-			clear_frozen = true;
+			/* clear FROZEN and propagate upwards */
+			while (freezer && (freezer->state & CGROUP_FROZEN)) {
+				freezer->state &= ~CGROUP_FROZEN;
+				freezer = parent_freezer(freezer);
+			}
 		}
 	}
 
-	/* propagate FROZEN clearing upwards */
-	while (clear_frozen && (freezer = parent_freezer(freezer))) {
-		freezer->state &= ~CGROUP_FROZEN;
-		clear_frozen = freezer->state & CGROUP_FREEZING;
-	}
-
 	mutex_unlock(&freezer_mutex);
 }
 
diff --git a/kernel/cgroup_pids.c b/kernel/cgroup_pids.c
index cdd8df4..b50d5a1 100644
--- a/kernel/cgroup_pids.c
+++ b/kernel/cgroup_pids.c
@@ -106,7 +106,7 @@
 {
 	struct pids_cgroup *p;
 
-	for (p = pids; p; p = parent_pids(p))
+	for (p = pids; parent_pids(p); p = parent_pids(p))
 		pids_cancel(p, num);
 }
 
@@ -123,7 +123,7 @@
 {
 	struct pids_cgroup *p;
 
-	for (p = pids; p; p = parent_pids(p))
+	for (p = pids; parent_pids(p); p = parent_pids(p))
 		atomic64_add(num, &p->counter);
 }
 
@@ -140,7 +140,7 @@
 {
 	struct pids_cgroup *p, *q;
 
-	for (p = pids; p; p = parent_pids(p)) {
+	for (p = pids; parent_pids(p); p = parent_pids(p)) {
 		int64_t new = atomic64_add_return(num, &p->counter);
 
 		/*
@@ -162,13 +162,13 @@
 	return -EAGAIN;
 }
 
-static int pids_can_attach(struct cgroup_subsys_state *css,
-			   struct cgroup_taskset *tset)
+static int pids_can_attach(struct cgroup_taskset *tset)
 {
-	struct pids_cgroup *pids = css_pids(css);
 	struct task_struct *task;
+	struct cgroup_subsys_state *dst_css;
 
-	cgroup_taskset_for_each(task, tset) {
+	cgroup_taskset_for_each(task, dst_css, tset) {
+		struct pids_cgroup *pids = css_pids(dst_css);
 		struct cgroup_subsys_state *old_css;
 		struct pids_cgroup *old_pids;
 
@@ -187,13 +187,13 @@
 	return 0;
 }
 
-static void pids_cancel_attach(struct cgroup_subsys_state *css,
-			       struct cgroup_taskset *tset)
+static void pids_cancel_attach(struct cgroup_taskset *tset)
 {
-	struct pids_cgroup *pids = css_pids(css);
 	struct task_struct *task;
+	struct cgroup_subsys_state *dst_css;
 
-	cgroup_taskset_for_each(task, tset) {
+	cgroup_taskset_for_each(task, dst_css, tset) {
+		struct pids_cgroup *pids = css_pids(dst_css);
 		struct cgroup_subsys_state *old_css;
 		struct pids_cgroup *old_pids;
 
@@ -205,65 +205,28 @@
 	}
 }
 
+/*
+ * task_css_check(true) in pids_can_fork() and pids_cancel_fork() relies
+ * on threadgroup_change_begin() held by the copy_process().
+ */
 static int pids_can_fork(struct task_struct *task, void **priv_p)
 {
 	struct cgroup_subsys_state *css;
 	struct pids_cgroup *pids;
-	int err;
 
-	/*
-	 * Use the "current" task_css for the pids subsystem as the tentative
-	 * css. It is possible we will charge the wrong hierarchy, in which
-	 * case we will forcefully revert/reapply the charge on the right
-	 * hierarchy after it is committed to the task proper.
-	 */
-	css = task_get_css(current, pids_cgrp_id);
+	css = task_css_check(current, pids_cgrp_id, true);
 	pids = css_pids(css);
-
-	err = pids_try_charge(pids, 1);
-	if (err)
-		goto err_css_put;
-
-	*priv_p = css;
-	return 0;
-
-err_css_put:
-	css_put(css);
-	return err;
+	return pids_try_charge(pids, 1);
 }
 
 static void pids_cancel_fork(struct task_struct *task, void *priv)
 {
-	struct cgroup_subsys_state *css = priv;
-	struct pids_cgroup *pids = css_pids(css);
-
-	pids_uncharge(pids, 1);
-	css_put(css);
-}
-
-static void pids_fork(struct task_struct *task, void *priv)
-{
 	struct cgroup_subsys_state *css;
-	struct cgroup_subsys_state *old_css = priv;
 	struct pids_cgroup *pids;
-	struct pids_cgroup *old_pids = css_pids(old_css);
 
-	css = task_get_css(task, pids_cgrp_id);
+	css = task_css_check(current, pids_cgrp_id, true);
 	pids = css_pids(css);
-
-	/*
-	 * If the association has changed, we have to revert and reapply the
-	 * charge/uncharge on the wrong hierarchy to the current one. Since
-	 * the association can only change due to an organisation event, its
-	 * okay for us to ignore the limit in this case.
-	 */
-	if (pids != old_pids) {
-		pids_uncharge(old_pids, 1);
-		pids_charge(pids, 1);
-	}
-
-	css_put(css);
-	css_put(old_css);
+	pids_uncharge(pids, 1);
 }
 
 static void pids_free(struct task_struct *task)
@@ -335,6 +298,7 @@
 	{
 		.name = "current",
 		.read_s64 = pids_current_read,
+		.flags = CFTYPE_NOT_ON_ROOT,
 	},
 	{ }	/* terminate */
 };
@@ -346,7 +310,6 @@
 	.cancel_attach 	= pids_cancel_attach,
 	.can_fork	= pids_can_fork,
 	.cancel_fork	= pids_cancel_fork,
-	.fork		= pids_fork,
 	.free		= pids_free,
 	.legacy_cftypes	= pids_files,
 	.dfl_cftypes	= pids_files,
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 10ae736..02a8ea5 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1429,15 +1429,16 @@
 static struct cpuset *cpuset_attach_old_cs;
 
 /* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
-static int cpuset_can_attach(struct cgroup_subsys_state *css,
-			     struct cgroup_taskset *tset)
+static int cpuset_can_attach(struct cgroup_taskset *tset)
 {
-	struct cpuset *cs = css_cs(css);
+	struct cgroup_subsys_state *css;
+	struct cpuset *cs;
 	struct task_struct *task;
 	int ret;
 
 	/* used later by cpuset_attach() */
-	cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset));
+	cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
+	cs = css_cs(css);
 
 	mutex_lock(&cpuset_mutex);
 
@@ -1447,7 +1448,7 @@
 	    (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)))
 		goto out_unlock;
 
-	cgroup_taskset_for_each(task, tset) {
+	cgroup_taskset_for_each(task, css, tset) {
 		ret = task_can_attach(task, cs->cpus_allowed);
 		if (ret)
 			goto out_unlock;
@@ -1467,9 +1468,14 @@
 	return ret;
 }
 
-static void cpuset_cancel_attach(struct cgroup_subsys_state *css,
-				 struct cgroup_taskset *tset)
+static void cpuset_cancel_attach(struct cgroup_taskset *tset)
 {
+	struct cgroup_subsys_state *css;
+	struct cpuset *cs;
+
+	cgroup_taskset_first(tset, &css);
+	cs = css_cs(css);
+
 	mutex_lock(&cpuset_mutex);
 	css_cs(css)->attach_in_progress--;
 	mutex_unlock(&cpuset_mutex);
@@ -1482,16 +1488,19 @@
  */
 static cpumask_var_t cpus_attach;
 
-static void cpuset_attach(struct cgroup_subsys_state *css,
-			  struct cgroup_taskset *tset)
+static void cpuset_attach(struct cgroup_taskset *tset)
 {
 	/* static buf protected by cpuset_mutex */
 	static nodemask_t cpuset_attach_nodemask_to;
 	struct task_struct *task;
 	struct task_struct *leader;
-	struct cpuset *cs = css_cs(css);
+	struct cgroup_subsys_state *css;
+	struct cpuset *cs;
 	struct cpuset *oldcs = cpuset_attach_old_cs;
 
+	cgroup_taskset_first(tset, &css);
+	cs = css_cs(css);
+
 	mutex_lock(&cpuset_mutex);
 
 	/* prepare for attach */
@@ -1502,7 +1511,7 @@
 
 	guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
 
-	cgroup_taskset_for_each(task, tset) {
+	cgroup_taskset_for_each(task, css, tset) {
 		/*
 		 * can_attach beforehand should guarantee that this doesn't
 		 * fail.  TODO: have a better way to handle failure here
@@ -1518,7 +1527,7 @@
 	 * sleep and should be moved outside migration path proper.
 	 */
 	cpuset_attach_nodemask_to = cs->effective_mems;
-	cgroup_taskset_for_each_leader(leader, tset) {
+	cgroup_taskset_for_each_leader(leader, css, tset) {
 		struct mm_struct *mm = get_task_mm(leader);
 
 		if (mm) {
diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c
index d659487..9c41800 100644
--- a/kernel/events/callchain.c
+++ b/kernel/events/callchain.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
  *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
- *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra
  *  Copyright  ©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  *
  * For licensing details see kernel-base/COPYING
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 36babfd..ef2d6ea 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
  *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
- *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra
  *  Copyright  ©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  *
  * For licensing details see kernel-base/COPYING
@@ -435,7 +435,7 @@
 	if (!is_cgroup_event(event))
 		return;
 
-	cgrp = perf_cgroup_from_task(current);
+	cgrp = perf_cgroup_from_task(current, event->ctx);
 	/*
 	 * Do not update time when cgroup is not active
 	 */
@@ -458,7 +458,7 @@
 	if (!task || !ctx->nr_cgroups)
 		return;
 
-	cgrp = perf_cgroup_from_task(task);
+	cgrp = perf_cgroup_from_task(task, ctx);
 	info = this_cpu_ptr(cgrp->info);
 	info->timestamp = ctx->timestamp;
 }
@@ -489,7 +489,6 @@
 	 * we reschedule only in the presence of cgroup
 	 * constrained events.
 	 */
-	rcu_read_lock();
 
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
 		cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
@@ -522,8 +521,10 @@
 				 * set cgrp before ctxsw in to allow
 				 * event_filter_match() to not have to pass
 				 * task around
+				 * we pass the cpuctx->ctx to perf_cgroup_from_task()
+				 * because cgorup events are only per-cpu
 				 */
-				cpuctx->cgrp = perf_cgroup_from_task(task);
+				cpuctx->cgrp = perf_cgroup_from_task(task, &cpuctx->ctx);
 				cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
 			}
 			perf_pmu_enable(cpuctx->ctx.pmu);
@@ -531,8 +532,6 @@
 		}
 	}
 
-	rcu_read_unlock();
-
 	local_irq_restore(flags);
 }
 
@@ -542,17 +541,20 @@
 	struct perf_cgroup *cgrp1;
 	struct perf_cgroup *cgrp2 = NULL;
 
+	rcu_read_lock();
 	/*
 	 * we come here when we know perf_cgroup_events > 0
+	 * we do not need to pass the ctx here because we know
+	 * we are holding the rcu lock
 	 */
-	cgrp1 = perf_cgroup_from_task(task);
+	cgrp1 = perf_cgroup_from_task(task, NULL);
 
 	/*
 	 * next is NULL when called from perf_event_enable_on_exec()
 	 * that will systematically cause a cgroup_switch()
 	 */
 	if (next)
-		cgrp2 = perf_cgroup_from_task(next);
+		cgrp2 = perf_cgroup_from_task(next, NULL);
 
 	/*
 	 * only schedule out current cgroup events if we know
@@ -561,6 +563,8 @@
 	 */
 	if (cgrp1 != cgrp2)
 		perf_cgroup_switch(task, PERF_CGROUP_SWOUT);
+
+	rcu_read_unlock();
 }
 
 static inline void perf_cgroup_sched_in(struct task_struct *prev,
@@ -569,13 +573,16 @@
 	struct perf_cgroup *cgrp1;
 	struct perf_cgroup *cgrp2 = NULL;
 
+	rcu_read_lock();
 	/*
 	 * we come here when we know perf_cgroup_events > 0
+	 * we do not need to pass the ctx here because we know
+	 * we are holding the rcu lock
 	 */
-	cgrp1 = perf_cgroup_from_task(task);
+	cgrp1 = perf_cgroup_from_task(task, NULL);
 
 	/* prev can never be NULL */
-	cgrp2 = perf_cgroup_from_task(prev);
+	cgrp2 = perf_cgroup_from_task(prev, NULL);
 
 	/*
 	 * only need to schedule in cgroup events if we are changing
@@ -584,6 +591,8 @@
 	 */
 	if (cgrp1 != cgrp2)
 		perf_cgroup_switch(task, PERF_CGROUP_SWIN);
+
+	rcu_read_unlock();
 }
 
 static inline int perf_cgroup_connect(int fd, struct perf_event *event,
@@ -4216,7 +4225,14 @@
 		goto retry;
 	}
 
-	__perf_event_period(&pe);
+	if (event->attr.freq) {
+		event->attr.sample_freq = value;
+	} else {
+		event->attr.sample_period = value;
+		event->hw.sample_period = value;
+	}
+
+	local64_set(&event->hw.period_left, 0);
 	raw_spin_unlock_irq(&ctx->lock);
 
 	return 0;
@@ -5667,6 +5683,17 @@
 }
 
 static void
+perf_event_aux_task_ctx(perf_event_aux_output_cb output, void *data,
+			struct perf_event_context *task_ctx)
+{
+	rcu_read_lock();
+	preempt_disable();
+	perf_event_aux_ctx(task_ctx, output, data);
+	preempt_enable();
+	rcu_read_unlock();
+}
+
+static void
 perf_event_aux(perf_event_aux_output_cb output, void *data,
 	       struct perf_event_context *task_ctx)
 {
@@ -5675,14 +5702,23 @@
 	struct pmu *pmu;
 	int ctxn;
 
+	/*
+	 * If we have task_ctx != NULL we only notify
+	 * the task context itself. The task_ctx is set
+	 * only for EXIT events before releasing task
+	 * context.
+	 */
+	if (task_ctx) {
+		perf_event_aux_task_ctx(output, data, task_ctx);
+		return;
+	}
+
 	rcu_read_lock();
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
 		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
 		if (cpuctx->unique_pmu != pmu)
 			goto next;
 		perf_event_aux_ctx(&cpuctx->ctx, output, data);
-		if (task_ctx)
-			goto next;
 		ctxn = pmu->task_ctx_nr;
 		if (ctxn < 0)
 			goto next;
@@ -5692,12 +5728,6 @@
 next:
 		put_cpu_ptr(pmu->pmu_cpu_context);
 	}
-
-	if (task_ctx) {
-		preempt_disable();
-		perf_event_aux_ctx(task_ctx, output, data);
-		preempt_enable();
-	}
 	rcu_read_unlock();
 }
 
@@ -8787,10 +8817,8 @@
 	struct perf_event_context *child_ctx, *clone_ctx = NULL;
 	unsigned long flags;
 
-	if (likely(!child->perf_event_ctxp[ctxn])) {
-		perf_event_task(child, NULL, 0);
+	if (likely(!child->perf_event_ctxp[ctxn]))
 		return;
-	}
 
 	local_irq_save(flags);
 	/*
@@ -8874,6 +8902,14 @@
 
 	for_each_task_context_nr(ctxn)
 		perf_event_exit_task_context(child, ctxn);
+
+	/*
+	 * The perf_event_exit_task_context calls perf_event_task
+	 * with child's task_ctx, which generates EXIT events for
+	 * child contexts and sets child->perf_event_ctxp[] to NULL.
+	 * At this point we need to send EXIT events to cpu contexts.
+	 */
+	perf_event_task(child, NULL, 0);
 }
 
 static void perf_free_event(struct perf_event *event,
@@ -9452,16 +9488,18 @@
 static int __perf_cgroup_move(void *info)
 {
 	struct task_struct *task = info;
+	rcu_read_lock();
 	perf_cgroup_switch(task, PERF_CGROUP_SWOUT | PERF_CGROUP_SWIN);
+	rcu_read_unlock();
 	return 0;
 }
 
-static void perf_cgroup_attach(struct cgroup_subsys_state *css,
-			       struct cgroup_taskset *tset)
+static void perf_cgroup_attach(struct cgroup_taskset *tset)
 {
 	struct task_struct *task;
+	struct cgroup_subsys_state *css;
 
-	cgroup_taskset_for_each(task, tset)
+	cgroup_taskset_for_each(task, css, tset)
 		task_function_call(task, __perf_cgroup_move, task);
 }
 
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index b5d1ea7..adfdc05 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
  *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
- *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra
  *  Copyright  ©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  *
  * For licensing details see kernel-base/COPYING
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 4e5e979..7dad849 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -19,7 +19,7 @@
  * Authors:
  *	Srikar Dronamraju
  *	Jim Keniston
- * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra
  */
 
 #include <linux/kernel.h>
diff --git a/kernel/fork.c b/kernel/fork.c
index f97f2c4..fce002e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1368,8 +1368,7 @@
 	p->real_start_time = ktime_get_boot_ns();
 	p->io_context = NULL;
 	p->audit_context = NULL;
-	if (clone_flags & CLONE_THREAD)
-		threadgroup_change_begin(current);
+	threadgroup_change_begin(current);
 	cgroup_fork(p);
 #ifdef CONFIG_NUMA
 	p->mempolicy = mpol_dup(p->mempolicy);
@@ -1610,8 +1609,7 @@
 
 	proc_fork_connector(p);
 	cgroup_post_fork(p, cgrp_ss_priv);
-	if (clone_flags & CLONE_THREAD)
-		threadgroup_change_end(current);
+	threadgroup_change_end(current);
 	perf_event_fork(p);
 
 	trace_task_newtask(p, clone_flags);
@@ -1652,8 +1650,7 @@
 	mpol_put(p->mempolicy);
 bad_fork_cleanup_threadgroup_lock:
 #endif
-	if (clone_flags & CLONE_THREAD)
-		threadgroup_change_end(current);
+	threadgroup_change_end(current);
 	delayacct_tsk_free(p);
 bad_fork_cleanup_count:
 	atomic_dec(&p->cred->user->processes);
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index cbf9fb8..bcf107c 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra
  *
  * Provides a framework for enqueueing and running callbacks from hardirq
  * context. The enqueueing is NMI-safe.
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index f7dd15d..05254ee 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -2,7 +2,7 @@
  * jump label support
  *
  * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
- * Copyright (C) 2011 Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2011 Peter Zijlstra
  *
  */
 #include <linux/memory.h>
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index deae390..60ace56 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -6,7 +6,7 @@
  * Started by Ingo Molnar:
  *
  *  Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * this code maps all the lock dependencies as they occur in a live kernel
  * and will warn about the following classes of locking bugs:
diff --git a/kernel/locking/lockdep_proc.c b/kernel/locking/lockdep_proc.c
index d83d798..dbb61a3 100644
--- a/kernel/locking/lockdep_proc.c
+++ b/kernel/locking/lockdep_proc.c
@@ -6,7 +6,7 @@
  * Started by Ingo Molnar:
  *
  *  Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * Code for /proc/lockdep and /proc/lockdep_stats:
  *
diff --git a/kernel/locking/osq_lock.c b/kernel/locking/osq_lock.c
index d092a0c..05a3785 100644
--- a/kernel/locking/osq_lock.c
+++ b/kernel/locking/osq_lock.c
@@ -93,10 +93,12 @@
 	node->cpu = curr;
 
 	/*
-	 * ACQUIRE semantics, pairs with corresponding RELEASE
-	 * in unlock() uncontended, or fastpath.
+	 * We need both ACQUIRE (pairs with corresponding RELEASE in
+	 * unlock() uncontended, or fastpath) and RELEASE (to publish
+	 * the node fields we just initialised) semantics when updating
+	 * the lock tail.
 	 */
-	old = atomic_xchg_acquire(&lock->tail, curr);
+	old = atomic_xchg(&lock->tail, curr);
 	if (old == OSQ_UNLOCKED_VAL)
 		return true;
 
diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c
index c0a2051..caf4041 100644
--- a/kernel/sched/clock.c
+++ b/kernel/sched/clock.c
@@ -1,7 +1,7 @@
 /*
  * sched_clock for unstable cpu clocks
  *
- *  Copyright (C) 2008 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008 Red Hat, Inc., Peter Zijlstra
  *
  *  Updates and enhancements:
  *    Copyright (C) 2008 Red Hat, Inc. Steven Rostedt <srostedt@redhat.com>
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 7063c6a..732e993 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8241,12 +8241,12 @@
 	sched_move_task(task);
 }
 
-static int cpu_cgroup_can_attach(struct cgroup_subsys_state *css,
-				 struct cgroup_taskset *tset)
+static int cpu_cgroup_can_attach(struct cgroup_taskset *tset)
 {
 	struct task_struct *task;
+	struct cgroup_subsys_state *css;
 
-	cgroup_taskset_for_each(task, tset) {
+	cgroup_taskset_for_each(task, css, tset) {
 #ifdef CONFIG_RT_GROUP_SCHED
 		if (!sched_rt_can_attach(css_tg(css), task))
 			return -EINVAL;
@@ -8259,12 +8259,12 @@
 	return 0;
 }
 
-static void cpu_cgroup_attach(struct cgroup_subsys_state *css,
-			      struct cgroup_taskset *tset)
+static void cpu_cgroup_attach(struct cgroup_taskset *tset)
 {
 	struct task_struct *task;
+	struct cgroup_subsys_state *css;
 
-	cgroup_taskset_for_each(task, tset)
+	cgroup_taskset_for_each(task, css, tset)
 		sched_move_task(task);
 }
 
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index f04fda8..90e26b1 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -17,7 +17,7 @@
  *  Copyright (C) 2007, Thomas Gleixner <tglx@linutronix.de>
  *
  *  Adaptive scheduling granularity, math enhancements by Peter Zijlstra
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  */
 
 #include <linux/latencytop.h>
diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c
index f10bd87..f15d6b6 100644
--- a/kernel/sched/wait.c
+++ b/kernel/sched/wait.c
@@ -392,7 +392,7 @@
 	do {
 		prepare_to_wait(wq, &q->wait, mode);
 		if (test_bit(q->key.bit_nr, q->key.flags))
-			ret = (*action)(&q->key);
+			ret = (*action)(&q->key, mode);
 	} while (test_bit(q->key.bit_nr, q->key.flags) && !ret);
 	finish_wait(wq, &q->wait);
 	return ret;
@@ -431,7 +431,7 @@
 		prepare_to_wait_exclusive(wq, &q->wait, mode);
 		if (!test_bit(q->key.bit_nr, q->key.flags))
 			continue;
-		ret = action(&q->key);
+		ret = action(&q->key, mode);
 		if (!ret)
 			continue;
 		abort_exclusive_wait(wq, &q->wait, mode, &q->key);
@@ -581,43 +581,43 @@
 }
 EXPORT_SYMBOL(wake_up_atomic_t);
 
-__sched int bit_wait(struct wait_bit_key *word)
+__sched int bit_wait(struct wait_bit_key *word, int mode)
 {
 	schedule();
-	if (signal_pending(current))
+	if (signal_pending_state(mode, current))
 		return -EINTR;
 	return 0;
 }
 EXPORT_SYMBOL(bit_wait);
 
-__sched int bit_wait_io(struct wait_bit_key *word)
+__sched int bit_wait_io(struct wait_bit_key *word, int mode)
 {
 	io_schedule();
-	if (signal_pending(current))
+	if (signal_pending_state(mode, current))
 		return -EINTR;
 	return 0;
 }
 EXPORT_SYMBOL(bit_wait_io);
 
-__sched int bit_wait_timeout(struct wait_bit_key *word)
+__sched int bit_wait_timeout(struct wait_bit_key *word, int mode)
 {
 	unsigned long now = READ_ONCE(jiffies);
 	if (time_after_eq(now, word->timeout))
 		return -EAGAIN;
 	schedule_timeout(word->timeout - now);
-	if (signal_pending(current))
+	if (signal_pending_state(mode, current))
 		return -EINTR;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(bit_wait_timeout);
 
-__sched int bit_wait_io_timeout(struct wait_bit_key *word)
+__sched int bit_wait_io_timeout(struct wait_bit_key *word, int mode)
 {
 	unsigned long now = READ_ONCE(jiffies);
 	if (time_after_eq(now, word->timeout))
 		return -EAGAIN;
 	io_schedule_timeout(word->timeout - now);
-	if (signal_pending(current))
+	if (signal_pending_state(mode, current))
 		return -EINTR;
 	return 0;
 }
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 867bc20..a3bbaee 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -531,7 +531,7 @@
 }
 early_initcall(cpu_stop_init);
 
-#ifdef CONFIG_STOP_MACHINE
+#if defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU)
 
 static int __stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus)
 {
@@ -631,4 +631,4 @@
 	return ret ?: done.ret;
 }
 
-#endif	/* CONFIG_STOP_MACHINE */
+#endif	/* CONFIG_SMP || CONFIG_HOTPLUG_CPU */
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index abfc903..cc9f7a9 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -1,7 +1,7 @@
 /*
  * trace event based perf event profiling/tracing
  *
- * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra
  * Copyright (C) 2009-2010 Frederic Weisbecker <fweisbec@gmail.com>
  */
 
diff --git a/lib/btree.c b/lib/btree.c
index 4264871..f93a945 100644
--- a/lib/btree.c
+++ b/lib/btree.c
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 2007-2008 Joern Engel <joern@logfs.org>
  * Bits and pieces stolen from Peter Zijlstra's code, which is
- * Copyright 2007, Red Hat Inc. Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright 2007, Red Hat Inc. Peter Zijlstra
  * GPLv2
  *
  * see http://programming.kicks-ass.net/kernel-patches/vma_lookup/btree.patch
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 8855f01..d34bd24 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -1464,7 +1464,7 @@
 	entry->type      = dma_debug_coherent;
 	entry->dev       = dev;
 	entry->pfn	 = page_to_pfn(virt_to_page(virt));
-	entry->offset	 = (size_t) virt & PAGE_MASK;
+	entry->offset	 = (size_t) virt & ~PAGE_MASK;
 	entry->size      = size;
 	entry->dev_addr  = dma_addr;
 	entry->direction = DMA_BIDIRECTIONAL;
@@ -1480,7 +1480,7 @@
 		.type           = dma_debug_coherent,
 		.dev            = dev,
 		.pfn		= page_to_pfn(virt_to_page(virt)),
-		.offset		= (size_t) virt & PAGE_MASK,
+		.offset		= (size_t) virt & ~PAGE_MASK,
 		.dev_addr       = addr,
 		.size           = size,
 		.direction      = DMA_BIDIRECTIONAL,
diff --git a/lib/proportions.c b/lib/proportions.c
index 6f72429..efa54f25 100644
--- a/lib/proportions.c
+++ b/lib/proportions.c
@@ -1,7 +1,7 @@
 /*
  * Floating proportions
  *
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * Description:
  *
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index a54ff89..eb9240c 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -389,33 +389,31 @@
 	return false;
 }
 
-int rhashtable_insert_rehash(struct rhashtable *ht)
+int rhashtable_insert_rehash(struct rhashtable *ht,
+			     struct bucket_table *tbl)
 {
 	struct bucket_table *old_tbl;
 	struct bucket_table *new_tbl;
-	struct bucket_table *tbl;
 	unsigned int size;
 	int err;
 
 	old_tbl = rht_dereference_rcu(ht->tbl, ht);
-	tbl = rhashtable_last_table(ht, old_tbl);
 
 	size = tbl->size;
 
+	err = -EBUSY;
+
 	if (rht_grow_above_75(ht, tbl))
 		size *= 2;
 	/* Do not schedule more than one rehash */
 	else if (old_tbl != tbl)
-		return -EBUSY;
+		goto fail;
+
+	err = -ENOMEM;
 
 	new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC);
-	if (new_tbl == NULL) {
-		/* Schedule async resize/rehash to try allocation
-		 * non-atomic context.
-		 */
-		schedule_work(&ht->run_work);
-		return -ENOMEM;
-	}
+	if (new_tbl == NULL)
+		goto fail;
 
 	err = rhashtable_rehash_attach(ht, tbl, new_tbl);
 	if (err) {
@@ -426,12 +424,24 @@
 		schedule_work(&ht->run_work);
 
 	return err;
+
+fail:
+	/* Do not fail the insert if someone else did a rehash. */
+	if (likely(rcu_dereference_raw(tbl->future_tbl)))
+		return 0;
+
+	/* Schedule async rehash to retry allocation in process context. */
+	if (err == -ENOMEM)
+		schedule_work(&ht->run_work);
+
+	return err;
 }
 EXPORT_SYMBOL_GPL(rhashtable_insert_rehash);
 
-int rhashtable_insert_slow(struct rhashtable *ht, const void *key,
-			   struct rhash_head *obj,
-			   struct bucket_table *tbl)
+struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
+					    const void *key,
+					    struct rhash_head *obj,
+					    struct bucket_table *tbl)
 {
 	struct rhash_head *head;
 	unsigned int hash;
@@ -467,7 +477,12 @@
 exit:
 	spin_unlock(rht_bucket_lock(tbl, hash));
 
-	return err;
+	if (err == 0)
+		return NULL;
+	else if (err == -EAGAIN)
+		return tbl;
+	else
+		return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(rhashtable_insert_slow);
 
@@ -503,10 +518,10 @@
 	if (!iter->walker)
 		return -ENOMEM;
 
-	mutex_lock(&ht->mutex);
+	spin_lock(&ht->lock);
 	iter->walker->tbl = rht_dereference(ht->tbl, ht);
 	list_add(&iter->walker->list, &iter->walker->tbl->walkers);
-	mutex_unlock(&ht->mutex);
+	spin_unlock(&ht->lock);
 
 	return 0;
 }
@@ -520,10 +535,10 @@
  */
 void rhashtable_walk_exit(struct rhashtable_iter *iter)
 {
-	mutex_lock(&iter->ht->mutex);
+	spin_lock(&iter->ht->lock);
 	if (iter->walker->tbl)
 		list_del(&iter->walker->list);
-	mutex_unlock(&iter->ht->mutex);
+	spin_unlock(&iter->ht->lock);
 	kfree(iter->walker);
 }
 EXPORT_SYMBOL_GPL(rhashtable_walk_exit);
@@ -547,14 +562,12 @@
 {
 	struct rhashtable *ht = iter->ht;
 
-	mutex_lock(&ht->mutex);
-
-	if (iter->walker->tbl)
-		list_del(&iter->walker->list);
-
 	rcu_read_lock();
 
-	mutex_unlock(&ht->mutex);
+	spin_lock(&ht->lock);
+	if (iter->walker->tbl)
+		list_del(&iter->walker->list);
+	spin_unlock(&ht->lock);
 
 	if (!iter->walker->tbl) {
 		iter->walker->tbl = rht_dereference_rcu(ht->tbl, ht);
@@ -723,9 +736,6 @@
 	if (params->nulls_base && params->nulls_base < (1U << RHT_BASE_SHIFT))
 		return -EINVAL;
 
-	if (params->nelem_hint)
-		size = rounded_hashtable_size(params);
-
 	memset(ht, 0, sizeof(*ht));
 	mutex_init(&ht->mutex);
 	spin_lock_init(&ht->lock);
@@ -745,6 +755,9 @@
 
 	ht->p.min_size = max(ht->p.min_size, HASH_MIN_SIZE);
 
+	if (params->nelem_hint)
+		size = rounded_hashtable_size(&ht->p);
+
 	/* The maximum (not average) chain length grows with the
 	 * size of the hash table, at a rate of (log N)/(log log N).
 	 * The value of 16 is selected so that even if the hash
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 8ed2ffd..7340353 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -957,8 +957,9 @@
  * jiffies for either a BDI to exit congestion of the given @sync queue
  * or a write to complete.
  *
- * In the absence of zone congestion, cond_resched() is called to yield
- * the processor if necessary but otherwise does not sleep.
+ * In the absence of zone congestion, a short sleep or a cond_resched is
+ * performed to yield the processor and to allow other subsystems to make
+ * a forward progress.
  *
  * The return value is 0 if the sleep is for the full timeout. Otherwise,
  * it is the number of jiffies that were still remaining when the function
@@ -978,7 +979,19 @@
 	 */
 	if (atomic_read(&nr_wb_congested[sync]) == 0 ||
 	    !test_bit(ZONE_CONGESTED, &zone->flags)) {
-		cond_resched();
+
+		/*
+		 * Memory allocation/reclaim might be called from a WQ
+		 * context and the current implementation of the WQ
+		 * concurrency control doesn't recognize that a particular
+		 * WQ is congested if the worker thread is looping without
+		 * ever sleeping. Therefore we have to do a short sleep
+		 * here rather than calling cond_resched().
+		 */
+		if (current->flags & PF_WQ_WORKER)
+			schedule_timeout(1);
+		else
+			cond_resched();
 
 		/* In case we scheduled, work out time remaining */
 		ret = timeout - (jiffies - start);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 827bb02..ef6963b 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -372,8 +372,10 @@
 		spin_unlock(&resv->lock);
 
 		trg = kmalloc(sizeof(*trg), GFP_KERNEL);
-		if (!trg)
+		if (!trg) {
+			kfree(nrg);
 			return -ENOMEM;
+		}
 
 		spin_lock(&resv->lock);
 		list_add(&trg->link, &resv->region_cache);
@@ -483,8 +485,16 @@
 retry:
 	spin_lock(&resv->lock);
 	list_for_each_entry_safe(rg, trg, head, link) {
-		if (rg->to <= f)
+		/*
+		 * Skip regions before the range to be deleted.  file_region
+		 * ranges are normally of the form [from, to).  However, there
+		 * may be a "placeholder" entry in the map which is of the form
+		 * (from, to) with from == to.  Check for placeholder entries
+		 * at the beginning of the range to be deleted.
+		 */
+		if (rg->to <= f && (rg->to != rg->from || rg->to != f))
 			continue;
+
 		if (rg->from >= t)
 			break;
 
@@ -1886,7 +1896,10 @@
 		page = __alloc_buddy_huge_page_with_mpol(h, vma, addr);
 		if (!page)
 			goto out_uncharge_cgroup;
-
+		if (!avoid_reserve && vma_has_reserves(vma, gbl_chg)) {
+			SetPagePrivate(page);
+			h->resv_huge_pages--;
+		}
 		spin_lock(&hugetlb_lock);
 		list_move(&page->lru, &h->hugepage_activelist);
 		/* Fall through */
@@ -3693,12 +3706,12 @@
 		} else if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
 			return VM_FAULT_HWPOISON_LARGE |
 				VM_FAULT_SET_HINDEX(hstate_index(h));
+	} else {
+		ptep = huge_pte_alloc(mm, address, huge_page_size(h));
+		if (!ptep)
+			return VM_FAULT_OOM;
 	}
 
-	ptep = huge_pte_alloc(mm, address, huge_page_size(h));
-	if (!ptep)
-		return VM_FAULT_OOM;
-
 	mapping = vma->vm_file->f_mapping;
 	idx = vma_hugecache_offset(h, vma, address);
 
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 9acfb16..e234c21 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2128,7 +2128,7 @@
 	 */
 	do {
 		if (page_counter_read(&memcg->memory) > memcg->high) {
-			current->memcg_nr_pages_over_high += nr_pages;
+			current->memcg_nr_pages_over_high += batch;
 			set_notify_resume(current);
 			break;
 		}
@@ -4779,23 +4779,18 @@
 	spin_unlock(&mc.lock);
 }
 
-static int mem_cgroup_can_attach(struct cgroup_subsys_state *css,
-				 struct cgroup_taskset *tset)
+static int mem_cgroup_can_attach(struct cgroup_taskset *tset)
 {
-	struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+	struct cgroup_subsys_state *css;
+	struct mem_cgroup *memcg;
 	struct mem_cgroup *from;
 	struct task_struct *leader, *p;
 	struct mm_struct *mm;
 	unsigned long move_flags;
 	int ret = 0;
 
-	/*
-	 * We are now commited to this value whatever it is. Changes in this
-	 * tunable will only affect upcoming migrations, not the current one.
-	 * So we need to save it, and keep it going.
-	 */
-	move_flags = READ_ONCE(memcg->move_charge_at_immigrate);
-	if (!move_flags)
+	/* charge immigration isn't supported on the default hierarchy */
+	if (cgroup_subsys_on_dfl(memory_cgrp_subsys))
 		return 0;
 
 	/*
@@ -4805,13 +4800,23 @@
 	 * multiple.
 	 */
 	p = NULL;
-	cgroup_taskset_for_each_leader(leader, tset) {
+	cgroup_taskset_for_each_leader(leader, css, tset) {
 		WARN_ON_ONCE(p);
 		p = leader;
+		memcg = mem_cgroup_from_css(css);
 	}
 	if (!p)
 		return 0;
 
+	/*
+	 * We are now commited to this value whatever it is. Changes in this
+	 * tunable will only affect upcoming migrations, not the current one.
+	 * So we need to save it, and keep it going.
+	 */
+	move_flags = READ_ONCE(memcg->move_charge_at_immigrate);
+	if (!move_flags)
+		return 0;
+
 	from = mem_cgroup_from_task(p);
 
 	VM_BUG_ON(from == memcg);
@@ -4842,8 +4847,7 @@
 	return ret;
 }
 
-static void mem_cgroup_cancel_attach(struct cgroup_subsys_state *css,
-				     struct cgroup_taskset *tset)
+static void mem_cgroup_cancel_attach(struct cgroup_taskset *tset)
 {
 	if (mc.to)
 		mem_cgroup_clear_mc();
@@ -4985,10 +4989,10 @@
 	atomic_dec(&mc.from->moving_account);
 }
 
-static void mem_cgroup_move_task(struct cgroup_subsys_state *css,
-				 struct cgroup_taskset *tset)
+static void mem_cgroup_move_task(struct cgroup_taskset *tset)
 {
-	struct task_struct *p = cgroup_taskset_first(tset);
+	struct cgroup_subsys_state *css;
+	struct task_struct *p = cgroup_taskset_first(tset, &css);
 	struct mm_struct *mm = get_task_mm(p);
 
 	if (mm) {
@@ -5000,17 +5004,14 @@
 		mem_cgroup_clear_mc();
 }
 #else	/* !CONFIG_MMU */
-static int mem_cgroup_can_attach(struct cgroup_subsys_state *css,
-				 struct cgroup_taskset *tset)
+static int mem_cgroup_can_attach(struct cgroup_taskset *tset)
 {
 	return 0;
 }
-static void mem_cgroup_cancel_attach(struct cgroup_subsys_state *css,
-				     struct cgroup_taskset *tset)
+static void mem_cgroup_cancel_attach(struct cgroup_taskset *tset)
 {
 }
-static void mem_cgroup_move_task(struct cgroup_subsys_state *css,
-				 struct cgroup_taskset *tset)
+static void mem_cgroup_move_task(struct cgroup_taskset *tset)
 {
 }
 #endif
@@ -5511,11 +5512,11 @@
  * mem_cgroup_replace_page - migrate a charge to another page
  * @oldpage: currently charged page
  * @newpage: page to transfer the charge to
- * @lrucare: either or both pages might be on the LRU already
  *
  * Migrate the charge from @oldpage to @newpage.
  *
  * Both pages must be locked, @newpage->mapping must be set up.
+ * Either or both pages might be on the LRU already.
  */
 void mem_cgroup_replace_page(struct page *oldpage, struct page *newpage)
 {
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index d13a339..c126809 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -608,6 +608,8 @@
 			continue;
 		if (unlikely(p->flags & PF_KTHREAD))
 			continue;
+		if (is_global_init(p))
+			continue;
 		if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
 			continue;
 
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 3e4d654..d15d88c 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2,7 +2,7 @@
  * mm/page-writeback.c
  *
  * Copyright (C) 2002, Linus Torvalds.
- * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * Contains functions related to writing back dirty pages at the
  * address_space level.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 17a3c66..9d666df 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3647,8 +3647,9 @@
 {
 	static const char types[MIGRATE_TYPES] = {
 		[MIGRATE_UNMOVABLE]	= 'U',
-		[MIGRATE_RECLAIMABLE]	= 'E',
 		[MIGRATE_MOVABLE]	= 'M',
+		[MIGRATE_RECLAIMABLE]	= 'E',
+		[MIGRATE_HIGHATOMIC]	= 'H',
 #ifdef CONFIG_CMA
 		[MIGRATE_CMA]		= 'C',
 #endif
diff --git a/mm/shmem.c b/mm/shmem.c
index 9187eee..2afcdbb 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -843,14 +843,14 @@
 		list_add_tail(&info->swaplist, &shmem_swaplist);
 
 	if (add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) {
+		spin_lock(&info->lock);
+		shmem_recalc_inode(inode);
+		info->swapped++;
+		spin_unlock(&info->lock);
+
 		swap_shmem_alloc(swap);
 		shmem_delete_from_page_cache(page, swp_to_radix_entry(swap));
 
-		spin_lock(&info->lock);
-		info->swapped++;
-		shmem_recalc_inode(inode);
-		spin_unlock(&info->lock);
-
 		mutex_unlock(&shmem_swaplist_mutex);
 		BUG_ON(page_mapped(page));
 		swap_writepage(page, wbc);
@@ -1078,7 +1078,7 @@
 	if (sgp != SGP_WRITE && sgp != SGP_FALLOC &&
 	    ((loff_t)index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
 		error = -EINVAL;
-		goto failed;
+		goto unlock;
 	}
 
 	if (page && sgp == SGP_WRITE)
@@ -1246,11 +1246,15 @@
 	/* Perhaps the file has been truncated since we checked */
 	if (sgp != SGP_WRITE && sgp != SGP_FALLOC &&
 	    ((loff_t)index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
+		if (alloced) {
+			ClearPageDirty(page);
+			delete_from_page_cache(page);
+			spin_lock(&info->lock);
+			shmem_recalc_inode(inode);
+			spin_unlock(&info->lock);
+		}
 		error = -EINVAL;
-		if (alloced)
-			goto trunc;
-		else
-			goto failed;
+		goto unlock;
 	}
 	*pagep = page;
 	return 0;
@@ -1258,23 +1262,13 @@
 	/*
 	 * Error recovery.
 	 */
-trunc:
-	info = SHMEM_I(inode);
-	ClearPageDirty(page);
-	delete_from_page_cache(page);
-	spin_lock(&info->lock);
-	info->alloced--;
-	inode->i_blocks -= BLOCKS_PER_PAGE;
-	spin_unlock(&info->lock);
 decused:
-	sbinfo = SHMEM_SB(inode->i_sb);
 	if (sbinfo->max_blocks)
 		percpu_counter_add(&sbinfo->used_blocks, -1);
 unacct:
 	shmem_unacct_blocks(info->flags, 1);
 failed:
-	if (swap.val && error != -EINVAL &&
-	    !shmem_confirm_swap(mapping, index, swap))
+	if (swap.val && !shmem_confirm_swap(mapping, index, swap))
 		error = -EEXIST;
 unlock:
 	if (page) {
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 879a2be..0d5712b 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -921,8 +921,8 @@
 #ifdef CONFIG_PROC_FS
 static char * const migratetype_names[MIGRATE_TYPES] = {
 	"Unmovable",
-	"Reclaimable",
 	"Movable",
+	"Reclaimable",
 	"HighAtomic",
 #ifdef CONFIG_CMA
 	"CMA",
@@ -1379,6 +1379,7 @@
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SMP
+static struct workqueue_struct *vmstat_wq;
 static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
 int sysctl_stat_interval __read_mostly = HZ;
 static cpumask_var_t cpu_stat_off;
@@ -1391,7 +1392,7 @@
 		 * to occur in the future. Keep on running the
 		 * update worker thread.
 		 */
-		schedule_delayed_work_on(smp_processor_id(),
+		queue_delayed_work_on(smp_processor_id(), vmstat_wq,
 			this_cpu_ptr(&vmstat_work),
 			round_jiffies_relative(sysctl_stat_interval));
 	} else {
@@ -1460,7 +1461,7 @@
 		if (need_update(cpu) &&
 			cpumask_test_and_clear_cpu(cpu, cpu_stat_off))
 
-			schedule_delayed_work_on(cpu,
+			queue_delayed_work_on(cpu, vmstat_wq,
 				&per_cpu(vmstat_work, cpu), 0);
 
 	put_online_cpus();
@@ -1549,6 +1550,7 @@
 
 	start_shepherd_timer();
 	cpu_notifier_register_done();
+	vmstat_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
 #endif
 #ifdef CONFIG_PROC_FS
 	proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
diff --git a/mm/zswap.c b/mm/zswap.c
index 025f8dc..bf14508 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -541,6 +541,7 @@
 	return last;
 }
 
+/* type and compressor must be null-terminated */
 static struct zswap_pool *zswap_pool_find_get(char *type, char *compressor)
 {
 	struct zswap_pool *pool;
@@ -548,10 +549,9 @@
 	assert_spin_locked(&zswap_pools_lock);
 
 	list_for_each_entry_rcu(pool, &zswap_pools, list) {
-		if (strncmp(pool->tfm_name, compressor, sizeof(pool->tfm_name)))
+		if (strcmp(pool->tfm_name, compressor))
 			continue;
-		if (strncmp(zpool_get_type(pool->zpool), type,
-			    sizeof(zswap_zpool_type)))
+		if (strcmp(zpool_get_type(pool->zpool), type))
 			continue;
 		/* if we can't get it, it's about to be destroyed */
 		if (!zswap_pool_get(pool))
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index ae3a47f..fbd0acf 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -805,6 +805,9 @@
 	struct sock *sk;
 	ax25_cb *ax25;
 
+	if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
+		return -EINVAL;
+
 	if (!net_eq(net, &init_net))
 		return -EAFNOSUPPORT;
 
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 83bc1aa..a49c705 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -566,6 +566,7 @@
 	int select;
 	batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
 	struct batadv_dat_candidate *res;
+	struct batadv_dat_entry dat;
 
 	if (!bat_priv->orig_hash)
 		return NULL;
@@ -575,7 +576,9 @@
 	if (!res)
 		return NULL;
 
-	ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst,
+	dat.ip = ip_dst;
+	dat.vid = 0;
+	ip_key = (batadv_dat_addr_t)batadv_hash_dat(&dat,
 						    BATADV_DAT_ADDR_MAX);
 
 	batadv_dbg(BATADV_DBG_DAT, bat_priv,
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 8d990b0..3207667 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -836,6 +836,7 @@
 	u8 *orig_addr;
 	struct batadv_orig_node *orig_node = NULL;
 	int check, hdr_size = sizeof(*unicast_packet);
+	enum batadv_subtype subtype;
 	bool is4addr;
 
 	unicast_packet = (struct batadv_unicast_packet *)skb->data;
@@ -863,10 +864,20 @@
 	/* packet for me */
 	if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
 		if (is4addr) {
-			batadv_dat_inc_counter(bat_priv,
-					       unicast_4addr_packet->subtype);
-			orig_addr = unicast_4addr_packet->src;
-			orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
+			subtype = unicast_4addr_packet->subtype;
+			batadv_dat_inc_counter(bat_priv, subtype);
+
+			/* Only payload data should be considered for speedy
+			 * join. For example, DAT also uses unicast 4addr
+			 * types, but those packets should not be considered
+			 * for speedy join, since the clients do not actually
+			 * reside at the sending originator.
+			 */
+			if (subtype == BATADV_P_DATA) {
+				orig_addr = unicast_4addr_packet->src;
+				orig_node = batadv_orig_hash_find(bat_priv,
+								  orig_addr);
+			}
 		}
 
 		if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb,
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 4228b10..76f19ba 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -68,13 +68,15 @@
 				 unsigned short vid, const char *message,
 				 bool roaming);
 
-/* returns 1 if they are the same mac addr */
+/* returns 1 if they are the same mac addr and vid */
 static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
 {
 	const void *data1 = container_of(node, struct batadv_tt_common_entry,
 					 hash_entry);
+	const struct batadv_tt_common_entry *tt1 = data1;
+	const struct batadv_tt_common_entry *tt2 = data2;
 
-	return batadv_compare_eth(data1, data2);
+	return (tt1->vid == tt2->vid) && batadv_compare_eth(data1, data2);
 }
 
 /**
@@ -1427,9 +1429,15 @@
 		}
 
 		/* if the client was temporary added before receiving the first
-		 * OGM announcing it, we have to clear the TEMP flag
+		 * OGM announcing it, we have to clear the TEMP flag. Also,
+		 * remove the previous temporary orig node and re-add it
+		 * if required. If the orig entry changed, the new one which
+		 * is a non-temporary entry is preferred.
 		 */
-		common->flags &= ~BATADV_TT_CLIENT_TEMP;
+		if (common->flags & BATADV_TT_CLIENT_TEMP) {
+			batadv_tt_global_del_orig_list(tt_global_entry);
+			common->flags &= ~BATADV_TT_CLIENT_TEMP;
+		}
 
 		/* the change can carry possible "attribute" flags like the
 		 * TT_CLIENT_WIFI, therefore they have to be copied in the
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index fe12966..f52bcbf 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -526,6 +526,9 @@
 	if (!addr || addr->sa_family != AF_BLUETOOTH)
 		return -EINVAL;
 
+	if (addr_len < sizeof(struct sockaddr_sco))
+		return -EINVAL;
+
 	lock_sock(sk);
 
 	if (sk->sk_state != BT_OPEN) {
diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c
index 2e4df84..d9ee8d0 100644
--- a/net/core/netclassid_cgroup.c
+++ b/net/core/netclassid_cgroup.c
@@ -81,9 +81,11 @@
 	css_task_iter_end(&it);
 }
 
-static void cgrp_attach(struct cgroup_subsys_state *css,
-			struct cgroup_taskset *tset)
+static void cgrp_attach(struct cgroup_taskset *tset)
 {
+	struct cgroup_subsys_state *css;
+
+	cgroup_taskset_first(tset, &css);
 	update_classid(css,
 		       (void *)(unsigned long)css_cls_state(css)->classid);
 }
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
index cbd0a19..40fd09f 100644
--- a/net/core/netprio_cgroup.c
+++ b/net/core/netprio_cgroup.c
@@ -218,13 +218,14 @@
 	return 0;
 }
 
-static void net_prio_attach(struct cgroup_subsys_state *css,
-			    struct cgroup_taskset *tset)
+static void net_prio_attach(struct cgroup_taskset *tset)
 {
 	struct task_struct *p;
-	void *v = (void *)(unsigned long)css->cgroup->id;
+	struct cgroup_subsys_state *css;
 
-	cgroup_taskset_for_each(p, tset) {
+	cgroup_taskset_for_each(p, css, tset) {
+		void *v = (void *)(unsigned long)css->cgroup->id;
+
 		task_lock(p);
 		iterate_fd(p->files, 0, update_netprio, v);
 		task_unlock(p);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 152b9c7..b2df375 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3643,7 +3643,8 @@
 	serr->ee.ee_info = tstype;
 	if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) {
 		serr->ee.ee_data = skb_shinfo(skb)->tskey;
-		if (sk->sk_protocol == IPPROTO_TCP)
+		if (sk->sk_protocol == IPPROTO_TCP &&
+		    sk->sk_type == SOCK_STREAM)
 			serr->ee.ee_data -= sk->sk_tskey;
 	}
 
@@ -4268,7 +4269,7 @@
 		return NULL;
 	}
 
-	memmove(skb->data - ETH_HLEN, skb->data - skb->mac_len,
+	memmove(skb->data - ETH_HLEN, skb->data - skb->mac_len - VLAN_HLEN,
 		2 * ETH_ALEN);
 	skb->mac_header += VLAN_HLEN;
 	return skb;
diff --git a/net/core/sock.c b/net/core/sock.c
index e31dfce..0d91f7d 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -433,8 +433,6 @@
 	}
 }
 
-#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
-
 static void sock_disable_timestamp(struct sock *sk, unsigned long flags)
 {
 	if (sk->sk_flags & flags) {
@@ -874,7 +872,8 @@
 
 		if (val & SOF_TIMESTAMPING_OPT_ID &&
 		    !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) {
-			if (sk->sk_protocol == IPPROTO_TCP) {
+			if (sk->sk_protocol == IPPROTO_TCP &&
+			    sk->sk_type == SOCK_STREAM) {
 				if (sk->sk_state != TCP_ESTABLISHED) {
 					ret = -EINVAL;
 					break;
@@ -1552,7 +1551,7 @@
 			 */
 			is_charged = sk_filter_charge(newsk, filter);
 
-		if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk))) {
+		if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) {
 			/* It is still raw copy of parent, so invalidate
 			 * destructor and make plain sk_free() */
 			newsk->sk_destruct = NULL;
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index eebf5ac..13d6b1a 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -678,6 +678,9 @@
 {
 	struct sock *sk;
 
+	if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
+		return -EINVAL;
+
 	if (!net_eq(net, &init_net))
 		return -EAFNOSUPPORT;
 
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 11c4ca1..5c5db66 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -257,6 +257,9 @@
 	int try_loading_module = 0;
 	int err;
 
+	if (protocol < 0 || protocol >= IPPROTO_MAX)
+		return -EINVAL;
+
 	sock->state = SS_UNCONNECTED;
 
 	/* Look for the requested type/protocol pair. */
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index cc8f3e5..4734475 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -1155,6 +1155,7 @@
 static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct netdev_notifier_changeupper_info *info;
 	struct in_device *in_dev;
 	struct net *net = dev_net(dev);
 	unsigned int flags;
@@ -1193,6 +1194,14 @@
 	case NETDEV_CHANGEMTU:
 		rt_cache_flush(net);
 		break;
+	case NETDEV_CHANGEUPPER:
+		info = ptr;
+		/* flush all routes if dev is linked to or unlinked from
+		 * an L3 master device (e.g., VRF)
+		 */
+		if (info->upper_dev && netif_is_l3_master(info->upper_dev))
+			fib_disable_ip(dev, NETDEV_DOWN, true);
+		break;
 	}
 	return NOTIFY_DONE;
 }
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index e0fcbbb..bd903fe 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -24,6 +24,7 @@
 	u16 type;
 	struct udp_offload udp_offloads;
 	struct list_head list;
+	struct rcu_head rcu;
 };
 
 #define FOU_F_REMCSUM_NOPARTIAL BIT(0)
@@ -417,7 +418,7 @@
 	list_del(&fou->list);
 	udp_tunnel_sock_release(sock);
 
-	kfree(fou);
+	kfree_rcu(fou, rcu);
 }
 
 static int fou_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg)
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index a355841..c187c60 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -60,6 +60,7 @@
 
 config NFT_DUP_IPV4
 	tristate "IPv4 nf_tables packet duplication support"
+	depends on !NF_CONNTRACK || NF_CONNTRACK
 	select NF_DUP_IPV4
 	help
 	  This module enables IPv4 packet duplication support for nf_tables.
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index db00343..d8841a2 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1493,7 +1493,7 @@
 	if (likely(sk->sk_rx_dst))
 		skb_dst_drop(skb);
 	else
-		skb_dst_force(skb);
+		skb_dst_force_safe(skb);
 
 	__skb_queue_tail(&tp->ucopy.prequeue, skb);
 	tp->ucopy.memory += skb->truesize;
@@ -1721,8 +1721,7 @@
 {
 	struct dst_entry *dst = skb_dst(skb);
 
-	if (dst) {
-		dst_hold(dst);
+	if (dst && dst_hold_safe(dst)) {
 		sk->sk_rx_dst = dst;
 		inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
 	}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index cb7ca56..9bfc39f 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -3150,7 +3150,7 @@
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct tcp_fastopen_request *fo = tp->fastopen_req;
-	int syn_loss = 0, space, err = 0, copied;
+	int syn_loss = 0, space, err = 0;
 	unsigned long last_syn_loss = 0;
 	struct sk_buff *syn_data;
 
@@ -3188,17 +3188,18 @@
 		goto fallback;
 	syn_data->ip_summed = CHECKSUM_PARTIAL;
 	memcpy(syn_data->cb, syn->cb, sizeof(syn->cb));
-	copied = copy_from_iter(skb_put(syn_data, space), space,
-				&fo->data->msg_iter);
-	if (unlikely(!copied)) {
-		kfree_skb(syn_data);
-		goto fallback;
+	if (space) {
+		int copied = copy_from_iter(skb_put(syn_data, space), space,
+					    &fo->data->msg_iter);
+		if (unlikely(!copied)) {
+			kfree_skb(syn_data);
+			goto fallback;
+		}
+		if (copied != space) {
+			skb_trim(syn_data, copied);
+			space = copied;
+		}
 	}
-	if (copied != space) {
-		skb_trim(syn_data, copied);
-		space = copied;
-	}
-
 	/* No more data pending in inet_wait_for_connect() */
 	if (space == fo->size)
 		fo->data = NULL;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 61f2685..17f8e7e 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -350,6 +350,12 @@
 	setup_timer(&ndev->rs_timer, addrconf_rs_timer,
 		    (unsigned long)ndev);
 	memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf));
+
+	if (ndev->cnf.stable_secret.initialized)
+		ndev->addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
+	else
+		ndev->addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64;
+
 	ndev->cnf.mtu6 = dev->mtu;
 	ndev->cnf.sysctl = NULL;
 	ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
@@ -2455,7 +2461,7 @@
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
 			if (in6_dev->cnf.optimistic_dad &&
 			    !net->ipv6.devconf_all->forwarding && sllao)
-				addr_flags = IFA_F_OPTIMISTIC;
+				addr_flags |= IFA_F_OPTIMISTIC;
 #endif
 
 			/* Do not allow to create too much of autoconfigured
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 8ec0df7..9f5137c 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -109,6 +109,9 @@
 	int try_loading_module = 0;
 	int err;
 
+	if (protocol < 0 || protocol >= IPPROTO_MAX)
+		return -EINVAL;
+
 	/* Look for the requested type/protocol pair. */
 lookup_protocol:
 	err = -ESOCKTNOSUPPORT;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 3c7b931..e5ea177 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1571,13 +1571,11 @@
 			return -EEXIST;
 	} else {
 		t = nt;
-
-		ip6gre_tunnel_unlink(ign, t);
-		ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]);
-		ip6gre_tunnel_link(ign, t);
-		netdev_state_change(dev);
 	}
 
+	ip6gre_tunnel_unlink(ign, t);
+	ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]);
+	ip6gre_tunnel_link(ign, t);
 	return 0;
 }
 
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index f6a024e..e10a04c 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -49,6 +49,7 @@
 
 config NFT_DUP_IPV6
 	tristate "IPv6 nf_tables packet duplication support"
+	depends on !NF_CONNTRACK || NF_CONNTRACK
 	select NF_DUP_IPV6
 	help
 	  This module enables IPv6 packet duplication support for nf_tables.
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index e7aab56..6b8a8a9 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -93,10 +93,9 @@
 {
 	struct dst_entry *dst = skb_dst(skb);
 
-	if (dst) {
+	if (dst && dst_hold_safe(dst)) {
 		const struct rt6_info *rt = (const struct rt6_info *)dst;
 
-		dst_hold(dst);
 		sk->sk_rx_dst = dst;
 		inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
 		inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt);
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index e6aa48b..923abd6 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1086,6 +1086,9 @@
 	struct sock *sk;
 	struct irda_sock *self;
 
+	if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
+		return -EINVAL;
+
 	if (net != &init_net)
 		return -EAFNOSUPPORT;
 
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index da471ee..c12f348 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1169,8 +1169,7 @@
 		 * rc isn't initialized here yet, so ignore it
 		 */
 		__ieee80211_vht_handle_opmode(sdata, sta,
-					      params->opmode_notif,
-					      band, false);
+					      params->opmode_notif, band);
 	}
 
 	if (ieee80211_vif_is_mesh(&sdata->vif))
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d832bd5..5322b4c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1709,10 +1709,10 @@
 void ieee80211_sta_set_rx_nss(struct sta_info *sta);
 u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
                                   struct sta_info *sta, u8 opmode,
-                                  enum ieee80211_band band, bool nss_only);
+				  enum ieee80211_band band);
 void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 				 struct sta_info *sta, u8 opmode,
-				 enum ieee80211_band band, bool nss_only);
+				 enum ieee80211_band band);
 void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
 				      struct ieee80211_sta_vht_cap *vht_cap);
 void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b140cc6..3aa0434 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1379,21 +1379,26 @@
 	 */
 	if (has_80211h_pwr &&
 	    (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) {
+		new_ap_level = pwr_level_80211h;
+
+		if (sdata->ap_power_level == new_ap_level)
+			return 0;
+
 		sdata_dbg(sdata,
 			  "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
 			  pwr_level_80211h, chan_pwr, pwr_reduction_80211h,
 			  sdata->u.mgd.bssid);
-		new_ap_level = pwr_level_80211h;
 	} else {  /* has_cisco_pwr is always true here. */
+		new_ap_level = pwr_level_cisco;
+
+		if (sdata->ap_power_level == new_ap_level)
+			return 0;
+
 		sdata_dbg(sdata,
 			  "Limiting TX power to %d dBm as advertised by %pM\n",
 			  pwr_level_cisco, sdata->u.mgd.bssid);
-		new_ap_level = pwr_level_cisco;
 	}
 
-	if (sdata->ap_power_level == new_ap_level)
-		return 0;
-
 	sdata->ap_power_level = new_ap_level;
 	if (__ieee80211_recalc_txpower(sdata))
 		return BSS_CHANGED_TXPOWER;
@@ -3575,7 +3580,7 @@
 
 	if (sta && elems.opmode_notif)
 		ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif,
-					    rx_status->band, true);
+					    rx_status->band);
 	mutex_unlock(&local->sta_mtx);
 
 	changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 8bae5de..82af407 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2736,8 +2736,7 @@
 			opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
 
 			ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
-						    opmode, status->band,
-						    false);
+						    opmode, status->band);
 			goto handled;
 		}
 		default:
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7405802..33344f5 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1641,6 +1641,29 @@
 	drv_stop(local);
 }
 
+static void ieee80211_flush_completed_scan(struct ieee80211_local *local,
+					   bool aborted)
+{
+	/* It's possible that we don't handle the scan completion in
+	 * time during suspend, so if it's still marked as completed
+	 * here, queue the work and flush it to clean things up.
+	 * Instead of calling the worker function directly here, we
+	 * really queue it to avoid potential races with other flows
+	 * scheduling the same work.
+	 */
+	if (test_bit(SCAN_COMPLETED, &local->scanning)) {
+		/* If coming from reconfiguration failure, abort the scan so
+		 * we don't attempt to continue a partial HW scan - which is
+		 * possible otherwise if (e.g.) the 2.4 GHz portion was the
+		 * completed scan, and a 5 GHz portion is still pending.
+		 */
+		if (aborted)
+			set_bit(SCAN_ABORTED, &local->scanning);
+		ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
+		flush_delayed_work(&local->scan_work);
+	}
+}
+
 static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
 {
 	struct ieee80211_sub_if_data *sdata;
@@ -1660,6 +1683,8 @@
 	local->suspended = false;
 	local->in_reconfig = false;
 
+	ieee80211_flush_completed_scan(local, true);
+
 	/* scheduled scan clearly can't be running any more, but tell
 	 * cfg80211 and clear local state
 	 */
@@ -1698,6 +1723,27 @@
 	mutex_unlock(&local->chanctx_mtx);
 }
 
+static void ieee80211_reconfig_stations(struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_local *local = sdata->local;
+	struct sta_info *sta;
+
+	/* add STAs back */
+	mutex_lock(&local->sta_mtx);
+	list_for_each_entry(sta, &local->sta_list, list) {
+		enum ieee80211_sta_state state;
+
+		if (!sta->uploaded || sta->sdata != sdata)
+			continue;
+
+		for (state = IEEE80211_STA_NOTEXIST;
+		     state < sta->sta_state; state++)
+			WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
+					      state + 1));
+	}
+	mutex_unlock(&local->sta_mtx);
+}
+
 int ieee80211_reconfig(struct ieee80211_local *local)
 {
 	struct ieee80211_hw *hw = &local->hw;
@@ -1833,50 +1879,11 @@
 				WARN_ON(drv_add_chanctx(local, ctx));
 		mutex_unlock(&local->chanctx_mtx);
 
-		list_for_each_entry(sdata, &local->interfaces, list) {
-			if (!ieee80211_sdata_running(sdata))
-				continue;
-			ieee80211_assign_chanctx(local, sdata);
-		}
-
 		sdata = rtnl_dereference(local->monitor_sdata);
 		if (sdata && ieee80211_sdata_running(sdata))
 			ieee80211_assign_chanctx(local, sdata);
 	}
 
-	/* add STAs back */
-	mutex_lock(&local->sta_mtx);
-	list_for_each_entry(sta, &local->sta_list, list) {
-		enum ieee80211_sta_state state;
-
-		if (!sta->uploaded)
-			continue;
-
-		/* AP-mode stations will be added later */
-		if (sta->sdata->vif.type == NL80211_IFTYPE_AP)
-			continue;
-
-		for (state = IEEE80211_STA_NOTEXIST;
-		     state < sta->sta_state; state++)
-			WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
-					      state + 1));
-	}
-	mutex_unlock(&local->sta_mtx);
-
-	/* reconfigure tx conf */
-	if (hw->queues >= IEEE80211_NUM_ACS) {
-		list_for_each_entry(sdata, &local->interfaces, list) {
-			if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
-			    sdata->vif.type == NL80211_IFTYPE_MONITOR ||
-			    !ieee80211_sdata_running(sdata))
-				continue;
-
-			for (i = 0; i < IEEE80211_NUM_ACS; i++)
-				drv_conf_tx(local, sdata, i,
-					    &sdata->tx_conf[i]);
-		}
-	}
-
 	/* reconfigure hardware */
 	ieee80211_hw_config(local, ~0);
 
@@ -1889,6 +1896,22 @@
 		if (!ieee80211_sdata_running(sdata))
 			continue;
 
+		ieee80211_assign_chanctx(local, sdata);
+
+		switch (sdata->vif.type) {
+		case NL80211_IFTYPE_AP_VLAN:
+		case NL80211_IFTYPE_MONITOR:
+			break;
+		default:
+			ieee80211_reconfig_stations(sdata);
+			/* fall through */
+		case NL80211_IFTYPE_AP: /* AP stations are handled later */
+			for (i = 0; i < IEEE80211_NUM_ACS; i++)
+				drv_conf_tx(local, sdata, i,
+					    &sdata->tx_conf[i]);
+			break;
+		}
+
 		/* common change flags for all interface types */
 		changed = BSS_CHANGED_ERP_CTS_PROT |
 			  BSS_CHANGED_ERP_PREAMBLE |
@@ -2074,17 +2097,7 @@
 	mb();
 	local->resuming = false;
 
-	/* It's possible that we don't handle the scan completion in
-	 * time during suspend, so if it's still marked as completed
-	 * here, queue the work and flush it to clean things up.
-	 * Instead of calling the worker function directly here, we
-	 * really queue it to avoid potential races with other flows
-	 * scheduling the same work.
-	 */
-	if (test_bit(SCAN_COMPLETED, &local->scanning)) {
-		ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
-		flush_delayed_work(&local->scan_work);
-	}
+	ieee80211_flush_completed_scan(local, false);
 
 	if (local->open_count && !reconfig_due_to_wowlan)
 		drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index ff1c798..c38b2f0 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -378,7 +378,7 @@
 
 u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 				  struct sta_info *sta, u8 opmode,
-				  enum ieee80211_band band, bool nss_only)
+				  enum ieee80211_band band)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_supported_band *sband;
@@ -401,9 +401,6 @@
 		changed |= IEEE80211_RC_NSS_CHANGED;
 	}
 
-	if (nss_only)
-		return changed;
-
 	switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
 	case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
 		sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
@@ -430,13 +427,12 @@
 
 void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 				 struct sta_info *sta, u8 opmode,
-				 enum ieee80211_band band, bool nss_only)
+				 enum ieee80211_band band)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
 
-	u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode,
-						    band, nss_only);
+	u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);
 
 	if (changed > 0)
 		rate_control_rate_update(local, sband, sta, changed);
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index c70d750..c32fc41 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -27,6 +27,8 @@
  */
 #define MAX_MP_SELECT_LABELS 4
 
+#define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1)
+
 static int zero = 0;
 static int label_limit = (1 << 20) - 1;
 
@@ -317,7 +319,13 @@
 		}
 	}
 
-	err = neigh_xmit(nh->nh_via_table, out_dev, mpls_nh_via(rt, nh), skb);
+	/* If via wasn't specified then send out using device address */
+	if (nh->nh_via_table == MPLS_NEIGH_TABLE_UNSPEC)
+		err = neigh_xmit(NEIGH_LINK_TABLE, out_dev,
+				 out_dev->dev_addr, skb);
+	else
+		err = neigh_xmit(nh->nh_via_table, out_dev,
+				 mpls_nh_via(rt, nh), skb);
 	if (err)
 		net_dbg_ratelimited("%s: packet transmission failed: %d\n",
 				    __func__, err);
@@ -534,6 +542,10 @@
 	if (!mpls_dev_get(dev))
 		goto errout;
 
+	if ((nh->nh_via_table == NEIGH_LINK_TABLE) &&
+	    (dev->addr_len != nh->nh_via_alen))
+		goto errout;
+
 	RCU_INIT_POINTER(nh->nh_dev, dev);
 
 	return 0;
@@ -592,10 +604,14 @@
 			goto errout;
 	}
 
-	err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table,
-			  __mpls_nh_via(rt, nh));
-	if (err)
-		goto errout;
+	if (via) {
+		err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table,
+				  __mpls_nh_via(rt, nh));
+		if (err)
+			goto errout;
+	} else {
+		nh->nh_via_table = MPLS_NEIGH_TABLE_UNSPEC;
+	}
 
 	err = mpls_nh_assign_dev(net, rt, nh, oif);
 	if (err)
@@ -677,9 +693,6 @@
 			nla_newdst = nla_find(attrs, attrlen, RTA_NEWDST);
 		}
 
-		if (!nla_via)
-			goto errout;
-
 		err = mpls_nh_build(cfg->rc_nlinfo.nl_net, rt, nh,
 				    rtnh->rtnh_ifindex, nla_via,
 				    nla_newdst);
@@ -1118,6 +1131,7 @@
 
 	cfg->rc_label		= LABEL_NOT_SPECIFIED;
 	cfg->rc_protocol	= rtm->rtm_protocol;
+	cfg->rc_via_table	= MPLS_NEIGH_TABLE_UNSPEC;
 	cfg->rc_nlflags		= nlh->nlmsg_flags;
 	cfg->rc_nlinfo.portid	= NETLINK_CB(skb).portid;
 	cfg->rc_nlinfo.nlh	= nlh;
@@ -1231,7 +1245,8 @@
 		    nla_put_labels(skb, RTA_NEWDST, nh->nh_labels,
 				   nh->nh_label))
 			goto nla_put_failure;
-		if (nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
+		if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC &&
+		    nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
 				nh->nh_via_alen))
 			goto nla_put_failure;
 		dev = rtnl_dereference(nh->nh_dev);
@@ -1257,7 +1272,8 @@
 							    nh->nh_labels,
 							    nh->nh_label))
 				goto nla_put_failure;
-			if (nla_put_via(skb, nh->nh_via_table,
+			if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC &&
+			    nla_put_via(skb, nh->nh_via_table,
 					mpls_nh_via(rt, nh),
 					nh->nh_via_alen))
 				goto nla_put_failure;
@@ -1319,7 +1335,8 @@
 
 		if (nh->nh_dev)
 			payload += nla_total_size(4); /* RTA_OIF */
-		payload += nla_total_size(2 + nh->nh_via_alen); /* RTA_VIA */
+		if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC) /* RTA_VIA */
+			payload += nla_total_size(2 + nh->nh_via_alen);
 		if (nh->nh_labels) /* RTA_NEWDST */
 			payload += nla_total_size(nh->nh_labels * 4);
 	} else {
@@ -1328,7 +1345,9 @@
 
 		for_nexthops(rt) {
 			nhsize += nla_total_size(sizeof(struct rtnexthop));
-			nhsize += nla_total_size(2 + nh->nh_via_alen);
+			/* RTA_VIA */
+			if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC)
+				nhsize += nla_total_size(2 + nh->nh_via_alen);
 			if (nh->nh_labels)
 				nhsize += nla_total_size(nh->nh_labels * 4);
 		} endfor_nexthops(rt);
diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c
index 67591ae..64afd3d 100644
--- a/net/mpls/mpls_iptunnel.c
+++ b/net/mpls/mpls_iptunnel.c
@@ -54,10 +54,10 @@
 	unsigned int ttl;
 
 	/* Obtain the ttl */
-	if (skb->protocol == htons(ETH_P_IP)) {
+	if (dst->ops->family == AF_INET) {
 		ttl = ip_hdr(skb)->ttl;
 		rt = (struct rtable *)dst;
-	} else if (skb->protocol == htons(ETH_P_IPV6)) {
+	} else if (dst->ops->family == AF_INET6) {
 		ttl = ipv6_hdr(skb)->hop_limit;
 		rt6 = (struct rt6_info *)dst;
 	} else {
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 93cc473..2cb429d 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -89,6 +89,7 @@
 }
 
 static void nft_ctx_init(struct nft_ctx *ctx,
+			 struct net *net,
 			 const struct sk_buff *skb,
 			 const struct nlmsghdr *nlh,
 			 struct nft_af_info *afi,
@@ -96,7 +97,7 @@
 			 struct nft_chain *chain,
 			 const struct nlattr * const *nla)
 {
-	ctx->net	= sock_net(skb->sk);
+	ctx->net	= net;
 	ctx->afi	= afi;
 	ctx->table	= table;
 	ctx->chain	= chain;
@@ -672,15 +673,14 @@
 	return ret;
 }
 
-static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
-			      const struct nlmsghdr *nlh,
+static int nf_tables_newtable(struct net *net, struct sock *nlsk,
+			      struct sk_buff *skb, const struct nlmsghdr *nlh,
 			      const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	const struct nlattr *name;
 	struct nft_af_info *afi;
 	struct nft_table *table;
-	struct net *net = sock_net(skb->sk);
 	int family = nfmsg->nfgen_family;
 	u32 flags = 0;
 	struct nft_ctx ctx;
@@ -706,7 +706,7 @@
 		if (nlh->nlmsg_flags & NLM_F_REPLACE)
 			return -EOPNOTSUPP;
 
-		nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
+		nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
 		return nf_tables_updtable(&ctx);
 	}
 
@@ -730,7 +730,7 @@
 	INIT_LIST_HEAD(&table->sets);
 	table->flags = flags;
 
-	nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
+	nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
 	err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE);
 	if (err < 0)
 		goto err3;
@@ -810,18 +810,17 @@
 	return err;
 }
 
-static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
-			      const struct nlmsghdr *nlh,
+static int nf_tables_deltable(struct net *net, struct sock *nlsk,
+			      struct sk_buff *skb, const struct nlmsghdr *nlh,
 			      const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	struct nft_af_info *afi;
 	struct nft_table *table;
-	struct net *net = sock_net(skb->sk);
 	int family = nfmsg->nfgen_family;
 	struct nft_ctx ctx;
 
-	nft_ctx_init(&ctx, skb, nlh, NULL, NULL, NULL, nla);
+	nft_ctx_init(&ctx, net, skb, nlh, NULL, NULL, NULL, nla);
 	if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL)
 		return nft_flush(&ctx, family);
 
@@ -1221,8 +1220,8 @@
 	}
 }
 
-static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
-			      const struct nlmsghdr *nlh,
+static int nf_tables_newchain(struct net *net, struct sock *nlsk,
+			      struct sk_buff *skb, const struct nlmsghdr *nlh,
 			      const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -1232,7 +1231,6 @@
 	struct nft_chain *chain;
 	struct nft_base_chain *basechain = NULL;
 	struct nlattr *ha[NFTA_HOOK_MAX + 1];
-	struct net *net = sock_net(skb->sk);
 	int family = nfmsg->nfgen_family;
 	struct net_device *dev = NULL;
 	u8 policy = NF_ACCEPT;
@@ -1313,7 +1311,7 @@
 				return PTR_ERR(stats);
 		}
 
-		nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
+		nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
 		trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN,
 					sizeof(struct nft_trans_chain));
 		if (trans == NULL) {
@@ -1461,7 +1459,7 @@
 	if (err < 0)
 		goto err1;
 
-	nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
+	nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
 	err = nft_trans_chain_add(&ctx, NFT_MSG_NEWCHAIN);
 	if (err < 0)
 		goto err2;
@@ -1476,15 +1474,14 @@
 	return err;
 }
 
-static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
-			      const struct nlmsghdr *nlh,
+static int nf_tables_delchain(struct net *net, struct sock *nlsk,
+			      struct sk_buff *skb, const struct nlmsghdr *nlh,
 			      const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	struct nft_af_info *afi;
 	struct nft_table *table;
 	struct nft_chain *chain;
-	struct net *net = sock_net(skb->sk);
 	int family = nfmsg->nfgen_family;
 	struct nft_ctx ctx;
 
@@ -1506,7 +1503,7 @@
 	if (chain->use > 0)
 		return -EBUSY;
 
-	nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
+	nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
 
 	return nft_delchain(&ctx);
 }
@@ -2010,13 +2007,12 @@
 
 static struct nft_expr_info *info;
 
-static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
-			     const struct nlmsghdr *nlh,
+static int nf_tables_newrule(struct net *net, struct sock *nlsk,
+			     struct sk_buff *skb, const struct nlmsghdr *nlh,
 			     const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	struct nft_af_info *afi;
-	struct net *net = sock_net(skb->sk);
 	struct nft_table *table;
 	struct nft_chain *chain;
 	struct nft_rule *rule, *old_rule = NULL;
@@ -2075,7 +2071,7 @@
 			return PTR_ERR(old_rule);
 	}
 
-	nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
+	nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
 
 	n = 0;
 	size = 0;
@@ -2176,13 +2172,12 @@
 	return err;
 }
 
-static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
-			     const struct nlmsghdr *nlh,
+static int nf_tables_delrule(struct net *net, struct sock *nlsk,
+			     struct sk_buff *skb, const struct nlmsghdr *nlh,
 			     const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	struct nft_af_info *afi;
-	struct net *net = sock_net(skb->sk);
 	struct nft_table *table;
 	struct nft_chain *chain = NULL;
 	struct nft_rule *rule;
@@ -2205,7 +2200,7 @@
 			return PTR_ERR(chain);
 	}
 
-	nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
+	nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
 
 	if (chain) {
 		if (nla[NFTA_RULE_HANDLE]) {
@@ -2344,12 +2339,11 @@
 	[NFTA_SET_DESC_SIZE]		= { .type = NLA_U32 },
 };
 
-static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
+static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
 				     const struct sk_buff *skb,
 				     const struct nlmsghdr *nlh,
 				     const struct nlattr * const nla[])
 {
-	struct net *net = sock_net(skb->sk);
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	struct nft_af_info *afi = NULL;
 	struct nft_table *table = NULL;
@@ -2371,7 +2365,7 @@
 			return -ENOENT;
 	}
 
-	nft_ctx_init(ctx, skb, nlh, afi, table, NULL, nla);
+	nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla);
 	return 0;
 }
 
@@ -2623,6 +2617,7 @@
 			    const struct nlmsghdr *nlh,
 			    const struct nlattr * const nla[])
 {
+	struct net *net = sock_net(skb->sk);
 	const struct nft_set *set;
 	struct nft_ctx ctx;
 	struct sk_buff *skb2;
@@ -2630,7 +2625,7 @@
 	int err;
 
 	/* Verify existence before starting dump */
-	err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla);
+	err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla);
 	if (err < 0)
 		return err;
 
@@ -2693,14 +2688,13 @@
 	return 0;
 }
 
-static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
-			    const struct nlmsghdr *nlh,
+static int nf_tables_newset(struct net *net, struct sock *nlsk,
+			    struct sk_buff *skb, const struct nlmsghdr *nlh,
 			    const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	const struct nft_set_ops *ops;
 	struct nft_af_info *afi;
-	struct net *net = sock_net(skb->sk);
 	struct nft_table *table;
 	struct nft_set *set;
 	struct nft_ctx ctx;
@@ -2798,7 +2792,7 @@
 	if (IS_ERR(table))
 		return PTR_ERR(table);
 
-	nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
+	nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
 
 	set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME]);
 	if (IS_ERR(set)) {
@@ -2882,8 +2876,8 @@
 	nft_set_destroy(set);
 }
 
-static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
-			    const struct nlmsghdr *nlh,
+static int nf_tables_delset(struct net *net, struct sock *nlsk,
+			    struct sk_buff *skb, const struct nlmsghdr *nlh,
 			    const struct nlattr * const nla[])
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -2896,7 +2890,7 @@
 	if (nla[NFTA_SET_TABLE] == NULL)
 		return -EINVAL;
 
-	err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla);
+	err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla);
 	if (err < 0)
 		return err;
 
@@ -3024,7 +3018,7 @@
 	[NFTA_SET_ELEM_LIST_SET_ID]	= { .type = NLA_U32 },
 };
 
-static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx,
+static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
 				      const struct sk_buff *skb,
 				      const struct nlmsghdr *nlh,
 				      const struct nlattr * const nla[],
@@ -3033,7 +3027,6 @@
 	const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
 	struct nft_af_info *afi;
 	struct nft_table *table;
-	struct net *net = sock_net(skb->sk);
 
 	afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
 	if (IS_ERR(afi))
@@ -3045,7 +3038,7 @@
 	if (!trans && (table->flags & NFT_TABLE_INACTIVE))
 		return -ENOENT;
 
-	nft_ctx_init(ctx, skb, nlh, afi, table, NULL, nla);
+	nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla);
 	return 0;
 }
 
@@ -3135,6 +3128,7 @@
 
 static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
 {
+	struct net *net = sock_net(skb->sk);
 	const struct nft_set *set;
 	struct nft_set_dump_args args;
 	struct nft_ctx ctx;
@@ -3150,8 +3144,8 @@
 	if (err < 0)
 		return err;
 
-	err = nft_ctx_init_from_elemattr(&ctx, cb->skb, cb->nlh, (void *)nla,
-					 false);
+	err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh,
+					 (void *)nla, false);
 	if (err < 0)
 		return err;
 
@@ -3212,11 +3206,12 @@
 				const struct nlmsghdr *nlh,
 				const struct nlattr * const nla[])
 {
+	struct net *net = sock_net(skb->sk);
 	const struct nft_set *set;
 	struct nft_ctx ctx;
 	int err;
 
-	err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false);
+	err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, false);
 	if (err < 0)
 		return err;
 
@@ -3528,11 +3523,10 @@
 	return err;
 }
 
-static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
-				const struct nlmsghdr *nlh,
+static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
+				struct sk_buff *skb, const struct nlmsghdr *nlh,
 				const struct nlattr * const nla[])
 {
-	struct net *net = sock_net(skb->sk);
 	const struct nlattr *attr;
 	struct nft_set *set;
 	struct nft_ctx ctx;
@@ -3541,7 +3535,7 @@
 	if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
 		return -EINVAL;
 
-	err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, true);
+	err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, true);
 	if (err < 0)
 		return err;
 
@@ -3623,8 +3617,8 @@
 	return err;
 }
 
-static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
-				const struct nlmsghdr *nlh,
+static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
+				struct sk_buff *skb, const struct nlmsghdr *nlh,
 				const struct nlattr * const nla[])
 {
 	const struct nlattr *attr;
@@ -3635,7 +3629,7 @@
 	if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
 		return -EINVAL;
 
-	err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false);
+	err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, false);
 	if (err < 0)
 		return err;
 
@@ -4030,7 +4024,8 @@
 	struct nft_trans *trans, *next;
 	struct nft_trans_elem *te;
 
-	list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
+	list_for_each_entry_safe_reverse(trans, next, &net->nft.commit_list,
+					 list) {
 		switch (trans->msg_type) {
 		case NFT_MSG_NEWTABLE:
 			if (nft_trans_table_update(trans)) {
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 46453ab..77afe91 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -295,8 +295,6 @@
 	if (!skb)
 		return netlink_ack(oskb, nlh, -ENOMEM);
 
-	skb->sk = oskb->sk;
-
 	nfnl_lock(subsys_id);
 	ss = rcu_dereference_protected(table[subsys_id].subsys,
 				       lockdep_is_held(&table[subsys_id].mutex));
@@ -381,7 +379,7 @@
 				goto ack;
 
 			if (nc->call_batch) {
-				err = nc->call_batch(net->nfnl, skb, nlh,
+				err = nc->call_batch(net, net->nfnl, skb, nlh,
 						     (const struct nlattr **)cda);
 			}
 
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 7d81d28..861c661 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -365,8 +365,9 @@
 		break;
 	}
 
+	nfnl_ct = rcu_dereference(nfnl_ct_hook);
+
 	if (queue->flags & NFQA_CFG_F_CONNTRACK) {
-		nfnl_ct = rcu_dereference(nfnl_ct_hook);
 		if (nfnl_ct != NULL) {
 			ct = nfnl_ct->get_ct(entskb, &ctinfo);
 			if (ct != NULL)
@@ -1064,9 +1065,10 @@
 	if (entry == NULL)
 		return -ENOENT;
 
+	/* rcu lock already held from nfnl->call_rcu. */
+	nfnl_ct = rcu_dereference(nfnl_ct_hook);
+
 	if (nfqa[NFQA_CT]) {
-		/* rcu lock already held from nfnl->call_rcu. */
-		nfnl_ct = rcu_dereference(nfnl_ct_hook);
 		if (nfnl_ct != NULL)
 			ct = nfqnl_ct_parse(nfnl_ct, nlh, nfqa, entry, &ctinfo);
 	}
@@ -1417,6 +1419,7 @@
 
 cleanup_netlink_notifier:
 	netlink_unregister_notifier(&nfqnl_rtnl_notifier);
+	unregister_pernet_subsys(&nfnl_queue_net_ops);
 out:
 	return status;
 }
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index c2cc111..3e88922 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -53,6 +53,8 @@
 	struct md_labels labels;
 };
 
+static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info);
+
 static u16 key_to_nfproto(const struct sw_flow_key *key)
 {
 	switch (ntohs(key->eth.type)) {
@@ -141,6 +143,7 @@
  * previously sent the packet to conntrack via the ct action.
  */
 static void ovs_ct_update_key(const struct sk_buff *skb,
+			      const struct ovs_conntrack_info *info,
 			      struct sw_flow_key *key, bool post_ct)
 {
 	const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
@@ -158,13 +161,15 @@
 		zone = nf_ct_zone(ct);
 	} else if (post_ct) {
 		state = OVS_CS_F_TRACKED | OVS_CS_F_INVALID;
+		if (info)
+			zone = &info->zone;
 	}
 	__ovs_ct_update_key(key, state, zone, ct);
 }
 
 void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
 {
-	ovs_ct_update_key(skb, key, false);
+	ovs_ct_update_key(skb, NULL, key, false);
 }
 
 int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
@@ -418,7 +423,7 @@
 		}
 	}
 
-	ovs_ct_update_key(skb, key, true);
+	ovs_ct_update_key(skb, info, key, true);
 
 	return 0;
 }
@@ -708,7 +713,7 @@
 	nf_conntrack_get(&ct_info.ct->ct_general);
 	return 0;
 err_free_ct:
-	nf_conntrack_free(ct_info.ct);
+	__ovs_ct_free_action(&ct_info);
 	return err;
 }
 
@@ -750,6 +755,11 @@
 {
 	struct ovs_conntrack_info *ct_info = nla_data(a);
 
+	__ovs_ct_free_action(ct_info);
+}
+
+static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
+{
 	if (ct_info->helper)
 		module_put(ct_info->helper->me);
 	if (ct_info->ct)
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index b41e9ea..f53bf3b6 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -49,7 +49,6 @@
 struct rfkill {
 	spinlock_t		lock;
 
-	const char		*name;
 	enum rfkill_type	type;
 
 	unsigned long		state;
@@ -73,6 +72,7 @@
 	struct delayed_work	poll_work;
 	struct work_struct	uevent_work;
 	struct work_struct	sync_work;
+	char			name[];
 };
 #define to_rfkill(d)	container_of(d, struct rfkill, dev)
 
@@ -876,14 +876,14 @@
 	if (WARN_ON(type == RFKILL_TYPE_ALL || type >= NUM_RFKILL_TYPES))
 		return NULL;
 
-	rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL);
+	rfkill = kzalloc(sizeof(*rfkill) + strlen(name) + 1, GFP_KERNEL);
 	if (!rfkill)
 		return NULL;
 
 	spin_lock_init(&rfkill->lock);
 	INIT_LIST_HEAD(&rfkill->node);
 	rfkill->type = type;
-	rfkill->name = name;
+	strcpy(rfkill->name, name);
 	rfkill->ops = ops;
 	rfkill->data = ops_data;
 
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 7ec667d..b5c2cf2 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -950,7 +950,7 @@
 		}
 		lockdep_set_class(qdisc_lock(sch), &qdisc_tx_lock);
 		if (!netif_is_multiqueue(dev))
-			sch->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT;
+			sch->flags |= TCQ_F_ONETXQUEUE;
 	}
 
 	sch->handle = handle;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index acb45b8..ec52912 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -323,14 +323,13 @@
 			}
 		}
 	}
-	rcu_read_unlock();
-
 	if (baddr) {
 		fl6->saddr = baddr->v6.sin6_addr;
 		fl6->fl6_sport = baddr->v6.sin6_port;
 		final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
 		dst = ip6_dst_lookup_flow(sk, fl6, final_p);
 	}
+	rcu_read_unlock();
 
 out:
 	if (!IS_ERR_OR_NULL(dst)) {
@@ -642,6 +641,7 @@
 	struct sock *newsk;
 	struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
 	struct sctp6_sock *newsctp6sk;
+	struct ipv6_txoptions *opt;
 
 	newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, 0);
 	if (!newsk)
@@ -661,6 +661,13 @@
 
 	memcpy(newnp, np, sizeof(struct ipv6_pinfo));
 
+	rcu_read_lock();
+	opt = rcu_dereference(np->opt);
+	if (opt)
+		opt = ipv6_dup_options(newsk, opt);
+	RCU_INIT_POINTER(newnp->opt, opt);
+	rcu_read_unlock();
+
 	/* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
 	 * and getpeername().
 	 */
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 7e8f0a1..c0380cf 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -324,6 +324,7 @@
 				 sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) :
 				 "illegal chunk");
 
+			sctp_chunk_hold(chunk);
 			sctp_outq_tail_data(q, chunk);
 			if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
 				SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);
@@ -1251,6 +1252,7 @@
 	 */
 
 	sack_a_rwnd = ntohl(sack->a_rwnd);
+	asoc->peer.zero_window_announced = !sack_a_rwnd;
 	outstanding = q->outstanding_bytes;
 
 	if (outstanding < sack_a_rwnd)
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 763e06a..5d6a03f 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1652,7 +1652,7 @@
 
 	/* Set an expiration time for the cookie.  */
 	cookie->c.expiration = ktime_add(asoc->cookie_life,
-					 ktime_get());
+					 ktime_get_real());
 
 	/* Copy the peer's init packet.  */
 	memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr,
@@ -1780,7 +1780,7 @@
 	if (sock_flag(ep->base.sk, SOCK_TIMESTAMP))
 		kt = skb_get_ktime(skb);
 	else
-		kt = ktime_get();
+		kt = ktime_get_real();
 
 	if (!asoc && ktime_before(bear_cookie->expiration, kt)) {
 		/*
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 6f46aa1..cd34a4a 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -5412,7 +5412,8 @@
 	SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS);
 
 	if (asoc->overall_error_count >= asoc->max_retrans) {
-		if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) {
+		if (asoc->peer.zero_window_announced &&
+		    asoc->state == SCTP_STATE_SHUTDOWN_PENDING) {
 			/*
 			 * We are here likely because the receiver had its rwnd
 			 * closed for a while and we have not been able to
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 03c82560..9b6cc6d 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1952,8 +1952,6 @@
 
 	/* Now send the (possibly) fragmented message. */
 	list_for_each_entry(chunk, &datamsg->chunks, frag_list) {
-		sctp_chunk_hold(chunk);
-
 		/* Do accounting for the write space.  */
 		sctp_set_owner_w(chunk);
 
@@ -1966,15 +1964,13 @@
 	 * breaks.
 	 */
 	err = sctp_primitive_SEND(net, asoc, datamsg);
+	sctp_datamsg_put(datamsg);
 	/* Did the lower layer accept the chunk? */
-	if (err) {
-		sctp_datamsg_free(datamsg);
+	if (err)
 		goto out_free;
-	}
 
 	pr_debug("%s: we sent primitively\n", __func__);
 
-	sctp_datamsg_put(datamsg);
 	err = msg_len;
 
 	if (unlikely(wait_connect)) {
@@ -7167,6 +7163,7 @@
 	newsk->sk_type = sk->sk_type;
 	newsk->sk_bound_dev_if = sk->sk_bound_dev_if;
 	newsk->sk_flags = sk->sk_flags;
+	newsk->sk_tsflags = sk->sk_tsflags;
 	newsk->sk_no_check_tx = sk->sk_no_check_tx;
 	newsk->sk_no_check_rx = sk->sk_no_check_rx;
 	newsk->sk_reuse = sk->sk_reuse;
@@ -7199,6 +7196,9 @@
 	newinet->mc_ttl = 1;
 	newinet->mc_index = 0;
 	newinet->mc_list = NULL;
+
+	if (newsk->sk_flags & SK_FLAGS_TIMESTAMP)
+		net_enable_timestamp();
 }
 
 static inline void sctp_copy_descendant(struct sock *sk_to,
diff --git a/net/socket.c b/net/socket.c
index 456fadb..29822d6 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1695,6 +1695,7 @@
 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
 	/* We assume all kernel code knows the size of sockaddr_storage */
 	msg.msg_namelen = 0;
+	msg.msg_iocb = NULL;
 	if (sock->file->f_flags & O_NONBLOCK)
 		flags |= MSG_DONTWAIT;
 	err = sock_recvmsg(sock, &msg, iov_iter_count(&msg.msg_iter), flags);
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index 95f82d8..229956b 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -353,20 +353,12 @@
 {
 	struct rpc_xprt *xprt = req->rq_xprt;
 	struct svc_serv *bc_serv = xprt->bc_serv;
-	struct xdr_buf *rq_rcv_buf = &req->rq_rcv_buf;
 
 	spin_lock(&xprt->bc_pa_lock);
 	list_del(&req->rq_bc_pa_list);
 	xprt_dec_alloc_count(xprt, 1);
 	spin_unlock(&xprt->bc_pa_lock);
 
-	if (copied <= rq_rcv_buf->head[0].iov_len) {
-		rq_rcv_buf->head[0].iov_len = copied;
-		rq_rcv_buf->page_len = 0;
-	} else {
-		rq_rcv_buf->page_len = copied - rq_rcv_buf->head[0].iov_len;
-	}
-
 	req->rq_private_buf.len = copied;
 	set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
 
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index f14f24e..73ad57a 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -250,11 +250,11 @@
 }
 EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
 
-static int rpc_wait_bit_killable(struct wait_bit_key *key)
+static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode)
 {
-	if (fatal_signal_pending(current))
-		return -ERESTARTSYS;
 	freezable_schedule_unsafe();
+	if (signal_pending_state(mode, current))
+		return -ERESTARTSYS;
 	return 0;
 }
 
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 7fccf96..cc98528 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1363,7 +1363,19 @@
 	memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
 	memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg));
 	memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res));
+
+	/* Adjust the argument buffer length */
 	rqstp->rq_arg.len = req->rq_private_buf.len;
+	if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) {
+		rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len;
+		rqstp->rq_arg.page_len = 0;
+	} else if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len +
+			rqstp->rq_arg.page_len)
+		rqstp->rq_arg.page_len = rqstp->rq_arg.len -
+			rqstp->rq_arg.head[0].iov_len;
+	else
+		rqstp->rq_arg.len = rqstp->rq_arg.head[0].iov_len +
+			rqstp->rq_arg.page_len;
 
 	/* reset result send buffer "put" position */
 	resv->iov_len = 0;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 45aebd9..a4631477 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2256,14 +2256,7 @@
 	/* Lock the socket to prevent queue disordering
 	 * while sleeps in memcpy_tomsg
 	 */
-	err = mutex_lock_interruptible(&u->readlock);
-	if (unlikely(err)) {
-		/* recvmsg() in non blocking mode is supposed to return -EAGAIN
-		 * sk_rcvtimeo is not honored by mutex_lock_interruptible()
-		 */
-		err = noblock ? -EAGAIN : -ERESTARTSYS;
-		goto out;
-	}
+	mutex_lock(&u->readlock);
 
 	if (flags & MSG_PEEK)
 		skip = sk_peek_offset(sk, flags);
@@ -2307,12 +2300,12 @@
 			timeo = unix_stream_data_wait(sk, timeo, last,
 						      last_len);
 
-			if (signal_pending(current) ||
-			    mutex_lock_interruptible(&u->readlock)) {
+			if (signal_pending(current)) {
 				err = sock_intr_errno(timeo);
 				goto out;
 			}
 
+			mutex_lock(&u->readlock);
 			continue;
 unlock:
 			unix_state_unlock(sk);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c71e274..75b0d23 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7941,8 +7941,10 @@
 	if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
 		if (!(rdev->wiphy.features &
 		      NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) ||
-		    !(rdev->wiphy.features & NL80211_FEATURE_QUIET))
+		    !(rdev->wiphy.features & NL80211_FEATURE_QUIET)) {
+			kzfree(connkeys);
 			return -EINVAL;
+		}
 		connect.flags |= ASSOC_REQ_USE_RRM;
 	}
 
@@ -9503,6 +9505,7 @@
 	if (new_triggers.tcp && new_triggers.tcp->sock)
 		sock_release(new_triggers.tcp->sock);
 	kfree(new_triggers.tcp);
+	kfree(new_triggers.nd_config);
 	return err;
 }
 #endif
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2e8d6f3..06d050d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -3029,6 +3029,7 @@
 		break;
 	default:
 		WARN(1, "invalid initiator %d\n", lr->initiator);
+		kfree(rd);
 		return -EINVAL;
 	}
 
@@ -3221,8 +3222,10 @@
 	/* We always try to get an update for the static regdomain */
 	err = regulatory_hint_core(cfg80211_world_regdom->alpha2);
 	if (err) {
-		if (err == -ENOMEM)
+		if (err == -ENOMEM) {
+			platform_device_unregister(reg_pdev);
 			return err;
+		}
 		/*
 		 * N.B. kobject_uevent_env() can fail mainly for when we're out
 		 * memory which is handled and propagated appropriately above
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 09bfcba..948fa55 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -303,6 +303,14 @@
 }
 EXPORT_SYMBOL(xfrm_policy_alloc);
 
+static void xfrm_policy_destroy_rcu(struct rcu_head *head)
+{
+	struct xfrm_policy *policy = container_of(head, struct xfrm_policy, rcu);
+
+	security_xfrm_policy_free(policy->security);
+	kfree(policy);
+}
+
 /* Destroy xfrm_policy: descendant resources must be released to this moment. */
 
 void xfrm_policy_destroy(struct xfrm_policy *policy)
@@ -312,8 +320,7 @@
 	if (del_timer(&policy->timer) || del_timer(&policy->polq.hold_timer))
 		BUG();
 
-	security_xfrm_policy_free(policy->security);
-	kfree(policy);
+	call_rcu(&policy->rcu, xfrm_policy_destroy_rcu);
 }
 EXPORT_SYMBOL(xfrm_policy_destroy);
 
@@ -1214,8 +1221,10 @@
 	struct xfrm_policy *pol;
 	struct net *net = sock_net(sk);
 
+	rcu_read_lock();
 	read_lock_bh(&net->xfrm.xfrm_policy_lock);
-	if ((pol = sk->sk_policy[dir]) != NULL) {
+	pol = rcu_dereference(sk->sk_policy[dir]);
+	if (pol != NULL) {
 		bool match = xfrm_selector_match(&pol->selector, fl,
 						 sk->sk_family);
 		int err = 0;
@@ -1239,6 +1248,7 @@
 	}
 out:
 	read_unlock_bh(&net->xfrm.xfrm_policy_lock);
+	rcu_read_unlock();
 	return pol;
 }
 
@@ -1307,13 +1317,14 @@
 #endif
 
 	write_lock_bh(&net->xfrm.xfrm_policy_lock);
-	old_pol = sk->sk_policy[dir];
-	sk->sk_policy[dir] = pol;
+	old_pol = rcu_dereference_protected(sk->sk_policy[dir],
+				lockdep_is_held(&net->xfrm.xfrm_policy_lock));
 	if (pol) {
 		pol->curlft.add_time = get_seconds();
 		pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir, 0);
 		xfrm_sk_policy_link(pol, dir);
 	}
+	rcu_assign_pointer(sk->sk_policy[dir], pol);
 	if (old_pol) {
 		if (pol)
 			xfrm_policy_requeue(old_pol, pol);
@@ -1361,17 +1372,26 @@
 	return newp;
 }
 
-int __xfrm_sk_clone_policy(struct sock *sk)
+int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk)
 {
-	struct xfrm_policy *p0 = sk->sk_policy[0],
-			   *p1 = sk->sk_policy[1];
+	const struct xfrm_policy *p;
+	struct xfrm_policy *np;
+	int i, ret = 0;
 
-	sk->sk_policy[0] = sk->sk_policy[1] = NULL;
-	if (p0 && (sk->sk_policy[0] = clone_policy(p0, 0)) == NULL)
-		return -ENOMEM;
-	if (p1 && (sk->sk_policy[1] = clone_policy(p1, 1)) == NULL)
-		return -ENOMEM;
-	return 0;
+	rcu_read_lock();
+	for (i = 0; i < 2; i++) {
+		p = rcu_dereference(osk->sk_policy[i]);
+		if (p) {
+			np = clone_policy(p, i);
+			if (unlikely(!np)) {
+				ret = -ENOMEM;
+				break;
+			}
+			rcu_assign_pointer(sk->sk_policy[i], np);
+		}
+	}
+	rcu_read_unlock();
+	return ret;
 }
 
 static int
@@ -2198,6 +2218,7 @@
 	xdst = NULL;
 	route = NULL;
 
+	sk = sk_const_to_full_sk(sk);
 	if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
 		num_pols = 1;
 		pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
@@ -2477,6 +2498,7 @@
 	}
 
 	pol = NULL;
+	sk = sk_to_full_sk(sk);
 	if (sk && sk->sk_policy[dir]) {
 		pol = xfrm_sk_policy_lookup(sk, dir, &fl);
 		if (IS_ERR(pol)) {
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 1a10d8a..dacf71a 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -62,7 +62,7 @@
 			-Wl,--start-group                                    \
 				 ${KBUILD_VMLINUX_MAIN}                      \
 			-Wl,--end-group                                      \
-			-lutil ${1}
+			-lutil -lrt ${1}
 		rm -f linux
 	fi
 }
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 963f824..bff5c8b 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -355,6 +355,8 @@
 					((pci)->device == 0x0d0c) || \
 					((pci)->device == 0x160c))
 
+#define IS_BROXTON(pci)	((pci)->device == 0x5a98)
+
 static char *driver_short_names[] = {
 	[AZX_DRIVER_ICH] = "HDA Intel",
 	[AZX_DRIVER_PCH] = "HDA Intel PCH",
@@ -506,15 +508,36 @@
         }
 }
 
+/*
+ * In BXT-P A0, HD-Audio DMA requests is later than expected,
+ * and makes an audio stream sensitive to system latencies when
+ * 24/32 bits are playing.
+ * Adjusting threshold of DMA fifo to force the DMA request
+ * sooner to improve latency tolerance at the expense of power.
+ */
+static void bxt_reduce_dma_latency(struct azx *chip)
+{
+	u32 val;
+
+	val = azx_readl(chip, SKL_EM4L);
+	val &= (0x3 << 20);
+	azx_writel(chip, SKL_EM4L, val);
+}
+
 static void hda_intel_init_chip(struct azx *chip, bool full_reset)
 {
 	struct hdac_bus *bus = azx_bus(chip);
+	struct pci_dev *pci = chip->pci;
 
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
 		snd_hdac_set_codec_wakeup(bus, true);
 	azx_init_chip(chip, full_reset);
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
 		snd_hdac_set_codec_wakeup(bus, false);
+
+	/* reduce dma latency to avoid noise */
+	if (IS_BROXTON(pci))
+		bxt_reduce_dma_latency(chip);
 }
 
 /* calculate runtime delay from LPIB */
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index f8a12ca4..4ef2259 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -778,7 +778,8 @@
 };
 
 static const struct snd_pci_quirk ca0132_quirks[] = {
-	SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", QUIRK_ALIENWARE),
+	SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
+	SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
 	{}
 };
 
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 9bedf7c..6c268da 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -111,6 +111,7 @@
 	void (*power_hook)(struct hda_codec *codec);
 #endif
 	void (*shutup)(struct hda_codec *codec);
+	void (*reboot_notify)(struct hda_codec *codec);
 
 	int init_amp;
 	int codec_variant;	/* flag for other variants */
@@ -773,6 +774,25 @@
 		snd_hda_shutup_pins(codec);
 }
 
+static void alc_reboot_notify(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	if (spec && spec->reboot_notify)
+		spec->reboot_notify(codec);
+	else
+		alc_shutup(codec);
+}
+
+/* power down codec to D3 at reboot/shutdown; set as reboot_notify ops */
+static void alc_d3_at_reboot(struct hda_codec *codec)
+{
+	snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
+	snd_hda_codec_write(codec, codec->core.afg, 0,
+			    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+	msleep(10);
+}
+
 #define alc_free	snd_hda_gen_free
 
 #ifdef CONFIG_PM
@@ -818,7 +838,7 @@
 	.suspend = alc_suspend,
 	.check_power_status = snd_hda_gen_check_power_status,
 #endif
-	.reboot_notify = alc_shutup,
+	.reboot_notify = alc_reboot_notify,
 };
 
 
@@ -4198,6 +4218,8 @@
 	struct alc_spec *spec = codec->spec;
 
 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		spec->shutup = alc_no_shutup; /* reduce click noise */
+		spec->reboot_notify = alc_d3_at_reboot; /* reduce noise */
 		spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
 		codec->power_save_node = 0; /* avoid click noises */
 		snd_hda_apply_pincfgs(codec, pincfgs);
@@ -4578,6 +4600,7 @@
 	ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
 	ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
 	ALC292_FIXUP_TPT440_DOCK,
+	ALC292_FIXUP_TPT440,
 	ALC283_FIXUP_BXBT2807_MIC,
 	ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
 	ALC282_FIXUP_ASPIRE_V5_PINS,
@@ -4593,9 +4616,11 @@
 	ALC288_FIXUP_DISABLE_AAMIX,
 	ALC292_FIXUP_DELL_E7X,
 	ALC292_FIXUP_DISABLE_AAMIX,
+	ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK,
 	ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
 	ALC275_FIXUP_DELL_XPS,
 	ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
+	ALC293_FIXUP_LENOVO_SPK_NOISE,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -5050,6 +5075,12 @@
 		.chained = true,
 		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
 	},
+	[ALC292_FIXUP_TPT440] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc_fixup_disable_aamix,
+		.chained = true,
+		.chain_id = ALC292_FIXUP_TPT440_DOCK,
+	},
 	[ALC283_FIXUP_BXBT2807_MIC] = {
 		.type = HDA_FIXUP_PINS,
 		.v.pins = (const struct hda_pintbl[]) {
@@ -5149,6 +5180,12 @@
 		.chained = true,
 		.chain_id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE
 	},
+	[ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc_fixup_disable_aamix,
+		.chained = true,
+		.chain_id = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE
+	},
 	[ALC292_FIXUP_DELL_E7X] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc_fixup_dell_xps13,
@@ -5187,6 +5224,12 @@
 		.chained = true,
 		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
 	},
+	[ALC293_FIXUP_LENOVO_SPK_NOISE] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc_fixup_disable_aamix,
+		.chained = true,
+		.chain_id = ALC269_FIXUP_THINKPAD_ACPI
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5221,11 +5264,11 @@
 	SND_PCI_QUIRK(0x1028, 0x06c7, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x06da, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
-	SND_PCI_QUIRK(0x1028, 0x06db, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
-	SND_PCI_QUIRK(0x1028, 0x06dd, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
-	SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
-	SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
-	SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
+	SND_PCI_QUIRK(0x1028, 0x06db, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
+	SND_PCI_QUIRK(0x1028, 0x06dd, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
+	SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
+	SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
+	SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
 	SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
 	SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -5325,15 +5368,17 @@
 	SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
-	SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440_DOCK),
+	SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440),
 	SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2211, "Thinkpad W541", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+	SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
+	SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
 	SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
 	SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
 	SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -5343,6 +5388,7 @@
 	SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
+	SND_PCI_QUIRK(0x17aa, 0x504b, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
 	SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
 	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
@@ -5423,6 +5469,7 @@
 	{.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"},
 	{.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
 	{.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"},
+	{.id = ALC292_FIXUP_TPT440, .name = "tpt440"},
 	{}
 };
 
@@ -6409,6 +6456,7 @@
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
 	SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
+	SND_PCI_QUIRK(0x1025, 0x0241, "Packard Bell DOTS", ALC662_FIXUP_INV_DMIC),
 	SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
 	SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 714df90..41c31db 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -741,10 +741,11 @@
 	{
 		/* change to/from double-speed: reset the DAC (if available) */
 		snd_rme96_reset_dac(rme96);
+		return 1; /* need to restore volume */
 	} else {
 		writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
+		return 0;
 	}
-	return 0;
 }
 
 static int
@@ -980,6 +981,7 @@
 	struct rme96 *rme96 = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int err, rate, dummy;
+	bool apply_dac_volume = false;
 
 	runtime->dma_area = (void __force *)(rme96->iobase +
 					     RME96_IO_PLAY_BUFFER);
@@ -993,24 +995,26 @@
 	{
                 /* slave clock */
                 if ((int)params_rate(params) != rate) {
-			spin_unlock_irq(&rme96->lock);
-			return -EIO;                    
-                }
-	} else if ((err = snd_rme96_playback_setrate(rme96, params_rate(params))) < 0) {
-		spin_unlock_irq(&rme96->lock);
-		return err;
+			err = -EIO;
+			goto error;
+		}
+	} else {
+		err = snd_rme96_playback_setrate(rme96, params_rate(params));
+		if (err < 0)
+			goto error;
+		apply_dac_volume = err > 0; /* need to restore volume later? */
 	}
-	if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) < 0) {
-		spin_unlock_irq(&rme96->lock);
-		return err;
-	}
+
+	err = snd_rme96_playback_setformat(rme96, params_format(params));
+	if (err < 0)
+		goto error;
 	snd_rme96_setframelog(rme96, params_channels(params), 1);
 	if (rme96->capture_periodsize != 0) {
 		if (params_period_size(params) << rme96->playback_frlog !=
 		    rme96->capture_periodsize)
 		{
-			spin_unlock_irq(&rme96->lock);
-			return -EBUSY;
+			err = -EBUSY;
+			goto error;
 		}
 	}
 	rme96->playback_periodsize =
@@ -1021,9 +1025,16 @@
 		rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);
 		writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	}
+
+	err = 0;
+ error:
 	spin_unlock_irq(&rme96->lock);
-		
-	return 0;
+	if (apply_dac_volume) {
+		usleep_range(3000, 10000);
+		snd_rme96_apply_dac_volume(rme96);
+	}
+
+	return err;
 }
 
 static int
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index f494dce..4f85757 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1354,6 +1354,8 @@
 		}
 	}
 
+	snd_usb_mixer_fu_apply_quirk(state->mixer, cval, unitid, kctl);
+
 	range = (cval->max - cval->min) / cval->res;
 	/*
 	 * Are there devices with volume range more than 255? I use a bit more
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index 6a803ef..ddca654 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -348,13 +348,6 @@
 	{ 0 }	/* terminator */
 };
 
-/* Dragonfly DAC 1.2, the dB conversion factor is 1 instead of 256 */
-static struct usbmix_dB_map dragonfly_1_2_dB = {0, 5000};
-static struct usbmix_name_map dragonfly_1_2_map[] = {
-	{ 7, NULL, .dB = &dragonfly_1_2_dB },
-	{ 0 }	/* terminator */
-};
-
 /*
  * Control map entries
  */
@@ -470,11 +463,6 @@
 		.id = USB_ID(0x05a7, 0x1020),
 		.map = bose_companion5_map,
 	},
-	{
-		/* Dragonfly DAC 1.2 */
-		.id = USB_ID(0x21b4, 0x0081),
-		.map = dragonfly_1_2_map,
-	},
 	{ 0 } /* terminator */
 };
 
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index fe91184..0ce888d 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -37,6 +37,7 @@
 #include <sound/control.h>
 #include <sound/hwdep.h>
 #include <sound/info.h>
+#include <sound/tlv.h>
 
 #include "usbaudio.h"
 #include "mixer.h"
@@ -1825,3 +1826,39 @@
 	}
 }
 
+static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer,
+					 struct snd_kcontrol *kctl)
+{
+	/* Approximation using 10 ranges based on output measurement on hw v1.2.
+	 * This seems close to the cubic mapping e.g. alsamixer uses. */
+	static const DECLARE_TLV_DB_RANGE(scale,
+		 0,  1, TLV_DB_MINMAX_ITEM(-5300, -4970),
+		 2,  5, TLV_DB_MINMAX_ITEM(-4710, -4160),
+		 6,  7, TLV_DB_MINMAX_ITEM(-3884, -3710),
+		 8, 14, TLV_DB_MINMAX_ITEM(-3443, -2560),
+		15, 16, TLV_DB_MINMAX_ITEM(-2475, -2324),
+		17, 19, TLV_DB_MINMAX_ITEM(-2228, -2031),
+		20, 26, TLV_DB_MINMAX_ITEM(-1910, -1393),
+		27, 31, TLV_DB_MINMAX_ITEM(-1322, -1032),
+		32, 40, TLV_DB_MINMAX_ITEM(-968, -490),
+		41, 50, TLV_DB_MINMAX_ITEM(-441, 0),
+	);
+
+	usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk\n");
+	kctl->tlv.p = scale;
+	kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+	kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+}
+
+void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
+				  struct usb_mixer_elem_info *cval, int unitid,
+				  struct snd_kcontrol *kctl)
+{
+	switch (mixer->chip->usb_id) {
+	case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
+		if (unitid == 7 && cval->min == 0 && cval->max == 50)
+			snd_dragonfly_quirk_db_scale(mixer, kctl);
+		break;
+	}
+}
+
diff --git a/sound/usb/mixer_quirks.h b/sound/usb/mixer_quirks.h
index bdbfab0..177c329 100644
--- a/sound/usb/mixer_quirks.h
+++ b/sound/usb/mixer_quirks.h
@@ -9,5 +9,9 @@
 void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
 				    int unitid);
 
+void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
+				  struct usb_mixer_elem_info *cval, int unitid,
+				  struct snd_kcontrol *kctl);
+
 #endif /* SND_USB_MIXER_QUIRKS_H */
 
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 7016ad8..b6c0c8e 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1125,6 +1125,7 @@
 	case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
 	case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
 	case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
+	case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */
 		return true;
 	}
 	return false;
diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h
index 0a3da64..4db7d56 100644
--- a/tools/virtio/linux/kernel.h
+++ b/tools/virtio/linux/kernel.h
@@ -110,4 +110,10 @@
 	(void) (&_min1 == &_min2);		\
 	_min1 < _min2 ? _min1 : _min2; })
 
+/* TODO: empty stubs for now. Broken but enough for virtio_ring.c */
+#define list_add_tail(a, b) do {} while (0)
+#define list_del(a) do {} while (0)
+#define list_for_each_entry(a, b, c) while (0)
+/* end of stubs */
+
 #endif /* KERNEL_H */
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
index a3e0701..ee125e7 100644
--- a/tools/virtio/linux/virtio.h
+++ b/tools/virtio/linux/virtio.h
@@ -3,12 +3,6 @@
 #include <linux/scatterlist.h>
 #include <linux/kernel.h>
 
-/* TODO: empty stubs for now. Broken but enough for virtio_ring.c */
-#define list_add_tail(a, b) do {} while (0)
-#define list_del(a) do {} while (0)
-#define list_for_each_entry(a, b, c) while (0)
-/* end of stubs */
-
 struct virtio_device {
 	void *dev;
 	u64 features;
diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h
index 806d683..57a6964 100644
--- a/tools/virtio/linux/virtio_config.h
+++ b/tools/virtio/linux/virtio_config.h
@@ -40,33 +40,39 @@
 #define virtio_has_feature(dev, feature) \
 	(__virtio_test_bit((dev), feature))
 
+static inline bool virtio_is_little_endian(struct virtio_device *vdev)
+{
+	return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
+		virtio_legacy_is_little_endian();
+}
+
+/* Memory accessors */
 static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val)
 {
-	return __virtio16_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+	return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
 }
 
 static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val)
 {
-	return __cpu_to_virtio16(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+	return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
 }
 
 static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val)
 {
-	return __virtio32_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+	return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
 }
 
 static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val)
 {
-	return __cpu_to_virtio32(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+	return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
 }
 
 static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val)
 {
-	return __virtio64_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+	return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
 }
 
 static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
 {
-	return __cpu_to_virtio64(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+	return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
 }
-
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 65461f8..7a2f449 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1114,7 +1114,7 @@
 			return true;
 	}
 
-	return dist_active_irq(vcpu);
+	return vgic_irq_is_active(vcpu, map->virt_irq);
 }
 
 /*