Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Linus Torvalds [Thu, 22 Mar 2012 20:08:22 +0000 (13:08 -0700)]
Pull drm main changes from Dave Airlie:
 "This is the main drm pull request, I'm probably going to send two more
  smaller ones, will explain below.

  This contains a patch that is also in the fbdev tree, but it should be
  the same patch, it added an API for hot unplugging framebuffer
  devices, and I need that API for a new driver.

  It also contains some changes to the i2c tree which Jean has acked,
  and one change to moorestown platform stuff in x86.

  Highlights:
   - new drivers: UDL driver for USB displaylink devices, kms only,
     should support correct hotplug operations.
   - core: i2c speedups + better hotplug support, EDID overriding via
     firmware interface - allows user to load a firmware for a broken
     monitor/kvm from userspace, it even has documentation for it.
   - exynos: new HDMI audio + hdmi 1.4 + virtual output driver
   - gma500: code cleanup
   - radeon: cleanups, CS optimisations, streamout support and pageflip
     fix
   - nouveau: NVD9 displayport support + more reclocking work
   - i915: re-enabling GMBUS, finish gpu patch (might help hibernation
     who knows), missed irq fixes, stencil tiling fixes, interlaced
     support, aliasesd PPGTT support for SNB/IVB, swizzling for SNB/IVB,
     semaphore fixes

  As well as the usual bunch of cleanups and fixes all over the place.

  I've got two things I'd like to merge a bit later:

   a) AMD support for all their new radeonhd 7000 series GPU and APUs.
      AMD dropped this a bit late due to insane internal review
      processes, (please AMD just follow Intel and let open source guys
      ship stuff early) however I don't want to penalise people who own
      this hardware (since its been on sale for 3-4 months and GPU hw
      doesn't exactly have a lifetime in years) and consign them to
      using closed drivers for longer than necessary.  The changes are
      well contained and just plug into the driver new gpu functionality
      so they should be fairly regression proof.  I just want to give
      them a bit of a run on the hw AMD kindly sent me.

   b) drm prime/dma-buf interface code.  This is just infrastructure
      code to expose the dma-buf stuff to drm drivers and to userspace.
      I'm not planning on pushing any driver support in this cycle
      (except maybe exynos), but I'd like to get the infrastructure code
      in so for the next cycle I can start getting the driver support
      into the individual drivers.  We have started driver support for
      i915, nouveau and udl along with I think exynos and omap in
      staging.  However this code relies on the dma-buf tree being
      pulled into your tree first since it needs the latest interfaces
      from that tree.  I'll push to get that tree sent asap.

  (oh and any warnings you see in i915 are gcc's fault from what anyone
  can see)."

Fix up trivial conflicts in arch/x86/platform/mrst/mrst.c due to the new
msic_thermal_platform_data() thermal function being added next to the
tc35876x_platform_data() i2c device function..

* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (326 commits)
  drm/i915: use DDC_ADDR instead of hard-coding it
  drm/radeon: use DDC_ADDR instead of hard-coding it
  drm: remove unneeded redefinition of DDC_ADDR
  drm/exynos: added virtual display driver.
  drm: allow loading an EDID as firmware to override broken monitor
  drm/exynos: enable hdmi audio feature
  drm/exynos: add default pixel format for plane
  drm/exynos: cleanup exynos_hdmi.h
  drm/exynos: add is_local member in exynos_drm_subdrv struct
  drm/exynos: add subdrv open/close functions
  drm/exynos: remove module of exynos drm subdrv
  drm/exynos: release pending pageflip events when closed
  drm/exynos: added new funtion to get/put dma address.
  drm/exynos: update gem and buffer framework.
  drm/exynos: added mode_fixup feature and code clean.
  drm/exynos: add HDMI version 1.4 support
  drm/exynos: remove exynos_mixer.h
  gma500: Fix mmap frambuffer
  drm/radeon: Drop radeon_gem_object_(un)pin.
  drm/radeon: Restrict offset for legacy display engine.
  ...

13 files changed:
1  2 
Documentation/kernel-parameters.txt
arch/x86/platform/mrst/mrst.c
drivers/gpu/drm/exynos/exynos_drm_connector.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/gma500/mmu.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/i2c/algos/i2c-algo-bit.c

@@@ -713,6 -713,21 +713,21 @@@ bytes respectively. Such letter suffixe
                        The filter can be disabled or changed to another
                        driver later using sysfs.
  
+       drm_kms_helper.edid_firmware=[<connector>:]<file>
+                       Broken monitors, graphic adapters and KVMs may
+                       send no or incorrect EDID data sets. This parameter
+                       allows to specify an EDID data set in the
+                       /lib/firmware directory that is used instead.
+                       Generic built-in EDID data sets are used, if one of
+                       edid/1024x768.bin, edid/1280x1024.bin,
+                       edid/1680x1050.bin, or edid/1920x1080.bin is given
+                       and no file with the same name exists. Details and
+                       instructions how to build your own EDID data are
+                       available in Documentation/EDID/HOWTO.txt. An EDID
+                       data set will only be used for a particular connector,
+                       if its name and a colon are prepended to the EDID
+                       name.
        dscc4.setup=    [NET]
  
        earlycon=       [KNL] Output early console device and options.
                             controller
        i8042.nopnp     [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
                             controllers
 -      i8042.notimeout [HW] Ignore timeout condition signalled by conroller
 +      i8042.notimeout [HW] Ignore timeout condition signalled by controller
        i8042.reset     [HW] Reset the controller during init and cleanup
        i8042.unlock    [HW] Unlock (ignore) the keylock
  
                        For more information see Documentation/vm/slub.txt.
  
        slub_min_order= [MM, SLUB]
 -                      Determines the mininum page order for slabs. Must be
 +                      Determines the minimum page order for slabs. Must be
                        lower than slub_max_order.
                        For more information see Documentation/vm/slub.txt.
  
  
        threadirqs      [KNL]
                        Force threading of all interrupt handlers except those
 -                      marked explicitely IRQF_NO_THREAD.
 +                      marked explicitly IRQF_NO_THREAD.
  
        topology=       [S390]
                        Format: {off | on}
                        to facilitate early boot debugging.
                        See also Documentation/trace/events.txt
  
 +      transparent_hugepage=
 +                      [KNL]
 +                      Format: [always|madvise|never]
 +                      Can be used to control the default behavior of the system
 +                      with respect to transparent hugepages.
 +                      See Documentation/vm/transhuge.txt for more details.
 +
        tsc=            Disable clocksource stability checks for TSC.
                        Format: <string>
                        [x86] reliable: mark tsc clocksource as reliable, this
@@@ -28,6 -28,8 +28,8 @@@
  #include <linux/module.h>
  #include <linux/notifier.h>
  #include <linux/mfd/intel_msic.h>
+ #include <linux/gpio.h>
+ #include <linux/i2c/tc35876x.h>
  
  #include <asm/setup.h>
  #include <asm/mpspec_def.h>
@@@ -78,11 -80,16 +80,11 @@@ int sfi_mrtc_num
  
  static void mrst_power_off(void)
  {
 -      if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT)
 -              intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 1);
  }
  
  static void mrst_reboot(void)
  {
 -      if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT)
 -              intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 0);
 -      else
 -              intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);
 +      intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);
  }
  
  /* parse all the mtimer info to a static mtimer array */
@@@ -195,28 -202,34 +197,28 @@@ int __init sfi_parse_mrtc(struct sfi_ta
  
  static unsigned long __init mrst_calibrate_tsc(void)
  {
 -      unsigned long flags, fast_calibrate;
 -      if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
 -              u32 lo, hi, ratio, fsb;
 -
 -              rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
 -              pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
 -              ratio = (hi >> 8) & 0x1f;
 -              pr_debug("ratio is %d\n", ratio);
 -              if (!ratio) {
 -                      pr_err("read a zero ratio, should be incorrect!\n");
 -                      pr_err("force tsc ratio to 16 ...\n");
 -                      ratio = 16;
 -              }
 -              rdmsr(MSR_FSB_FREQ, lo, hi);
 -              if ((lo & 0x7) == 0x7)
 -                      fsb = PENWELL_FSB_FREQ_83SKU;
 -              else
 -                      fsb = PENWELL_FSB_FREQ_100SKU;
 -              fast_calibrate = ratio * fsb;
 -              pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
 -              lapic_timer_frequency = fsb * 1000 / HZ;
 -              /* mark tsc clocksource as reliable */
 -              set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
 -      } else {
 -              local_irq_save(flags);
 -              fast_calibrate = apbt_quick_calibrate();
 -              local_irq_restore(flags);
 +      unsigned long fast_calibrate;
 +      u32 lo, hi, ratio, fsb;
 +
 +      rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
 +      pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
 +      ratio = (hi >> 8) & 0x1f;
 +      pr_debug("ratio is %d\n", ratio);
 +      if (!ratio) {
 +              pr_err("read a zero ratio, should be incorrect!\n");
 +              pr_err("force tsc ratio to 16 ...\n");
 +              ratio = 16;
        }
 +      rdmsr(MSR_FSB_FREQ, lo, hi);
 +      if ((lo & 0x7) == 0x7)
 +              fsb = PENWELL_FSB_FREQ_83SKU;
 +      else
 +              fsb = PENWELL_FSB_FREQ_100SKU;
 +      fast_calibrate = ratio * fsb;
 +      pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
 +      lapic_timer_frequency = fsb * 1000 / HZ;
 +      /* mark tsc clocksource as reliable */
 +      set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
        
        if (fast_calibrate)
                return fast_calibrate;
@@@ -250,11 -263,16 +252,11 @@@ static void __cpuinit mrst_arch_setup(v
  {
        if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27)
                __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
 -      else if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x26)
 -              __mrst_cpu_chip = MRST_CPU_CHIP_LINCROFT;
        else {
 -              pr_err("Unknown Moorestown CPU (%d:%d), default to Lincroft\n",
 +              pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n",
                        boot_cpu_data.x86, boot_cpu_data.x86_model);
 -              __mrst_cpu_chip = MRST_CPU_CHIP_LINCROFT;
 +              __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
        }
 -      pr_debug("Moorestown CPU %s identified\n",
 -              (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) ?
 -              "Lincroft" : "Penwell");
  }
  
  /* MID systems don't have i8042 controller */
@@@ -670,11 -688,19 +672,24 @@@ static void *msic_ocd_platform_data(voi
        return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
  }
  
 +static void *msic_thermal_platform_data(void *info)
 +{
 +      return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_THERMAL);
 +}
 +
+ /* tc35876x DSI-LVDS bridge chip and panel platform data */
+ static void *tc35876x_platform_data(void *data)
+ {
+        static struct tc35876x_platform_data pdata;
+        /* gpio pins set to -1 will not be used by the driver */
+        pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN");
+        pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN");
+        pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3");
+        return &pdata;
+ }
  static const struct devs_id __initconst device_ids[] = {
        {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data},
        {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
        {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},
        {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
        {"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data},
+       {"i2c_disp_brig", SFI_DEV_TYPE_I2C, 0, &tc35876x_platform_data},
  
        /* MSIC subdevices */
        {"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data},
        {"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data},
        {"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data},
        {"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data},
 +      {"msic_thermal", SFI_DEV_TYPE_IPC, 1, &msic_thermal_platform_data},
  
        {},
  };
@@@ -54,14 -54,14 +54,14 @@@ convert_to_display_mode(struct drm_disp
        mode->vrefresh = timing->refresh;
  
        mode->hdisplay = timing->xres;
 -      mode->hsync_start = mode->hdisplay + timing->left_margin;
 +      mode->hsync_start = mode->hdisplay + timing->right_margin;
        mode->hsync_end = mode->hsync_start + timing->hsync_len;
 -      mode->htotal = mode->hsync_end + timing->right_margin;
 +      mode->htotal = mode->hsync_end + timing->left_margin;
  
        mode->vdisplay = timing->yres;
 -      mode->vsync_start = mode->vdisplay + timing->upper_margin;
 +      mode->vsync_start = mode->vdisplay + timing->lower_margin;
        mode->vsync_end = mode->vsync_start + timing->vsync_len;
 -      mode->vtotal = mode->vsync_end + timing->lower_margin;
 +      mode->vtotal = mode->vsync_end + timing->upper_margin;
        mode->width_mm = panel->width_mm;
        mode->height_mm = panel->height_mm;
  
@@@ -85,14 -85,14 +85,14 @@@ convert_to_video_timing(struct fb_video
        timing->refresh = drm_mode_vrefresh(mode);
  
        timing->xres = mode->hdisplay;
 -      timing->left_margin = mode->hsync_start - mode->hdisplay;
 +      timing->right_margin = mode->hsync_start - mode->hdisplay;
        timing->hsync_len = mode->hsync_end - mode->hsync_start;
 -      timing->right_margin = mode->htotal - mode->hsync_end;
 +      timing->left_margin = mode->htotal - mode->hsync_end;
  
        timing->yres = mode->vdisplay;
 -      timing->upper_margin = mode->vsync_start - mode->vdisplay;
 +      timing->lower_margin = mode->vsync_start - mode->vdisplay;
        timing->vsync_len = mode->vsync_end - mode->vsync_start;
 -      timing->lower_margin = mode->vtotal - mode->vsync_end;
 +      timing->upper_margin = mode->vtotal - mode->vsync_end;
  
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                timing->vmode = FB_VMODE_INTERLACED;
@@@ -225,6 -225,29 +225,29 @@@ static struct drm_connector_helper_func
        .best_encoder   = exynos_drm_best_encoder,
  };
  
+ static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
+                               unsigned int max_width, unsigned int max_height)
+ {
+       struct exynos_drm_connector *exynos_connector =
+                                       to_exynos_connector(connector);
+       struct exynos_drm_manager *manager = exynos_connector->manager;
+       struct exynos_drm_manager_ops *ops = manager->ops;
+       unsigned int width, height;
+       width = max_width;
+       height = max_height;
+       /*
+        * if specific driver want to find desired_mode using maxmum
+        * resolution then get max width and height from that driver.
+        */
+       if (ops && ops->get_max_resol)
+               ops->get_max_resol(manager->dev, &width, &height);
+       return drm_helper_probe_single_connector_modes(connector, width,
+                                                       height);
+ }
  /* get detection status of display device. */
  static enum drm_connector_status
  exynos_drm_connector_detect(struct drm_connector *connector, bool force)
@@@ -262,7 -285,7 +285,7 @@@ static void exynos_drm_connector_destro
  
  static struct drm_connector_funcs exynos_connector_funcs = {
        .dpms           = drm_helper_connector_dpms,
-       .fill_modes     = drm_helper_probe_single_connector_modes,
+       .fill_modes     = exynos_drm_connector_fill_modes,
        .detect         = exynos_drm_connector_detect,
        .destroy        = exynos_drm_connector_destroy,
  };
@@@ -292,6 -315,10 +315,10 @@@ struct drm_connector *exynos_drm_connec
                connector->interlace_allowed = true;
                connector->polled = DRM_CONNECTOR_POLL_HPD;
                break;
+       case EXYNOS_DISPLAY_TYPE_VIDI:
+               type = DRM_MODE_CONNECTOR_VIRTUAL;
+               connector->polled = DRM_CONNECTOR_POLL_HPD;
+               break;
        default:
                type = DRM_MODE_CONNECTOR_Unknown;
                break;
@@@ -325,9 -352,3 +352,3 @@@ err_connector
        kfree(exynos_connector);
        return NULL;
  }
- MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
- MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
- MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
- MODULE_DESCRIPTION("Samsung SoC DRM Connector Driver");
- MODULE_LICENSE("GPL");
@@@ -38,6 -38,7 +38,7 @@@
  #include "exynos_drm_fb.h"
  #include "exynos_drm_gem.h"
  #include "exynos_drm_plane.h"
+ #include "exynos_drm_vidi.h"
  
  #define DRIVER_NAME   "exynos"
  #define DRIVER_DESC   "Samsung SoC DRM"
@@@ -144,11 -145,34 +145,34 @@@ static int exynos_drm_unload(struct drm
        return 0;
  }
  
+ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
+ {
+       DRM_DEBUG_DRIVER("%s\n", __FILE__);
+       return exynos_drm_subdrv_open(dev, file);
+ }
  static void exynos_drm_preclose(struct drm_device *dev,
                                        struct drm_file *file)
  {
+       struct exynos_drm_private *private = dev->dev_private;
+       struct drm_pending_vblank_event *e, *t;
+       unsigned long flags;
        DRM_DEBUG_DRIVER("%s\n", __FILE__);
  
+       /* release events of current file */
+       spin_lock_irqsave(&dev->event_lock, flags);
+       list_for_each_entry_safe(e, t, &private->pageflip_event_list,
+                       base.link) {
+               if (e->base.file_priv == file) {
+                       list_del(&e->base.link);
+                       e->base.destroy(&e->base);
+               }
+       }
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+       exynos_drm_subdrv_close(dev, file);
  }
  
  static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
@@@ -185,6 -209,8 +209,8 @@@ static struct drm_ioctl_desc exynos_ioc
                        exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH),
        DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS, exynos_plane_set_zpos_ioctl,
                        DRM_UNLOCKED | DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION,
+                       vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH),
  };
  
  static const struct file_operations exynos_drm_driver_fops = {
@@@ -202,6 -228,7 +228,7 @@@ static struct drm_driver exynos_drm_dri
                                  DRIVER_MODESET | DRIVER_GEM,
        .load                   = exynos_drm_load,
        .unload                 = exynos_drm_unload,
+       .open                   = exynos_drm_open,
        .preclose               = exynos_drm_preclose,
        .lastclose              = exynos_drm_lastclose,
        .postclose              = exynos_drm_postclose,
@@@ -246,15 -273,66 +273,66 @@@ static struct platform_driver exynos_dr
        .remove         = __devexit_p(exynos_drm_platform_remove),
        .driver         = {
                .owner  = THIS_MODULE,
 -              .name   = DRIVER_NAME,
 +              .name   = "exynos-drm",
        },
  };
  
  static int __init exynos_drm_init(void)
  {
+       int ret;
        DRM_DEBUG_DRIVER("%s\n", __FILE__);
  
-       return platform_driver_register(&exynos_drm_platform_driver);
+ #ifdef CONFIG_DRM_EXYNOS_FIMD
+       ret = platform_driver_register(&fimd_driver);
+       if (ret < 0)
+               goto out_fimd;
+ #endif
+ #ifdef CONFIG_DRM_EXYNOS_HDMI
+       ret = platform_driver_register(&hdmi_driver);
+       if (ret < 0)
+               goto out_hdmi;
+       ret = platform_driver_register(&mixer_driver);
+       if (ret < 0)
+               goto out_mixer;
+       ret = platform_driver_register(&exynos_drm_common_hdmi_driver);
+       if (ret < 0)
+               goto out_common_hdmi;
+ #endif
+ #ifdef CONFIG_DRM_EXYNOS_VIDI
+       ret = platform_driver_register(&vidi_driver);
+       if (ret < 0)
+               goto out_vidi;
+ #endif
+       ret = platform_driver_register(&exynos_drm_platform_driver);
+       if (ret < 0)
+               goto out;
+       return 0;
+ out:
+ #ifdef CONFIG_DRM_EXYNOS_VIDI
+ out_vidi:
+       platform_driver_unregister(&vidi_driver);
+ #endif
+ #ifdef CONFIG_DRM_EXYNOS_HDMI
+       platform_driver_unregister(&exynos_drm_common_hdmi_driver);
+ out_common_hdmi:
+       platform_driver_unregister(&mixer_driver);
+ out_mixer:
+       platform_driver_unregister(&hdmi_driver);
+ out_hdmi:
+ #endif
+ #ifdef CONFIG_DRM_EXYNOS_FIMD
+       platform_driver_unregister(&fimd_driver);
+ out_fimd:
+ #endif
+       return ret;
  }
  
  static void __exit exynos_drm_exit(void)
        DRM_DEBUG_DRIVER("%s\n", __FILE__);
  
        platform_driver_unregister(&exynos_drm_platform_driver);
+ #ifdef CONFIG_DRM_EXYNOS_HDMI
+       platform_driver_unregister(&exynos_drm_common_hdmi_driver);
+       platform_driver_unregister(&mixer_driver);
+       platform_driver_unregister(&hdmi_driver);
+ #endif
+ #ifdef CONFIG_DRM_EXYNOS_VIDI
+       platform_driver_unregister(&vidi_driver);
+ #endif
+ #ifdef CONFIG_DRM_EXYNOS_FIMD
+       platform_driver_unregister(&fimd_driver);
+ #endif
  }
  
  module_init(exynos_drm_init);
@@@ -817,6 -817,8 +817,6 @@@ static int __devinit fimd_probe(struct 
                goto err_clk_get;
        }
  
 -      clk_enable(ctx->bus_clk);
 -
        ctx->lcd_clk = clk_get(dev, "sclk_fimd");
        if (IS_ERR(ctx->lcd_clk)) {
                dev_err(dev, "failed to get lcd clock\n");
                goto err_bus_clk;
        }
  
 -      clk_enable(ctx->lcd_clk);
 -
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "failed to find registers\n");
                goto err_req_irq;
        }
  
 -      ctx->clkdiv = fimd_calc_clkdiv(ctx, &panel->timing);
        ctx->vidcon0 = pdata->vidcon0;
        ctx->vidcon1 = pdata->vidcon1;
        ctx->default_win = pdata->default_win;
        ctx->panel = panel;
  
 -      panel->timing.pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv;
 -
 -      DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n",
 -                      panel->timing.pixclock, ctx->clkdiv);
 -
        subdrv = &ctx->subdrv;
  
        subdrv->probe = fimd_subdrv_probe;
  
        platform_set_drvdata(pdev, ctx);
  
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
  
 +      ctx->clkdiv = fimd_calc_clkdiv(ctx, &panel->timing);
 +      panel->timing.pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv;
 +
 +      DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n",
 +                      panel->timing.pixclock, ctx->clkdiv);
 +
        for (win = 0; win < WINDOWS_NR; win++)
                fimd_clear_win(ctx, win);
  
@@@ -1007,7 -1012,7 +1007,7 @@@ static const struct dev_pm_ops fimd_pm_
        SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
  };
  
- static struct platform_driver fimd_driver = {
+ struct platform_driver fimd_driver = {
        .probe          = fimd_probe,
        .remove         = __devexit_p(fimd_remove),
        .driver         = {
                .pm     = &fimd_pm_ops,
        },
  };
- static int __init fimd_init(void)
- {
-       return platform_driver_register(&fimd_driver);
- }
- static void __exit fimd_exit(void)
- {
-       platform_driver_unregister(&fimd_driver);
- }
- module_init(fimd_init);
- module_exit(fimd_exit);
- MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
- MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
- MODULE_DESCRIPTION("Samsung DRM FIMD Driver");
- MODULE_LICENSE("GPL");
@@@ -125,14 -125,14 +125,14 @@@ static void psb_page_clflush(struct psb
        int i;
        uint8_t *clf;
  
 -      clf = kmap_atomic(page, KM_USER0);
 +      clf = kmap_atomic(page);
        mb();
        for (i = 0; i < clflush_count; ++i) {
                psb_clflush(clf);
                clf += clflush_add;
        }
        mb();
 -      kunmap_atomic(clf, KM_USER0);
 +      kunmap_atomic(clf);
  }
  
  static void psb_pages_clflush(struct psb_mmu_driver *driver,
@@@ -270,7 -270,7 +270,7 @@@ out_err1
        return NULL;
  }
  
- void psb_mmu_free_pt(struct psb_mmu_pt *pt)
+ static void psb_mmu_free_pt(struct psb_mmu_pt *pt)
  {
        __free_page(pt->p);
        kfree(pt);
@@@ -325,7 -325,7 +325,7 @@@ static struct psb_mmu_pt *psb_mmu_alloc
  
        spin_lock(lock);
  
 -      v = kmap_atomic(pt->p, KM_USER0);
 +      v = kmap_atomic(pt->p);
        clf = (uint8_t *) v;
        ptes = (uint32_t *) v;
        for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
                mb();
        }
  
 -      kunmap_atomic(v, KM_USER0);
 +      kunmap_atomic(v);
        spin_unlock(lock);
  
        pt->count = 0;
        return pt;
  }
  
- struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
+ static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
                                             unsigned long addr)
  {
        uint32_t index = psb_mmu_pd_index(addr);
                        continue;
                }
  
 -              v = kmap_atomic(pd->p, KM_USER0);
 +              v = kmap_atomic(pd->p);
                pd->tables[index] = pt;
                v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
                pt->index = index;
 -              kunmap_atomic((void *) v, KM_USER0);
 +              kunmap_atomic((void *) v);
  
                if (pd->hw_context != -1) {
                        psb_mmu_clflush(pd->driver, (void *) &v[index]);
                        atomic_set(&pd->driver->needs_tlbflush, 1);
                }
        }
 -      pt->v = kmap_atomic(pt->p, KM_USER0);
 +      pt->v = kmap_atomic(pt->p);
        return pt;
  }
  
@@@ -404,7 -404,7 +404,7 @@@ static struct psb_mmu_pt *psb_mmu_pt_ma
                spin_unlock(lock);
                return NULL;
        }
 -      pt->v = kmap_atomic(pt->p, KM_USER0);
 +      pt->v = kmap_atomic(pt->p);
        return pt;
  }
  
@@@ -413,9 -413,9 +413,9 @@@ static void psb_mmu_pt_unmap_unlock(str
        struct psb_mmu_pd *pd = pt->pd;
        uint32_t *v;
  
 -      kunmap_atomic(pt->v, KM_USER0);
 +      kunmap_atomic(pt->v);
        if (pt->count == 0) {
 -              v = kmap_atomic(pd->p, KM_USER0);
 +              v = kmap_atomic(pd->p);
                v[pt->index] = pd->invalid_pde;
                pd->tables[pt->index] = NULL;
  
                                        (void *) &v[pt->index]);
                        atomic_set(&pd->driver->needs_tlbflush, 1);
                }
 -              kunmap_atomic(pt->v, KM_USER0);
 +              kunmap_atomic(pt->v);
                spin_unlock(&pd->driver->lock);
                psb_mmu_free_pt(pt);
                return;
@@@ -457,7 -457,7 +457,7 @@@ void psb_mmu_mirror_gtt(struct psb_mmu_
        down_read(&driver->sem);
        spin_lock(&driver->lock);
  
 -      v = kmap_atomic(pd->p, KM_USER0);
 +      v = kmap_atomic(pd->p);
        v += start;
  
        while (gtt_pages--) {
  
        /*ttm_tt_cache_flush(&pd->p, num_pages);*/
        psb_pages_clflush(pd->driver, &pd->p, num_pages);
 -      kunmap_atomic(v, KM_USER0);
 +      kunmap_atomic(v);
        spin_unlock(&driver->lock);
  
        if (pd->hw_context != -1)
@@@ -488,15 -488,6 +488,6 @@@ struct psb_mmu_pd *psb_mmu_get_default_
        return pd;
  }
  
- /* Returns the physical address of the PD shared by sgx/msvdx */
- uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
- {
-       struct psb_mmu_pd *pd;
-       pd = psb_mmu_get_default_pd(driver);
-       return page_to_pfn(pd->p) << PAGE_SHIFT;
- }
  void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
  {
        psb_mmu_free_pagedir(driver->default_pd);
@@@ -830,9 -821,9 +821,9 @@@ int psb_mmu_virtual_to_pfn(struct psb_m
                uint32_t *v;
  
                spin_lock(lock);
 -              v = kmap_atomic(pd->p, KM_USER0);
 +              v = kmap_atomic(pd->p);
                tmp = v[psb_mmu_pd_index(virtual)];
 -              kunmap_atomic(v, KM_USER0);
 +              kunmap_atomic(v);
                spin_unlock(lock);
  
                if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
  #define   GEN6_MBC_SNPCR_LOW  (2<<21)
  #define   GEN6_MBC_SNPCR_MIN  (3<<21) /* only 1/16th of the cache is shared */
  
+ #define GEN6_MBCTL            0x0907c
+ #define   GEN6_MBCTL_ENABLE_BOOT_FETCH        (1 << 4)
+ #define   GEN6_MBCTL_CTX_FETCH_NEEDED (1 << 3)
+ #define   GEN6_MBCTL_BME_UPDATE_ENABLE        (1 << 2)
+ #define   GEN6_MBCTL_MAE_UPDATE_ENABLE        (1 << 1)
+ #define   GEN6_MBCTL_BOOT_FETCH_MECH  (1 << 0)
  #define GEN6_GDRST    0x941c
  #define  GEN6_GRDOM_FULL              (1 << 0)
  #define  GEN6_GRDOM_RENDER            (1 << 1)
  #define  GEN6_GRDOM_MEDIA             (1 << 2)
  #define  GEN6_GRDOM_BLT                       (1 << 3)
  
+ /* PPGTT stuff */
+ #define GEN6_GTT_ADDR_ENCODE(addr)    ((addr) | (((addr) >> 28) & 0xff0))
+ #define GEN6_PDE_VALID                        (1 << 0)
+ #define GEN6_PDE_LARGE_PAGE           (2 << 0) /* use 32kb pages */
+ /* gen6+ has bit 11-4 for physical addr bit 39-32 */
+ #define GEN6_PDE_ADDR_ENCODE(addr)    GEN6_GTT_ADDR_ENCODE(addr)
+ #define GEN6_PTE_VALID                        (1 << 0)
+ #define GEN6_PTE_UNCACHED             (1 << 1)
+ #define GEN6_PTE_CACHE_LLC            (2 << 1)
+ #define GEN6_PTE_CACHE_LLC_MLC                (3 << 1)
+ #define GEN6_PTE_CACHE_BITS           (3 << 1)
+ #define GEN6_PTE_GFDT                 (1 << 3)
+ #define GEN6_PTE_ADDR_ENCODE(addr)    GEN6_GTT_ADDR_ENCODE(addr)
+ #define RING_PP_DIR_BASE(ring)                ((ring)->mmio_base+0x228)
+ #define RING_PP_DIR_BASE_READ(ring)   ((ring)->mmio_base+0x518)
+ #define RING_PP_DIR_DCLV(ring)                ((ring)->mmio_base+0x220)
+ #define   PP_DIR_DCLV_2G              0xffffffff
+ #define GAM_ECOCHK                    0x4090
+ #define   ECOCHK_SNB_BIT              (1<<10)
+ #define   ECOCHK_PPGTT_CACHE64B               (0x3<<3)
+ #define   ECOCHK_PPGTT_CACHE4B                (0x0<<3)
  /* VGA stuff */
  
  #define VGA_ST01_MDA 0x3ba
  #define FENCE_REG_SANDYBRIDGE_0               0x100000
  #define   SANDYBRIDGE_FENCE_PITCH_SHIFT       32
  
+ /* control register for cpu gtt access */
+ #define TILECTL                               0x101000
+ #define   TILECTL_SWZCTL                      (1 << 0)
+ #define   TILECTL_TLB_PREFETCH_DIS    (1 << 2)
+ #define   TILECTL_BACKSNOOP_DIS               (1 << 3)
  /*
   * Instruction and interrupt control regs
   */
  #define RING_MAX_IDLE(base)   ((base)+0x54)
  #define RING_HWS_PGA(base)    ((base)+0x80)
  #define RING_HWS_PGA_GEN6(base)       ((base)+0x2080)
+ #define ARB_MODE              0x04030
+ #define   ARB_MODE_SWIZZLE_SNB        (1<<4)
+ #define   ARB_MODE_SWIZZLE_IVB        (1<<5)
+ #define   ARB_MODE_ENABLE(x)  GFX_MODE_ENABLE(x)
+ #define   ARB_MODE_DISABLE(x) GFX_MODE_DISABLE(x)
  #define RENDER_HWS_PGA_GEN7   (0x04080)
+ #define RING_FAULT_REG(ring)  (0x4094 + 0x100*(ring)->id)
+ #define DONE_REG              0x40b0
  #define BSD_HWS_PGA_GEN7      (0x04180)
  #define BLT_HWS_PGA_GEN7      (0x04280)
  #define RING_ACTHD(base)      ((base)+0x74)
  #define IPEIR_I965    0x02064
  #define IPEHR_I965    0x02068
  #define INSTDONE_I965 0x0206c
+ #define RING_IPEIR(base)      ((base)+0x64)
+ #define RING_IPEHR(base)      ((base)+0x68)
+ #define RING_INSTDONE(base)   ((base)+0x6c)
+ #define RING_INSTPS(base)     ((base)+0x70)
+ #define RING_DMA_FADD(base)   ((base)+0x78)
+ #define RING_INSTPM(base)     ((base)+0xc0)
  #define INSTPS                0x02070 /* 965+ only */
  #define INSTDONE1     0x0207c /* 965+ only */
  #define ACTHD_I965    0x02074
  #define INSTDONE      0x02090
  #define NOPID         0x02094
  #define HWSTAM                0x02098
- #define VCS_INSTDONE  0x1206C
- #define VCS_IPEIR     0x12064
- #define VCS_IPEHR     0x12068
- #define VCS_ACTHD     0x12074
- #define BCS_INSTDONE  0x2206C
- #define BCS_IPEIR     0x22064
- #define BCS_IPEHR     0x22068
- #define BCS_ACTHD     0x22074
  
  #define ERROR_GEN6    0x040a0
  
  
  #define MI_MODE               0x0209c
  # define VS_TIMER_DISPATCH                            (1 << 6)
- # define MI_FLUSH_ENABLE                              (1 << 11)
+ # define MI_FLUSH_ENABLE                              (1 << 12)
  
  #define GFX_MODE      0x02520
  #define GFX_MODE_GEN7 0x0229c
+ #define RING_MODE_GEN7(ring)  ((ring)->mmio_base+0x29c)
  #define   GFX_RUN_LIST_ENABLE         (1<<15)
  #define   GFX_TLB_INVALIDATE_ALWAYS   (1<<13)
  #define   GFX_SURFACE_FAULT_ENABLE    (1<<12)
  #define C0DRB3                        0x10206
  #define C1DRB3                        0x10606
  
+ /** snb MCH registers for reading the DRAM channel configuration */
+ #define MAD_DIMM_C0                   (MCHBAR_MIRROR_BASE_SNB + 0x5004)
+ #define MAD_DIMM_C1                   (MCHBAR_MIRROR_BASE_SNB + 0x5008)
+ #define MAD_DIMM_C2                   (MCHBAR_MIRROR_BASE_SNB + 0x500C)
+ #define   MAD_DIMM_ECC_MASK           (0x3 << 24)
+ #define   MAD_DIMM_ECC_OFF            (0x0 << 24)
+ #define   MAD_DIMM_ECC_IO_ON_LOGIC_OFF        (0x1 << 24)
+ #define   MAD_DIMM_ECC_IO_OFF_LOGIC_ON        (0x2 << 24)
+ #define   MAD_DIMM_ECC_ON             (0x3 << 24)
+ #define   MAD_DIMM_ENH_INTERLEAVE     (0x1 << 22)
+ #define   MAD_DIMM_RANK_INTERLEAVE    (0x1 << 21)
+ #define   MAD_DIMM_B_WIDTH_X16                (0x1 << 20) /* X8 chips if unset */
+ #define   MAD_DIMM_A_WIDTH_X16                (0x1 << 19) /* X8 chips if unset */
+ #define   MAD_DIMM_B_DUAL_RANK                (0x1 << 18)
+ #define   MAD_DIMM_A_DUAL_RANK                (0x1 << 17)
+ #define   MAD_DIMM_A_SELECT           (0x1 << 16)
+ /* DIMM sizes are in multiples of 256mb. */
+ #define   MAD_DIMM_B_SIZE_SHIFT               8
+ #define   MAD_DIMM_B_SIZE_MASK                (0xff << MAD_DIMM_B_SIZE_SHIFT)
+ #define   MAD_DIMM_A_SIZE_SHIFT               0
+ #define   MAD_DIMM_A_SIZE_MASK                (0xff << MAD_DIMM_A_SIZE_SHIFT)
  /* Clocking configuration register */
  #define CLKCFG                        0x10c00
  #define CLKCFG_FSB_400                                        (5 << 0)        /* hrawclk 100 */
  #define _VSYNC_A              0x60014
  #define _PIPEASRC     0x6001c
  #define _BCLRPAT_A    0x60020
+ #define _VSYNCSHIFT_A 0x60028
  
  /* Pipe B timing regs */
  #define _HTOTAL_B     0x61000
  #define _VSYNC_B              0x61014
  #define _PIPEBSRC     0x6101c
  #define _BCLRPAT_B    0x61020
+ #define _VSYNCSHIFT_B 0x61028
  
  #define HTOTAL(pipe) _PIPE(pipe, _HTOTAL_A, _HTOTAL_B)
  #define HBLANK(pipe) _PIPE(pipe, _HBLANK_A, _HBLANK_B)
  #define VBLANK(pipe) _PIPE(pipe, _VBLANK_A, _VBLANK_B)
  #define VSYNC(pipe) _PIPE(pipe, _VSYNC_A, _VSYNC_B)
  #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
+ #define VSYNCSHIFT(pipe) _PIPE(pipe, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
  
  /* VGA port control */
  #define ADPA                  0x61100
  #define   PIPECONF_PALETTE    0
  #define   PIPECONF_GAMMA              (1<<24)
  #define   PIPECONF_FORCE_BORDER       (1<<25)
- #define   PIPECONF_PROGRESSIVE        (0 << 21)
- #define   PIPECONF_INTERLACE_W_FIELD_INDICATION       (6 << 21)
- #define   PIPECONF_INTERLACE_FIELD_0_ONLY             (7 << 21)
  #define   PIPECONF_INTERLACE_MASK     (7 << 21)
+ /* Note that pre-gen3 does not support interlaced display directly. Panel
+  * fitting must be disabled on pre-ilk for interlaced. */
+ #define   PIPECONF_PROGRESSIVE                        (0 << 21)
+ #define   PIPECONF_INTERLACE_W_SYNC_SHIFT_PANEL       (4 << 21) /* gen4 only */
+ #define   PIPECONF_INTERLACE_W_SYNC_SHIFT     (5 << 21) /* gen4 only */
+ #define   PIPECONF_INTERLACE_W_FIELD_INDICATION       (6 << 21)
+ #define   PIPECONF_INTERLACE_FIELD_0_ONLY     (7 << 21) /* gen3 only */
+ /* Ironlake and later have a complete new set of values for interlaced. PFIT
+  * means panel fitter required, PF means progressive fetch, DBL means power
+  * saving pixel doubling. */
+ #define   PIPECONF_PFIT_PF_INTERLACED_ILK     (1 << 21)
+ #define   PIPECONF_INTERLACED_ILK             (3 << 21)
+ #define   PIPECONF_INTERLACED_DBL_ILK         (4 << 21) /* ilk/snb only */
+ #define   PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
  #define   PIPECONF_CXSR_DOWNCLOCK     (1<<16)
  #define   PIPECONF_BPP_MASK   (0x000000e0)
  #define   PIPECONF_BPP_8      (0<<5)
  #define   DVS_FORMAT_RGBX888  (2<<25)
  #define   DVS_FORMAT_RGBX161616       (3<<25)
  #define   DVS_SOURCE_KEY      (1<<22)
 -#define   DVS_RGB_ORDER_RGBX  (1<<20)
 +#define   DVS_RGB_ORDER_XBGR  (1<<20)
  #define   DVS_YUV_BYTE_ORDER_MASK (3<<16)
  #define   DVS_YUV_ORDER_YUYV  (0<<16)
  #define   DVS_YUV_ORDER_UYVY  (1<<16)
  #define _TRANS_VSYNC_A           0xe0014
  #define  TRANS_VSYNC_END_SHIFT  16
  #define  TRANS_VSYNC_START_SHIFT 0
+ #define _TRANS_VSYNCSHIFT_A   0xe0028
  
  #define _TRANSA_DATA_M1          0xe0030
  #define _TRANSA_DATA_N1          0xe0034
  #define _TRANS_VTOTAL_B          0xe100c
  #define _TRANS_VBLANK_B          0xe1010
  #define _TRANS_VSYNC_B           0xe1014
+ #define _TRANS_VSYNCSHIFT_B    0xe1028
  
  #define TRANS_HTOTAL(pipe) _PIPE(pipe, _TRANS_HTOTAL_A, _TRANS_HTOTAL_B)
  #define TRANS_HBLANK(pipe) _PIPE(pipe, _TRANS_HBLANK_A, _TRANS_HBLANK_B)
  #define TRANS_VTOTAL(pipe) _PIPE(pipe, _TRANS_VTOTAL_A, _TRANS_VTOTAL_B)
  #define TRANS_VBLANK(pipe) _PIPE(pipe, _TRANS_VBLANK_A, _TRANS_VBLANK_B)
  #define TRANS_VSYNC(pipe) _PIPE(pipe, _TRANS_VSYNC_A, _TRANS_VSYNC_B)
+ #define TRANS_VSYNCSHIFT(pipe) _PIPE(pipe, _TRANS_VSYNCSHIFT_A, \
+                                    _TRANS_VSYNCSHIFT_B)
  
  #define _TRANSB_DATA_M1          0xe1030
  #define _TRANSB_DATA_N1          0xe1034
  #define  TRANS_FSYNC_DELAY_HB4  (3<<27)
  #define  TRANS_DP_AUDIO_ONLY    (1<<26)
  #define  TRANS_DP_VIDEO_AUDIO   (0<<26)
+ #define  TRANS_INTERLACE_MASK   (7<<21)
  #define  TRANS_PROGRESSIVE      (0<<21)
+ #define  TRANS_INTERLACED       (3<<21)
+ #define  TRANS_LEGACY_INTERLACED_ILK (2<<21)
  #define  TRANS_8BPC             (0<<5)
  #define  TRANS_10BPC            (1<<5)
  #define  TRANS_6BPC             (2<<5)
  #define  ECOBUS                                       0xa180
  #define    FORCEWAKE_MT_ENABLE                        (1<<5)
  
+ #define  GTFIFODBG                            0x120000
+ #define    GT_FIFO_CPU_ERROR_MASK             7
+ #define    GT_FIFO_OVFERR                     (1<<2)
+ #define    GT_FIFO_IAWRERR                    (1<<1)
+ #define    GT_FIFO_IARDERR                    (1<<0)
  #define  GT_FIFO_FREE_ENTRIES                 0x120008
  #define    GT_FIFO_NUM_RESERVED_ENTRIES               20
  
   */
  #define GEN7_SO_WRITE_OFFSET(n)               (0x5280 + (n) * 4)
  
+ #define IBX_AUD_CONFIG_A                      0xe2000
+ #define CPT_AUD_CONFIG_A                      0xe5000
+ #define   AUD_CONFIG_N_VALUE_INDEX            (1 << 29)
+ #define   AUD_CONFIG_N_PROG_ENABLE            (1 << 28)
+ #define   AUD_CONFIG_UPPER_N_SHIFT            20
+ #define   AUD_CONFIG_UPPER_N_VALUE            (0xff << 20)
+ #define   AUD_CONFIG_LOWER_N_SHIFT            4
+ #define   AUD_CONFIG_LOWER_N_VALUE            (0xfff << 4)
+ #define   AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT   16
+ #define   AUD_CONFIG_PIXEL_CLOCK_HDMI         (0xf << 16)
+ #define   AUD_CONFIG_DISABLE_NCTS             (1 << 3)
  #endif /* _I915_REG_H_ */
@@@ -75,7 -75,7 +75,7 @@@ struct intel_limit 
        intel_range_t   dot, vco, n, m, m1, m2, p, p1;
        intel_p2_t          p2;
        bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
-                       int, int, intel_clock_t *);
+                       int, int, intel_clock_t *, intel_clock_t *);
  };
  
  /* FDI */
  
  static bool
  intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                   int target, int refclk, intel_clock_t *best_clock);
+                   int target, int refclk, intel_clock_t *match_clock,
+                   intel_clock_t *best_clock);
  static bool
  intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                       int target, int refclk, intel_clock_t *best_clock);
+                       int target, int refclk, intel_clock_t *match_clock,
+                       intel_clock_t *best_clock);
  
  static bool
  intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
-                     int target, int refclk, intel_clock_t *best_clock);
+                     int target, int refclk, intel_clock_t *match_clock,
+                     intel_clock_t *best_clock);
  static bool
  intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc,
-                          int target, int refclk, intel_clock_t *best_clock);
+                          int target, int refclk, intel_clock_t *match_clock,
+                          intel_clock_t *best_clock);
  
  static inline u32 /* units of 100MHz */
  intel_fdi_link_freq(struct drm_device *dev)
@@@ -515,7 -519,8 +519,8 @@@ static bool intel_PLL_is_valid(struct d
  
  static bool
  intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                   int target, int refclk, intel_clock_t *best_clock)
+                   int target, int refclk, intel_clock_t *match_clock,
+                   intel_clock_t *best_clock)
  
  {
        struct drm_device *dev = crtc->dev;
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
+                                       if (match_clock &&
+                                           clock.p != match_clock->p)
+                                               continue;
  
                                        this_err = abs(clock.dot - target);
                                        if (this_err < err) {
  
  static bool
  intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                       int target, int refclk, intel_clock_t *best_clock)
+                       int target, int refclk, intel_clock_t *match_clock,
+                       intel_clock_t *best_clock)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
+                                       if (match_clock &&
+                                           clock.p != match_clock->p)
+                                               continue;
  
                                        this_err = abs(clock.dot - target);
                                        if (this_err < err_most) {
  
  static bool
  intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
-                          int target, int refclk, intel_clock_t *best_clock)
+                          int target, int refclk, intel_clock_t *match_clock,
+                          intel_clock_t *best_clock)
  {
        struct drm_device *dev = crtc->dev;
        intel_clock_t clock;
  /* DisplayPort has only two frequencies, 162MHz and 270MHz */
  static bool
  intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
-                     int target, int refclk, intel_clock_t *best_clock)
+                     int target, int refclk, intel_clock_t *match_clock,
+                     intel_clock_t *best_clock)
  {
        intel_clock_t clock;
        if (target < 200000) {
@@@ -922,6 -936,10 +936,10 @@@ void assert_pipe(struct drm_i915_privat
        u32 val;
        bool cur_state;
  
+       /* if we need the pipe A quirk it must be always on */
+       if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
+               state = true;
        reg = PIPECONF(pipe);
        val = I915_READ(reg);
        cur_state = !!(val & PIPECONF_ENABLE);
             pipe_name(pipe), state_string(state), state_string(cur_state));
  }
  
- static void assert_plane_enabled(struct drm_i915_private *dev_priv,
-                                enum plane plane)
+ static void assert_plane(struct drm_i915_private *dev_priv,
+                        enum plane plane, bool state)
  {
        int reg;
        u32 val;
+       bool cur_state;
  
        reg = DSPCNTR(plane);
        val = I915_READ(reg);
-       WARN(!(val & DISPLAY_PLANE_ENABLE),
-            "plane %c assertion failure, should be active but is disabled\n",
-            plane_name(plane));
+       cur_state = !!(val & DISPLAY_PLANE_ENABLE);
+       WARN(cur_state != state,
+            "plane %c assertion failure (expected %s, current %s)\n",
+            plane_name(plane), state_string(state), state_string(cur_state));
  }
  
+ #define assert_plane_enabled(d, p) assert_plane(d, p, true)
+ #define assert_plane_disabled(d, p) assert_plane(d, p, false)
  static void assert_planes_disabled(struct drm_i915_private *dev_priv,
                                   enum pipe pipe)
  {
        int cur_pipe;
  
        /* Planes are fixed to pipes on ILK+ */
-       if (HAS_PCH_SPLIT(dev_priv->dev))
+       if (HAS_PCH_SPLIT(dev_priv->dev)) {
+               reg = DSPCNTR(pipe);
+               val = I915_READ(reg);
+               WARN((val & DISPLAY_PLANE_ENABLE),
+                    "plane %c assertion failure, should be disabled but not\n",
+                    plane_name(pipe));
                return;
+       }
  
        /* Need to check both planes against the pipe */
        for (i = 0; i < 2; i++) {
@@@ -1071,7 -1100,7 +1100,7 @@@ static void assert_pch_hdmi_disabled(st
  {
        u32 val = I915_READ(reg);
        WARN(hdmi_pipe_enabled(dev_priv, val, pipe),
-            "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
+            "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
  }
  
@@@ -1237,7 -1266,8 +1266,8 @@@ static void intel_enable_transcoder(str
                                    enum pipe pipe)
  {
        int reg;
-       u32 val;
+       u32 val, pipeconf_val;
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
  
        /* PCH only available on ILK+ */
        BUG_ON(dev_priv->info->gen < 5);
  
        reg = TRANSCONF(pipe);
        val = I915_READ(reg);
+       pipeconf_val = I915_READ(PIPECONF(pipe));
  
        if (HAS_PCH_IBX(dev_priv->dev)) {
                /*
                 * that in pipeconf reg.
                 */
                val &= ~PIPE_BPC_MASK;
-               val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
+               val |= pipeconf_val & PIPE_BPC_MASK;
        }
+       val &= ~TRANS_INTERLACE_MASK;
+       if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK)
+               if (HAS_PCH_IBX(dev_priv->dev) &&
+                   intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO))
+                       val |= TRANS_LEGACY_INTERLACED_ILK;
+               else
+                       val |= TRANS_INTERLACED;
+       else
+               val |= TRANS_PROGRESSIVE;
        I915_WRITE(reg, val | TRANS_ENABLE);
        if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
                DRM_ERROR("failed to enable transcoder %d\n", pipe);
@@@ -2012,6 -2054,8 +2054,8 @@@ intel_pin_and_fence_fb_obj(struct drm_d
                ret = i915_gem_object_get_fence(obj, pipelined);
                if (ret)
                        goto err_unpin;
+               i915_gem_object_pin_fence(obj);
        }
  
        dev_priv->mm.interruptible = true;
@@@ -2024,6 -2068,12 +2068,12 @@@ err_interruptible
        return ret;
  }
  
+ void intel_unpin_fb_obj(struct drm_i915_gem_object *obj)
+ {
+       i915_gem_object_unpin_fence(obj);
+       i915_gem_object_unpin(obj);
+ }
  static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                             int x, int y)
  {
@@@ -2255,7 -2305,7 +2305,7 @@@ intel_pipe_set_base(struct drm_crtc *cr
        ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,
                                         LEAVE_ATOMIC_MODE_SET);
        if (ret) {
-               i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj);
+               intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
                mutex_unlock(&dev->struct_mutex);
                DRM_ERROR("failed to update base address\n");
                return ret;
  
        if (old_fb) {
                intel_wait_for_vblank(dev, intel_crtc->pipe);
-               i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj);
+               intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
        }
  
        mutex_unlock(&dev->struct_mutex);
@@@ -2936,6 -2986,7 +2986,7 @@@ static void ironlake_pch_enable(struct 
        I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(pipe)));
        I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe)));
        I915_WRITE(TRANS_VSYNC(pipe),  I915_READ(VSYNC(pipe)));
+       I915_WRITE(TRANS_VSYNCSHIFT(pipe),  I915_READ(VSYNCSHIFT(pipe)));
  
        intel_fdi_normal_train(crtc);
  
@@@ -3321,10 -3372,12 +3372,12 @@@ static void intel_crtc_disable(struct d
        struct drm_device *dev = crtc->dev;
  
        crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+       assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
+       assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
  
        if (crtc->fb) {
                mutex_lock(&dev->struct_mutex);
-               i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj);
+               intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
                mutex_unlock(&dev->struct_mutex);
        }
  }
@@@ -3398,11 -3451,8 +3451,8 @@@ static bool intel_crtc_mode_fixup(struc
                        return false;
        }
  
-       /* XXX some encoders set the crtcinfo, others don't.
-        * Obviously we need some form of conflict resolution here...
-        */
-       if (adjusted_mode->crtc_htotal == 0)
-               drm_mode_set_crtcinfo(adjusted_mode, 0);
+       /* All interlaced capable intel hw wants timings in frames. */
+       drm_mode_set_crtcinfo(adjusted_mode, 0);
  
        return true;
  }
@@@ -4521,6 -4571,7 +4571,7 @@@ void sandybridge_update_wm(struct drm_d
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
+       u32 val;
        int fbc_wm, plane_wm, cursor_wm;
        unsigned int enabled;
  
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
-               I915_WRITE(WM0_PIPEA_ILK,
-                          (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+               val = I915_READ(WM0_PIPEA_ILK);
+               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
+               I915_WRITE(WM0_PIPEA_ILK, val |
+                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
                DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
                              " plane %d, " "cursor: %d\n",
                              plane_wm, cursor_wm);
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
-               I915_WRITE(WM0_PIPEB_ILK,
-                          (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+               val = I915_READ(WM0_PIPEB_ILK);
+               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
+               I915_WRITE(WM0_PIPEB_ILK, val |
+                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
                DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
-               I915_WRITE(WM0_PIPEC_IVB,
-                          (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+               val = I915_READ(WM0_PIPEC_IVB);
+               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
+               I915_WRITE(WM0_PIPEC_IVB, val |
+                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
                DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
@@@ -4709,6 -4766,7 +4766,7 @@@ static void sandybridge_update_sprite_w
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
+       u32 val;
        int sprite_wm, reg;
        int ret;
  
                return;
        }
  
-       I915_WRITE(reg, I915_READ(reg) | (sprite_wm << WM0_PIPE_SPRITE_SHIFT));
+       val = I915_READ(reg);
+       val &= ~WM0_PIPE_SPRITE_MASK;
+       I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT));
        DRM_DEBUG_KMS("sprite watermarks For pipe %d - %d\n", pipe, sprite_wm);
  
  
@@@ -4977,6 -5037,82 +5037,82 @@@ static bool intel_choose_pipe_bpp_dithe
        return display_bpc != bpc;
  }
  
+ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
+ {
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int refclk;
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_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 if (!IS_GEN2(dev)) {
+               refclk = 96000;
+       } else {
+               refclk = 48000;
+       }
+       return refclk;
+ }
+ static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode,
+                                     intel_clock_t *clock)
+ {
+       /* SDVO TV has fixed PLL values depend on its clock range,
+          this mirrors vbios setting. */
+       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;
+       }
+ }
+ static void i9xx_update_pll_dividers(struct drm_crtc *crtc,
+                                    intel_clock_t *clock,
+                                    intel_clock_t *reduced_clock)
+ {
+       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 fp, fp2 = 0;
+       if (IS_PINEVIEW(dev)) {
+               fp = (1 << clock->n) << 16 | clock->m1 << 8 | clock->m2;
+               if (reduced_clock)
+                       fp2 = (1 << reduced_clock->n) << 16 |
+                               reduced_clock->m1 << 8 | reduced_clock->m2;
+       } else {
+               fp = clock->n << 16 | clock->m1 << 8 | clock->m2;
+               if (reduced_clock)
+                       fp2 = reduced_clock->n << 16 | reduced_clock->m1 << 8 |
+                               reduced_clock->m2;
+       }
+       I915_WRITE(FP0(pipe), fp);
+       intel_crtc->lowfreq_avail = false;
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+           reduced_clock && i915_powersave) {
+               I915_WRITE(FP1(pipe), fp2);
+               intel_crtc->lowfreq_avail = true;
+       } else {
+               I915_WRITE(FP1(pipe), fp);
+       }
+ }
  static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                              struct drm_display_mode *mode,
                              struct drm_display_mode *adjusted_mode,
        int plane = intel_crtc->plane;
        int refclk, num_connectors = 0;
        intel_clock_t clock, reduced_clock;
-       u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf;
+       u32 dpll, dspcntr, pipeconf, vsyncshift;
        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 drm_mode_config *mode_config = &dev->mode_config;
                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 if (!IS_GEN2(dev)) {
-               refclk = 96000;
-       } else {
-               refclk = 48000;
-       }
+       refclk = i9xx_get_refclk(crtc, num_connectors);
  
        /*
         * Returns a set of divisors for the desired target clock with the given
         * 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);
+       ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
+                            &clock);
        if (!ok) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
                return -EINVAL;
        intel_crtc_update_cursor(crtc, true);
  
        if (is_lvds && dev_priv->lvds_downclock_avail) {
+               /*
+                * Ensure we match the reduced clock's P to the target clock.
+                * If the clocks don't match, we can't switch the display clock
+                * by using the FP0/FP1. In such case we will disable the LVDS
+                * downclock feature.
+               */
                has_reduced_clock = limit->find_pll(limit, crtc,
                                                    dev_priv->lvds_downclock,
                                                    refclk,
+                                                   &clock,
                                                    &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;
-               }
        }
  
-       if (IS_PINEVIEW(dev)) {
-               fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
-               if (has_reduced_clock)
-                       fp2 = (1 << reduced_clock.n) << 16 |
-                               reduced_clock.m1 << 8 | reduced_clock.m2;
-       } else {
-               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;
-       }
+       if (is_sdvo && is_tv)
+               i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock);
+       i9xx_update_pll_dividers(crtc, &clock, has_reduced_clock ?
+                                &reduced_clock : NULL);
  
        dpll = DPLL_VGA_MODE_DIS;
  
        /* Set up the display plane register */
        dspcntr = DISPPLANE_GAMMA_ENABLE;
  
-       /* Ironlake's plane is forced to pipe, bit 24 is to
-          enable color space conversion */
        if (pipe == 0)
                dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
        else
        DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
        drm_mode_debug_printmodeline(mode);
  
-       I915_WRITE(FP0(pipe), fp);
        I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
  
        POSTING_READ(DPLL(pipe));
                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)) {
+       if (HAS_PIPE_CXSR(dev)) {
+               if (intel_crtc->lowfreq_avail) {
                        DRM_DEBUG_KMS("enabling CxSR downclocking\n");
                        pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
-               }
-       } else {
-               I915_WRITE(FP1(pipe), fp);
-               if (HAS_PIPE_CXSR(dev)) {
+               } else {
                        DRM_DEBUG_KMS("disabling CxSR downclocking\n");
                        pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
                }
        }
  
        pipeconf &= ~PIPECONF_INTERLACE_MASK;
-       if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+       if (!IS_GEN2(dev) &&
+           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
+               vsyncshift = adjusted_mode->crtc_hsync_start
+                            - adjusted_mode->crtc_htotal/2;
+       } else {
                pipeconf |= PIPECONF_PROGRESSIVE;
+               vsyncshift = 0;
+       }
+       if (!IS_GEN3(dev))
+               I915_WRITE(VSYNCSHIFT(pipe), vsyncshift);
  
        I915_WRITE(HTOTAL(pipe),
                   (adjusted_mode->crtc_hdisplay - 1) |
@@@ -5593,7 -5688,8 +5688,8 @@@ static int ironlake_crtc_mode_set(struc
         * 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);
+       ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
+                            &clock);
        if (!ok) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
                return -EINVAL;
        intel_crtc_update_cursor(crtc, true);
  
        if (is_lvds && dev_priv->lvds_downclock_avail) {
+               /*
+                * Ensure we match the reduced clock's P to the target clock.
+                * If the clocks don't match, we can't switch the display clock
+                * by using the FP0/FP1. In such case we will disable the LVDS
+                * downclock feature.
+               */
                has_reduced_clock = limit->find_pll(limit, crtc,
                                                    dev_priv->lvds_downclock,
                                                    refclk,
+                                                   &clock,
                                                    &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. */
  
        pipeconf &= ~PIPECONF_INTERLACE_MASK;
        if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
-               pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+               pipeconf |= PIPECONF_INTERLACED_ILK;
                /* 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
+               I915_WRITE(VSYNCSHIFT(pipe),
+                          adjusted_mode->crtc_hsync_start
+                          - adjusted_mode->crtc_htotal/2);
+       } else {
                pipeconf |= PIPECONF_PROGRESSIVE;
+               I915_WRITE(VSYNCSHIFT(pipe), 0);
+       }
  
        I915_WRITE(HTOTAL(pipe),
                   (adjusted_mode->crtc_hdisplay - 1) |
  
        intel_wait_for_vblank(dev, pipe);
  
-       if (IS_GEN5(dev)) {
-               /* enable address swizzle for tiling buffer */
-               temp = I915_READ(DISP_ARB_CTL);
-               I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING);
-       }
        I915_WRITE(DSPCNTR(plane), dspcntr);
        POSTING_READ(DSPCNTR(plane));
  
@@@ -6086,15 -6173,18 +6173,18 @@@ static void ironlake_write_eld(struct d
        uint32_t i;
        int len;
        int hdmiw_hdmiedid;
+       int aud_config;
        int aud_cntl_st;
        int aud_cntrl_st2;
  
        if (HAS_PCH_IBX(connector->dev)) {
                hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A;
+               aud_config = IBX_AUD_CONFIG_A;
                aud_cntl_st = IBX_AUD_CNTL_ST_A;
                aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
        } else {
                hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A;
+               aud_config = CPT_AUD_CONFIG_A;
                aud_cntl_st = CPT_AUD_CNTL_ST_A;
                aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
        }
        i = to_intel_crtc(crtc)->pipe;
        hdmiw_hdmiedid += i * 0x100;
        aud_cntl_st += i * 0x100;
+       aud_config += i * 0x100;
  
        DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
  
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
                DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
                eld[5] |= (1 << 2);     /* Conn_Type, 0x1 = DisplayPort */
-       }
+               I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */
+       } else
+               I915_WRITE(aud_config, 0);
  
        if (intel_eld_uptodate(connector,
                               aud_cntrl_st2, eldv,
@@@ -6927,9 -7020,7 +7020,7 @@@ static void intel_increase_pllclock(str
        if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
                DRM_DEBUG_DRIVER("upclocking LVDS\n");
  
-               /* Unlock panel regs */
-               I915_WRITE(PP_CONTROL,
-                          I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
+               assert_panel_unlocked(dev_priv, pipe);
  
                dpll &= ~DISPLAY_RATE_SELECT_FPA1;
                I915_WRITE(dpll_reg, dpll);
                dpll = I915_READ(dpll_reg);
                if (dpll & DISPLAY_RATE_SELECT_FPA1)
                        DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
-               /* ...and lock them again */
-               I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
        }
  
        /* Schedule downclock */
@@@ -6970,9 -7058,7 +7058,7 @@@ static void intel_decrease_pllclock(str
        if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
                DRM_DEBUG_DRIVER("downclocking LVDS\n");
  
-               /* Unlock panel regs */
-               I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
-                          PANEL_UNLOCK_REGS);
+               assert_panel_unlocked(dev_priv, pipe);
  
                dpll |= DISPLAY_RATE_SELECT_FPA1;
                I915_WRITE(dpll_reg, dpll);
                dpll = I915_READ(dpll_reg);
                if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
                        DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
-               /* ...and lock them again */
-               I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
        }
  
  }
@@@ -7097,7 -7180,7 +7180,7 @@@ static void intel_unpin_work_fn(struct 
                container_of(__work, struct intel_unpin_work, work);
  
        mutex_lock(&work->dev->struct_mutex);
-       i915_gem_object_unpin(work->old_fb_obj);
+       intel_unpin_fb_obj(work->old_fb_obj);
        drm_gem_object_unreference(&work->pending_flip_obj->base);
        drm_gem_object_unreference(&work->old_fb_obj->base);
  
@@@ -7247,7 -7330,7 +7330,7 @@@ static int intel_gen2_queue_flip(struc
                 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
        OUT_RING(fb->pitches[0]);
        OUT_RING(obj->gtt_offset + offset);
-       OUT_RING(MI_NOOP);
+       OUT_RING(0); /* aux display base address, unused */
        ADVANCE_LP_RING();
  out:
        return ret;
@@@ -7681,10 -7764,9 +7764,9 @@@ static void intel_setup_outputs(struct 
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *encoder;
        bool dpd_is_edp = false;
-       bool has_lvds = false;
+       bool has_lvds;
  
-       if (IS_MOBILE(dev) && !IS_I830(dev))
-               has_lvds = intel_lvds_init(dev);
+       has_lvds = intel_lvds_init(dev);
        if (!has_lvds && !HAS_PCH_SPLIT(dev)) {
                /* disable the panel fitter on everything but LVDS */
                I915_WRITE(PFIT_CONTROL, 0);
@@@ -7828,7 -7910,6 +7910,7 @@@ int intel_framebuffer_init(struct drm_d
        case DRM_FORMAT_RGB332:
        case DRM_FORMAT_RGB565:
        case DRM_FORMAT_XRGB8888:
 +      case DRM_FORMAT_XBGR8888:
        case DRM_FORMAT_ARGB8888:
        case DRM_FORMAT_XRGB2101010:
        case DRM_FORMAT_ARGB2101010:
        case DRM_FORMAT_VYUY:
                break;
        default:
-               DRM_ERROR("unsupported pixel format\n");
+               DRM_DEBUG_KMS("unsupported pixel format %u\n",
+                               mode_cmd->pixel_format);
                return -EINVAL;
        }
  
@@@ -8162,6 -8244,7 +8245,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, rc6_mask = 0;
+       u32 gtfifodbg;
        int cur_freq, min_freq, max_freq;
        int i;
  
         */
        I915_WRITE(GEN6_RC_STATE, 0);
        mutex_lock(&dev_priv->dev->struct_mutex);
+       /* Clear the DBG now so we don't confuse earlier errors */
+       if ((gtfifodbg = I915_READ(GTFIFODBG))) {
+               DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg);
+               I915_WRITE(GTFIFODBG, gtfifodbg);
+       }
        gen6_gt_force_wake_get(dev_priv);
  
        /* disable the counters and set deterministic thresholds */
@@@ -8959,8 -9049,6 +9050,6 @@@ struct intel_quirk 
  };
  
  struct intel_quirk intel_quirks[] = {
-       /* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */
-       { 0x2a42, 0x103c, 0x30eb, quirk_pipea_force },
        /* HP Mini needs pipe A force quirk (LP: #322104) */
        { 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
  
@@@ -9037,6 -9125,9 +9126,9 @@@ void intel_modeset_init(struct drm_devi
        dev->mode_config.min_width = 0;
        dev->mode_config.min_height = 0;
  
+       dev->mode_config.preferred_depth = 24;
+       dev->mode_config.prefer_shadow = 1;
        dev->mode_config.funcs = (void *)&intel_mode_funcs;
  
        intel_init_quirks(dev);
@@@ -225,16 -225,16 +225,16 @@@ snb_update_plane(struct drm_plane *plan
  
        /* Mask out pixel format bits in case we change it */
        dvscntr &= ~DVS_PIXFORMAT_MASK;
 -      dvscntr &= ~DVS_RGB_ORDER_RGBX;
 +      dvscntr &= ~DVS_RGB_ORDER_XBGR;
        dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
  
        switch (fb->pixel_format) {
        case DRM_FORMAT_XBGR8888:
 -              dvscntr |= DVS_FORMAT_RGBX888;
 +              dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
                pixel_size = 4;
                break;
        case DRM_FORMAT_XRGB8888:
 -              dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_RGBX;
 +              dvscntr |= DVS_FORMAT_RGBX888;
                pixel_size = 4;
                break;
        case DRM_FORMAT_YUYV:
@@@ -501,7 -501,7 +501,7 @@@ intel_update_plane(struct drm_plane *pl
                        intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
                        mutex_lock(&dev->struct_mutex);
                }
-               i915_gem_object_unpin(old_obj);
+               intel_unpin_fb_obj(old_obj);
        }
  
  out_unlock:
@@@ -528,7 -528,7 +528,7 @@@ intel_disable_plane(struct drm_plane *p
                goto out;
  
        mutex_lock(&dev->struct_mutex);
-       i915_gem_object_unpin(intel_plane->obj);
+       intel_unpin_fb_obj(intel_plane->obj);
        intel_plane->obj = NULL;
        mutex_unlock(&dev->struct_mutex);
  out:
@@@ -53,9 -53,8 +53,8 @@@ void rv515_debugfs(struct radeon_devic
        }
  }
  
- void rv515_ring_start(struct radeon_device *rdev)
+ void rv515_ring_start(struct radeon_device *rdev, struct radeon_ring *ring)
  {
-       struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        int r;
  
        r = radeon_ring_lock(rdev, ring, 64);
@@@ -150,7 -149,7 +149,7 @@@ void rv515_gpu_init(struct radeon_devic
  
        if (r100_gui_wait_for_idle(rdev)) {
                printk(KERN_WARNING "Failed to wait GUI idle while "
 -                     "reseting GPU. Bad things might happen.\n");
 +                     "resetting GPU. Bad things might happen.\n");
        }
        rv515_vga_render_disable(rdev);
        r420_pipes_init(rdev);
        WREG32_PLL(0x000D, tmp);
        if (r100_gui_wait_for_idle(rdev)) {
                printk(KERN_WARNING "Failed to wait GUI idle while "
 -                     "reseting GPU. Bad things might happen.\n");
 +                     "resetting GPU. Bad things might happen.\n");
        }
        if (rv515_mc_wait_for_idle(rdev)) {
                printk(KERN_WARNING "Failed to wait MC idle while "
@@@ -413,7 -412,7 +412,7 @@@ static int rv515_startup(struct radeon_
        if (r)
                return r;
  
-       r = r100_ib_test(rdev);
+       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        if (r) {
                dev_err(rdev->dev, "failed testing IB (%d).\n", r);
                rdev->accel_working = false;
@@@ -28,6 -28,8 +28,8 @@@
   * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
   */
  
+ #define pr_fmt(fmt) "[TTM] " fmt
  #include <linux/sched.h>
  #include <linux/highmem.h>
  #include <linux/pagemap.h>
@@@ -196,7 -198,7 +198,7 @@@ int ttm_tt_init(struct ttm_tt *ttm, str
        ttm_tt_alloc_page_directory(ttm);
        if (!ttm->pages) {
                ttm_tt_destroy(ttm);
-               printk(KERN_ERR TTM_PFX "Failed allocating page table\n");
+               pr_err("Failed allocating page table\n");
                return -ENOMEM;
        }
        return 0;
@@@ -229,7 -231,7 +231,7 @@@ int ttm_dma_tt_init(struct ttm_dma_tt *
        ttm_dma_tt_alloc_page_directory(ttm_dma);
        if (!ttm->pages || !ttm_dma->dma_address) {
                ttm_tt_destroy(ttm);
-               printk(KERN_ERR TTM_PFX "Failed allocating page table\n");
+               pr_err("Failed allocating page table\n");
                return -ENOMEM;
        }
        return 0;
@@@ -309,11 -311,11 +311,11 @@@ int ttm_tt_swapin(struct ttm_tt *ttm
                        goto out_err;
  
                preempt_disable();
 -              from_virtual = kmap_atomic(from_page, KM_USER0);
 -              to_virtual = kmap_atomic(to_page, KM_USER1);
 +              from_virtual = kmap_atomic(from_page);
 +              to_virtual = kmap_atomic(to_page);
                memcpy(to_virtual, from_virtual, PAGE_SIZE);
 -              kunmap_atomic(to_virtual, KM_USER1);
 -              kunmap_atomic(from_virtual, KM_USER0);
 +              kunmap_atomic(to_virtual);
 +              kunmap_atomic(from_virtual);
                preempt_enable();
                page_cache_release(from_page);
        }
@@@ -347,7 -349,7 +349,7 @@@ int ttm_tt_swapout(struct ttm_tt *ttm, 
                                                ttm->num_pages << PAGE_SHIFT,
                                                0);
                if (unlikely(IS_ERR(swap_storage))) {
-                       printk(KERN_ERR "Failed allocating swap storage.\n");
+                       pr_err("Failed allocating swap storage\n");
                        return PTR_ERR(swap_storage);
                }
        } else
                        goto out_err;
                }
                preempt_disable();
 -              from_virtual = kmap_atomic(from_page, KM_USER0);
 -              to_virtual = kmap_atomic(to_page, KM_USER1);
 +              from_virtual = kmap_atomic(from_page);
 +              to_virtual = kmap_atomic(to_page);
                memcpy(to_virtual, from_virtual, PAGE_SIZE);
 -              kunmap_atomic(to_virtual, KM_USER1);
 -              kunmap_atomic(from_virtual, KM_USER0);
 +              kunmap_atomic(to_virtual);
 +              kunmap_atomic(from_virtual);
                preempt_enable();
                set_page_dirty(to_page);
                mark_page_accessed(to_page);
  #define VMWGFX_CHIP_SVGAII 0
  #define VMW_FB_RESERVATION 0
  
+ #define VMW_MIN_INITIAL_WIDTH 800
+ #define VMW_MIN_INITIAL_HEIGHT 600
  /**
   * Fully encoded drm commands. Might move to vmw_drm.h
   */
@@@ -387,6 -391,41 +391,41 @@@ void vmw_3d_resource_dec(struct vmw_pri
        BUG_ON(n3d < 0);
  }
  
+ /**
+  * Sets the initial_[width|height] fields on the given vmw_private.
+  *
+  * It does so by reading SVGA_REG_[WIDTH|HEIGHT] regs and then
+  * clamping the value to fb_max_[width|height] fields and the
+  * VMW_MIN_INITIAL_[WIDTH|HEIGHT].
+  * If the values appear to be invalid, set them to
+  * VMW_MIN_INITIAL_[WIDTH|HEIGHT].
+  */
+ static void vmw_get_initial_size(struct vmw_private *dev_priv)
+ {
+       uint32_t width;
+       uint32_t height;
+       width = vmw_read(dev_priv, SVGA_REG_WIDTH);
+       height = vmw_read(dev_priv, SVGA_REG_HEIGHT);
+       width = max_t(uint32_t, width, VMW_MIN_INITIAL_WIDTH);
+       height = max_t(uint32_t, height, VMW_MIN_INITIAL_HEIGHT);
+       if (width > dev_priv->fb_max_width ||
+           height > dev_priv->fb_max_height) {
+               /*
+                * This is a host error and shouldn't occur.
+                */
+               width = VMW_MIN_INITIAL_WIDTH;
+               height = VMW_MIN_INITIAL_HEIGHT;
+       }
+       dev_priv->initial_width = width;
+       dev_priv->initial_height = height;
+ }
  static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
  {
        struct vmw_private *dev_priv;
        }
        memset(dev_priv, 0, sizeof(*dev_priv));
  
+       pci_set_master(dev->pdev);
        dev_priv->dev = dev;
        dev_priv->vmw_chipset = chipset;
        dev_priv->last_read_seqno = (uint32_t) -100;
        svga_id = vmw_read(dev_priv, SVGA_REG_ID);
        if (svga_id != SVGA_ID_2) {
                ret = -ENOSYS;
 -              DRM_ERROR("Unsuported SVGA ID 0x%x\n", svga_id);
 +              DRM_ERROR("Unsupported SVGA ID 0x%x\n", svga_id);
                mutex_unlock(&dev_priv->hw_mutex);
                goto out_err0;
        }
        dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE);
        dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH);
        dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT);
+       vmw_get_initial_size(dev_priv);
        if (dev_priv->capabilities & SVGA_CAP_GMR) {
                dev_priv->max_gmr_descriptors =
                        vmw_read(dev_priv,
@@@ -688,6 -732,15 +732,15 @@@ static int vmw_driver_unload(struct drm
        return 0;
  }
  
+ static void vmw_preclose(struct drm_device *dev,
+                        struct drm_file *file_priv)
+ {
+       struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       vmw_event_fence_fpriv_gone(dev_priv->fman, &vmw_fp->fence_events);
+ }
  static void vmw_postclose(struct drm_device *dev,
                         struct drm_file *file_priv)
  {
@@@ -710,6 -763,7 +763,7 @@@ static int vmw_driver_open(struct drm_d
        if (unlikely(vmw_fp == NULL))
                return ret;
  
+       INIT_LIST_HEAD(&vmw_fp->fence_events);
        vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10);
        if (unlikely(vmw_fp->tfile == NULL))
                goto out_no_tfile;
@@@ -1102,6 -1156,7 +1156,7 @@@ static struct drm_driver driver = 
        .master_set = vmw_master_set,
        .master_drop = vmw_master_drop,
        .open = vmw_driver_open,
+       .preclose = vmw_preclose,
        .postclose = vmw_postclose,
        .fops = &vmwgfx_driver_fops,
        .name = VMWGFX_DRIVER_NAME,
@@@ -103,14 -103,8 +103,14 @@@ static int sclhi(struct i2c_algo_bit_da
                 * chips may hold it low ("clock stretching") while they
                 * are processing data internally.
                 */
 -              if (time_after(jiffies, start + adap->timeout))
 +              if (time_after(jiffies, start + adap->timeout)) {
 +                      /* Test one last time, as we may have been preempted
 +                       * between last check and timeout test.
 +                       */
 +                      if (getscl(adap))
 +                              break;
                        return -ETIMEDOUT;
 +              }
                cond_resched();
        }
  #ifdef DEBUG
@@@ -616,10 -610,11 +616,11 @@@ static u32 bit_func(struct i2c_adapter 
  
  /* -----exported algorithm data: -------------------------------------        */
  
- static const struct i2c_algorithm i2c_bit_algo = {
+ const struct i2c_algorithm i2c_bit_algo = {
        .master_xfer    = bit_xfer,
        .functionality  = bit_func,
  };
+ EXPORT_SYMBOL(i2c_bit_algo);
  
  /*
   * registering functions to load algorithms at runtime