]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'drm-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 May 2011 19:06:40 +0000 (12:06 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 May 2011 19:06:40 +0000 (12:06 -0700)
* 'drm-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (169 commits)
  drivers/gpu/drm/radeon/atom.c: fix warning
  drm/radeon/kms: bump kms version number
  drm/radeon/kms: properly set num banks for fusion asics
  drm/radeon/kms/atom: move dig phy init out of modesetting
  drm/radeon/kms/cayman: fix typo in register mask
  drm/radeon/kms: fix typo in spread spectrum code
  drm/radeon/kms: fix tile_config value reported to userspace on cayman.
  drm/radeon/kms: fix incorrect comparison in cayman setup code.
  drm/radeon/kms: add wait idle ioctl for eg->cayman
  drm/radeon/cayman: setup hdp to invalidate and flush when asked
  drm/radeon/evergreen/btc/fusion: setup hdp to invalidate and flush when asked
  agp/uninorth: Fix lockups with radeon KMS and >1x.
  drm/radeon/kms: the SS_Id field in the LCD table if for LVDS only
  drm/radeon/kms: properly set the CLK_REF bit for DCE3 devices
  drm/radeon/kms: fixup eDP connector handling
  drm/radeon/kms: bail early for eDP in hotplug callback
  drm/radeon/kms: simplify hotplug handler logic
  drm/radeon/kms: rewrite DP handling
  drm/radeon/kms/atom: add support for setting DP panel mode
  drm/radeon/kms: atombios.h updates for DP panel mode
  ...

1  2 
MAINTAINERS
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/vga/vga_switcheroo.c
drivers/pci/pci.c
drivers/platform/x86/Kconfig
include/linux/pci.h

diff --combined MAINTAINERS
index 0b415248ae252b0706f16e3e5cb85e721e0b14d0,ae65b29ad936a718b48e07fbc7e50277ed05a537..b64825ddaf322eed758b0fafc1a8d9b5ffecef10
@@@ -405,8 -405,8 +405,8 @@@ S: Maintaine
  F:    sound/oss/aedsp16.c
  
  AFFS FILE SYSTEM
 -M:    Roman Zippel <zippel@linux-m68k.org>
 -S:    Maintained
 +L:    linux-fsdevel@vger.kernel.org
 +S:    Orphan
  F:    Documentation/filesystems/affs.txt
  F:    fs/affs/
  
@@@ -548,11 -548,10 +548,11 @@@ S:      Maintaine
  F:    sound/aoa/
  
  APM DRIVER
 -L:    linux-laptop@vger.kernel.org
 -S:    Orphan
 +M:    Jiri Kosina <jkosina@suse.cz>
 +S:    Odd fixes
  F:    arch/x86/kernel/apm_32.c
  F:    include/linux/apm_bios.h
 +F:    drivers/char/apm-emulation.c
  
  APPLE BCM5974 MULTITOUCH DRIVER
  M:    Henrik Rydberg <rydberg@euromail.se>
@@@ -730,7 -729,7 +730,7 @@@ ARM/EZX SMARTPHONES (A780, A910, A1200
  M:    Daniel Ribeiro <drwyrm@gmail.com>
  M:    Stefan Schmidt <stefan@openezx.org>
  M:    Harald Welte <laforge@openezx.org>
 -L:    openezx-devel@lists.openezx.org (subscribers-only)
 +L:    openezx-devel@lists.openezx.org (moderated for non-subscribers)
  W:    http://www.openezx.org/
  S:    Maintained
  T:    topgit git://git.openezx.org/openezx.git
@@@ -1233,6 -1232,13 +1233,6 @@@ W:     http://wireless.kernel.org/en/users/
  S:    Supported
  F:    drivers/net/wireless/ath/ath9k/
  
 -ATHEROS AR9170 WIRELESS DRIVER
 -M:    Christian Lamparter <chunkeey@web.de>
 -L:    linux-wireless@vger.kernel.org
 -W:    http://wireless.kernel.org/en/users/Drivers/ar9170
 -S:    Obsolete
 -F:    drivers/net/wireless/ath/ar9170/
 -
  CARL9170 LINUX COMMUNITY WIRELESS DRIVER
  M:    Christian Lamparter <chunkeey@googlemail.com>
  L:    linux-wireless@vger.kernel.org
@@@ -2245,10 -2251,10 +2245,10 @@@ F:   drivers/gpu/drm
  F:    include/drm/
  
  INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
- M:    Chris Wilson <chris@chris-wilson.co.uk>
+ M:    Keith Packard <keithp@keithp.com>
  L:    intel-gfx@lists.freedesktop.org (subscribers-only)
  L:    dri-devel@lists.freedesktop.org
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ickle/drm-intel.git
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/keithp/linux-2.6.git
  S:    Supported
  F:    drivers/gpu/drm/i915
  F:    include/drm/i915*
@@@ -2807,19 -2813,38 +2807,19 @@@ F:   Documentation/gpio.tx
  F:    drivers/gpio/
  F:    include/linux/gpio*
  
 +GRE DEMULTIPLEXER DRIVER
 +M:    Dmitry Kozlov <xeb@mail.ru>
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +F:    net/ipv4/gre.c
 +F:    include/net/gre.h
 +
  GRETH 10/100/1G Ethernet MAC device driver
  M:    Kristoffer Glembo <kristoffer@gaisler.com>
  L:    netdev@vger.kernel.org
  S:    Maintained
  F:    drivers/net/greth*
  
 -HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
 -M:    Frank Seidel <frank@f-seidel.de>
 -L:    platform-driver-x86@vger.kernel.org
 -W:    http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
 -S:    Maintained
 -F:    drivers/platform/x86/hdaps.c
 -
 -HWPOISON MEMORY FAILURE HANDLING
 -M:    Andi Kleen <andi@firstfloor.org>
 -L:    linux-mm@kvack.org
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git hwpoison
 -S:    Maintained
 -F:    mm/memory-failure.c
 -F:    mm/hwpoison-inject.c
 -
 -HYPERVISOR VIRTUAL CONSOLE DRIVER
 -L:    linuxppc-dev@lists.ozlabs.org
 -S:    Odd Fixes
 -F:    drivers/tty/hvc/
 -
 -iSCSI BOOT FIRMWARE TABLE (iBFT) DRIVER
 -M:    Peter Jones <pjones@redhat.com>
 -M:    Konrad Rzeszutek Wilk <konrad@kernel.org>
 -S:    Maintained
 -F:    drivers/firmware/iscsi_ibft*
 -
  GSPCA FINEPIX SUBDRIVER
  M:    Frank Zago <frank@zago.net>
  L:    linux-media@vger.kernel.org
@@@ -2870,26 -2895,6 +2870,26 @@@ T:    git git://git.kernel.org/pub/scm/lin
  S:    Maintained
  F:    drivers/media/video/gspca/
  
 +HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
 +M:    Frank Seidel <frank@f-seidel.de>
 +L:    platform-driver-x86@vger.kernel.org
 +W:    http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
 +S:    Maintained
 +F:    drivers/platform/x86/hdaps.c
 +
 +HWPOISON MEMORY FAILURE HANDLING
 +M:    Andi Kleen <andi@firstfloor.org>
 +L:    linux-mm@kvack.org
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git hwpoison
 +S:    Maintained
 +F:    mm/memory-failure.c
 +F:    mm/hwpoison-inject.c
 +
 +HYPERVISOR VIRTUAL CONSOLE DRIVER
 +L:    linuxppc-dev@lists.ozlabs.org
 +S:    Odd Fixes
 +F:    drivers/tty/hvc/
 +
  HARDWARE MONITORING
  M:    Jean Delvare <khali@linux-fr.org>
  M:    Guenter Roeck <guenter.roeck@ericsson.com>
@@@ -2940,8 -2945,8 +2940,8 @@@ F:      drivers/block/cciss
  F:    include/linux/cciss_ioctl.h
  
  HFS FILESYSTEM
 -M:    Roman Zippel <zippel@linux-m68k.org>
 -S:    Maintained
 +L:    linux-fsdevel@vger.kernel.org
 +S:    Orphan
  F:    Documentation/filesystems/hfs.txt
  F:    fs/hfs/
  
@@@ -3357,12 -3362,6 +3357,12 @@@ F:    Documentation/wimax/README.i2400
  F:    drivers/net/wimax/i2400m/
  F:    include/linux/wimax/i2400m.h
  
 +INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy)
 +M:    Stanislaw Gruszka <sgruszka@redhat.com>
 +L:    linux-wireless@vger.kernel.org
 +S:    Supported
 +F:    drivers/net/wireless/iwlegacy/
 +
  INTEL WIRELESS WIFI LINK (iwlwifi)
  M:    Wey-Yi Guy <wey-yi.w.guy@intel.com>
  M:    Intel Linux Wireless <ilw@linux.intel.com>
@@@ -3479,12 -3478,6 +3479,12 @@@ F:    Documentation/isapnp.tx
  F:    drivers/pnp/isapnp/
  F:    include/linux/isapnp.h
  
 +iSCSI BOOT FIRMWARE TABLE (iBFT) DRIVER
 +M:    Peter Jones <pjones@redhat.com>
 +M:    Konrad Rzeszutek Wilk <konrad@kernel.org>
 +S:    Maintained
 +F:    drivers/firmware/iscsi_ibft*
 +
  ISCSI
  M:    Mike Christie <michaelc@cs.wisc.edu>
  L:    open-iscsi@googlegroups.com
@@@ -3814,7 -3807,7 +3814,7 @@@ M:      Rusty Russell <rusty@rustcorp.com.au
  L:    lguest@lists.ozlabs.org
  W:    http://lguest.ozlabs.org/
  S:    Odd Fixes
 -F:    Documentation/lguest/
 +F:    Documentation/virtual/lguest/
  F:    arch/x86/lguest/
  F:    drivers/lguest/
  F:    include/linux/lguest*.h
@@@ -4001,6 -3994,7 +4001,6 @@@ F:      arch/m32r
  
  M68K ARCHITECTURE
  M:    Geert Uytterhoeven <geert@linux-m68k.org>
 -M:    Roman Zippel <zippel@linux-m68k.org>
  L:    linux-m68k@lists.linux-m68k.org
  W:    http://www.linux-m68k.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git
@@@ -4253,7 -4247,7 +4253,7 @@@ F:      include/linux/isicom.
  MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
  M:    Felipe Balbi <balbi@ti.com>
  L:    linux-usb@vger.kernel.org
 -T:    git git://gitorious.org/usb/usb.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
  S:    Maintained
  F:    drivers/usb/musb/
  
@@@ -4270,13 -4264,6 +4270,13 @@@ M:    Tim Hockin <thockin@hockin.org
  S:    Maintained
  F:    drivers/net/natsemi.c
  
 +NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER
 +M:    Daniel Mack <zonque@gmail.com>
 +S:    Maintained
 +L:    alsa-devel@alsa-project.org
 +W:    http://www.native-instruments.com
 +F:    sound/usb/caiaq/
 +
  NCP FILESYSTEM
  M:    Petr Vandrovec <petr@vandrovec.name>
  S:    Odd Fixes
@@@ -4392,7 -4379,6 +4392,7 @@@ S:      Maintaine
  F:    net/ipv4/
  F:    net/ipv6/
  F:    include/net/ip*
 +F:    arch/x86/net/*
  
  NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK)
  M:    Paul Moore <paul.moore@hp.com>
@@@ -4588,7 -4574,6 +4588,7 @@@ M:      Felipe Balbi <balbi@ti.com
  M:    David Brownell <dbrownell@users.sourceforge.net>
  L:    linux-usb@vger.kernel.org
  L:    linux-omap@vger.kernel.org
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
  S:    Maintained
  F:    drivers/usb/*/*omap*
  F:    arch/arm/*omap*/usb*
@@@ -5004,13 -4989,6 +5004,13 @@@ F:    Documentation/pps
  F:    drivers/pps/
  F:    include/linux/pps*.h
  
 +PPTP DRIVER
 +M:    Dmitry Kozlov <xeb@mail.ru>
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +F:    drivers/net/pptp.c
 +W:    http://sourceforge.net/projects/accel-pptp
 +
  PREEMPTIBLE KERNEL
  M:    Robert Love <rml@tech9.net>
  L:    kpreempt-tech@lists.sourceforge.net
@@@ -5440,7 -5418,6 +5440,7 @@@ F:      include/linux/timex.
  F:    kernel/time/clocksource.c
  F:    kernel/time/time*.c
  F:    kernel/time/ntp.c
 +F:    drivers/clocksource
  
  TLG2300 VIDEO4LINUX-2 DRIVER
  M:    Huang Shijie <shijie8@gmail.com>
@@@ -5621,9 -5598,9 +5621,9 @@@ F:      include/linux/ata.
  F:    include/linux/libata.h
  
  SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
 -M:    Jayamohan Kallickal <jayamohank@serverengines.com>
 +M:    Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
  L:    linux-scsi@vger.kernel.org
 -W:    http://www.serverengines.com
 +W:    http://www.emulex.com
  S:    Supported
  F:    drivers/scsi/be2iscsi/
  
@@@ -5841,13 -5818,6 +5841,13 @@@ S:    Maintaine
  F:    drivers/ssb/
  F:    include/linux/ssb/
  
 +BROADCOM SPECIFIC AMBA DRIVER (BCMA)
 +M:    Rafał Miłecki <zajec5@gmail.com>
 +L:    linux-wireless@vger.kernel.org
 +S:    Maintained
 +F:    drivers/bcma/
 +F:    include/linux/bcma/
 +
  SONY VAIO CONTROL DEVICE DRIVER
  M:    Mattia Dongili <malattia@linux.it>
  L:    platform-driver-x86@vger.kernel.org
@@@ -5877,7 -5847,7 +5877,7 @@@ F:      include/sound
  F:    sound/
  
  SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
 -M:    Liam Girdwood <lrg@slimlogic.co.uk>
 +M:    Liam Girdwood <lrg@ti.com>
  M:    Mark Brown <broonie@opensource.wolfsonmicro.com>
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git
  L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
@@@ -6128,7 -6098,7 +6128,7 @@@ F:      drivers/mmc/host/tifm_sd.
  F:    include/linux/tifm.h
  
  TI TWL4030 SERIES SOC CODEC DRIVER
 -M:    Peter Ujfalusi <peter.ujfalusi@nokia.com>
 +M:    Peter Ujfalusi <peter.ujfalusi@ti.com>
  L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
  S:    Maintained
  F:    sound/soc/codecs/twl4030*
@@@ -6231,7 -6201,6 +6231,7 @@@ TRIVIAL PATCHE
  M:    Jiri Kosina <trivial@kernel.org>
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git
  S:    Maintained
 +K:    ^Subject:.*(?i)trivial
  
  TTY LAYER
  M:    Greg Kroah-Hartman <gregkh@suse.de>
@@@ -6649,7 -6618,7 +6649,7 @@@ L:      user-mode-linux-devel@lists.sourcefo
  L:    user-mode-linux-user@lists.sourceforge.net
  W:    http://user-mode-linux.sourceforge.net
  S:    Maintained
 -F:    Documentation/uml/
 +F:    Documentation/virtual/uml/
  F:    arch/um/
  F:    fs/hostfs/
  F:    fs/hppfs/
@@@ -6773,7 -6742,7 +6773,7 @@@ F:      drivers/scsi/vmw_pvscsi.
  F:    drivers/scsi/vmw_pvscsi.h
  
  VOLTAGE AND CURRENT REGULATOR FRAMEWORK
 -M:    Liam Girdwood <lrg@slimlogic.co.uk>
 +M:    Liam Girdwood <lrg@ti.com>
  M:    Mark Brown <broonie@opensource.wolfsonmicro.com>
  W:    http://opensource.wolfsonmicro.com/node/15
  W:    http://www.slimlogic.co.uk/?p=48
@@@ -7055,6 -7024,20 +7055,6 @@@ M:     "Maciej W. Rozycki" <macro@linux-mip
  S:    Maintained
  F:    drivers/tty/serial/zs.*
  
 -GRE DEMULTIPLEXER DRIVER
 -M:    Dmitry Kozlov <xeb@mail.ru>
 -L:    netdev@vger.kernel.org
 -S:    Maintained
 -F:    net/ipv4/gre.c
 -F:    include/net/gre.h
 -
 -PPTP DRIVER
 -M:    Dmitry Kozlov <xeb@mail.ru>
 -L:    netdev@vger.kernel.org
 -S:    Maintained
 -F:    drivers/net/pptp.c
 -W:    http://sourceforge.net/projects/accel-pptp
 -
  THE REST
  M:    Linus Torvalds <torvalds@linux-foundation.org>
  L:    linux-kernel@vger.kernel.org
index 32d1b3e829c8d35433f0b170052e9be96f358a1c,817fd9cbb113a8f3bd0098d1ff66028b6c23d162..0defd42705943e1776b3e9447a770048142d1a73
@@@ -49,12 -49,15 +49,15 @@@ module_param_named(panel_ignore_lid, i9
  unsigned int i915_powersave = 1;
  module_param_named(powersave, i915_powersave, int, 0600);
  
 -unsigned int i915_semaphores = 1;
 +unsigned int i915_semaphores = 0;
  module_param_named(semaphores, i915_semaphores, int, 0600);
  
- unsigned int i915_enable_rc6 = 0;
+ unsigned int i915_enable_rc6 = 1;
  module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
  
+ unsigned int i915_enable_fbc = 0;
+ module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
  unsigned int i915_lvds_downclock = 0;
  module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
  
@@@ -169,7 -172,7 +172,7 @@@ static const struct intel_device_info i
  static const struct intel_device_info intel_ironlake_m_info = {
        .gen = 5, .is_mobile = 1,
        .need_gfx_hws = 1, .has_hotplug = 1,
-       .has_fbc = 0, /* disabled due to buggy hardware */
+       .has_fbc = 1,
        .has_bsd_ring = 1,
  };
  
@@@ -188,6 -191,21 +191,21 @@@ static const struct intel_device_info i
        .has_blt_ring = 1,
  };
  
+ static const struct intel_device_info intel_ivybridge_d_info = {
+       .is_ivybridge = 1, .gen = 7,
+       .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_bsd_ring = 1,
+       .has_blt_ring = 1,
+ };
+ static const struct intel_device_info intel_ivybridge_m_info = {
+       .is_ivybridge = 1, .gen = 7, .is_mobile = 1,
+       .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_fbc = 0,   /* FBC is not enabled on Ivybridge mobile yet */
+       .has_bsd_ring = 1,
+       .has_blt_ring = 1,
+ };
  static const struct pci_device_id pciidlist[] = {             /* aka */
        INTEL_VGA_DEVICE(0x3577, &intel_i830_info),             /* I830_M */
        INTEL_VGA_DEVICE(0x2562, &intel_845g_info),             /* 845_G */
        INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info),
        INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info),
        INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info),
+       INTEL_VGA_DEVICE(0x0156, &intel_ivybridge_m_info), /* GT1 mobile */
+       INTEL_VGA_DEVICE(0x0166, &intel_ivybridge_m_info), /* GT2 mobile */
+       INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */
+       INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */
+       INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */
        {0, 0, 0}
  };
  
@@@ -235,7 -258,9 +258,9 @@@ MODULE_DEVICE_TABLE(pci, pciidlist)
  #endif
  
  #define INTEL_PCH_DEVICE_ID_MASK      0xff00
+ #define INTEL_PCH_IBX_DEVICE_ID_TYPE  0x3b00
  #define INTEL_PCH_CPT_DEVICE_ID_TYPE  0x1c00
+ #define INTEL_PCH_PPT_DEVICE_ID_TYPE  0x1e00
  
  void intel_detect_pch (struct drm_device *dev)
  {
                        int id;
                        id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
  
-                       if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
+                       if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
+                               dev_priv->pch_type = PCH_IBX;
+                               DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
+                       } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = PCH_CPT;
                                DRM_DEBUG_KMS("Found CougarPoint PCH\n");
+                       } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
+                               /* PantherPoint is CPT compatible */
+                               dev_priv->pch_type = PCH_CPT;
+                               DRM_DEBUG_KMS("Found PatherPoint PCH\n");
                        }
                }
                pci_dev_put(pch);
        }
  }
  
- void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
  {
        int count;
  
                udelay(10);
  }
  
- void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+ /*
+  * Generally this is called implicitly by the register read function. However,
+  * if some sequence requires the GT to not power down then this function should
+  * be called at the beginning of the sequence followed by a call to
+  * gen6_gt_force_wake_put() at the end of the sequence.
+  */
+ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+ {
+       WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+       /* Forcewake is atomic in case we get in here without the lock */
+       if (atomic_add_return(1, &dev_priv->forcewake_count) == 1)
+               __gen6_gt_force_wake_get(dev_priv);
+ }
+ static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
  {
        I915_WRITE_NOTRACE(FORCEWAKE, 0);
        POSTING_READ(FORCEWAKE);
  }
  
+ /*
+  * see gen6_gt_force_wake_get()
+  */
+ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+ {
+       WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+       if (atomic_dec_and_test(&dev_priv->forcewake_count))
+               __gen6_gt_force_wake_put(dev_priv);
+ }
  void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
  {
        int loop = 500;
index 2166ee071ddbe99655c3c977beecec68bb6a7a19,311fffede6f8a3b42cdb131c73115394fc1dfd76..f553ddfdc16819fa343b4780c27de14fa37d1337
@@@ -76,255 -76,6 +76,6 @@@ struct intel_limit 
                      int, int, intel_clock_t *);
  };
  
- #define I8XX_DOT_MIN            25000
- #define I8XX_DOT_MAX           350000
- #define I8XX_VCO_MIN           930000
- #define I8XX_VCO_MAX          1400000
- #define I8XX_N_MIN                  3
- #define I8XX_N_MAX                 16
- #define I8XX_M_MIN                 96
- #define I8XX_M_MAX                140
- #define I8XX_M1_MIN                18
- #define I8XX_M1_MAX                26
- #define I8XX_M2_MIN                 6
- #define I8XX_M2_MAX                16
- #define I8XX_P_MIN                  4
- #define I8XX_P_MAX                128
- #define I8XX_P1_MIN                 2
- #define I8XX_P1_MAX                33
- #define I8XX_P1_LVDS_MIN            1
- #define I8XX_P1_LVDS_MAX            6
- #define I8XX_P2_SLOW                4
- #define I8XX_P2_FAST                2
- #define I8XX_P2_LVDS_SLOW           14
- #define I8XX_P2_LVDS_FAST           7
- #define I8XX_P2_SLOW_LIMIT     165000
- #define I9XX_DOT_MIN            20000
- #define I9XX_DOT_MAX           400000
- #define I9XX_VCO_MIN          1400000
- #define I9XX_VCO_MAX          2800000
- #define PINEVIEW_VCO_MIN              1700000
- #define PINEVIEW_VCO_MAX              3500000
- #define I9XX_N_MIN                  1
- #define I9XX_N_MAX                  6
- /* Pineview's Ncounter is a ring counter */
- #define PINEVIEW_N_MIN                      3
- #define PINEVIEW_N_MAX                      6
- #define I9XX_M_MIN                 70
- #define I9XX_M_MAX                120
- #define PINEVIEW_M_MIN                      2
- #define PINEVIEW_M_MAX                    256
- #define I9XX_M1_MIN                10
- #define I9XX_M1_MAX                22
- #define I9XX_M2_MIN                 5
- #define I9XX_M2_MAX                 9
- /* Pineview M1 is reserved, and must be 0 */
- #define PINEVIEW_M1_MIN                     0
- #define PINEVIEW_M1_MAX                     0
- #define PINEVIEW_M2_MIN                     0
- #define PINEVIEW_M2_MAX                     254
- #define I9XX_P_SDVO_DAC_MIN         5
- #define I9XX_P_SDVO_DAC_MAX        80
- #define I9XX_P_LVDS_MIN                     7
- #define I9XX_P_LVDS_MAX                    98
- #define PINEVIEW_P_LVDS_MIN                 7
- #define PINEVIEW_P_LVDS_MAX                112
- #define I9XX_P1_MIN                 1
- #define I9XX_P1_MAX                 8
- #define I9XX_P2_SDVO_DAC_SLOW              10
- #define I9XX_P2_SDVO_DAC_FAST               5
- #define I9XX_P2_SDVO_DAC_SLOW_LIMIT    200000
- #define I9XX_P2_LVDS_SLOW                  14
- #define I9XX_P2_LVDS_FAST                   7
- #define I9XX_P2_LVDS_SLOW_LIMIT                112000
- /*The parameter is for SDVO on G4x platform*/
- #define G4X_DOT_SDVO_MIN           25000
- #define G4X_DOT_SDVO_MAX           270000
- #define G4X_VCO_MIN                1750000
- #define G4X_VCO_MAX                3500000
- #define G4X_N_SDVO_MIN             1
- #define G4X_N_SDVO_MAX             4
- #define G4X_M_SDVO_MIN             104
- #define G4X_M_SDVO_MAX             138
- #define G4X_M1_SDVO_MIN            17
- #define G4X_M1_SDVO_MAX            23
- #define G4X_M2_SDVO_MIN            5
- #define G4X_M2_SDVO_MAX            11
- #define G4X_P_SDVO_MIN             10
- #define G4X_P_SDVO_MAX             30
- #define G4X_P1_SDVO_MIN            1
- #define G4X_P1_SDVO_MAX            3
- #define G4X_P2_SDVO_SLOW           10
- #define G4X_P2_SDVO_FAST           10
- #define G4X_P2_SDVO_LIMIT          270000
- /*The parameter is for HDMI_DAC on G4x platform*/
- #define G4X_DOT_HDMI_DAC_MIN           22000
- #define G4X_DOT_HDMI_DAC_MAX           400000
- #define G4X_N_HDMI_DAC_MIN             1
- #define G4X_N_HDMI_DAC_MAX             4
- #define G4X_M_HDMI_DAC_MIN             104
- #define G4X_M_HDMI_DAC_MAX             138
- #define G4X_M1_HDMI_DAC_MIN            16
- #define G4X_M1_HDMI_DAC_MAX            23
- #define G4X_M2_HDMI_DAC_MIN            5
- #define G4X_M2_HDMI_DAC_MAX            11
- #define G4X_P_HDMI_DAC_MIN             5
- #define G4X_P_HDMI_DAC_MAX             80
- #define G4X_P1_HDMI_DAC_MIN            1
- #define G4X_P1_HDMI_DAC_MAX            8
- #define G4X_P2_HDMI_DAC_SLOW           10
- #define G4X_P2_HDMI_DAC_FAST           5
- #define G4X_P2_HDMI_DAC_LIMIT          165000
- /*The parameter is for SINGLE_CHANNEL_LVDS on G4x platform*/
- #define G4X_DOT_SINGLE_CHANNEL_LVDS_MIN           20000
- #define G4X_DOT_SINGLE_CHANNEL_LVDS_MAX           115000
- #define G4X_N_SINGLE_CHANNEL_LVDS_MIN             1
- #define G4X_N_SINGLE_CHANNEL_LVDS_MAX             3
- #define G4X_M_SINGLE_CHANNEL_LVDS_MIN             104
- #define G4X_M_SINGLE_CHANNEL_LVDS_MAX             138
- #define G4X_M1_SINGLE_CHANNEL_LVDS_MIN            17
- #define G4X_M1_SINGLE_CHANNEL_LVDS_MAX            23
- #define G4X_M2_SINGLE_CHANNEL_LVDS_MIN            5
- #define G4X_M2_SINGLE_CHANNEL_LVDS_MAX            11
- #define G4X_P_SINGLE_CHANNEL_LVDS_MIN             28
- #define G4X_P_SINGLE_CHANNEL_LVDS_MAX             112
- #define G4X_P1_SINGLE_CHANNEL_LVDS_MIN            2
- #define G4X_P1_SINGLE_CHANNEL_LVDS_MAX            8
- #define G4X_P2_SINGLE_CHANNEL_LVDS_SLOW           14
- #define G4X_P2_SINGLE_CHANNEL_LVDS_FAST           14
- #define G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT          0
- /*The parameter is for DUAL_CHANNEL_LVDS on G4x platform*/
- #define G4X_DOT_DUAL_CHANNEL_LVDS_MIN           80000
- #define G4X_DOT_DUAL_CHANNEL_LVDS_MAX           224000
- #define G4X_N_DUAL_CHANNEL_LVDS_MIN             1
- #define G4X_N_DUAL_CHANNEL_LVDS_MAX             3
- #define G4X_M_DUAL_CHANNEL_LVDS_MIN             104
- #define G4X_M_DUAL_CHANNEL_LVDS_MAX             138
- #define G4X_M1_DUAL_CHANNEL_LVDS_MIN            17
- #define G4X_M1_DUAL_CHANNEL_LVDS_MAX            23
- #define G4X_M2_DUAL_CHANNEL_LVDS_MIN            5
- #define G4X_M2_DUAL_CHANNEL_LVDS_MAX            11
- #define G4X_P_DUAL_CHANNEL_LVDS_MIN             14
- #define G4X_P_DUAL_CHANNEL_LVDS_MAX             42
- #define G4X_P1_DUAL_CHANNEL_LVDS_MIN            2
- #define G4X_P1_DUAL_CHANNEL_LVDS_MAX            6
- #define G4X_P2_DUAL_CHANNEL_LVDS_SLOW           7
- #define G4X_P2_DUAL_CHANNEL_LVDS_FAST           7
- #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT          0
- /*The parameter is for DISPLAY PORT on G4x platform*/
- #define G4X_DOT_DISPLAY_PORT_MIN           161670
- #define G4X_DOT_DISPLAY_PORT_MAX           227000
- #define G4X_N_DISPLAY_PORT_MIN             1
- #define G4X_N_DISPLAY_PORT_MAX             2
- #define G4X_M_DISPLAY_PORT_MIN             97
- #define G4X_M_DISPLAY_PORT_MAX             108
- #define G4X_M1_DISPLAY_PORT_MIN            0x10
- #define G4X_M1_DISPLAY_PORT_MAX            0x12
- #define G4X_M2_DISPLAY_PORT_MIN            0x05
- #define G4X_M2_DISPLAY_PORT_MAX            0x06
- #define G4X_P_DISPLAY_PORT_MIN             10
- #define G4X_P_DISPLAY_PORT_MAX             20
- #define G4X_P1_DISPLAY_PORT_MIN            1
- #define G4X_P1_DISPLAY_PORT_MAX            2
- #define G4X_P2_DISPLAY_PORT_SLOW           10
- #define G4X_P2_DISPLAY_PORT_FAST           10
- #define G4X_P2_DISPLAY_PORT_LIMIT          0
- /* Ironlake / Sandybridge */
- /* as we calculate clock using (register_value + 2) for
-    N/M1/M2, so here the range value for them is (actual_value-2).
-  */
- #define IRONLAKE_DOT_MIN         25000
- #define IRONLAKE_DOT_MAX         350000
- #define IRONLAKE_VCO_MIN         1760000
- #define IRONLAKE_VCO_MAX         3510000
- #define IRONLAKE_M1_MIN          12
- #define IRONLAKE_M1_MAX          22
- #define IRONLAKE_M2_MIN          5
- #define IRONLAKE_M2_MAX          9
- #define IRONLAKE_P2_DOT_LIMIT    225000 /* 225Mhz */
- /* We have parameter ranges for different type of outputs. */
- /* DAC & HDMI Refclk 120Mhz */
- #define IRONLAKE_DAC_N_MIN    1
- #define IRONLAKE_DAC_N_MAX    5
- #define IRONLAKE_DAC_M_MIN    79
- #define IRONLAKE_DAC_M_MAX    127
- #define IRONLAKE_DAC_P_MIN    5
- #define IRONLAKE_DAC_P_MAX    80
- #define IRONLAKE_DAC_P1_MIN   1
- #define IRONLAKE_DAC_P1_MAX   8
- #define IRONLAKE_DAC_P2_SLOW  10
- #define IRONLAKE_DAC_P2_FAST  5
- /* LVDS single-channel 120Mhz refclk */
- #define IRONLAKE_LVDS_S_N_MIN 1
- #define IRONLAKE_LVDS_S_N_MAX 3
- #define IRONLAKE_LVDS_S_M_MIN 79
- #define IRONLAKE_LVDS_S_M_MAX 118
- #define IRONLAKE_LVDS_S_P_MIN 28
- #define IRONLAKE_LVDS_S_P_MAX 112
- #define IRONLAKE_LVDS_S_P1_MIN        2
- #define IRONLAKE_LVDS_S_P1_MAX        8
- #define IRONLAKE_LVDS_S_P2_SLOW       14
- #define IRONLAKE_LVDS_S_P2_FAST       14
- /* LVDS dual-channel 120Mhz refclk */
- #define IRONLAKE_LVDS_D_N_MIN 1
- #define IRONLAKE_LVDS_D_N_MAX 3
- #define IRONLAKE_LVDS_D_M_MIN 79
- #define IRONLAKE_LVDS_D_M_MAX 127
- #define IRONLAKE_LVDS_D_P_MIN 14
- #define IRONLAKE_LVDS_D_P_MAX 56
- #define IRONLAKE_LVDS_D_P1_MIN        2
- #define IRONLAKE_LVDS_D_P1_MAX        8
- #define IRONLAKE_LVDS_D_P2_SLOW       7
- #define IRONLAKE_LVDS_D_P2_FAST       7
- /* LVDS single-channel 100Mhz refclk */
- #define IRONLAKE_LVDS_S_SSC_N_MIN     1
- #define IRONLAKE_LVDS_S_SSC_N_MAX     2
- #define IRONLAKE_LVDS_S_SSC_M_MIN     79
- #define IRONLAKE_LVDS_S_SSC_M_MAX     126
- #define IRONLAKE_LVDS_S_SSC_P_MIN     28
- #define IRONLAKE_LVDS_S_SSC_P_MAX     112
- #define IRONLAKE_LVDS_S_SSC_P1_MIN    2
- #define IRONLAKE_LVDS_S_SSC_P1_MAX    8
- #define IRONLAKE_LVDS_S_SSC_P2_SLOW   14
- #define IRONLAKE_LVDS_S_SSC_P2_FAST   14
- /* LVDS dual-channel 100Mhz refclk */
- #define IRONLAKE_LVDS_D_SSC_N_MIN     1
- #define IRONLAKE_LVDS_D_SSC_N_MAX     3
- #define IRONLAKE_LVDS_D_SSC_M_MIN     79
- #define IRONLAKE_LVDS_D_SSC_M_MAX     126
- #define IRONLAKE_LVDS_D_SSC_P_MIN     14
- #define IRONLAKE_LVDS_D_SSC_P_MAX     42
- #define IRONLAKE_LVDS_D_SSC_P1_MIN    2
- #define IRONLAKE_LVDS_D_SSC_P1_MAX    6
- #define IRONLAKE_LVDS_D_SSC_P2_SLOW   7
- #define IRONLAKE_LVDS_D_SSC_P2_FAST   7
- /* DisplayPort */
- #define IRONLAKE_DP_N_MIN             1
- #define IRONLAKE_DP_N_MAX             2
- #define IRONLAKE_DP_M_MIN             81
- #define IRONLAKE_DP_M_MAX             90
- #define IRONLAKE_DP_P_MIN             10
- #define IRONLAKE_DP_P_MAX             20
- #define IRONLAKE_DP_P2_FAST           10
- #define IRONLAKE_DP_P2_SLOW           10
- #define IRONLAKE_DP_P2_LIMIT          0
- #define IRONLAKE_DP_P1_MIN            1
- #define IRONLAKE_DP_P1_MAX            2
  /* FDI */
  #define IRONLAKE_FDI_FREQ             2700000 /* in kHz for mode->clock */
  
@@@ -353,292 -104,253 +104,253 @@@ intel_fdi_link_freq(struct drm_device *
  }
  
  static const intel_limit_t intel_limits_i8xx_dvo = {
-         .dot = { .min = I8XX_DOT_MIN,         .max = I8XX_DOT_MAX },
-         .vco = { .min = I8XX_VCO_MIN,         .max = I8XX_VCO_MAX },
-         .n   = { .min = I8XX_N_MIN,           .max = I8XX_N_MAX },
-         .m   = { .min = I8XX_M_MIN,           .max = I8XX_M_MAX },
-         .m1  = { .min = I8XX_M1_MIN,          .max = I8XX_M1_MAX },
-         .m2  = { .min = I8XX_M2_MIN,          .max = I8XX_M2_MAX },
-         .p   = { .min = I8XX_P_MIN,           .max = I8XX_P_MAX },
-         .p1  = { .min = I8XX_P1_MIN,          .max = I8XX_P1_MAX },
-       .p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
-                .p2_slow = I8XX_P2_SLOW,       .p2_fast = I8XX_P2_FAST },
+         .dot = { .min = 25000, .max = 350000 },
+         .vco = { .min = 930000, .max = 1400000 },
+         .n = { .min = 3, .max = 16 },
+         .m = { .min = 96, .max = 140 },
+         .m1 = { .min = 18, .max = 26 },
+         .m2 = { .min = 6, .max = 16 },
+         .p = { .min = 4, .max = 128 },
+         .p1 = { .min = 2, .max = 33 },
+       .p2 = { .dot_limit = 165000,
+               .p2_slow = 4, .p2_fast = 2 },
        .find_pll = intel_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_i8xx_lvds = {
-         .dot = { .min = I8XX_DOT_MIN,         .max = I8XX_DOT_MAX },
-         .vco = { .min = I8XX_VCO_MIN,         .max = I8XX_VCO_MAX },
-         .n   = { .min = I8XX_N_MIN,           .max = I8XX_N_MAX },
-         .m   = { .min = I8XX_M_MIN,           .max = I8XX_M_MAX },
-         .m1  = { .min = I8XX_M1_MIN,          .max = I8XX_M1_MAX },
-         .m2  = { .min = I8XX_M2_MIN,          .max = I8XX_M2_MAX },
-         .p   = { .min = I8XX_P_MIN,           .max = I8XX_P_MAX },
-         .p1  = { .min = I8XX_P1_LVDS_MIN,     .max = I8XX_P1_LVDS_MAX },
-       .p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
-                .p2_slow = I8XX_P2_LVDS_SLOW,  .p2_fast = I8XX_P2_LVDS_FAST },
+         .dot = { .min = 25000, .max = 350000 },
+         .vco = { .min = 930000, .max = 1400000 },
+         .n = { .min = 3, .max = 16 },
+         .m = { .min = 96, .max = 140 },
+         .m1 = { .min = 18, .max = 26 },
+         .m2 = { .min = 6, .max = 16 },
+         .p = { .min = 4, .max = 128 },
+         .p1 = { .min = 1, .max = 6 },
+       .p2 = { .dot_limit = 165000,
+               .p2_slow = 14, .p2_fast = 7 },
        .find_pll = intel_find_best_PLL,
  };
-       
  static const intel_limit_t intel_limits_i9xx_sdvo = {
-         .dot = { .min = I9XX_DOT_MIN,         .max = I9XX_DOT_MAX },
-         .vco = { .min = I9XX_VCO_MIN,         .max = I9XX_VCO_MAX },
-         .n   = { .min = I9XX_N_MIN,           .max = I9XX_N_MAX },
-         .m   = { .min = I9XX_M_MIN,           .max = I9XX_M_MAX },
-         .m1  = { .min = I9XX_M1_MIN,          .max = I9XX_M1_MAX },
-         .m2  = { .min = I9XX_M2_MIN,          .max = I9XX_M2_MAX },
-         .p   = { .min = I9XX_P_SDVO_DAC_MIN,  .max = I9XX_P_SDVO_DAC_MAX },
-         .p1  = { .min = I9XX_P1_MIN,          .max = I9XX_P1_MAX },
-       .p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
-                .p2_slow = I9XX_P2_SDVO_DAC_SLOW,      .p2_fast = I9XX_P2_SDVO_DAC_FAST },
+         .dot = { .min = 20000, .max = 400000 },
+         .vco = { .min = 1400000, .max = 2800000 },
+         .n = { .min = 1, .max = 6 },
+         .m = { .min = 70, .max = 120 },
+         .m1 = { .min = 10, .max = 22 },
+         .m2 = { .min = 5, .max = 9 },
+         .p = { .min = 5, .max = 80 },
+         .p1 = { .min = 1, .max = 8 },
+       .p2 = { .dot_limit = 200000,
+               .p2_slow = 10, .p2_fast = 5 },
        .find_pll = intel_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_i9xx_lvds = {
-         .dot = { .min = I9XX_DOT_MIN,         .max = I9XX_DOT_MAX },
-         .vco = { .min = I9XX_VCO_MIN,         .max = I9XX_VCO_MAX },
-         .n   = { .min = I9XX_N_MIN,           .max = I9XX_N_MAX },
-         .m   = { .min = I9XX_M_MIN,           .max = I9XX_M_MAX },
-         .m1  = { .min = I9XX_M1_MIN,          .max = I9XX_M1_MAX },
-         .m2  = { .min = I9XX_M2_MIN,          .max = I9XX_M2_MAX },
-         .p   = { .min = I9XX_P_LVDS_MIN,      .max = I9XX_P_LVDS_MAX },
-         .p1  = { .min = I9XX_P1_MIN,          .max = I9XX_P1_MAX },
-       /* The single-channel range is 25-112Mhz, and dual-channel
-        * is 80-224Mhz.  Prefer single channel as much as possible.
-        */
-       .p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
-                .p2_slow = I9XX_P2_LVDS_SLOW,  .p2_fast = I9XX_P2_LVDS_FAST },
+         .dot = { .min = 20000, .max = 400000 },
+         .vco = { .min = 1400000, .max = 2800000 },
+         .n = { .min = 1, .max = 6 },
+         .m = { .min = 70, .max = 120 },
+         .m1 = { .min = 10, .max = 22 },
+         .m2 = { .min = 5, .max = 9 },
+         .p = { .min = 7, .max = 98 },
+         .p1 = { .min = 1, .max = 8 },
+       .p2 = { .dot_limit = 112000,
+               .p2_slow = 14, .p2_fast = 7 },
        .find_pll = intel_find_best_PLL,
  };
  
-     /* below parameter and function is for G4X Chipset Family*/
  static const intel_limit_t intel_limits_g4x_sdvo = {
-       .dot = { .min = G4X_DOT_SDVO_MIN,       .max = G4X_DOT_SDVO_MAX },
-       .vco = { .min = G4X_VCO_MIN,            .max = G4X_VCO_MAX},
-       .n   = { .min = G4X_N_SDVO_MIN,         .max = G4X_N_SDVO_MAX },
-       .m   = { .min = G4X_M_SDVO_MIN,         .max = G4X_M_SDVO_MAX },
-       .m1  = { .min = G4X_M1_SDVO_MIN,        .max = G4X_M1_SDVO_MAX },
-       .m2  = { .min = G4X_M2_SDVO_MIN,        .max = G4X_M2_SDVO_MAX },
-       .p   = { .min = G4X_P_SDVO_MIN,         .max = G4X_P_SDVO_MAX },
-       .p1  = { .min = G4X_P1_SDVO_MIN,        .max = G4X_P1_SDVO_MAX},
-       .p2  = { .dot_limit = G4X_P2_SDVO_LIMIT,
-                .p2_slow = G4X_P2_SDVO_SLOW,
-                .p2_fast = G4X_P2_SDVO_FAST
+       .dot = { .min = 25000, .max = 270000 },
+       .vco = { .min = 1750000, .max = 3500000},
+       .n = { .min = 1, .max = 4 },
+       .m = { .min = 104, .max = 138 },
+       .m1 = { .min = 17, .max = 23 },
+       .m2 = { .min = 5, .max = 11 },
+       .p = { .min = 10, .max = 30 },
+       .p1 = { .min = 1, .max = 3},
+       .p2 = { .dot_limit = 270000,
+               .p2_slow = 10,
+               .p2_fast = 10
        },
        .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_g4x_hdmi = {
-       .dot = { .min = G4X_DOT_HDMI_DAC_MIN,   .max = G4X_DOT_HDMI_DAC_MAX },
-       .vco = { .min = G4X_VCO_MIN,            .max = G4X_VCO_MAX},
-       .n   = { .min = G4X_N_HDMI_DAC_MIN,     .max = G4X_N_HDMI_DAC_MAX },
-       .m   = { .min = G4X_M_HDMI_DAC_MIN,     .max = G4X_M_HDMI_DAC_MAX },
-       .m1  = { .min = G4X_M1_HDMI_DAC_MIN,    .max = G4X_M1_HDMI_DAC_MAX },
-       .m2  = { .min = G4X_M2_HDMI_DAC_MIN,    .max = G4X_M2_HDMI_DAC_MAX },
-       .p   = { .min = G4X_P_HDMI_DAC_MIN,     .max = G4X_P_HDMI_DAC_MAX },
-       .p1  = { .min = G4X_P1_HDMI_DAC_MIN,    .max = G4X_P1_HDMI_DAC_MAX},
-       .p2  = { .dot_limit = G4X_P2_HDMI_DAC_LIMIT,
-                .p2_slow = G4X_P2_HDMI_DAC_SLOW,
-                .p2_fast = G4X_P2_HDMI_DAC_FAST
-       },
+       .dot = { .min = 22000, .max = 400000 },
+       .vco = { .min = 1750000, .max = 3500000},
+       .n = { .min = 1, .max = 4 },
+       .m = { .min = 104, .max = 138 },
+       .m1 = { .min = 16, .max = 23 },
+       .m2 = { .min = 5, .max = 11 },
+       .p = { .min = 5, .max = 80 },
+       .p1 = { .min = 1, .max = 8},
+       .p2 = { .dot_limit = 165000,
+               .p2_slow = 10, .p2_fast = 5 },
        .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
-       .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN,
-                .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX },
-       .vco = { .min = G4X_VCO_MIN,
-                .max = G4X_VCO_MAX },
-       .n   = { .min = G4X_N_SINGLE_CHANNEL_LVDS_MIN,
-                .max = G4X_N_SINGLE_CHANNEL_LVDS_MAX },
-       .m   = { .min = G4X_M_SINGLE_CHANNEL_LVDS_MIN,
-                .max = G4X_M_SINGLE_CHANNEL_LVDS_MAX },
-       .m1  = { .min = G4X_M1_SINGLE_CHANNEL_LVDS_MIN,
-                .max = G4X_M1_SINGLE_CHANNEL_LVDS_MAX },
-       .m2  = { .min = G4X_M2_SINGLE_CHANNEL_LVDS_MIN,
-                .max = G4X_M2_SINGLE_CHANNEL_LVDS_MAX },
-       .p   = { .min = G4X_P_SINGLE_CHANNEL_LVDS_MIN,
-                .max = G4X_P_SINGLE_CHANNEL_LVDS_MAX },
-       .p1  = { .min = G4X_P1_SINGLE_CHANNEL_LVDS_MIN,
-                .max = G4X_P1_SINGLE_CHANNEL_LVDS_MAX },
-       .p2  = { .dot_limit = G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT,
-                .p2_slow = G4X_P2_SINGLE_CHANNEL_LVDS_SLOW,
-                .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST
+       .dot = { .min = 20000, .max = 115000 },
+       .vco = { .min = 1750000, .max = 3500000 },
+       .n = { .min = 1, .max = 3 },
+       .m = { .min = 104, .max = 138 },
+       .m1 = { .min = 17, .max = 23 },
+       .m2 = { .min = 5, .max = 11 },
+       .p = { .min = 28, .max = 112 },
+       .p1 = { .min = 2, .max = 8 },
+       .p2 = { .dot_limit = 0,
+               .p2_slow = 14, .p2_fast = 14
        },
        .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
-       .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN,
-                .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX },
-       .vco = { .min = G4X_VCO_MIN,
-                .max = G4X_VCO_MAX },
-       .n   = { .min = G4X_N_DUAL_CHANNEL_LVDS_MIN,
-                .max = G4X_N_DUAL_CHANNEL_LVDS_MAX },
-       .m   = { .min = G4X_M_DUAL_CHANNEL_LVDS_MIN,
-                .max = G4X_M_DUAL_CHANNEL_LVDS_MAX },
-       .m1  = { .min = G4X_M1_DUAL_CHANNEL_LVDS_MIN,
-                .max = G4X_M1_DUAL_CHANNEL_LVDS_MAX },
-       .m2  = { .min = G4X_M2_DUAL_CHANNEL_LVDS_MIN,
-                .max = G4X_M2_DUAL_CHANNEL_LVDS_MAX },
-       .p   = { .min = G4X_P_DUAL_CHANNEL_LVDS_MIN,
-                .max = G4X_P_DUAL_CHANNEL_LVDS_MAX },
-       .p1  = { .min = G4X_P1_DUAL_CHANNEL_LVDS_MIN,
-                .max = G4X_P1_DUAL_CHANNEL_LVDS_MAX },
-       .p2  = { .dot_limit = G4X_P2_DUAL_CHANNEL_LVDS_LIMIT,
-                .p2_slow = G4X_P2_DUAL_CHANNEL_LVDS_SLOW,
-                .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST
+       .dot = { .min = 80000, .max = 224000 },
+       .vco = { .min = 1750000, .max = 3500000 },
+       .n = { .min = 1, .max = 3 },
+       .m = { .min = 104, .max = 138 },
+       .m1 = { .min = 17, .max = 23 },
+       .m2 = { .min = 5, .max = 11 },
+       .p = { .min = 14, .max = 42 },
+       .p1 = { .min = 2, .max = 6 },
+       .p2 = { .dot_limit = 0,
+               .p2_slow = 7, .p2_fast = 7
        },
        .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_g4x_display_port = {
-         .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN,
-                  .max = G4X_DOT_DISPLAY_PORT_MAX },
-         .vco = { .min = G4X_VCO_MIN,
-                  .max = G4X_VCO_MAX},
-         .n   = { .min = G4X_N_DISPLAY_PORT_MIN,
-                  .max = G4X_N_DISPLAY_PORT_MAX },
-         .m   = { .min = G4X_M_DISPLAY_PORT_MIN,
-                  .max = G4X_M_DISPLAY_PORT_MAX },
-         .m1  = { .min = G4X_M1_DISPLAY_PORT_MIN,
-                  .max = G4X_M1_DISPLAY_PORT_MAX },
-         .m2  = { .min = G4X_M2_DISPLAY_PORT_MIN,
-                  .max = G4X_M2_DISPLAY_PORT_MAX },
-         .p   = { .min = G4X_P_DISPLAY_PORT_MIN,
-                  .max = G4X_P_DISPLAY_PORT_MAX },
-         .p1  = { .min = G4X_P1_DISPLAY_PORT_MIN,
-                  .max = G4X_P1_DISPLAY_PORT_MAX},
-         .p2  = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT,
-                  .p2_slow = G4X_P2_DISPLAY_PORT_SLOW,
-                  .p2_fast = G4X_P2_DISPLAY_PORT_FAST },
+         .dot = { .min = 161670, .max = 227000 },
+         .vco = { .min = 1750000, .max = 3500000},
+         .n = { .min = 1, .max = 2 },
+         .m = { .min = 97, .max = 108 },
+         .m1 = { .min = 0x10, .max = 0x12 },
+         .m2 = { .min = 0x05, .max = 0x06 },
+         .p = { .min = 10, .max = 20 },
+         .p1 = { .min = 1, .max = 2},
+         .p2 = { .dot_limit = 0,
+               .p2_slow = 10, .p2_fast = 10 },
          .find_pll = intel_find_pll_g4x_dp,
  };
  
  static const intel_limit_t intel_limits_pineview_sdvo = {
-         .dot = { .min = I9XX_DOT_MIN,         .max = I9XX_DOT_MAX},
-         .vco = { .min = PINEVIEW_VCO_MIN,             .max = PINEVIEW_VCO_MAX },
-         .n   = { .min = PINEVIEW_N_MIN,               .max = PINEVIEW_N_MAX },
-         .m   = { .min = PINEVIEW_M_MIN,               .max = PINEVIEW_M_MAX },
-         .m1  = { .min = PINEVIEW_M1_MIN,              .max = PINEVIEW_M1_MAX },
-         .m2  = { .min = PINEVIEW_M2_MIN,              .max = PINEVIEW_M2_MAX },
-         .p   = { .min = I9XX_P_SDVO_DAC_MIN,    .max = I9XX_P_SDVO_DAC_MAX },
-         .p1  = { .min = I9XX_P1_MIN,          .max = I9XX_P1_MAX },
-       .p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
-                .p2_slow = I9XX_P2_SDVO_DAC_SLOW,      .p2_fast = I9XX_P2_SDVO_DAC_FAST },
+         .dot = { .min = 20000, .max = 400000},
+         .vco = { .min = 1700000, .max = 3500000 },
+       /* Pineview's Ncounter is a ring counter */
+         .n = { .min = 3, .max = 6 },
+         .m = { .min = 2, .max = 256 },
+       /* Pineview only has one combined m divider, which we treat as m2. */
+         .m1 = { .min = 0, .max = 0 },
+         .m2 = { .min = 0, .max = 254 },
+         .p = { .min = 5, .max = 80 },
+         .p1 = { .min = 1, .max = 8 },
+       .p2 = { .dot_limit = 200000,
+               .p2_slow = 10, .p2_fast = 5 },
        .find_pll = intel_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_pineview_lvds = {
-         .dot = { .min = I9XX_DOT_MIN,         .max = I9XX_DOT_MAX },
-         .vco = { .min = PINEVIEW_VCO_MIN,             .max = PINEVIEW_VCO_MAX },
-         .n   = { .min = PINEVIEW_N_MIN,               .max = PINEVIEW_N_MAX },
-         .m   = { .min = PINEVIEW_M_MIN,               .max = PINEVIEW_M_MAX },
-         .m1  = { .min = PINEVIEW_M1_MIN,              .max = PINEVIEW_M1_MAX },
-         .m2  = { .min = PINEVIEW_M2_MIN,              .max = PINEVIEW_M2_MAX },
-         .p   = { .min = PINEVIEW_P_LVDS_MIN,  .max = PINEVIEW_P_LVDS_MAX },
-         .p1  = { .min = I9XX_P1_MIN,          .max = I9XX_P1_MAX },
-       /* Pineview only supports single-channel mode. */
-       .p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
-                .p2_slow = I9XX_P2_LVDS_SLOW,  .p2_fast = I9XX_P2_LVDS_SLOW },
+         .dot = { .min = 20000, .max = 400000 },
+         .vco = { .min = 1700000, .max = 3500000 },
+         .n = { .min = 3, .max = 6 },
+         .m = { .min = 2, .max = 256 },
+         .m1 = { .min = 0, .max = 0 },
+         .m2 = { .min = 0, .max = 254 },
+         .p = { .min = 7, .max = 112 },
+         .p1 = { .min = 1, .max = 8 },
+       .p2 = { .dot_limit = 112000,
+               .p2_slow = 14, .p2_fast = 14 },
        .find_pll = intel_find_best_PLL,
  };
  
+ /* Ironlake / Sandybridge
+  *
+  * We calculate clock using (register_value + 2) for N/M1/M2, so here
+  * the range value for them is (actual_value - 2).
+  */
  static const intel_limit_t intel_limits_ironlake_dac = {
-       .dot = { .min = IRONLAKE_DOT_MIN,          .max = IRONLAKE_DOT_MAX },
-       .vco = { .min = IRONLAKE_VCO_MIN,          .max = IRONLAKE_VCO_MAX },
-       .n   = { .min = IRONLAKE_DAC_N_MIN,        .max = IRONLAKE_DAC_N_MAX },
-       .m   = { .min = IRONLAKE_DAC_M_MIN,        .max = IRONLAKE_DAC_M_MAX },
-       .m1  = { .min = IRONLAKE_M1_MIN,           .max = IRONLAKE_M1_MAX },
-       .m2  = { .min = IRONLAKE_M2_MIN,           .max = IRONLAKE_M2_MAX },
-       .p   = { .min = IRONLAKE_DAC_P_MIN,        .max = IRONLAKE_DAC_P_MAX },
-       .p1  = { .min = IRONLAKE_DAC_P1_MIN,       .max = IRONLAKE_DAC_P1_MAX },
-       .p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
-                .p2_slow = IRONLAKE_DAC_P2_SLOW,
-                .p2_fast = IRONLAKE_DAC_P2_FAST },
+       .dot = { .min = 25000, .max = 350000 },
+       .vco = { .min = 1760000, .max = 3510000 },
+       .n = { .min = 1, .max = 5 },
+       .m = { .min = 79, .max = 127 },
+       .m1 = { .min = 12, .max = 22 },
+       .m2 = { .min = 5, .max = 9 },
+       .p = { .min = 5, .max = 80 },
+       .p1 = { .min = 1, .max = 8 },
+       .p2 = { .dot_limit = 225000,
+               .p2_slow = 10, .p2_fast = 5 },
        .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_ironlake_single_lvds = {
-       .dot = { .min = IRONLAKE_DOT_MIN,          .max = IRONLAKE_DOT_MAX },
-       .vco = { .min = IRONLAKE_VCO_MIN,          .max = IRONLAKE_VCO_MAX },
-       .n   = { .min = IRONLAKE_LVDS_S_N_MIN,     .max = IRONLAKE_LVDS_S_N_MAX },
-       .m   = { .min = IRONLAKE_LVDS_S_M_MIN,     .max = IRONLAKE_LVDS_S_M_MAX },
-       .m1  = { .min = IRONLAKE_M1_MIN,           .max = IRONLAKE_M1_MAX },
-       .m2  = { .min = IRONLAKE_M2_MIN,           .max = IRONLAKE_M2_MAX },
-       .p   = { .min = IRONLAKE_LVDS_S_P_MIN,     .max = IRONLAKE_LVDS_S_P_MAX },
-       .p1  = { .min = IRONLAKE_LVDS_S_P1_MIN,    .max = IRONLAKE_LVDS_S_P1_MAX },
-       .p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
-                .p2_slow = IRONLAKE_LVDS_S_P2_SLOW,
-                .p2_fast = IRONLAKE_LVDS_S_P2_FAST },
+       .dot = { .min = 25000, .max = 350000 },
+       .vco = { .min = 1760000, .max = 3510000 },
+       .n = { .min = 1, .max = 3 },
+       .m = { .min = 79, .max = 118 },
+       .m1 = { .min = 12, .max = 22 },
+       .m2 = { .min = 5, .max = 9 },
+       .p = { .min = 28, .max = 112 },
+       .p1 = { .min = 2, .max = 8 },
+       .p2 = { .dot_limit = 225000,
+               .p2_slow = 14, .p2_fast = 14 },
        .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_ironlake_dual_lvds = {
-       .dot = { .min = IRONLAKE_DOT_MIN,          .max = IRONLAKE_DOT_MAX },
-       .vco = { .min = IRONLAKE_VCO_MIN,          .max = IRONLAKE_VCO_MAX },
-       .n   = { .min = IRONLAKE_LVDS_D_N_MIN,     .max = IRONLAKE_LVDS_D_N_MAX },
-       .m   = { .min = IRONLAKE_LVDS_D_M_MIN,     .max = IRONLAKE_LVDS_D_M_MAX },
-       .m1  = { .min = IRONLAKE_M1_MIN,           .max = IRONLAKE_M1_MAX },
-       .m2  = { .min = IRONLAKE_M2_MIN,           .max = IRONLAKE_M2_MAX },
-       .p   = { .min = IRONLAKE_LVDS_D_P_MIN,     .max = IRONLAKE_LVDS_D_P_MAX },
-       .p1  = { .min = IRONLAKE_LVDS_D_P1_MIN,    .max = IRONLAKE_LVDS_D_P1_MAX },
-       .p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
-                .p2_slow = IRONLAKE_LVDS_D_P2_SLOW,
-                .p2_fast = IRONLAKE_LVDS_D_P2_FAST },
+       .dot = { .min = 25000, .max = 350000 },
+       .vco = { .min = 1760000, .max = 3510000 },
+       .n = { .min = 1, .max = 3 },
+       .m = { .min = 79, .max = 127 },
+       .m1 = { .min = 12, .max = 22 },
+       .m2 = { .min = 5, .max = 9 },
+       .p = { .min = 14, .max = 56 },
+       .p1 = { .min = 2, .max = 8 },
+       .p2 = { .dot_limit = 225000,
+               .p2_slow = 7, .p2_fast = 7 },
        .find_pll = intel_g4x_find_best_PLL,
  };
  
+ /* LVDS 100mhz refclk limits. */
  static const intel_limit_t intel_limits_ironlake_single_lvds_100m = {
-       .dot = { .min = IRONLAKE_DOT_MIN,          .max = IRONLAKE_DOT_MAX },
-       .vco = { .min = IRONLAKE_VCO_MIN,          .max = IRONLAKE_VCO_MAX },
-       .n   = { .min = IRONLAKE_LVDS_S_SSC_N_MIN, .max = IRONLAKE_LVDS_S_SSC_N_MAX },
-       .m   = { .min = IRONLAKE_LVDS_S_SSC_M_MIN, .max = IRONLAKE_LVDS_S_SSC_M_MAX },
-       .m1  = { .min = IRONLAKE_M1_MIN,           .max = IRONLAKE_M1_MAX },
-       .m2  = { .min = IRONLAKE_M2_MIN,           .max = IRONLAKE_M2_MAX },
-       .p   = { .min = IRONLAKE_LVDS_S_SSC_P_MIN, .max = IRONLAKE_LVDS_S_SSC_P_MAX },
-       .p1  = { .min = IRONLAKE_LVDS_S_SSC_P1_MIN,.max = IRONLAKE_LVDS_S_SSC_P1_MAX },
-       .p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
-                .p2_slow = IRONLAKE_LVDS_S_SSC_P2_SLOW,
-                .p2_fast = IRONLAKE_LVDS_S_SSC_P2_FAST },
+       .dot = { .min = 25000, .max = 350000 },
+       .vco = { .min = 1760000, .max = 3510000 },
+       .n = { .min = 1, .max = 2 },
+       .m = { .min = 79, .max = 126 },
+       .m1 = { .min = 12, .max = 22 },
+       .m2 = { .min = 5, .max = 9 },
+       .p = { .min = 28, .max = 112 },
+       .p1 = { .min = 2,.max = 8 },
+       .p2 = { .dot_limit = 225000,
+               .p2_slow = 14, .p2_fast = 14 },
        .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
-       .dot = { .min = IRONLAKE_DOT_MIN,          .max = IRONLAKE_DOT_MAX },
-       .vco = { .min = IRONLAKE_VCO_MIN,          .max = IRONLAKE_VCO_MAX },
-       .n   = { .min = IRONLAKE_LVDS_D_SSC_N_MIN, .max = IRONLAKE_LVDS_D_SSC_N_MAX },
-       .m   = { .min = IRONLAKE_LVDS_D_SSC_M_MIN, .max = IRONLAKE_LVDS_D_SSC_M_MAX },
-       .m1  = { .min = IRONLAKE_M1_MIN,           .max = IRONLAKE_M1_MAX },
-       .m2  = { .min = IRONLAKE_M2_MIN,           .max = IRONLAKE_M2_MAX },
-       .p   = { .min = IRONLAKE_LVDS_D_SSC_P_MIN, .max = IRONLAKE_LVDS_D_SSC_P_MAX },
-       .p1  = { .min = IRONLAKE_LVDS_D_SSC_P1_MIN,.max = IRONLAKE_LVDS_D_SSC_P1_MAX },
-       .p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
-                .p2_slow = IRONLAKE_LVDS_D_SSC_P2_SLOW,
-                .p2_fast = IRONLAKE_LVDS_D_SSC_P2_FAST },
+       .dot = { .min = 25000, .max = 350000 },
+       .vco = { .min = 1760000, .max = 3510000 },
+       .n = { .min = 1, .max = 3 },
+       .m = { .min = 79, .max = 126 },
+       .m1 = { .min = 12, .max = 22 },
+       .m2 = { .min = 5, .max = 9 },
+       .p = { .min = 14, .max = 42 },
+       .p1 = { .min = 2,.max = 6 },
+       .p2 = { .dot_limit = 225000,
+               .p2_slow = 7, .p2_fast = 7 },
        .find_pll = intel_g4x_find_best_PLL,
  };
  
  static const intel_limit_t intel_limits_ironlake_display_port = {
-         .dot = { .min = IRONLAKE_DOT_MIN,
-                  .max = IRONLAKE_DOT_MAX },
-         .vco = { .min = IRONLAKE_VCO_MIN,
-                  .max = IRONLAKE_VCO_MAX},
-         .n   = { .min = IRONLAKE_DP_N_MIN,
-                  .max = IRONLAKE_DP_N_MAX },
-         .m   = { .min = IRONLAKE_DP_M_MIN,
-                  .max = IRONLAKE_DP_M_MAX },
-         .m1  = { .min = IRONLAKE_M1_MIN,
-                  .max = IRONLAKE_M1_MAX },
-         .m2  = { .min = IRONLAKE_M2_MIN,
-                  .max = IRONLAKE_M2_MAX },
-         .p   = { .min = IRONLAKE_DP_P_MIN,
-                  .max = IRONLAKE_DP_P_MAX },
-         .p1  = { .min = IRONLAKE_DP_P1_MIN,
-                  .max = IRONLAKE_DP_P1_MAX},
-         .p2  = { .dot_limit = IRONLAKE_DP_P2_LIMIT,
-                  .p2_slow = IRONLAKE_DP_P2_SLOW,
-                  .p2_fast = IRONLAKE_DP_P2_FAST },
+         .dot = { .min = 25000, .max = 350000 },
+         .vco = { .min = 1760000, .max = 3510000},
+         .n = { .min = 1, .max = 2 },
+         .m = { .min = 81, .max = 90 },
+         .m1 = { .min = 12, .max = 22 },
+         .m2 = { .min = 5, .max = 9 },
+         .p = { .min = 10, .max = 20 },
+         .p1 = { .min = 1, .max = 2},
+         .p2 = { .dot_limit = 0,
+               .p2_slow = 10, .p2_fast = 10 },
          .find_pll = intel_find_pll_ironlake_dp,
  };
  
@@@ -1828,7 -1540,7 +1540,7 @@@ static void sandybridge_blit_fbc_update
        u32 blt_ecoskpd;
  
        /* Make sure blitter notifies FBC of writes */
-       __gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv);
        blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD);
        blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY <<
                GEN6_BLITTER_LOCK_SHIFT;
                         GEN6_BLITTER_LOCK_SHIFT);
        I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
        POSTING_READ(GEN6_BLITTER_ECOSKPD);
-       __gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv);
  }
  
  static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
@@@ -2019,6 -1731,11 +1731,11 @@@ static void intel_update_fbc(struct drm
        intel_fb = to_intel_framebuffer(fb);
        obj = intel_fb->obj;
  
+       if (!i915_enable_fbc) {
+               DRM_DEBUG_KMS("fbc disabled per module param (default off)\n");
+               dev_priv->no_fbc_reason = FBC_MODULE_PARAM;
+               goto out_disable;
+       }
        if (intel_fb->obj->base.size > dev_priv->cfb_size) {
                DRM_DEBUG_KMS("framebuffer too large, disabling "
                              "compression\n");
@@@ -2339,8 -2056,13 +2056,13 @@@ static void intel_fdi_normal_train(stru
        /* enable normal train */
        reg = FDI_TX_CTL(pipe);
        temp = I915_READ(reg);
-       temp &= ~FDI_LINK_TRAIN_NONE;
-       temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;
+       if (IS_IVYBRIDGE(dev)) {
+               temp &= ~FDI_LINK_TRAIN_NONE_IVB;
+               temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE;
+       } else {
+               temp &= ~FDI_LINK_TRAIN_NONE;
+               temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;
+       }
        I915_WRITE(reg, temp);
  
        reg = FDI_RX_CTL(pipe);
        /* wait one idle pattern time */
        POSTING_READ(reg);
        udelay(1000);
+       /* IVB wants error correction enabled */
+       if (IS_IVYBRIDGE(dev))
+               I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE |
+                          FDI_FE_ERRC_ENABLE);
  }
  
  /* The FDI link training functions for ILK/Ibexpeak. */
@@@ -2584,7 -2311,116 +2311,116 @@@ static void gen6_fdi_link_train(struct 
        DRM_DEBUG_KMS("FDI train done.\n");
  }
  
- static void ironlake_fdi_enable(struct drm_crtc *crtc)
+ /* Manual link training for Ivy Bridge A0 parts */
+ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
+ {
+       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;
+       u32 reg, temp, i;
+       /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
+          for train result */
+       reg = FDI_RX_IMR(pipe);
+       temp = I915_READ(reg);
+       temp &= ~FDI_RX_SYMBOL_LOCK;
+       temp &= ~FDI_RX_BIT_LOCK;
+       I915_WRITE(reg, temp);
+       POSTING_READ(reg);
+       udelay(150);
+       /* enable CPU FDI TX and PCH FDI RX */
+       reg = FDI_TX_CTL(pipe);
+       temp = I915_READ(reg);
+       temp &= ~(7 << 19);
+       temp |= (intel_crtc->fdi_lanes - 1) << 19;
+       temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB);
+       temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
+       temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
+       temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
+       I915_WRITE(reg, temp | FDI_TX_ENABLE);
+       reg = FDI_RX_CTL(pipe);
+       temp = I915_READ(reg);
+       temp &= ~FDI_LINK_TRAIN_AUTO;
+       temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+       temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+       I915_WRITE(reg, temp | FDI_RX_ENABLE);
+       POSTING_READ(reg);
+       udelay(150);
+       for (i = 0; i < 4; i++ ) {
+               reg = FDI_TX_CTL(pipe);
+               temp = I915_READ(reg);
+               temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
+               temp |= snb_b_fdi_train_param[i];
+               I915_WRITE(reg, temp);
+               POSTING_READ(reg);
+               udelay(500);
+               reg = FDI_RX_IIR(pipe);
+               temp = I915_READ(reg);
+               DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
+               if (temp & FDI_RX_BIT_LOCK ||
+                   (I915_READ(reg) & FDI_RX_BIT_LOCK)) {
+                       I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
+                       DRM_DEBUG_KMS("FDI train 1 done.\n");
+                       break;
+               }
+       }
+       if (i == 4)
+               DRM_ERROR("FDI train 1 fail!\n");
+       /* Train 2 */
+       reg = FDI_TX_CTL(pipe);
+       temp = I915_READ(reg);
+       temp &= ~FDI_LINK_TRAIN_NONE_IVB;
+       temp |= FDI_LINK_TRAIN_PATTERN_2_IVB;
+       temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
+       temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
+       I915_WRITE(reg, temp);
+       reg = FDI_RX_CTL(pipe);
+       temp = I915_READ(reg);
+       temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+       temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
+       I915_WRITE(reg, temp);
+       POSTING_READ(reg);
+       udelay(150);
+       for (i = 0; i < 4; i++ ) {
+               reg = FDI_TX_CTL(pipe);
+               temp = I915_READ(reg);
+               temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
+               temp |= snb_b_fdi_train_param[i];
+               I915_WRITE(reg, temp);
+               POSTING_READ(reg);
+               udelay(500);
+               reg = FDI_RX_IIR(pipe);
+               temp = I915_READ(reg);
+               DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
+               if (temp & FDI_RX_SYMBOL_LOCK) {
+                       I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
+                       DRM_DEBUG_KMS("FDI train 2 done.\n");
+                       break;
+               }
+       }
+       if (i == 4)
+               DRM_ERROR("FDI train 2 fail!\n");
+       DRM_DEBUG_KMS("FDI train done.\n");
+ }
+ static void ironlake_fdi_pll_enable(struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@@ -2757,10 -2593,7 +2593,7 @@@ static void ironlake_pch_enable(struct 
        u32 reg, temp;
  
        /* For PCH output, training FDI link */
-       if (IS_GEN6(dev))
-               gen6_fdi_link_train(crtc);
-       else
-               ironlake_fdi_link_train(crtc);
+       dev_priv->display.fdi_link_train(crtc);
  
        intel_enable_pch_pll(dev_priv, pipe);
  
@@@ -2850,7 -2683,7 +2683,7 @@@ static void ironlake_crtc_enable(struc
        is_pch_port = intel_crtc_driving_pch(crtc);
  
        if (is_pch_port)
-               ironlake_fdi_enable(crtc);
+               ironlake_fdi_pll_enable(crtc);
        else
                ironlake_fdi_disable(crtc);
  
                ironlake_pch_enable(crtc);
  
        intel_crtc_load_lut(crtc);
+       mutex_lock(&dev->struct_mutex);
        intel_update_fbc(dev);
+       mutex_unlock(&dev->struct_mutex);
        intel_crtc_update_cursor(crtc, true);
  }
  
@@@ -2969,8 -2806,11 +2806,11 @@@ static void ironlake_crtc_disable(struc
  
        intel_crtc->active = false;
        intel_update_watermarks(dev);
+       mutex_lock(&dev->struct_mutex);
        intel_update_fbc(dev);
        intel_clear_scanline_wait(dev);
+       mutex_unlock(&dev->struct_mutex);
  }
  
  static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
@@@ -3497,11 -3337,11 +3337,11 @@@ static unsigned long intel_calculate_wm
                1000;
        entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size);
  
-       DRM_DEBUG_KMS("FIFO entries required for mode: %d\n", entries_required);
+       DRM_DEBUG_KMS("FIFO entries required for mode: %ld\n", entries_required);
  
        wm_size = fifo_size - (entries_required + wm->guard_size);
  
-       DRM_DEBUG_KMS("FIFO watermark level: %d\n", wm_size);
+       DRM_DEBUG_KMS("FIFO watermark level: %ld\n", wm_size);
  
        /* Don't promote wm_size to unsigned... */
        if (wm_size > (long)wm->max_wm)
@@@ -3823,13 -3663,13 +3663,13 @@@ static bool g4x_check_srwm(struct drm_d
                      display_wm, cursor_wm);
  
        if (display_wm > display->max_wm) {
-               DRM_DEBUG_KMS("display watermark is too large(%d), disabling\n",
+               DRM_DEBUG_KMS("display watermark is too large(%d/%ld), disabling\n",
                              display_wm, display->max_wm);
                return false;
        }
  
        if (cursor_wm > cursor->max_wm) {
-               DRM_DEBUG_KMS("cursor watermark is too large(%d), disabling\n",
+               DRM_DEBUG_KMS("cursor watermark is too large(%d/%ld), disabling\n",
                              cursor_wm, cursor->max_wm);
                return false;
        }
@@@ -4516,34 -4356,28 +4356,28 @@@ static inline bool intel_panel_use_ssc(
        return dev_priv->lvds_use_ssc && i915_panel_use_ssc;
  }
  
- static int intel_crtc_mode_set(struct drm_crtc *crtc,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode,
-                              int x, int y,
-                              struct drm_framebuffer *old_fb)
+ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
+                             struct drm_display_mode *mode,
+                             struct drm_display_mode *adjusted_mode,
+                             int x, int y,
+                             struct drm_framebuffer *old_fb)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
-       u32 fp_reg, dpll_reg;
        int refclk, num_connectors = 0;
        intel_clock_t clock, reduced_clock;
        u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf;
        bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
        bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
-       struct intel_encoder *has_edp_encoder = NULL;
        struct drm_mode_config *mode_config = &dev->mode_config;
        struct intel_encoder *encoder;
        const intel_limit_t *limit;
        int ret;
-       struct fdi_m_n m_n = {0};
-       u32 reg, temp;
+       u32 temp;
        u32 lvds_sync = 0;
-       int target_clock;
-       drm_vblank_pre_modeset(dev, pipe);
  
        list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
                if (encoder->base.crtc != crtc)
                case INTEL_OUTPUT_DISPLAYPORT:
                        is_dp = true;
                        break;
-               case INTEL_OUTPUT_EDP:
-                       has_edp_encoder = encoder;
-                       break;
                }
  
                num_connectors++;
                              refclk / 1000);
        } else if (!IS_GEN2(dev)) {
                refclk = 96000;
-               if (HAS_PCH_SPLIT(dev) &&
-                   (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)))
-                       refclk = 120000; /* 120Mhz refclk */
        } else {
                refclk = 48000;
        }
        ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock);
        if (!ok) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
-               drm_vblank_post_modeset(dev, pipe);
                return -EINVAL;
        }
  
                }
        }
  
-       /* FDI link */
-       if (HAS_PCH_SPLIT(dev)) {
-               int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
-               int lane = 0, link_bw, bpp;
-               /* CPU eDP doesn't require FDI link, so just set DP M/N
-                  according to current link config */
-               if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-                       target_clock = mode->clock;
-                       intel_edp_link_config(has_edp_encoder,
-                                             &lane, &link_bw);
-               } else {
-                       /* [e]DP over FDI requires target mode clock
-                          instead of link clock */
-                       if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base))
-                               target_clock = mode->clock;
-                       else
-                               target_clock = adjusted_mode->clock;
-                       /* FDI is a binary signal running at ~2.7GHz, encoding
-                        * each output octet as 10 bits. The actual frequency
-                        * is stored as a divider into a 100MHz clock, and the
-                        * mode pixel clock is stored in units of 1KHz.
-                        * Hence the bw of each lane in terms of the mode signal
-                        * is:
-                        */
-                       link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
-               }
-               /* determine panel color depth */
-               temp = I915_READ(PIPECONF(pipe));
-               temp &= ~PIPE_BPC_MASK;
-               if (is_lvds) {
-                       /* the BPC will be 6 if it is 18-bit LVDS panel */
-                       if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
-                               temp |= PIPE_8BPC;
-                       else
-                               temp |= PIPE_6BPC;
-               } else if (has_edp_encoder) {
-                       switch (dev_priv->edp.bpp/3) {
-                       case 8:
-                               temp |= PIPE_8BPC;
-                               break;
-                       case 10:
-                               temp |= PIPE_10BPC;
-                               break;
-                       case 6:
-                               temp |= PIPE_6BPC;
-                               break;
-                       case 12:
-                               temp |= PIPE_12BPC;
-                               break;
-                       }
-               } else
-                       temp |= PIPE_8BPC;
-               I915_WRITE(PIPECONF(pipe), temp);
-               switch (temp & PIPE_BPC_MASK) {
-               case PIPE_8BPC:
-                       bpp = 24;
-                       break;
-               case PIPE_10BPC:
-                       bpp = 30;
-                       break;
-               case PIPE_6BPC:
-                       bpp = 18;
-                       break;
-               case PIPE_12BPC:
-                       bpp = 36;
-                       break;
-               default:
-                       DRM_ERROR("unknown pipe bpc value\n");
-                       bpp = 24;
-               }
-               if (!lane) {
-                       /* 
-                        * Account for spread spectrum to avoid
-                        * oversubscribing the link. Max center spread
-                        * is 2.5%; use 5% for safety's sake.
-                        */
-                       u32 bps = target_clock * bpp * 21 / 20;
-                       lane = bps / (link_bw * 8) + 1;
-               }
-               intel_crtc->fdi_lanes = lane;
-               if (pixel_multiplier > 1)
-                       link_bw *= pixel_multiplier;
-               ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
-       }
-       /* Ironlake: try to setup display ref clock before DPLL
-        * enabling. This is only under driver's control after
-        * PCH B stepping, previous chipset stepping should be
-        * ignoring this setting.
-        */
-       if (HAS_PCH_SPLIT(dev)) {
-               temp = I915_READ(PCH_DREF_CONTROL);
-               /* Always enable nonspread source */
-               temp &= ~DREF_NONSPREAD_SOURCE_MASK;
-               temp |= DREF_NONSPREAD_SOURCE_ENABLE;
-               temp &= ~DREF_SSC_SOURCE_MASK;
-               temp |= DREF_SSC_SOURCE_ENABLE;
-               I915_WRITE(PCH_DREF_CONTROL, temp);
-               POSTING_READ(PCH_DREF_CONTROL);
-               udelay(200);
-               if (has_edp_encoder) {
-                       if (intel_panel_use_ssc(dev_priv)) {
-                               temp |= DREF_SSC1_ENABLE;
-                               I915_WRITE(PCH_DREF_CONTROL, temp);
-                               POSTING_READ(PCH_DREF_CONTROL);
-                               udelay(200);
-                       }
-                       temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
-                       /* Enable CPU source on CPU attached eDP */
-                       if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-                               if (intel_panel_use_ssc(dev_priv))
-                                       temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
-                               else
-                                       temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
-                       } else {
-                               /* Enable SSC on PCH eDP if needed */
-                               if (intel_panel_use_ssc(dev_priv)) {
-                                       DRM_ERROR("enabling SSC on PCH\n");
-                                       temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
-                               }
-                       }
-                       I915_WRITE(PCH_DREF_CONTROL, temp);
-                       POSTING_READ(PCH_DREF_CONTROL);
-                       udelay(200);
-               }
-       }
        if (IS_PINEVIEW(dev)) {
                fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
                if (has_reduced_clock)
                                reduced_clock.m2;
        }
  
-       /* Enable autotuning of the PLL clock (if permissible) */
-       if (HAS_PCH_SPLIT(dev)) {
-               int factor = 21;
-               if (is_lvds) {
-                       if ((intel_panel_use_ssc(dev_priv) &&
-                            dev_priv->lvds_ssc_freq == 100) ||
-                           (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
-                               factor = 25;
-               } else if (is_sdvo && is_tv)
-                       factor = 20;
-               if (clock.m1 < factor * clock.n)
-                       fp |= FP_CB_TUNE;
-       }
-       dpll = 0;
-       if (!HAS_PCH_SPLIT(dev))
-               dpll = DPLL_VGA_MODE_DIS;
+       dpll = DPLL_VGA_MODE_DIS;
  
        if (!IS_GEN2(dev)) {
                if (is_lvds)
                        if (pixel_multiplier > 1) {
                                if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
                                        dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
-                               else if (HAS_PCH_SPLIT(dev))
-                                       dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
                        }
                        dpll |= DPLL_DVO_HIGH_SPEED;
                }
-               if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base))
+               if (is_dp)
                        dpll |= DPLL_DVO_HIGH_SPEED;
  
                /* compute bitmask from p1 value */
                        dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW;
                else {
                        dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-                       /* also FPA1 */
-                       if (HAS_PCH_SPLIT(dev))
-                               dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
                        if (IS_G4X(dev) && has_reduced_clock)
                                dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
                }
                        dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
                        break;
                }
-               if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
+               if (INTEL_INFO(dev)->gen >= 4)
                        dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
        } else {
                if (is_lvds) {
  
        /* Ironlake's plane is forced to pipe, bit 24 is to
           enable color space conversion */
-       if (!HAS_PCH_SPLIT(dev)) {
-               if (pipe == 0)
-                       dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
-               else
-                       dspcntr |= DISPPLANE_SEL_PIPE_B;
-       }
+       if (pipe == 0)
+               dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
+       else
+               dspcntr |= DISPPLANE_SEL_PIPE_B;
  
        if (pipe == 0 && INTEL_INFO(dev)->gen < 4) {
                /* Enable pixel doubling when the dot clock is > 90% of the (display)
                        pipeconf &= ~PIPECONF_DOUBLE_WIDE;
        }
  
-       if (!HAS_PCH_SPLIT(dev))
-               dpll |= DPLL_VCO_ENABLE;
+       dpll |= DPLL_VCO_ENABLE;
  
        DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
        drm_mode_debug_printmodeline(mode);
  
-       /* assign to Ironlake registers */
-       if (HAS_PCH_SPLIT(dev)) {
-               fp_reg = PCH_FP0(pipe);
-               dpll_reg = PCH_DPLL(pipe);
-       } else {
-               fp_reg = FP0(pipe);
-               dpll_reg = DPLL(pipe);
-       }
-       /* PCH eDP needs FDI, but CPU eDP does not */
-       if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-               I915_WRITE(fp_reg, fp);
-               I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
-               POSTING_READ(dpll_reg);
-               udelay(150);
-       }
-       /* enable transcoder DPLL */
-       if (HAS_PCH_CPT(dev)) {
-               temp = I915_READ(PCH_DPLL_SEL);
-               switch (pipe) {
-               case 0:
-                       temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL;
-                       break;
-               case 1:
-                       temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL;
-                       break;
-               case 2:
-                       /* FIXME: manage transcoder PLLs? */
-                       temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL;
-                       break;
-               default:
-                       BUG();
-               }
-               I915_WRITE(PCH_DPLL_SEL, temp);
+       I915_WRITE(FP0(pipe), fp);
+       I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
  
-               POSTING_READ(PCH_DPLL_SEL);
-               udelay(150);
-       }
+       POSTING_READ(DPLL(pipe));
+       udelay(150);
  
        /* The LVDS pin pair needs to be on before the DPLLs are enabled.
         * This is an exception to the general rule that mode_set doesn't turn
         * things on.
         */
        if (is_lvds) {
-               reg = LVDS;
-               if (HAS_PCH_SPLIT(dev))
-                       reg = PCH_LVDS;
-               temp = I915_READ(reg);
+               temp = I915_READ(LVDS);
                temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
                if (pipe == 1) {
-                       if (HAS_PCH_CPT(dev))
-                               temp |= PORT_TRANS_B_SEL_CPT;
-                       else
-                               temp |= LVDS_PIPEB_SELECT;
+                       temp |= LVDS_PIPEB_SELECT;
                } else {
-                       if (HAS_PCH_CPT(dev))
-                               temp &= ~PORT_TRANS_SEL_MASK;
-                       else
-                               temp &= ~LVDS_PIPEB_SELECT;
+                       temp &= ~LVDS_PIPEB_SELECT;
                }
                /* set the corresponsding LVDS_BORDER bit */
                temp |= dev_priv->lvds_border_bits;
                 * appropriately here, but we need to look more thoroughly into how
                 * panels behave in the two modes.
                 */
-               /* set the dithering flag on non-PCH LVDS as needed */
-               if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
+               /* set the dithering flag on LVDS as needed */
+               if (INTEL_INFO(dev)->gen >= 4) {
                        if (dev_priv->lvds_dither)
                                temp |= LVDS_ENABLE_DITHER;
                        else
                        temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
                        temp |= lvds_sync;
                }
-               I915_WRITE(reg, temp);
+               I915_WRITE(LVDS, temp);
        }
  
-       /* set the dithering flag and clear for anything other than a panel. */
-       if (HAS_PCH_SPLIT(dev)) {
-               pipeconf &= ~PIPECONF_DITHER_EN;
-               pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
-               if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) {
-                       pipeconf |= PIPECONF_DITHER_EN;
-                       pipeconf |= PIPECONF_DITHER_TYPE_ST1;
-               }
+       if (is_dp) {
+               intel_dp_set_m_n(crtc, mode, adjusted_mode);
        }
  
-       if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-               intel_dp_set_m_n(crtc, mode, adjusted_mode);
-       } else if (HAS_PCH_SPLIT(dev)) {
-               /* For non-DP output, clear any trans DP clock recovery setting.*/
-               I915_WRITE(TRANSDATA_M1(pipe), 0);
+       I915_WRITE(DPLL(pipe), dpll);
+       /* Wait for the clocks to stabilize. */
+       POSTING_READ(DPLL(pipe));
+       udelay(150);
+       if (INTEL_INFO(dev)->gen >= 4) {
+               temp = 0;
+               if (is_sdvo) {
+                       temp = intel_mode_get_pixel_multiplier(adjusted_mode);
+                       if (temp > 1)
+                               temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
+                       else
+                               temp = 0;
+               }
+               I915_WRITE(DPLL_MD(pipe), temp);
+       } else {
+               /* The pixel multiplier can only be updated once the
+                * DPLL is enabled and the clocks are stable.
+                *
+                * So write it again.
+                */
+               I915_WRITE(DPLL(pipe), dpll);
+       }
+       intel_crtc->lowfreq_avail = false;
+       if (is_lvds && has_reduced_clock && i915_powersave) {
+               I915_WRITE(FP1(pipe), fp2);
+               intel_crtc->lowfreq_avail = true;
+               if (HAS_PIPE_CXSR(dev)) {
+                       DRM_DEBUG_KMS("enabling CxSR downclocking\n");
+                       pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
+               }
+       } else {
+               I915_WRITE(FP1(pipe), fp);
+               if (HAS_PIPE_CXSR(dev)) {
+                       DRM_DEBUG_KMS("disabling CxSR downclocking\n");
+                       pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+               }
+       }
+       if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+               pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+               /* the chip adds 2 halflines automatically */
+               adjusted_mode->crtc_vdisplay -= 1;
+               adjusted_mode->crtc_vtotal -= 1;
+               adjusted_mode->crtc_vblank_start -= 1;
+               adjusted_mode->crtc_vblank_end -= 1;
+               adjusted_mode->crtc_vsync_end -= 1;
+               adjusted_mode->crtc_vsync_start -= 1;
+       } else
+               pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */
+       I915_WRITE(HTOTAL(pipe),
+                  (adjusted_mode->crtc_hdisplay - 1) |
+                  ((adjusted_mode->crtc_htotal - 1) << 16));
+       I915_WRITE(HBLANK(pipe),
+                  (adjusted_mode->crtc_hblank_start - 1) |
+                  ((adjusted_mode->crtc_hblank_end - 1) << 16));
+       I915_WRITE(HSYNC(pipe),
+                  (adjusted_mode->crtc_hsync_start - 1) |
+                  ((adjusted_mode->crtc_hsync_end - 1) << 16));
+       I915_WRITE(VTOTAL(pipe),
+                  (adjusted_mode->crtc_vdisplay - 1) |
+                  ((adjusted_mode->crtc_vtotal - 1) << 16));
+       I915_WRITE(VBLANK(pipe),
+                  (adjusted_mode->crtc_vblank_start - 1) |
+                  ((adjusted_mode->crtc_vblank_end - 1) << 16));
+       I915_WRITE(VSYNC(pipe),
+                  (adjusted_mode->crtc_vsync_start - 1) |
+                  ((adjusted_mode->crtc_vsync_end - 1) << 16));
+       /* pipesrc and dspsize control the size that is scaled from,
+        * which should always be the user's requested size.
+        */
+       I915_WRITE(DSPSIZE(plane),
+                  ((mode->vdisplay - 1) << 16) |
+                  (mode->hdisplay - 1));
+       I915_WRITE(DSPPOS(plane), 0);
+       I915_WRITE(PIPESRC(pipe),
+                  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+       I915_WRITE(PIPECONF(pipe), pipeconf);
+       POSTING_READ(PIPECONF(pipe));
+       intel_enable_pipe(dev_priv, pipe, false);
+       intel_wait_for_vblank(dev, pipe);
+       I915_WRITE(DSPCNTR(plane), dspcntr);
+       POSTING_READ(DSPCNTR(plane));
+       ret = intel_pipe_set_base(crtc, x, y, old_fb);
+       intel_update_watermarks(dev);
+       return ret;
+ }
+ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
+                                 struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode,
+                                 int x, int y,
+                                 struct drm_framebuffer *old_fb)
+ {
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       int plane = intel_crtc->plane;
+       int refclk, num_connectors = 0;
+       intel_clock_t clock, reduced_clock;
+       u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf;
+       bool ok, has_reduced_clock = false, is_sdvo = false;
+       bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
+       struct intel_encoder *has_edp_encoder = NULL;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct intel_encoder *encoder;
+       const intel_limit_t *limit;
+       int ret;
+       struct fdi_m_n m_n = {0};
+       u32 temp;
+       u32 lvds_sync = 0;
+       int target_clock, pixel_multiplier, lane, link_bw, bpp, factor;
+       list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
+               if (encoder->base.crtc != crtc)
+                       continue;
+               switch (encoder->type) {
+               case INTEL_OUTPUT_LVDS:
+                       is_lvds = true;
+                       break;
+               case INTEL_OUTPUT_SDVO:
+               case INTEL_OUTPUT_HDMI:
+                       is_sdvo = true;
+                       if (encoder->needs_tv_clock)
+                               is_tv = true;
+                       break;
+               case INTEL_OUTPUT_TVOUT:
+                       is_tv = true;
+                       break;
+               case INTEL_OUTPUT_ANALOG:
+                       is_crt = true;
+                       break;
+               case INTEL_OUTPUT_DISPLAYPORT:
+                       is_dp = true;
+                       break;
+               case INTEL_OUTPUT_EDP:
+                       has_edp_encoder = encoder;
+                       break;
+               }
+               num_connectors++;
+       }
+       if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
+               refclk = dev_priv->lvds_ssc_freq * 1000;
+               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
+                             refclk / 1000);
+       } else {
+               refclk = 96000;
+               if (!has_edp_encoder ||
+                   intel_encoder_is_pch_edp(&has_edp_encoder->base))
+                       refclk = 120000; /* 120Mhz refclk */
+       }
+       /*
+        * Returns a set of divisors for the desired target clock with the given
+        * refclk, or FALSE.  The returned values represent the clock equation:
+        * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+        */
+       limit = intel_limit(crtc, refclk);
+       ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock);
+       if (!ok) {
+               DRM_ERROR("Couldn't find PLL settings for mode!\n");
+               return -EINVAL;
+       }
+       /* Ensure that the cursor is valid for the new mode before changing... */
+       intel_crtc_update_cursor(crtc, true);
+       if (is_lvds && dev_priv->lvds_downclock_avail) {
+               has_reduced_clock = limit->find_pll(limit, crtc,
+                                                   dev_priv->lvds_downclock,
+                                                   refclk,
+                                                   &reduced_clock);
+               if (has_reduced_clock && (clock.p != reduced_clock.p)) {
+                       /*
+                        * If the different P is found, it means that we can't
+                        * switch the display clock by using the FP0/FP1.
+                        * In such case we will disable the LVDS downclock
+                        * feature.
+                        */
+                       DRM_DEBUG_KMS("Different P is found for "
+                                     "LVDS clock/downclock\n");
+                       has_reduced_clock = 0;
+               }
+       }
+       /* SDVO TV has fixed PLL values depend on its clock range,
+          this mirrors vbios setting. */
+       if (is_sdvo && is_tv) {
+               if (adjusted_mode->clock >= 100000
+                   && adjusted_mode->clock < 140500) {
+                       clock.p1 = 2;
+                       clock.p2 = 10;
+                       clock.n = 3;
+                       clock.m1 = 16;
+                       clock.m2 = 8;
+               } else if (adjusted_mode->clock >= 140500
+                          && adjusted_mode->clock <= 200000) {
+                       clock.p1 = 1;
+                       clock.p2 = 10;
+                       clock.n = 6;
+                       clock.m1 = 12;
+                       clock.m2 = 8;
+               }
+       }
+       /* FDI link */
+       pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
+       lane = 0;
+       /* CPU eDP doesn't require FDI link, so just set DP M/N
+          according to current link config */
+       if (has_edp_encoder &&
+           !intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+               target_clock = mode->clock;
+               intel_edp_link_config(has_edp_encoder,
+                                     &lane, &link_bw);
+       } else {
+               /* [e]DP over FDI requires target mode clock
+                  instead of link clock */
+               if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base))
+                       target_clock = mode->clock;
+               else
+                       target_clock = adjusted_mode->clock;
+               /* FDI is a binary signal running at ~2.7GHz, encoding
+                * each output octet as 10 bits. The actual frequency
+                * is stored as a divider into a 100MHz clock, and the
+                * mode pixel clock is stored in units of 1KHz.
+                * Hence the bw of each lane in terms of the mode signal
+                * is:
+                */
+               link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
+       }
+       /* determine panel color depth */
+       temp = I915_READ(PIPECONF(pipe));
+       temp &= ~PIPE_BPC_MASK;
+       if (is_lvds) {
+               /* the BPC will be 6 if it is 18-bit LVDS panel */
+               if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
+                       temp |= PIPE_8BPC;
+               else
+                       temp |= PIPE_6BPC;
+       } else if (has_edp_encoder) {
+               switch (dev_priv->edp.bpp/3) {
+               case 8:
+                       temp |= PIPE_8BPC;
+                       break;
+               case 10:
+                       temp |= PIPE_10BPC;
+                       break;
+               case 6:
+                       temp |= PIPE_6BPC;
+                       break;
+               case 12:
+                       temp |= PIPE_12BPC;
+                       break;
+               }
+       } else
+               temp |= PIPE_8BPC;
+       I915_WRITE(PIPECONF(pipe), temp);
+       switch (temp & PIPE_BPC_MASK) {
+       case PIPE_8BPC:
+               bpp = 24;
+               break;
+       case PIPE_10BPC:
+               bpp = 30;
+               break;
+       case PIPE_6BPC:
+               bpp = 18;
+               break;
+       case PIPE_12BPC:
+               bpp = 36;
+               break;
+       default:
+               DRM_ERROR("unknown pipe bpc value\n");
+               bpp = 24;
+       }
+       if (!lane) {
+               /*
+                * Account for spread spectrum to avoid
+                * oversubscribing the link. Max center spread
+                * is 2.5%; use 5% for safety's sake.
+                */
+               u32 bps = target_clock * bpp * 21 / 20;
+               lane = bps / (link_bw * 8) + 1;
+       }
+       intel_crtc->fdi_lanes = lane;
+       if (pixel_multiplier > 1)
+               link_bw *= pixel_multiplier;
+       ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
+       /* Ironlake: try to setup display ref clock before DPLL
+        * enabling. This is only under driver's control after
+        * PCH B stepping, previous chipset stepping should be
+        * ignoring this setting.
+        */
+       temp = I915_READ(PCH_DREF_CONTROL);
+       /* Always enable nonspread source */
+       temp &= ~DREF_NONSPREAD_SOURCE_MASK;
+       temp |= DREF_NONSPREAD_SOURCE_ENABLE;
+       temp &= ~DREF_SSC_SOURCE_MASK;
+       temp |= DREF_SSC_SOURCE_ENABLE;
+       I915_WRITE(PCH_DREF_CONTROL, temp);
+       POSTING_READ(PCH_DREF_CONTROL);
+       udelay(200);
+       if (has_edp_encoder) {
+               if (intel_panel_use_ssc(dev_priv)) {
+                       temp |= DREF_SSC1_ENABLE;
+                       I915_WRITE(PCH_DREF_CONTROL, temp);
+                       POSTING_READ(PCH_DREF_CONTROL);
+                       udelay(200);
+               }
+               temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+               /* Enable CPU source on CPU attached eDP */
+               if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+                       if (intel_panel_use_ssc(dev_priv))
+                               temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+                       else
+                               temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
+               } else {
+                       /* Enable SSC on PCH eDP if needed */
+                       if (intel_panel_use_ssc(dev_priv)) {
+                               DRM_ERROR("enabling SSC on PCH\n");
+                               temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
+                       }
+               }
+               I915_WRITE(PCH_DREF_CONTROL, temp);
+               POSTING_READ(PCH_DREF_CONTROL);
+               udelay(200);
+       }
+       fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+       if (has_reduced_clock)
+               fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
+                       reduced_clock.m2;
+       /* Enable autotuning of the PLL clock (if permissible) */
+       factor = 21;
+       if (is_lvds) {
+               if ((intel_panel_use_ssc(dev_priv) &&
+                    dev_priv->lvds_ssc_freq == 100) ||
+                   (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+                       factor = 25;
+       } else if (is_sdvo && is_tv)
+               factor = 20;
+       if (clock.m1 < factor * clock.n)
+               fp |= FP_CB_TUNE;
+       dpll = 0;
+       if (is_lvds)
+               dpll |= DPLLB_MODE_LVDS;
+       else
+               dpll |= DPLLB_MODE_DAC_SERIAL;
+       if (is_sdvo) {
+               int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
+               if (pixel_multiplier > 1) {
+                       dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
+               }
+               dpll |= DPLL_DVO_HIGH_SPEED;
+       }
+       if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base))
+               dpll |= DPLL_DVO_HIGH_SPEED;
+       /* compute bitmask from p1 value */
+       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+       /* also FPA1 */
+       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
+       switch (clock.p2) {
+       case 5:
+               dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+               break;
+       case 7:
+               dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+               break;
+       case 10:
+               dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+               break;
+       case 14:
+               dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+               break;
+       }
+       if (is_sdvo && is_tv)
+               dpll |= PLL_REF_INPUT_TVCLKINBC;
+       else if (is_tv)
+               /* XXX: just matching BIOS for now */
+               /*      dpll |= PLL_REF_INPUT_TVCLKINBC; */
+               dpll |= 3;
+       else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+               dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+       else
+               dpll |= PLL_REF_INPUT_DREFCLK;
+       /* setup pipeconf */
+       pipeconf = I915_READ(PIPECONF(pipe));
+       /* Set up the display plane register */
+       dspcntr = DISPPLANE_GAMMA_ENABLE;
+       DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+       drm_mode_debug_printmodeline(mode);
+       /* PCH eDP needs FDI, but CPU eDP does not */
+       if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+               I915_WRITE(PCH_FP0(pipe), fp);
+               I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
+               POSTING_READ(PCH_DPLL(pipe));
+               udelay(150);
+       }
+       /* enable transcoder DPLL */
+       if (HAS_PCH_CPT(dev)) {
+               temp = I915_READ(PCH_DPLL_SEL);
+               switch (pipe) {
+               case 0:
+                       temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL;
+                       break;
+               case 1:
+                       temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL;
+                       break;
+               case 2:
+                       /* FIXME: manage transcoder PLLs? */
+                       temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL;
+                       break;
+               default:
+                       BUG();
+               }
+               I915_WRITE(PCH_DPLL_SEL, temp);
+               POSTING_READ(PCH_DPLL_SEL);
+               udelay(150);
+       }
+       /* The LVDS pin pair needs to be on before the DPLLs are enabled.
+        * This is an exception to the general rule that mode_set doesn't turn
+        * things on.
+        */
+       if (is_lvds) {
+               temp = I915_READ(PCH_LVDS);
+               temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
+               if (pipe == 1) {
+                       if (HAS_PCH_CPT(dev))
+                               temp |= PORT_TRANS_B_SEL_CPT;
+                       else
+                               temp |= LVDS_PIPEB_SELECT;
+               } else {
+                       if (HAS_PCH_CPT(dev))
+                               temp &= ~PORT_TRANS_SEL_MASK;
+                       else
+                               temp &= ~LVDS_PIPEB_SELECT;
+               }
+               /* set the corresponsding LVDS_BORDER bit */
+               temp |= dev_priv->lvds_border_bits;
+               /* Set the B0-B3 data pairs corresponding to whether we're going to
+                * set the DPLLs for dual-channel mode or not.
+                */
+               if (clock.p2 == 7)
+                       temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+               else
+                       temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
+               /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+                * appropriately here, but we need to look more thoroughly into how
+                * panels behave in the two modes.
+                */
+               if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+                       lvds_sync |= LVDS_HSYNC_POLARITY;
+               if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+                       lvds_sync |= LVDS_VSYNC_POLARITY;
+               if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY))
+                   != lvds_sync) {
+                       char flags[2] = "-+";
+                       DRM_INFO("Changing LVDS panel from "
+                                "(%chsync, %cvsync) to (%chsync, %cvsync)\n",
+                                flags[!(temp & LVDS_HSYNC_POLARITY)],
+                                flags[!(temp & LVDS_VSYNC_POLARITY)],
+                                flags[!(lvds_sync & LVDS_HSYNC_POLARITY)],
+                                flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]);
+                       temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
+                       temp |= lvds_sync;
+               }
+               I915_WRITE(PCH_LVDS, temp);
+       }
+       /* set the dithering flag and clear for anything other than a panel. */
+       pipeconf &= ~PIPECONF_DITHER_EN;
+       pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
+       if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) {
+               pipeconf |= PIPECONF_DITHER_EN;
+               pipeconf |= PIPECONF_DITHER_TYPE_ST1;
+       }
+       if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+               intel_dp_set_m_n(crtc, mode, adjusted_mode);
+       } else {
+               /* For non-DP output, clear any trans DP clock recovery setting.*/
+               I915_WRITE(TRANSDATA_M1(pipe), 0);
                I915_WRITE(TRANSDATA_N1(pipe), 0);
                I915_WRITE(TRANSDPLINK_M1(pipe), 0);
                I915_WRITE(TRANSDPLINK_N1(pipe), 0);
        }
  
-       if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-               I915_WRITE(dpll_reg, dpll);
+       if (!has_edp_encoder ||
+           intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+               I915_WRITE(PCH_DPLL(pipe), dpll);
  
                /* Wait for the clocks to stabilize. */
-               POSTING_READ(dpll_reg);
+               POSTING_READ(PCH_DPLL(pipe));
                udelay(150);
  
-               if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-                       temp = 0;
-                       if (is_sdvo) {
-                               temp = intel_mode_get_pixel_multiplier(adjusted_mode);
-                               if (temp > 1)
-                                       temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
-                               else
-                                       temp = 0;
-                       }
-                       I915_WRITE(DPLL_MD(pipe), temp);
-               } else {
-                       /* The pixel multiplier can only be updated once the
-                        * DPLL is enabled and the clocks are stable.
-                        *
-                        * So write it again.
-                        */
-                       I915_WRITE(dpll_reg, dpll);
-               }
+               /* The pixel multiplier can only be updated once the
+                * DPLL is enabled and the clocks are stable.
+                *
+                * So write it again.
+                */
+               I915_WRITE(PCH_DPLL(pipe), dpll);
        }
  
        intel_crtc->lowfreq_avail = false;
        if (is_lvds && has_reduced_clock && i915_powersave) {
-               I915_WRITE(fp_reg + 4, fp2);
+               I915_WRITE(PCH_FP1(pipe), fp2);
                intel_crtc->lowfreq_avail = true;
                if (HAS_PIPE_CXSR(dev)) {
                        DRM_DEBUG_KMS("enabling CxSR downclocking\n");
                        pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
                }
        } else {
-               I915_WRITE(fp_reg + 4, fp);
+               I915_WRITE(PCH_FP1(pipe), fp);
                if (HAS_PIPE_CXSR(dev)) {
                        DRM_DEBUG_KMS("disabling CxSR downclocking\n");
                        pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
                   (adjusted_mode->crtc_vsync_start - 1) |
                   ((adjusted_mode->crtc_vsync_end - 1) << 16));
  
-       /* pipesrc and dspsize control the size that is scaled from,
-        * which should always be the user's requested size.
+       /* pipesrc controls the size that is scaled from, which should
+        * always be the user's requested size.
         */
-       if (!HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(DSPSIZE(plane),
-                          ((mode->vdisplay - 1) << 16) |
-                          (mode->hdisplay - 1));
-               I915_WRITE(DSPPOS(plane), 0);
-       }
        I915_WRITE(PIPESRC(pipe),
                   ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
  
-       if (HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
-               I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
-               I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
-               I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
+       I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
+       I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
+       I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
+       I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
  
-               if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-                       ironlake_set_pll_edp(crtc, adjusted_mode->clock);
-               }
+       if (has_edp_encoder &&
+           !intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+               ironlake_set_pll_edp(crtc, adjusted_mode->clock);
        }
  
        I915_WRITE(PIPECONF(pipe), pipeconf);
        POSTING_READ(PIPECONF(pipe));
-       if (!HAS_PCH_SPLIT(dev))
-               intel_enable_pipe(dev_priv, pipe, false);
  
        intel_wait_for_vblank(dev, pipe);
  
  
        I915_WRITE(DSPCNTR(plane), dspcntr);
        POSTING_READ(DSPCNTR(plane));
 +      if (!HAS_PCH_SPLIT(dev))
 +              intel_enable_plane(dev_priv, plane, pipe);
  
        ret = intel_pipe_set_base(crtc, x, y, old_fb);
  
        intel_update_watermarks(dev);
  
+       return ret;
+ }
+ static int intel_crtc_mode_set(struct drm_crtc *crtc,
+                              struct drm_display_mode *mode,
+                              struct drm_display_mode *adjusted_mode,
+                              int x, int y,
+                              struct drm_framebuffer *old_fb)
+ {
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       int ret;
+       drm_vblank_pre_modeset(dev, pipe);
+       ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
+                                             x, y, old_fb);
        drm_vblank_post_modeset(dev, pipe);
  
        return ret;
@@@ -5483,43 -5612,140 +5614,140 @@@ static struct drm_display_mode load_det
                 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
  };
  
- struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
-                                           struct drm_connector *connector,
-                                           struct drm_display_mode *mode,
-                                           int *dpms_mode)
+ static struct drm_framebuffer *
+ intel_framebuffer_create(struct drm_device *dev,
+                        struct drm_mode_fb_cmd *mode_cmd,
+                        struct drm_i915_gem_object *obj)
+ {
+       struct intel_framebuffer *intel_fb;
+       int ret;
+       intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
+       if (!intel_fb) {
+               drm_gem_object_unreference_unlocked(&obj->base);
+               return ERR_PTR(-ENOMEM);
+       }
+       ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
+       if (ret) {
+               drm_gem_object_unreference_unlocked(&obj->base);
+               kfree(intel_fb);
+               return ERR_PTR(ret);
+       }
+       return &intel_fb->base;
+ }
+ static u32
+ intel_framebuffer_pitch_for_width(int width, int bpp)
+ {
+       u32 pitch = DIV_ROUND_UP(width * bpp, 8);
+       return ALIGN(pitch, 64);
+ }
+ static u32
+ intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
+ {
+       u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp);
+       return ALIGN(pitch * mode->vdisplay, PAGE_SIZE);
+ }
+ static struct drm_framebuffer *
+ intel_framebuffer_create_for_mode(struct drm_device *dev,
+                                 struct drm_display_mode *mode,
+                                 int depth, int bpp)
+ {
+       struct drm_i915_gem_object *obj;
+       struct drm_mode_fb_cmd mode_cmd;
+       obj = i915_gem_alloc_object(dev,
+                                   intel_framebuffer_size_for_mode(mode, bpp));
+       if (obj == NULL)
+               return ERR_PTR(-ENOMEM);
+       mode_cmd.width = mode->hdisplay;
+       mode_cmd.height = mode->vdisplay;
+       mode_cmd.depth = depth;
+       mode_cmd.bpp = bpp;
+       mode_cmd.pitch = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp);
+       return intel_framebuffer_create(dev, &mode_cmd, obj);
+ }
+ static struct drm_framebuffer *
+ mode_fits_in_fbdev(struct drm_device *dev,
+                  struct drm_display_mode *mode)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_gem_object *obj;
+       struct drm_framebuffer *fb;
+       if (dev_priv->fbdev == NULL)
+               return NULL;
+       obj = dev_priv->fbdev->ifb.obj;
+       if (obj == NULL)
+               return NULL;
+       fb = &dev_priv->fbdev->ifb.base;
+       if (fb->pitch < intel_framebuffer_pitch_for_width(mode->hdisplay,
+                                                         fb->bits_per_pixel))
+               return NULL;
+       if (obj->base.size < mode->vdisplay * fb->pitch)
+               return NULL;
+       return fb;
+ }
+ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
+                               struct drm_connector *connector,
+                               struct drm_display_mode *mode,
+                               struct intel_load_detect_pipe *old)
  {
        struct intel_crtc *intel_crtc;
        struct drm_crtc *possible_crtc;
-       struct drm_crtc *supported_crtc =NULL;
        struct drm_encoder *encoder = &intel_encoder->base;
        struct drm_crtc *crtc = NULL;
        struct drm_device *dev = encoder->dev;
-       struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
-       struct drm_crtc_helper_funcs *crtc_funcs;
+       struct drm_framebuffer *old_fb;
        int i = -1;
  
+       DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
+                     connector->base.id, drm_get_connector_name(connector),
+                     encoder->base.id, drm_get_encoder_name(encoder));
        /*
         * Algorithm gets a little messy:
+        *
         *   - if the connector already has an assigned crtc, use it (but make
         *     sure it's on first)
+        *
         *   - try to find the first unused crtc that can drive this connector,
         *     and use that if we find one
-        *   - if there are no unused crtcs available, try to use the first
-        *     one we found that supports the connector
         */
  
        /* See if we already have a CRTC for this connector */
        if (encoder->crtc) {
                crtc = encoder->crtc;
-               /* Make sure the crtc and connector are running */
                intel_crtc = to_intel_crtc(crtc);
-               *dpms_mode = intel_crtc->dpms_mode;
+               old->dpms_mode = intel_crtc->dpms_mode;
+               old->load_detect_temp = false;
+               /* Make sure the crtc and connector are running */
                if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
+                       struct drm_encoder_helper_funcs *encoder_funcs;
+                       struct drm_crtc_helper_funcs *crtc_funcs;
                        crtc_funcs = crtc->helper_private;
                        crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+                       encoder_funcs = encoder->helper_private;
                        encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
                }
-               return crtc;
+               return true;
        }
  
        /* Find an unused one (if possible) */
                        crtc = possible_crtc;
                        break;
                }
-               if (!supported_crtc)
-                       supported_crtc = possible_crtc;
        }
  
        /*
         * If we didn't find an unused CRTC, don't use any.
         */
        if (!crtc) {
-               return NULL;
+               DRM_DEBUG_KMS("no pipe available for load-detect\n");
+               return false;
        }
  
        encoder->crtc = crtc;
        connector->encoder = encoder;
-       intel_encoder->load_detect_temp = true;
  
        intel_crtc = to_intel_crtc(crtc);
-       *dpms_mode = intel_crtc->dpms_mode;
+       old->dpms_mode = intel_crtc->dpms_mode;
+       old->load_detect_temp = true;
+       old->release_fb = NULL;
  
-       if (!crtc->enabled) {
-               if (!mode)
-                       mode = &load_detect_mode;
-               drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb);
-       } else {
-               if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
-                       crtc_funcs = crtc->helper_private;
-                       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-               }
+       if (!mode)
+               mode = &load_detect_mode;
  
-               /* Add this connector to the crtc */
-               encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->mode);
-               encoder_funcs->commit(encoder);
+       old_fb = crtc->fb;
+       /* We need a framebuffer large enough to accommodate all accesses
+        * that the plane may generate whilst we perform load detection.
+        * We can not rely on the fbcon either being present (we get called
+        * during its initialisation to detect all boot displays, or it may
+        * not even exist) or that it is large enough to satisfy the
+        * requested mode.
+        */
+       crtc->fb = mode_fits_in_fbdev(dev, mode);
+       if (crtc->fb == NULL) {
+               DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
+               crtc->fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
+               old->release_fb = crtc->fb;
+       } else
+               DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
+       if (IS_ERR(crtc->fb)) {
+               DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
+               crtc->fb = old_fb;
+               return false;
        }
+       if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) {
+               DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
+               if (old->release_fb)
+                       old->release_fb->funcs->destroy(old->release_fb);
+               crtc->fb = old_fb;
+               return false;
+       }
        /* let the connector get through one full cycle before testing */
        intel_wait_for_vblank(dev, intel_crtc->pipe);
  
-       return crtc;
+       return true;
  }
  
  void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
-                                   struct drm_connector *connector, int dpms_mode)
+                                   struct drm_connector *connector,
+                                   struct intel_load_detect_pipe *old)
  {
        struct drm_encoder *encoder = &intel_encoder->base;
        struct drm_device *dev = encoder->dev;
        struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
        struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
  
-       if (intel_encoder->load_detect_temp) {
-               encoder->crtc = NULL;
+       DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
+                     connector->base.id, drm_get_connector_name(connector),
+                     encoder->base.id, drm_get_encoder_name(encoder));
+       if (old->load_detect_temp) {
                connector->encoder = NULL;
-               intel_encoder->load_detect_temp = false;
-               crtc->enabled = drm_helper_crtc_in_use(crtc);
                drm_helper_disable_unused_functions(dev);
+               if (old->release_fb)
+                       old->release_fb->funcs->destroy(old->release_fb);
+               return;
        }
  
        /* Switch crtc and encoder back off if necessary */
-       if (crtc->enabled && dpms_mode != DRM_MODE_DPMS_ON) {
-               if (encoder->crtc == crtc)
-                       encoder_funcs->dpms(encoder, dpms_mode);
-               crtc_funcs->dpms(crtc, dpms_mode);
+       if (old->dpms_mode != DRM_MODE_DPMS_ON) {
+               encoder_funcs->dpms(encoder, old->dpms_mode);
+               crtc_funcs->dpms(crtc, old->dpms_mode);
        }
  }
  
@@@ -6185,6 -6436,7 +6438,7 @@@ static int intel_crtc_page_flip(struct 
                break;
  
        case 6:
+       case 7:
                OUT_RING(MI_DISPLAY_FLIP |
                         MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
                OUT_RING(fb->pitch | obj->tiling_mode);
@@@ -6504,6 -6756,9 +6758,9 @@@ static void intel_setup_outputs(struct 
        }
  
        intel_panel_setup_backlight(dev);
+       /* disable all the possible outputs/crtcs before entering KMS mode */
+       drm_helper_disable_unused_functions(dev);
  }
  
  static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@@ -6571,27 -6826,12 +6828,12 @@@ intel_user_framebuffer_create(struct dr
                              struct drm_mode_fb_cmd *mode_cmd)
  {
        struct drm_i915_gem_object *obj;
-       struct intel_framebuffer *intel_fb;
-       int ret;
  
        obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle));
        if (&obj->base == NULL)
                return ERR_PTR(-ENOENT);
  
-       intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
-       if (!intel_fb) {
-               drm_gem_object_unreference_unlocked(&obj->base);
-               return ERR_PTR(-ENOMEM);
-       }
-       ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
-       if (ret) {
-               drm_gem_object_unreference_unlocked(&obj->base);
-               kfree(intel_fb);
-               return ERR_PTR(ret);
-       }
-       return &intel_fb->base;
+       return intel_framebuffer_create(dev, mode_cmd, obj);
  }
  
  static const struct drm_mode_config_funcs intel_mode_funcs = {
@@@ -6605,13 -6845,14 +6847,14 @@@ intel_alloc_context_page(struct drm_dev
        struct drm_i915_gem_object *ctx;
        int ret;
  
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
        ctx = i915_gem_alloc_object(dev, 4096);
        if (!ctx) {
                DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
                return NULL;
        }
  
-       mutex_lock(&dev->struct_mutex);
        ret = i915_gem_object_pin(ctx, 4096, true);
        if (ret) {
                DRM_ERROR("failed to pin power context: %d\n", ret);
                DRM_ERROR("failed to set-domain on power context: %d\n", ret);
                goto err_unpin;
        }
-       mutex_unlock(&dev->struct_mutex);
  
        return ctx;
  
@@@ -6758,6 -6998,11 +7000,11 @@@ void gen6_disable_rps(struct drm_devic
        I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
        I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
        I915_WRITE(GEN6_PMIER, 0);
+       spin_lock_irq(&dev_priv->rps_lock);
+       dev_priv->pm_iir = 0;
+       spin_unlock_irq(&dev_priv->rps_lock);
        I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
  }
  
@@@ -6851,7 -7096,7 +7098,7 @@@ void gen6_enable_rps(struct drm_i915_pr
  {
        u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
        u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
-       u32 pcu_mbox;
+       u32 pcu_mbox, rc6_mask = 0;
        int cur_freq, min_freq, max_freq;
        int i;
  
         * userspace...
         */
        I915_WRITE(GEN6_RC_STATE, 0);
-       __gen6_gt_force_wake_get(dev_priv);
+       mutex_lock(&dev_priv->dev->struct_mutex);
+       gen6_gt_force_wake_get(dev_priv);
  
        /* disable the counters and set deterministic thresholds */
        I915_WRITE(GEN6_RC_CONTROL, 0);
        I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
        I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
  
+       if (i915_enable_rc6)
+               rc6_mask = GEN6_RC_CTL_RC6p_ENABLE |
+                       GEN6_RC_CTL_RC6_ENABLE;
        I915_WRITE(GEN6_RC_CONTROL,
-                  GEN6_RC_CTL_RC6p_ENABLE |
-                  GEN6_RC_CTL_RC6_ENABLE |
+                  rc6_mask |
                   GEN6_RC_CTL_EI_MODE(1) |
                   GEN6_RC_CTL_HW_ENABLE);
  
                   GEN6_PM_RP_DOWN_THRESHOLD |
                   GEN6_PM_RP_UP_EI_EXPIRED |
                   GEN6_PM_RP_DOWN_EI_EXPIRED);
+       spin_lock_irq(&dev_priv->rps_lock);
+       WARN_ON(dev_priv->pm_iir != 0);
        I915_WRITE(GEN6_PMIMR, 0);
+       spin_unlock_irq(&dev_priv->rps_lock);
        /* enable all PM interrupts */
        I915_WRITE(GEN6_PMINTRMSK, 0);
  
-       __gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv);
+       mutex_unlock(&dev_priv->dev->struct_mutex);
+ }
+ static void ironlake_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+       /* Required for FBC */
+       dspclk_gate |= DPFCUNIT_CLOCK_GATE_DISABLE |
+               DPFCRUNIT_CLOCK_GATE_DISABLE |
+               DPFDUNIT_CLOCK_GATE_DISABLE;
+       /* Required for CxSR */
+       dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE;
+       I915_WRITE(PCH_3DCGDIS0,
+                  MARIUNIT_CLOCK_GATE_DISABLE |
+                  SVSMUNIT_CLOCK_GATE_DISABLE);
+       I915_WRITE(PCH_3DCGDIS1,
+                  VFMUNIT_CLOCK_GATE_DISABLE);
+       I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
+       /*
+        * According to the spec the following bits should be set in
+        * order to enable memory self-refresh
+        * The bit 22/21 of 0x42004
+        * The bit 5 of 0x42020
+        * The bit 15 of 0x45000
+        */
+       I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                  (I915_READ(ILK_DISPLAY_CHICKEN2) |
+                   ILK_DPARB_GATE | ILK_VSDPFD_FULL));
+       I915_WRITE(ILK_DSPCLK_GATE,
+                  (I915_READ(ILK_DSPCLK_GATE) |
+                   ILK_DPARB_CLK_GATE));
+       I915_WRITE(DISP_ARB_CTL,
+                  (I915_READ(DISP_ARB_CTL) |
+                   DISP_FBC_WM_DIS));
+       I915_WRITE(WM3_LP_ILK, 0);
+       I915_WRITE(WM2_LP_ILK, 0);
+       I915_WRITE(WM1_LP_ILK, 0);
+       /*
+        * Based on the document from hardware guys the following bits
+        * should be set unconditionally in order to enable FBC.
+        * The bit 22 of 0x42000
+        * The bit 22 of 0x42004
+        * The bit 7,8,9 of 0x42020.
+        */
+       if (IS_IRONLAKE_M(dev)) {
+               I915_WRITE(ILK_DISPLAY_CHICKEN1,
+                          I915_READ(ILK_DISPLAY_CHICKEN1) |
+                          ILK_FBCQ_DIS);
+               I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                          I915_READ(ILK_DISPLAY_CHICKEN2) |
+                          ILK_DPARB_GATE);
+               I915_WRITE(ILK_DSPCLK_GATE,
+                          I915_READ(ILK_DSPCLK_GATE) |
+                          ILK_DPFC_DIS1 |
+                          ILK_DPFC_DIS2 |
+                          ILK_CLK_FBC);
+       }
+       I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                  I915_READ(ILK_DISPLAY_CHICKEN2) |
+                  ILK_ELPIN_409_SELECT);
+       I915_WRITE(_3D_CHICKEN2,
+                  _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
+                  _3D_CHICKEN2_WM_READ_PIPELINED);
  }
  
void intel_enable_clock_gating(struct drm_device *dev)
static void gen6_init_clock_gating(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe;
+       uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+       I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
+       I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                  I915_READ(ILK_DISPLAY_CHICKEN2) |
+                  ILK_ELPIN_409_SELECT);
+       I915_WRITE(WM3_LP_ILK, 0);
+       I915_WRITE(WM2_LP_ILK, 0);
+       I915_WRITE(WM1_LP_ILK, 0);
  
        /*
-        * Disable clock gating reported to work incorrectly according to the
-        * specs, but enable as much else as we can.
+        * According to the spec the following bits should be
+        * set in order to enable memory self-refresh and fbc:
+        * The bit21 and bit22 of 0x42000
+        * The bit21 and bit22 of 0x42004
+        * The bit5 and bit7 of 0x42020
+        * The bit14 of 0x70180
+        * The bit14 of 0x71180
         */
-       if (HAS_PCH_SPLIT(dev)) {
-               uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+       I915_WRITE(ILK_DISPLAY_CHICKEN1,
+                  I915_READ(ILK_DISPLAY_CHICKEN1) |
+                  ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS);
+       I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                  I915_READ(ILK_DISPLAY_CHICKEN2) |
+                  ILK_DPARB_GATE | ILK_VSDPFD_FULL);
+       I915_WRITE(ILK_DSPCLK_GATE,
+                  I915_READ(ILK_DSPCLK_GATE) |
+                  ILK_DPARB_CLK_GATE  |
+                  ILK_DPFD_CLK_GATE);
  
-               if (IS_GEN5(dev)) {
-                       /* Required for FBC */
-                       dspclk_gate |= DPFCUNIT_CLOCK_GATE_DISABLE |
-                               DPFCRUNIT_CLOCK_GATE_DISABLE |
-                               DPFDUNIT_CLOCK_GATE_DISABLE;
-                       /* Required for CxSR */
-                       dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE;
-                       I915_WRITE(PCH_3DCGDIS0,
-                                  MARIUNIT_CLOCK_GATE_DISABLE |
-                                  SVSMUNIT_CLOCK_GATE_DISABLE);
-                       I915_WRITE(PCH_3DCGDIS1,
-                                  VFMUNIT_CLOCK_GATE_DISABLE);
-               }
+       for_each_pipe(pipe)
+               I915_WRITE(DSPCNTR(pipe),
+                          I915_READ(DSPCNTR(pipe)) |
+                          DISPPLANE_TRICKLE_FEED_DISABLE);
+ }
  
-               I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
+ static void ivybridge_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipe;
+       uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
  
-               /*
-                * On Ibex Peak and Cougar Point, we need to disable clock
-                * gating for the panel power sequencer or it will fail to
-                * start up when no ports are active.
-                */
-               I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
+       I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
  
-               /*
-                * According to the spec the following bits should be set in
-                * order to enable memory self-refresh
-                * The bit 22/21 of 0x42004
-                * The bit 5 of 0x42020
-                * The bit 15 of 0x45000
-                */
-               if (IS_GEN5(dev)) {
-                       I915_WRITE(ILK_DISPLAY_CHICKEN2,
-                                       (I915_READ(ILK_DISPLAY_CHICKEN2) |
-                                       ILK_DPARB_GATE | ILK_VSDPFD_FULL));
-                       I915_WRITE(ILK_DSPCLK_GATE,
-                                       (I915_READ(ILK_DSPCLK_GATE) |
-                                               ILK_DPARB_CLK_GATE));
-                       I915_WRITE(DISP_ARB_CTL,
-                                       (I915_READ(DISP_ARB_CTL) |
-                                               DISP_FBC_WM_DIS));
-                       I915_WRITE(WM3_LP_ILK, 0);
-                       I915_WRITE(WM2_LP_ILK, 0);
-                       I915_WRITE(WM1_LP_ILK, 0);
-               }
-               /*
-                * Based on the document from hardware guys the following bits
-                * should be set unconditionally in order to enable FBC.
-                * The bit 22 of 0x42000
-                * The bit 22 of 0x42004
-                * The bit 7,8,9 of 0x42020.
-                */
-               if (IS_IRONLAKE_M(dev)) {
-                       I915_WRITE(ILK_DISPLAY_CHICKEN1,
-                                  I915_READ(ILK_DISPLAY_CHICKEN1) |
-                                  ILK_FBCQ_DIS);
-                       I915_WRITE(ILK_DISPLAY_CHICKEN2,
-                                  I915_READ(ILK_DISPLAY_CHICKEN2) |
-                                  ILK_DPARB_GATE);
-                       I915_WRITE(ILK_DSPCLK_GATE,
-                                  I915_READ(ILK_DSPCLK_GATE) |
-                                  ILK_DPFC_DIS1 |
-                                  ILK_DPFC_DIS2 |
-                                  ILK_CLK_FBC);
-               }
+       I915_WRITE(WM3_LP_ILK, 0);
+       I915_WRITE(WM2_LP_ILK, 0);
+       I915_WRITE(WM1_LP_ILK, 0);
  
-               I915_WRITE(ILK_DISPLAY_CHICKEN2,
-                          I915_READ(ILK_DISPLAY_CHICKEN2) |
-                          ILK_ELPIN_409_SELECT);
+       I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
  
-               if (IS_GEN5(dev)) {
-                       I915_WRITE(_3D_CHICKEN2,
-                                  _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
-                                  _3D_CHICKEN2_WM_READ_PIPELINED);
-               }
+       for_each_pipe(pipe)
+               I915_WRITE(DSPCNTR(pipe),
+                          I915_READ(DSPCNTR(pipe)) |
+                          DISPPLANE_TRICKLE_FEED_DISABLE);
+ }
+ static void g4x_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t dspclk_gate;
  
-               if (IS_GEN6(dev)) {
-                       I915_WRITE(WM3_LP_ILK, 0);
-                       I915_WRITE(WM2_LP_ILK, 0);
-                       I915_WRITE(WM1_LP_ILK, 0);
+       I915_WRITE(RENCLK_GATE_D1, 0);
+       I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE |
+                  GS_UNIT_CLOCK_GATE_DISABLE |
+                  CL_UNIT_CLOCK_GATE_DISABLE);
+       I915_WRITE(RAMCLK_GATE_D, 0);
+       dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
+               OVRUNIT_CLOCK_GATE_DISABLE |
+               OVCUNIT_CLOCK_GATE_DISABLE;
+       if (IS_GM45(dev))
+               dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
+       I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
+ }
  
-                       /*
-                        * According to the spec the following bits should be
-                        * set in order to enable memory self-refresh and fbc:
-                        * The bit21 and bit22 of 0x42000
-                        * The bit21 and bit22 of 0x42004
-                        * The bit5 and bit7 of 0x42020
-                        * The bit14 of 0x70180
-                        * The bit14 of 0x71180
-                        */
-                       I915_WRITE(ILK_DISPLAY_CHICKEN1,
-                                  I915_READ(ILK_DISPLAY_CHICKEN1) |
-                                  ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS);
-                       I915_WRITE(ILK_DISPLAY_CHICKEN2,
-                                  I915_READ(ILK_DISPLAY_CHICKEN2) |
-                                  ILK_DPARB_GATE | ILK_VSDPFD_FULL);
-                       I915_WRITE(ILK_DSPCLK_GATE,
-                                  I915_READ(ILK_DSPCLK_GATE) |
-                                  ILK_DPARB_CLK_GATE  |
-                                  ILK_DPFD_CLK_GATE);
-                       for_each_pipe(pipe)
-                               I915_WRITE(DSPCNTR(pipe),
-                                          I915_READ(DSPCNTR(pipe)) |
-                                          DISPPLANE_TRICKLE_FEED_DISABLE);
-               }
-       } else if (IS_G4X(dev)) {
-               uint32_t dspclk_gate;
-               I915_WRITE(RENCLK_GATE_D1, 0);
-               I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE |
-                      GS_UNIT_CLOCK_GATE_DISABLE |
-                      CL_UNIT_CLOCK_GATE_DISABLE);
-               I915_WRITE(RAMCLK_GATE_D, 0);
-               dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
-                       OVRUNIT_CLOCK_GATE_DISABLE |
-                       OVCUNIT_CLOCK_GATE_DISABLE;
-               if (IS_GM45(dev))
-                       dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
-               I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
-       } else if (IS_CRESTLINE(dev)) {
-               I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
-               I915_WRITE(RENCLK_GATE_D2, 0);
-               I915_WRITE(DSPCLK_GATE_D, 0);
-               I915_WRITE(RAMCLK_GATE_D, 0);
-               I915_WRITE16(DEUC, 0);
-       } else if (IS_BROADWATER(dev)) {
-               I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE |
-                      I965_RCC_CLOCK_GATE_DISABLE |
-                      I965_RCPB_CLOCK_GATE_DISABLE |
-                      I965_ISC_CLOCK_GATE_DISABLE |
-                      I965_FBC_CLOCK_GATE_DISABLE);
-               I915_WRITE(RENCLK_GATE_D2, 0);
-       } else if (IS_GEN3(dev)) {
-               u32 dstate = I915_READ(D_STATE);
+ static void crestline_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
  
-               dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING |
-                       DSTATE_DOT_CLOCK_GATING;
-               I915_WRITE(D_STATE, dstate);
-       } else if (IS_I85X(dev) || IS_I865G(dev)) {
-               I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
-       } else if (IS_I830(dev)) {
-               I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
-       }
+       I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
+       I915_WRITE(RENCLK_GATE_D2, 0);
+       I915_WRITE(DSPCLK_GATE_D, 0);
+       I915_WRITE(RAMCLK_GATE_D, 0);
+       I915_WRITE16(DEUC, 0);
+ }
+ static void broadwater_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE |
+                  I965_RCC_CLOCK_GATE_DISABLE |
+                  I965_RCPB_CLOCK_GATE_DISABLE |
+                  I965_ISC_CLOCK_GATE_DISABLE |
+                  I965_FBC_CLOCK_GATE_DISABLE);
+       I915_WRITE(RENCLK_GATE_D2, 0);
+ }
+ static void gen3_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 dstate = I915_READ(D_STATE);
+       dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING |
+               DSTATE_DOT_CLOCK_GATING;
+       I915_WRITE(D_STATE, dstate);
+ }
+ static void i85x_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
+ }
+ static void i830_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
+ }
+ static void ibx_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       /*
+        * On Ibex Peak and Cougar Point, we need to disable clock
+        * gating for the panel power sequencer or it will fail to
+        * start up when no ports are active.
+        */
+       I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
+ }
+ static void cpt_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       /*
+        * On Ibex Peak and Cougar Point, we need to disable clock
+        * gating for the panel power sequencer or it will fail to
+        * start up when no ports are active.
+        */
+       I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
+       I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
+                  DPLS_EDP_PPS_FIX_DIS);
  }
  
  static void ironlake_teardown_rc6(struct drm_device *dev)
@@@ -7187,9 -7505,12 +7507,12 @@@ void ironlake_enable_rc6(struct drm_dev
        if (!i915_enable_rc6)
                return;
  
+       mutex_lock(&dev->struct_mutex);
        ret = ironlake_setup_rc6(dev);
-       if (ret)
+       if (ret) {
+               mutex_unlock(&dev->struct_mutex);
                return;
+       }
  
        /*
         * GPU can automatically power down the render unit if given a page
        ret = BEGIN_LP_RING(6);
        if (ret) {
                ironlake_teardown_rc6(dev);
+               mutex_unlock(&dev->struct_mutex);
                return;
        }
  
        OUT_RING(MI_FLUSH);
        ADVANCE_LP_RING();
  
+       /*
+        * Wait for the command parser to advance past MI_SET_CONTEXT. The HW
+        * does an implicit flush, combined with MI_FLUSH above, it should be
+        * safe to assume that renderctx is valid
+        */
+       ret = intel_wait_ring_idle(LP_RING(dev_priv));
+       if (ret) {
+               DRM_ERROR("failed to enable ironlake power power savings\n");
+               ironlake_teardown_rc6(dev);
+               mutex_unlock(&dev->struct_mutex);
+               return;
+       }
        I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN);
        I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
+       mutex_unlock(&dev->struct_mutex);
  }
  
+ void intel_init_clock_gating(struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       dev_priv->display.init_clock_gating(dev);
+       if (dev_priv->display.init_pch_clock_gating)
+               dev_priv->display.init_pch_clock_gating(dev);
+ }
  
  /* Set up chip specific display functions */
  static void intel_init_display(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
  
        /* We always want a DPMS function */
-       if (HAS_PCH_SPLIT(dev))
+       if (HAS_PCH_SPLIT(dev)) {
                dev_priv->display.dpms = ironlake_crtc_dpms;
-       else
+               dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
+       } else {
                dev_priv->display.dpms = i9xx_crtc_dpms;
+               dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
+       }
  
        if (I915_HAS_FBC(dev)) {
                if (HAS_PCH_SPLIT(dev)) {
  
        /* For FIFO watermark updates */
        if (HAS_PCH_SPLIT(dev)) {
+               if (HAS_PCH_IBX(dev))
+                       dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating;
+               else if (HAS_PCH_CPT(dev))
+                       dev_priv->display.init_pch_clock_gating = cpt_init_clock_gating;
                if (IS_GEN5(dev)) {
                        if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK)
                                dev_priv->display.update_wm = ironlake_update_wm;
                                              "Disable CxSR\n");
                                dev_priv->display.update_wm = NULL;
                        }
+                       dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
+                       dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
                } else if (IS_GEN6(dev)) {
                        if (SNB_READ_WM0_LATENCY()) {
                                dev_priv->display.update_wm = sandybridge_update_wm;
                                              "Disable CxSR\n");
                                dev_priv->display.update_wm = NULL;
                        }
+                       dev_priv->display.fdi_link_train = gen6_fdi_link_train;
+                       dev_priv->display.init_clock_gating = gen6_init_clock_gating;
+               } else if (IS_IVYBRIDGE(dev)) {
+                       /* FIXME: detect B0+ stepping and use auto training */
+                       dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
+                       if (SNB_READ_WM0_LATENCY()) {
+                               dev_priv->display.update_wm = sandybridge_update_wm;
+                       } else {
+                               DRM_DEBUG_KMS("Failed to read display plane latency. "
+                                             "Disable CxSR\n");
+                               dev_priv->display.update_wm = NULL;
+                       }
+                       dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
                } else
                        dev_priv->display.update_wm = NULL;
        } else if (IS_PINEVIEW(dev)) {
                        dev_priv->display.update_wm = NULL;
                } else
                        dev_priv->display.update_wm = pineview_update_wm;
-       } else if (IS_G4X(dev))
+       } else if (IS_G4X(dev)) {
                dev_priv->display.update_wm = g4x_update_wm;
-       else if (IS_GEN4(dev))
+               dev_priv->display.init_clock_gating = g4x_init_clock_gating;
+       } else if (IS_GEN4(dev)) {
                dev_priv->display.update_wm = i965_update_wm;
-       else if (IS_GEN3(dev)) {
+               if (IS_CRESTLINE(dev))
+                       dev_priv->display.init_clock_gating = crestline_init_clock_gating;
+               else if (IS_BROADWATER(dev))
+                       dev_priv->display.init_clock_gating = broadwater_init_clock_gating;
+       } else if (IS_GEN3(dev)) {
                dev_priv->display.update_wm = i9xx_update_wm;
                dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
+               dev_priv->display.init_clock_gating = gen3_init_clock_gating;
+       } else if (IS_I865G(dev)) {
+               dev_priv->display.update_wm = i830_update_wm;
+               dev_priv->display.init_clock_gating = i85x_init_clock_gating;
+               dev_priv->display.get_fifo_size = i830_get_fifo_size;
        } else if (IS_I85X(dev)) {
                dev_priv->display.update_wm = i9xx_update_wm;
                dev_priv->display.get_fifo_size = i85x_get_fifo_size;
+               dev_priv->display.init_clock_gating = i85x_init_clock_gating;
        } else {
                dev_priv->display.update_wm = i830_update_wm;
+               dev_priv->display.init_clock_gating = i830_init_clock_gating;
                if (IS_845G(dev))
                        dev_priv->display.get_fifo_size = i845_get_fifo_size;
                else
@@@ -7441,12 -7822,11 +7824,11 @@@ void intel_modeset_init(struct drm_devi
                intel_crtc_init(dev, i);
        }
  
-       intel_setup_outputs(dev);
-       intel_enable_clock_gating(dev);
        /* Just disable it once at startup */
        i915_disable_vga(dev);
+       intel_setup_outputs(dev);
+       intel_init_clock_gating(dev);
  
        if (IS_IRONLAKE_M(dev)) {
                ironlake_enable_drps(dev);
        if (IS_GEN6(dev))
                gen6_enable_rps(dev_priv);
  
-       if (IS_IRONLAKE_M(dev))
-               ironlake_enable_rc6(dev);
        INIT_WORK(&dev_priv->idle_work, intel_idle_update);
        setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
                    (unsigned long)dev);
+ }
+ void intel_modeset_gem_init(struct drm_device *dev)
+ {
+       if (IS_IRONLAKE_M(dev))
+               ironlake_enable_rc6(dev);
  
        intel_setup_overlay(dev);
  }
index 9073e3bfb08c7cde39ee411700e0ba838611fc2c,34cd5a878088b19f65a87cffd9c491cdd31ae0c2..7c37638095f7d1fa01624116d464e1d2a22ce8d9
@@@ -1578,7 -1578,7 +1578,7 @@@ static void evergreen_gpu_init(struct r
        u32 sq_stack_resource_mgmt_2;
        u32 sq_stack_resource_mgmt_3;
        u32 vgt_cache_invalidation;
-       u32 hdp_host_path_cntl;
+       u32 hdp_host_path_cntl, tmp;
        int i, j, num_shader_engines, ps_thread_count;
  
        switch (rdev->family) {
  
  
        mc_shared_chmap = RREG32(MC_SHARED_CHMAP);
 -      mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
 +      if (rdev->flags & RADEON_IS_IGP)
 +              mc_arb_ramcfg = RREG32(FUS_MC_ARB_RAMCFG);
 +      else
 +              mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
  
        switch (rdev->config.evergreen.max_tile_pipes) {
        case 1:
                rdev->config.evergreen.tile_config |= (3 << 0);
                break;
        }
-       rdev->config.evergreen.tile_config |=
-               ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
+       /* num banks is 8 on all fusion asics */
+       if (rdev->flags & RADEON_IS_IGP)
+               rdev->config.evergreen.tile_config |= 8 << 4;
+       else
+               rdev->config.evergreen.tile_config |=
+                       ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
        rdev->config.evergreen.tile_config |=
                ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8;
        rdev->config.evergreen.tile_config |=
        for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4)
                WREG32(i, 0);
  
+       tmp = RREG32(HDP_MISC_CNTL);
+       tmp |= HDP_FLUSH_INVALIDATE_CACHE;
+       WREG32(HDP_MISC_CNTL, tmp);
        hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
        WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
  
index fc40e0cc34516bb96af19f1a7615b6889a7425e3,75b57e394f2bd5179de72c5b9f513074bca3c468..f37e91ee8a1114aed16bab49143fd5d1fe206914
@@@ -64,6 -64,8 +64,8 @@@
  #define GB_BACKEND_MAP                                0x98FC
  #define DMIF_ADDR_CONFIG                              0xBD4
  #define HDP_ADDR_CONFIG                               0x2F48
+ #define HDP_MISC_CNTL                                         0x2F4C
+ #define               HDP_FLUSH_INVALIDATE_CACHE              (1 << 0)
  
  #define       CC_SYS_RB_BACKEND_DISABLE                       0x3F88
  #define       GC_USER_RB_BACKEND_DISABLE                      0x9B7C
  #define               BURSTLENGTH_SHIFT                               9
  #define               BURSTLENGTH_MASK                                0x00000200
  #define               CHANSIZE_OVERRIDE                               (1 << 11)
 +#define       FUS_MC_ARB_RAMCFG                               0x2768
  #define       MC_VM_AGP_TOP                                   0x2028
  #define       MC_VM_AGP_BOT                                   0x202C
  #define       MC_VM_AGP_BASE                                  0x2030
index 3d8a7634bbe99ade0344aeb2061bc5f3ac183757,a0cc7a5ff03136e8aedea35d61610412a7dbee89..b205ba1cdd8f9b562a2033c9fec000a7b0b83e7e
@@@ -417,7 -417,7 +417,7 @@@ static u32 cayman_get_tile_pipe_to_back
                num_shader_engines = 1;
        if (num_shader_engines > rdev->config.cayman.max_shader_engines)
                num_shader_engines = rdev->config.cayman.max_shader_engines;
-       if (num_backends_per_asic > num_shader_engines)
+       if (num_backends_per_asic < num_shader_engines)
                num_backends_per_asic = num_shader_engines;
        if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines))
                num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines;
@@@ -674,7 -674,7 +674,7 @@@ static void cayman_gpu_init(struct rade
  
        cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE);
        cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG);
 -      cgts_tcc_disable = RREG32(CGTS_TCC_DISABLE);
 +      cgts_tcc_disable = 0xff000000;
        gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE);
        gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG);
        cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE);
        rdev->config.cayman.tile_config |=
                ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
        rdev->config.cayman.tile_config |=
-               (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT;
+               ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8;
        rdev->config.cayman.tile_config |=
                ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12;
  
  
        smx_dc_ctl0 = RREG32(SMX_DC_CTL0);
        smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff);
 -      smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets);
 +      smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.cayman.sx_num_of_sets);
        WREG32(SMX_DC_CTL0, smx_dc_ctl0);
  
        WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE);
  
        WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO);
  
 -      WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) |
 -                                      POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) |
 -                                      SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1)));
 +      WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.cayman.sx_max_export_size / 4) - 1) |
 +                                      POSITION_BUFFER_SIZE((rdev->config.cayman.sx_max_export_pos_size / 4) - 1) |
 +                                      SMX_BUFFER_SIZE((rdev->config.cayman.sx_max_export_smx_size / 4) - 1)));
  
 -      WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.evergreen.sc_prim_fifo_size) |
 -                               SC_HIZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_hiz_tile_fifo_size) |
 -                               SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_earlyz_tile_fifo_size)));
 +      WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.cayman.sc_prim_fifo_size) |
 +                               SC_HIZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_hiz_tile_fifo_size) |
 +                               SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_earlyz_tile_fifo_size)));
  
  
        WREG32(VGT_NUM_INSTANCES, 1);
  
        WREG32(CP_PERFMON_CNTL, 0);
  
 -      WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.evergreen.sq_num_cf_insts) |
 +      WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.cayman.sq_num_cf_insts) |
                                  FETCH_FIFO_HIWATER(0x4) |
                                  DONE_FIFO_HIWATER(0xe0) |
                                  ALU_UPDATE_FIFO_HIWATER(0x8)));
        WREG32(CB_PERF_CTR3_SEL_0, 0);
        WREG32(CB_PERF_CTR3_SEL_1, 0);
  
+       tmp = RREG32(HDP_MISC_CNTL);
+       tmp |= HDP_FLUSH_INVALIDATE_CACHE;
+       WREG32(HDP_MISC_CNTL, tmp);
        hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
        WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
  
index 498b284e5ef955d11b3ccc3b4a9aaad7bd275df6,f0f244d2943849c1436bbcde741bc3390ebada61..58434e804d91c5863c460390addcf10c2530bc29
@@@ -215,10 -215,12 +215,9 @@@ static int vga_switchoff(struct vga_swi
  /* stage one happens before delay */
  static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
  {
-       int ret;
        int i;
        struct vga_switcheroo_client *active = NULL;
  
 -      if (new_client->active == true)
 -              return 0;
 -
        for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
                if (vgasr_priv.clients[i].active == true) {
                        active = &vgasr_priv.clients[i];
        if (!active)
                return 0;
  
-       /* power up the first device */
-       ret = pci_enable_device(new_client->pdev);
-       if (ret)
-               return ret;
        if (new_client->pwr_state == VGA_SWITCHEROO_OFF)
                vga_switchon(new_client);
  
@@@ -369,9 -366,6 +363,9 @@@ vga_switcheroo_debugfs_write(struct fil
                goto out;
        }
  
 +      if (client->active == true)
 +              goto out;
 +
        /* okay we want a switch - test if devices are willing to switch */
        can_switch = true;
        for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
diff --combined drivers/pci/pci.c
index 22c9b27fdd8d8bd0bc9790416cd2ef883f5b67e9,a339237f4f96b331d707a613499e43d391c8e0de..56098b3e17c054a678253c028221610dc17f3ff5
@@@ -830,7 -830,7 +830,7 @@@ static int pci_save_pcie_state(struct p
                dev_err(&dev->dev, "buffer not found in %s\n", __func__);
                return -ENOMEM;
        }
 -      cap = (u16 *)&save_state->data[0];
 +      cap = (u16 *)&save_state->cap.data[0];
  
        pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
  
@@@ -863,7 -863,7 +863,7 @@@ static void pci_restore_pcie_state(stru
        pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
        if (!save_state || pos <= 0)
                return;
 -      cap = (u16 *)&save_state->data[0];
 +      cap = (u16 *)&save_state->cap.data[0];
  
        pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
  
@@@ -899,8 -899,7 +899,8 @@@ static int pci_save_pcix_state(struct p
                return -ENOMEM;
        }
  
 -      pci_read_config_word(dev, pos + PCI_X_CMD, (u16 *)save_state->data);
 +      pci_read_config_word(dev, pos + PCI_X_CMD,
 +                           (u16 *)save_state->cap.data);
  
        return 0;
  }
@@@ -915,7 -914,7 +915,7 @@@ static void pci_restore_pcix_state(stru
        pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
        if (!save_state || pos <= 0)
                return;
 -      cap = (u16 *)&save_state->data[0];
 +      cap = (u16 *)&save_state->cap.data[0];
  
        pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
  }
@@@ -976,104 -975,6 +976,104 @@@ void pci_restore_state(struct pci_dev *
        dev->state_saved = false;
  }
  
 +struct pci_saved_state {
 +      u32 config_space[16];
 +      struct pci_cap_saved_data cap[0];
 +};
 +
 +/**
 + * pci_store_saved_state - Allocate and return an opaque struct containing
 + *                       the device saved state.
 + * @dev: PCI device that we're dealing with
 + *
 + * Rerturn NULL if no state or error.
 + */
 +struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev)
 +{
 +      struct pci_saved_state *state;
 +      struct pci_cap_saved_state *tmp;
 +      struct pci_cap_saved_data *cap;
 +      struct hlist_node *pos;
 +      size_t size;
 +
 +      if (!dev->state_saved)
 +              return NULL;
 +
 +      size = sizeof(*state) + sizeof(struct pci_cap_saved_data);
 +
 +      hlist_for_each_entry(tmp, pos, &dev->saved_cap_space, next)
 +              size += sizeof(struct pci_cap_saved_data) + tmp->cap.size;
 +
 +      state = kzalloc(size, GFP_KERNEL);
 +      if (!state)
 +              return NULL;
 +
 +      memcpy(state->config_space, dev->saved_config_space,
 +             sizeof(state->config_space));
 +
 +      cap = state->cap;
 +      hlist_for_each_entry(tmp, pos, &dev->saved_cap_space, next) {
 +              size_t len = sizeof(struct pci_cap_saved_data) + tmp->cap.size;
 +              memcpy(cap, &tmp->cap, len);
 +              cap = (struct pci_cap_saved_data *)((u8 *)cap + len);
 +      }
 +      /* Empty cap_save terminates list */
 +
 +      return state;
 +}
 +EXPORT_SYMBOL_GPL(pci_store_saved_state);
 +
 +/**
 + * pci_load_saved_state - Reload the provided save state into struct pci_dev.
 + * @dev: PCI device that we're dealing with
 + * @state: Saved state returned from pci_store_saved_state()
 + */
 +int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state)
 +{
 +      struct pci_cap_saved_data *cap;
 +
 +      dev->state_saved = false;
 +
 +      if (!state)
 +              return 0;
 +
 +      memcpy(dev->saved_config_space, state->config_space,
 +             sizeof(state->config_space));
 +
 +      cap = state->cap;
 +      while (cap->size) {
 +              struct pci_cap_saved_state *tmp;
 +
 +              tmp = pci_find_saved_cap(dev, cap->cap_nr);
 +              if (!tmp || tmp->cap.size != cap->size)
 +                      return -EINVAL;
 +
 +              memcpy(tmp->cap.data, cap->data, tmp->cap.size);
 +              cap = (struct pci_cap_saved_data *)((u8 *)cap +
 +                     sizeof(struct pci_cap_saved_data) + cap->size);
 +      }
 +
 +      dev->state_saved = true;
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(pci_load_saved_state);
 +
 +/**
 + * pci_load_and_free_saved_state - Reload the save state pointed to by state,
 + *                               and free the memory allocated for it.
 + * @dev: PCI device that we're dealing with
 + * @state: Pointer to saved state returned from pci_store_saved_state()
 + */
 +int pci_load_and_free_saved_state(struct pci_dev *dev,
 +                                struct pci_saved_state **state)
 +{
 +      int ret = pci_load_saved_state(dev, *state);
 +      kfree(*state);
 +      *state = NULL;
 +      return ret;
 +}
 +EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state);
 +
  static int do_pci_enable_device(struct pci_dev *dev, int bars)
  {
        int err;
@@@ -1870,8 -1771,7 +1870,8 @@@ static int pci_add_cap_save_buffer
        if (!save_state)
                return -ENOMEM;
  
 -      save_state->cap_nr = cap;
 +      save_state->cap.cap_nr = cap;
 +      save_state->cap.size = size;
        pci_add_saved_cap(dev, save_state);
  
        return 0;
@@@ -1934,300 -1834,6 +1934,300 @@@ void pci_enable_ari(struct pci_dev *dev
        bridge->ari_enabled = 1;
  }
  
 +/**
 + * pci_enable_ido - enable ID-based ordering on a device
 + * @dev: the PCI device
 + * @type: which types of IDO to enable
 + *
 + * Enable ID-based ordering on @dev.  @type can contain the bits
 + * %PCI_EXP_IDO_REQUEST and/or %PCI_EXP_IDO_COMPLETION to indicate
 + * which types of transactions are allowed to be re-ordered.
 + */
 +void pci_enable_ido(struct pci_dev *dev, unsigned long type)
 +{
 +      int pos;
 +      u16 ctrl;
 +
 +      pos = pci_pcie_cap(dev);
 +      if (!pos)
 +              return;
 +
 +      pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
 +      if (type & PCI_EXP_IDO_REQUEST)
 +              ctrl |= PCI_EXP_IDO_REQ_EN;
 +      if (type & PCI_EXP_IDO_COMPLETION)
 +              ctrl |= PCI_EXP_IDO_CMP_EN;
 +      pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
 +}
 +EXPORT_SYMBOL(pci_enable_ido);
 +
 +/**
 + * pci_disable_ido - disable ID-based ordering on a device
 + * @dev: the PCI device
 + * @type: which types of IDO to disable
 + */
 +void pci_disable_ido(struct pci_dev *dev, unsigned long type)
 +{
 +      int pos;
 +      u16 ctrl;
 +
 +      if (!pci_is_pcie(dev))
 +              return;
 +
 +      pos = pci_pcie_cap(dev);
 +      if (!pos)
 +              return;
 +
 +      pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
 +      if (type & PCI_EXP_IDO_REQUEST)
 +              ctrl &= ~PCI_EXP_IDO_REQ_EN;
 +      if (type & PCI_EXP_IDO_COMPLETION)
 +              ctrl &= ~PCI_EXP_IDO_CMP_EN;
 +      pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
 +}
 +EXPORT_SYMBOL(pci_disable_ido);
 +
 +/**
 + * pci_enable_obff - enable optimized buffer flush/fill
 + * @dev: PCI device
 + * @type: type of signaling to use
 + *
 + * Try to enable @type OBFF signaling on @dev.  It will try using WAKE#
 + * signaling if possible, falling back to message signaling only if
 + * WAKE# isn't supported.  @type should indicate whether the PCIe link
 + * be brought out of L0s or L1 to send the message.  It should be either
 + * %PCI_EXP_OBFF_SIGNAL_ALWAYS or %PCI_OBFF_SIGNAL_L0.
 + *
 + * If your device can benefit from receiving all messages, even at the
 + * power cost of bringing the link back up from a low power state, use
 + * %PCI_EXP_OBFF_SIGNAL_ALWAYS.  Otherwise, use %PCI_OBFF_SIGNAL_L0 (the
 + * preferred type).
 + *
 + * RETURNS:
 + * Zero on success, appropriate error number on failure.
 + */
 +int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
 +{
 +      int pos;
 +      u32 cap;
 +      u16 ctrl;
 +      int ret;
 +
 +      if (!pci_is_pcie(dev))
 +              return -ENOTSUPP;
 +
 +      pos = pci_pcie_cap(dev);
 +      if (!pos)
 +              return -ENOTSUPP;
 +
 +      pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap);
 +      if (!(cap & PCI_EXP_OBFF_MASK))
 +              return -ENOTSUPP; /* no OBFF support at all */
 +
 +      /* Make sure the topology supports OBFF as well */
 +      if (dev->bus) {
 +              ret = pci_enable_obff(dev->bus->self, type);
 +              if (ret)
 +                      return ret;
 +      }
 +
 +      pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
 +      if (cap & PCI_EXP_OBFF_WAKE)
 +              ctrl |= PCI_EXP_OBFF_WAKE_EN;
 +      else {
 +              switch (type) {
 +              case PCI_EXP_OBFF_SIGNAL_L0:
 +                      if (!(ctrl & PCI_EXP_OBFF_WAKE_EN))
 +                              ctrl |= PCI_EXP_OBFF_MSGA_EN;
 +                      break;
 +              case PCI_EXP_OBFF_SIGNAL_ALWAYS:
 +                      ctrl &= ~PCI_EXP_OBFF_WAKE_EN;
 +                      ctrl |= PCI_EXP_OBFF_MSGB_EN;
 +                      break;
 +              default:
 +                      WARN(1, "bad OBFF signal type\n");
 +                      return -ENOTSUPP;
 +              }
 +      }
 +      pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL(pci_enable_obff);
 +
 +/**
 + * pci_disable_obff - disable optimized buffer flush/fill
 + * @dev: PCI device
 + *
 + * Disable OBFF on @dev.
 + */
 +void pci_disable_obff(struct pci_dev *dev)
 +{
 +      int pos;
 +      u16 ctrl;
 +
 +      if (!pci_is_pcie(dev))
 +              return;
 +
 +      pos = pci_pcie_cap(dev);
 +      if (!pos)
 +              return;
 +
 +      pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
 +      ctrl &= ~PCI_EXP_OBFF_WAKE_EN;
 +      pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
 +}
 +EXPORT_SYMBOL(pci_disable_obff);
 +
 +/**
 + * pci_ltr_supported - check whether a device supports LTR
 + * @dev: PCI device
 + *
 + * RETURNS:
 + * True if @dev supports latency tolerance reporting, false otherwise.
 + */
 +bool pci_ltr_supported(struct pci_dev *dev)
 +{
 +      int pos;
 +      u32 cap;
 +
 +      if (!pci_is_pcie(dev))
 +              return false;
 +
 +      pos = pci_pcie_cap(dev);
 +      if (!pos)
 +              return false;
 +
 +      pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap);
 +
 +      return cap & PCI_EXP_DEVCAP2_LTR;
 +}
 +EXPORT_SYMBOL(pci_ltr_supported);
 +
 +/**
 + * pci_enable_ltr - enable latency tolerance reporting
 + * @dev: PCI device
 + *
 + * Enable LTR on @dev if possible, which means enabling it first on
 + * upstream ports.
 + *
 + * RETURNS:
 + * Zero on success, errno on failure.
 + */
 +int pci_enable_ltr(struct pci_dev *dev)
 +{
 +      int pos;
 +      u16 ctrl;
 +      int ret;
 +
 +      if (!pci_ltr_supported(dev))
 +              return -ENOTSUPP;
 +
 +      pos = pci_pcie_cap(dev);
 +      if (!pos)
 +              return -ENOTSUPP;
 +
 +      /* Only primary function can enable/disable LTR */
 +      if (PCI_FUNC(dev->devfn) != 0)
 +              return -EINVAL;
 +
 +      /* Enable upstream ports first */
 +      if (dev->bus) {
 +              ret = pci_enable_ltr(dev->bus->self);
 +              if (ret)
 +                      return ret;
 +      }
 +
 +      pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
 +      ctrl |= PCI_EXP_LTR_EN;
 +      pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL(pci_enable_ltr);
 +
 +/**
 + * pci_disable_ltr - disable latency tolerance reporting
 + * @dev: PCI device
 + */
 +void pci_disable_ltr(struct pci_dev *dev)
 +{
 +      int pos;
 +      u16 ctrl;
 +
 +      if (!pci_ltr_supported(dev))
 +              return;
 +
 +      pos = pci_pcie_cap(dev);
 +      if (!pos)
 +              return;
 +
 +      /* Only primary function can enable/disable LTR */
 +      if (PCI_FUNC(dev->devfn) != 0)
 +              return;
 +
 +      pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
 +      ctrl &= ~PCI_EXP_LTR_EN;
 +      pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
 +}
 +EXPORT_SYMBOL(pci_disable_ltr);
 +
 +static int __pci_ltr_scale(int *val)
 +{
 +      int scale = 0;
 +
 +      while (*val > 1023) {
 +              *val = (*val + 31) / 32;
 +              scale++;
 +      }
 +      return scale;
 +}
 +
 +/**
 + * pci_set_ltr - set LTR latency values
 + * @dev: PCI device
 + * @snoop_lat_ns: snoop latency in nanoseconds
 + * @nosnoop_lat_ns: nosnoop latency in nanoseconds
 + *
 + * Figure out the scale and set the LTR values accordingly.
 + */
 +int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns)
 +{
 +      int pos, ret, snoop_scale, nosnoop_scale;
 +      u16 val;
 +
 +      if (!pci_ltr_supported(dev))
 +              return -ENOTSUPP;
 +
 +      snoop_scale = __pci_ltr_scale(&snoop_lat_ns);
 +      nosnoop_scale = __pci_ltr_scale(&nosnoop_lat_ns);
 +
 +      if (snoop_lat_ns > PCI_LTR_VALUE_MASK ||
 +          nosnoop_lat_ns > PCI_LTR_VALUE_MASK)
 +              return -EINVAL;
 +
 +      if ((snoop_scale > (PCI_LTR_SCALE_MASK >> PCI_LTR_SCALE_SHIFT)) ||
 +          (nosnoop_scale > (PCI_LTR_SCALE_MASK >> PCI_LTR_SCALE_SHIFT)))
 +              return -EINVAL;
 +
 +      pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
 +      if (!pos)
 +              return -ENOTSUPP;
 +
 +      val = (snoop_scale << PCI_LTR_SCALE_SHIFT) | snoop_lat_ns;
 +      ret = pci_write_config_word(dev, pos + PCI_LTR_MAX_SNOOP_LAT, val);
 +      if (ret != 4)
 +              return -EIO;
 +
 +      val = (nosnoop_scale << PCI_LTR_SCALE_SHIFT) | nosnoop_lat_ns;
 +      ret = pci_write_config_word(dev, pos + PCI_LTR_MAX_NOSNOOP_LAT, val);
 +      if (ret != 4)
 +              return -EIO;
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL(pci_set_ltr);
 +
  static int pci_acs_enable;
  
  /**
@@@ -2873,21 -2479,6 +2873,21 @@@ clear
        return 0;
  }
  
 +/**
 + * pci_pm_reset - Put device into PCI_D3 and back into PCI_D0.
 + * @dev: Device to reset.
 + * @probe: If set, only check if the device can be reset this way.
 + *
 + * If @dev supports native PCI PM and its PCI_PM_CTRL_NO_SOFT_RESET flag is
 + * unset, it will be reinitialized internally when going from PCI_D3hot to
 + * PCI_D0.  If that's the case and the device is not in a low-power state
 + * already, force it into PCI_D3hot and back to PCI_D0, causing it to be reset.
 + *
 + * NOTE: This causes the caller to sleep for twice the device power transition
 + * cooldown period, which for the D0->D3hot and D3hot->D0 transitions is 10 ms
 + * by devault (i.e. unless the @dev's d3_delay field has a different value).
 + * Moreover, only devices in D0 can be reset by this function.
 + */
  static int pci_pm_reset(struct pci_dev *dev, int probe)
  {
        u16 csr;
@@@ -3284,31 -2875,34 +3284,34 @@@ static int pci_set_vga_state_arch(struc
   * @dev: the PCI device
   * @decode: true = enable decoding, false = disable decoding
   * @command_bits: PCI_COMMAND_IO and/or PCI_COMMAND_MEMORY
-  * @change_bridge: traverse ancestors and change bridges
+  * @change_bridge_flags: traverse ancestors and change bridges
+  * CHANGE_BRIDGE_ONLY / CHANGE_BRIDGE
   */
  int pci_set_vga_state(struct pci_dev *dev, bool decode,
-                     unsigned int command_bits, bool change_bridge)
+                     unsigned int command_bits, u32 flags)
  {
        struct pci_bus *bus;
        struct pci_dev *bridge;
        u16 cmd;
        int rc;
  
-       WARN_ON(command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY));
+       WARN_ON((flags & PCI_VGA_STATE_CHANGE_DECODES) & (command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY)));
  
        /* ARCH specific VGA enables */
-       rc = pci_set_vga_state_arch(dev, decode, command_bits, change_bridge);
+       rc = pci_set_vga_state_arch(dev, decode, command_bits, flags);
        if (rc)
                return rc;
  
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       if (decode == true)
-               cmd |= command_bits;
-       else
-               cmd &= ~command_bits;
-       pci_write_config_word(dev, PCI_COMMAND, cmd);
+       if (flags & PCI_VGA_STATE_CHANGE_DECODES) {
+               pci_read_config_word(dev, PCI_COMMAND, &cmd);
+               if (decode == true)
+                       cmd |= command_bits;
+               else
+                       cmd &= ~command_bits;
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
+       }
  
-       if (change_bridge == false)
+       if (!(flags & PCI_VGA_STATE_CHANGE_BRIDGE))
                return 0;
  
        bus = dev->bus;
index 485c09eef424eeb3d1b2e4f06c191cc33722a4f3,006c6d5c78052a3a6866e3f7e872a0c21cb1b16e..5cb999b50f95a7580d90fe6ea3675282ccdea6f4
@@@ -111,7 -111,7 +111,7 @@@ config DELL_WMI_AI
          All-In-One machines.
  
          To compile this driver as a module, choose M here: the module will
 -        be called dell-wmi.
 +        be called dell-wmi-aio.
  
  
  config FUJITSU_LAPTOP
@@@ -753,4 -753,11 +753,11 @@@ config SAMSUNG_LAPTO
          To compile this driver as a module, choose M here: the module
          will be called samsung-laptop.
  
+ config MXM_WMI
+        tristate "WMI support for MXM Laptop Graphics"
+        depends on ACPI_WMI
+        ---help---
+           MXM is a standard for laptop graphics cards, the WMI interface
+         is required for switchable nvidia graphics machines
  endif # X86_PLATFORM_DEVICES
diff --combined include/linux/pci.h
index 4604d1d5514d9b84bba1eecf8a254a2699fe5575,f2e57b2e6a8116dc7da8bdf0200d2a4c067fa6ec..c446b5ca2d38e0e58b650b217bec0f0f90945dd7
@@@ -214,17 -214,12 +214,17 @@@ enum pci_bus_speed 
        PCI_SPEED_UNKNOWN               = 0xff,
  };
  
 -struct pci_cap_saved_state {
 -      struct hlist_node next;
 +struct pci_cap_saved_data {
        char cap_nr;
 +      unsigned int size;
        u32 data[0];
  };
  
 +struct pci_cap_saved_state {
 +      struct hlist_node next;
 +      struct pci_cap_saved_data cap;
 +};
 +
  struct pcie_link_state;
  struct pci_vpd;
  struct pci_sriov;
@@@ -371,7 -366,7 +371,7 @@@ static inline struct pci_cap_saved_stat
        struct hlist_node *pos;
  
        hlist_for_each_entry(tmp, pos, &pci_dev->saved_cap_space, next) {
 -              if (tmp->cap_nr == cap)
 +              if (tmp->cap.cap_nr == cap)
                        return tmp;
        }
        return NULL;
@@@ -812,10 -807,6 +812,10 @@@ size_t pci_get_rom_size(struct pci_dev 
  /* Power management related routines */
  int pci_save_state(struct pci_dev *dev);
  void pci_restore_state(struct pci_dev *dev);
 +struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev);
 +int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state);
 +int pci_load_and_free_saved_state(struct pci_dev *dev,
 +                                struct pci_saved_state **state);
  int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state);
  int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
  pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
@@@ -837,23 -828,6 +837,23 @@@ static inline int pci_enable_wake(struc
        return __pci_enable_wake(dev, state, false, enable);
  }
  
 +#define PCI_EXP_IDO_REQUEST   (1<<0)
 +#define PCI_EXP_IDO_COMPLETION        (1<<1)
 +void pci_enable_ido(struct pci_dev *dev, unsigned long type);
 +void pci_disable_ido(struct pci_dev *dev, unsigned long type);
 +
 +enum pci_obff_signal_type {
 +      PCI_EXP_OBFF_SIGNAL_L0,
 +      PCI_EXP_OBFF_SIGNAL_ALWAYS,
 +};
 +int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type);
 +void pci_disable_obff(struct pci_dev *dev);
 +
 +bool pci_ltr_supported(struct pci_dev *dev);
 +int pci_enable_ltr(struct pci_dev *dev);
 +void pci_disable_ltr(struct pci_dev *dev);
 +int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns);
 +
  /* For use by arch with custom probe code */
  void set_pcie_port_type(struct pci_dev *pdev);
  void set_pcie_hotplug_bridge(struct pci_dev *pdev);
@@@ -941,8 -915,11 +941,11 @@@ int pci_cfg_space_size_ext(struct pci_d
  int pci_cfg_space_size(struct pci_dev *dev);
  unsigned char pci_bus_max_busnr(struct pci_bus *bus);
  
+ #define PCI_VGA_STATE_CHANGE_BRIDGE (1 << 0)
+ #define PCI_VGA_STATE_CHANGE_DECODES (1 << 1)
  int pci_set_vga_state(struct pci_dev *pdev, bool decode,
-                     unsigned int command_bits, bool change_bridge);
+                     unsigned int command_bits, u32 flags);
  /* kmem_cache style wrapper around pci_alloc_consistent() */
  
  #include <linux/pci-dma.h>
@@@ -1087,7 -1064,7 +1090,7 @@@ static inline int pci_proc_domain(struc
  
  /* some architectures require additional setup to direct VGA traffic */
  typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
-                     unsigned int command_bits, bool change_bridge);
+                     unsigned int command_bits, u32 flags);
  extern void pci_register_set_vga_state(arch_set_vga_state_t func);
  
  #else /* CONFIG_PCI is not enabled */
@@@ -1233,23 -1210,6 +1236,23 @@@ static inline int pci_enable_wake(struc
        return 0;
  }
  
 +static inline void pci_enable_ido(struct pci_dev *dev, unsigned long type)
 +{
 +}
 +
 +static inline void pci_disable_ido(struct pci_dev *dev, unsigned long type)
 +{
 +}
 +
 +static inline int pci_enable_obff(struct pci_dev *dev, unsigned long type)
 +{
 +      return 0;
 +}
 +
 +static inline void pci_disable_obff(struct pci_dev *dev)
 +{
 +}
 +
  static inline int pci_request_regions(struct pci_dev *dev, const char *res_name)
  {
        return -EIO;