]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 3 May 2013 02:40:34 +0000 (19:40 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 3 May 2013 02:40:34 +0000 (19:40 -0700)
Pull drm updates from Dave Airlie:
 "This is the main drm pull request for 3.10.

  Wierd bits:
   - OMAP drm changes required OMAP dss changes, in drivers/video, so I
     took them in here.
   - one more fbcon fix for font handover
   - VT switch avoidance in pm code
   - scatterlist helpers for gpu drivers - have acks from akpm

  Highlights:
   - qxl kms driver - driver for the spice qxl virtual GPU

  Nouveau:
   - fermi/kepler VRAM compression
   - GK110/nvf0 modesetting support.

  Tegra:
   - host1x core merged with 2D engine support

  i915:
   - vt switchless resume
   - more valleyview support
   - vblank fixes
   - modesetting pipe config rework

  radeon:
   - UVD engine support
   - SI chip tiling support
   - GPU registers initialisation from golden values.

  exynos:
   - device tree changes
   - fimc block support

  Otherwise:
   - bunches of fixes all over the place."

* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (513 commits)
  qxl: update to new idr interfaces.
  drm/nouveau: fix build with nv50->nvc0
  drm/radeon: fix handling of v6 power tables
  drm/radeon: clarify family checks in pm table parsing
  drm/radeon: consolidate UVD clock programming
  drm/radeon: fix UPLL_REF_DIV_MASK definition
  radeon: add bo tracking debugfs
  drm/radeon: add new richland pci ids
  drm/radeon: add some new SI PCI ids
  drm/radeon: fix scratch reg handling for UVD fence
  drm/radeon: allocate SA bo in the requested domain
  drm/radeon: fix possible segfault when parsing pm tables
  drm/radeon: fix endian bugs in atom_allocate_fb_scratch()
  OMAPDSS: TFP410: return EPROBE_DEFER if the i2c adapter not found
  OMAPDSS: VENC: Add error handling for venc_probe_pdata
  OMAPDSS: HDMI: Add error handling for hdmi_probe_pdata
  OMAPDSS: RFBI: Add error handling for rfbi_probe_pdata
  OMAPDSS: DSI: Add error handling for dsi_probe_pdata
  OMAPDSS: SDI: Add error handling for sdi_probe_pdata
  OMAPDSS: DPI: Add error handling for dpi_probe_pdata
  ...

13 files changed:
1  2 
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-h4.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/tilcdc/tilcdc_panel.c
drivers/video/Kconfig
drivers/video/fbmem.c
drivers/video/omap2/omapfb/omapfb-main.c
include/drm/drmP.h
include/linux/scatterlist.h

index cb0596b631cff4feef830b27f0904be930416b47,1322ed707b302deec3580298f9104c6b36c0c451..5b86423c89faf6944658f59d10e30355891f225a
@@@ -38,7 -38,7 +38,7 @@@
  #include "gpmc-smc91x.h"
  
  #include <video/omapdss.h>
- #include <video/omap-panel-generic-dpi.h>
+ #include <video/omap-panel-data.h>
  
  #include "mux.h"
  #include "hsmmc.h"
@@@ -166,7 -166,7 +166,7 @@@ static void __init sdp2430_display_init
        omap_display_init(&sdp2430_dss_data);
  }
  
 -#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
 +#if IS_ENABLED(CONFIG_SMC91X)
  
  static struct omap_smc91x_platform_data board_smc91x_data = {
        .cs             = 5,
index 5b4ec51c385f06ecdaf0b3f0b231e0f281bee3c2,0c1bdd7ee32d7d3817b10c46c28b8fd7e072aa49..69c0acf5aa63cbf9f9f0eaeb89edb0bc52c6590c
@@@ -34,7 -34,7 +34,7 @@@
  #include <asm/mach/map.h>
  
  #include <video/omapdss.h>
- #include <video/omap-panel-generic-dpi.h>
+ #include <video/omap-panel-data.h>
  
  #include "common.h"
  #include "mux.h"
@@@ -246,7 -246,7 +246,7 @@@ static u32 is_gpmc_muxed(void
                return 0;
  }
  
 -#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
 +#if IS_ENABLED(CONFIG_SMC91X)
  
  static struct omap_smc91x_platform_data board_smc91x_data = {
        .cs             = 1,
index 892ff9f959754263eb318da91347cbfffcc25ae7,6764dce44e84e9a48e984a929c5cfe39f25cea42..b78cbe74dadfaa3b99a9e0a5781c89eec159dc46
@@@ -1398,7 -1398,7 +1398,7 @@@ static void drm_setup_crtcs(struct drm_
        struct drm_mode_set *modeset;
        bool *enabled;
        int width, height;
-       int i, ret;
+       int i;
  
        DRM_DEBUG_KMS("\n");
  
  
        drm_enable_connectors(fb_helper, enabled);
  
-       ret = drm_target_cloned(fb_helper, modes, enabled, width, height);
-       if (!ret) {
-               ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
-               if (!ret)
+       if (!(fb_helper->funcs->initial_config &&
+             fb_helper->funcs->initial_config(fb_helper, crtcs, modes,
+                                              enabled, width, height))) {
+               memset(modes, 0, dev->mode_config.num_connector*sizeof(modes[0]));
+               memset(crtcs, 0, dev->mode_config.num_connector*sizeof(crtcs[0]));
+               if (!drm_target_cloned(fb_helper,
+                                      modes, enabled, width, height) &&
+                   !drm_target_preferred(fb_helper,
+                                         modes, enabled, width, height))
                        DRM_ERROR("Unable to find initial modes\n");
-       }
  
-       DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height);
+               DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n",
+                             width, height);
  
-       drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
+               drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
+       }
  
        /* need to set the modesets up here for use later */
        /* fill out the connector<->crtc mappings into the modesets */
@@@ -1544,10 -1551,10 +1551,10 @@@ int drm_fb_helper_hotplug_event(struct 
        if (!fb_helper->fb)
                return 0;
  
 -      drm_modeset_lock_all(dev);
 +      mutex_lock(&fb_helper->dev->mode_config.mutex);
        if (!drm_fb_helper_is_bound(fb_helper)) {
                fb_helper->delayed_hotplug = true;
 -              drm_modeset_unlock_all(dev);
 +              mutex_unlock(&fb_helper->dev->mode_config.mutex);
                return 0;
        }
        DRM_DEBUG_KMS("\n");
  
        count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
                                                    max_height);
 +      mutex_unlock(&fb_helper->dev->mode_config.mutex);
 +
 +      drm_modeset_lock_all(dev);
        drm_setup_crtcs(fb_helper);
        drm_modeset_unlock_all(dev);
 -
        drm_fb_helper_set_par(fb_helper->fbdev);
  
        return 0;
index f83f0719922e47b3e79cae946ce4ce9bdcbb9cd5,f264d08062f0963f95845a6366c2c8515adbb37e..faa79df0264802e985719da65be37ee369a87a69
@@@ -506,7 -506,7 +506,7 @@@ drm_gtf_mode(struct drm_device *dev, in
  }
  EXPORT_SYMBOL(drm_gtf_mode);
  
 -#if IS_ENABLED(CONFIG_VIDEOMODE)
 +#ifdef CONFIG_VIDEOMODE_HELPERS
  int drm_display_mode_from_videomode(const struct videomode *vm,
                                    struct drm_display_mode *dmode)
  {
        dmode->clock = vm->pixelclock / 1000;
  
        dmode->flags = 0;
 -      if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
 +      if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
                dmode->flags |= DRM_MODE_FLAG_PHSYNC;
 -      else if (vm->dmt_flags & VESA_DMT_HSYNC_LOW)
 +      else if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
                dmode->flags |= DRM_MODE_FLAG_NHSYNC;
 -      if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH)
 +      if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
                dmode->flags |= DRM_MODE_FLAG_PVSYNC;
 -      else if (vm->dmt_flags & VESA_DMT_VSYNC_LOW)
 +      else if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
                dmode->flags |= DRM_MODE_FLAG_NVSYNC;
 -      if (vm->data_flags & DISPLAY_FLAGS_INTERLACED)
 +      if (vm->flags & DISPLAY_FLAGS_INTERLACED)
                dmode->flags |= DRM_MODE_FLAG_INTERLACE;
 -      if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN)
 +      if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
                dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
        drm_mode_set_name(dmode);
  
        return 0;
  }
  EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
 -#endif
  
 -#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
 +#ifdef CONFIG_OF
  /**
   * of_get_drm_display_mode - get a drm_display_mode from devicetree
   * @np: device_node with the timing specification
@@@ -571,8 -572,7 +571,8 @@@ int of_get_drm_display_mode(struct devi
        return 0;
  }
  EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
 -#endif
 +#endif /* CONFIG_OF */
 +#endif /* CONFIG_VIDEOMODE_HELPERS */
  
  /**
   * drm_mode_set_name - set the name on a mode
@@@ -848,6 -848,26 +848,26 @@@ bool drm_mode_equal(const struct drm_di
        } else if (mode1->clock != mode2->clock)
                return false;
  
+       return drm_mode_equal_no_clocks(mode1, mode2);
+ }
+ EXPORT_SYMBOL(drm_mode_equal);
+ /**
+  * drm_mode_equal_no_clocks - test modes for equality
+  * @mode1: first mode
+  * @mode2: second mode
+  *
+  * LOCKING:
+  * None.
+  *
+  * Check to see if @mode1 and @mode2 are equivalent, but
+  * don't check the pixel clocks.
+  *
+  * RETURNS:
+  * True if the modes are equal, false otherwise.
+  */
+ bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
+ {
        if (mode1->hdisplay == mode2->hdisplay &&
            mode1->hsync_start == mode2->hsync_start &&
            mode1->hsync_end == mode2->hsync_end &&
  
        return false;
  }
- EXPORT_SYMBOL(drm_mode_equal);
+ EXPORT_SYMBOL(drm_mode_equal_no_clocks);
  
  /**
   * drm_mode_validate_size - make sure modes adhere to size constraints
index c3f5bd8a50775c7c808cf487412b99cb47413608,91ca291e38558c08dc4a93b403e50ad404a8a353..fb2fbc1e08b9ba0048b17c02badb8fd8ed29d089
@@@ -109,29 -109,6 +109,6 @@@ bool intel_encoder_is_pch_edp(struct dr
  
  static void intel_dp_link_down(struct intel_dp *intel_dp);
  
- void
- intel_edp_link_config(struct intel_encoder *intel_encoder,
-                      int *lane_num, int *link_bw)
- {
-       struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
-       *lane_num = intel_dp->lane_count;
-       *link_bw = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
- }
- int
- intel_edp_target_clock(struct intel_encoder *intel_encoder,
-                      struct drm_display_mode *mode)
- {
-       struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
-       struct intel_connector *intel_connector = intel_dp->attached_connector;
-       if (intel_connector->panel.fixed_mode)
-               return intel_connector->panel.fixed_mode->clock;
-       else
-               return mode->clock;
- }
  static int
  intel_dp_max_link_bw(struct intel_dp *intel_dp)
  {
@@@ -177,34 -154,6 +154,6 @@@ intel_dp_max_data_rate(int max_link_clo
        return (max_link_clock * max_lanes * 8) / 10;
  }
  
- static bool
- intel_dp_adjust_dithering(struct intel_dp *intel_dp,
-                         struct drm_display_mode *mode,
-                         bool adjust_mode)
- {
-       int max_link_clock =
-               drm_dp_bw_code_to_link_rate(intel_dp_max_link_bw(intel_dp));
-       int max_lanes = drm_dp_max_lane_count(intel_dp->dpcd);
-       int max_rate, mode_rate;
-       mode_rate = intel_dp_link_required(mode->clock, 24);
-       max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
-       if (mode_rate > max_rate) {
-               mode_rate = intel_dp_link_required(mode->clock, 18);
-               if (mode_rate > max_rate)
-                       return false;
-               if (adjust_mode)
-                       mode->private_flags
-                               |= INTEL_MODE_DP_FORCE_6BPC;
-               return true;
-       }
-       return true;
- }
  static int
  intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
        struct intel_dp *intel_dp = intel_attached_dp(connector);
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
+       int target_clock = mode->clock;
+       int max_rate, mode_rate, max_lanes, max_link_clock;
  
        if (is_edp(intel_dp) && fixed_mode) {
                if (mode->hdisplay > fixed_mode->hdisplay)
  
                if (mode->vdisplay > fixed_mode->vdisplay)
                        return MODE_PANEL;
+               target_clock = fixed_mode->clock;
        }
  
-       if (!intel_dp_adjust_dithering(intel_dp, mode, false))
+       max_link_clock = drm_dp_bw_code_to_link_rate(intel_dp_max_link_bw(intel_dp));
+       max_lanes = drm_dp_max_lane_count(intel_dp->dpcd);
+       max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
+       mode_rate = intel_dp_link_required(target_clock, 18);
+       if (mode_rate > max_rate)
                return MODE_CLOCK_HIGH;
  
        if (mode->clock < 10000)
@@@ -294,16 -253,20 +253,20 @@@ static bool ironlake_edp_have_panel_pow
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 pp_stat_reg;
  
-       return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
+       pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
+       return (I915_READ(pp_stat_reg) & PP_ON) != 0;
  }
  
  static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 pp_ctrl_reg;
  
-       return (I915_READ(PCH_PP_CONTROL) & EDP_FORCE_VDD) != 0;
+       pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+       return (I915_READ(pp_ctrl_reg) & EDP_FORCE_VDD) != 0;
  }
  
  static void
@@@ -311,14 -274,19 +274,19 @@@ intel_dp_check_edp(struct intel_dp *int
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 pp_stat_reg, pp_ctrl_reg;
  
        if (!is_edp(intel_dp))
                return;
+       pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
+       pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
        if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) {
                WARN(1, "eDP powered off while attempting aux channel communication.\n");
                DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
-                             I915_READ(PCH_PP_STATUS),
-                             I915_READ(PCH_PP_CONTROL));
+                               I915_READ(pp_stat_reg),
+                               I915_READ(pp_ctrl_reg));
        }
  }
  
@@@ -328,29 -296,10 +296,10 @@@ intel_dp_aux_wait_done(struct intel_dp 
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_device *dev = intel_dig_port->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t ch_ctl = intel_dp->output_reg + 0x10;
+       uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg;
        uint32_t status;
        bool done;
  
-       if (IS_HASWELL(dev)) {
-               switch (intel_dig_port->port) {
-               case PORT_A:
-                       ch_ctl = DPA_AUX_CH_CTL;
-                       break;
-               case PORT_B:
-                       ch_ctl = PCH_DPB_AUX_CH_CTL;
-                       break;
-               case PORT_C:
-                       ch_ctl = PCH_DPC_AUX_CH_CTL;
-                       break;
-               case PORT_D:
-                       ch_ctl = PCH_DPD_AUX_CH_CTL;
-                       break;
-               default:
-                       BUG();
-               }
-       }
  #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
        if (has_aux_irq)
                done = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
@@@ -370,11 -319,10 +319,10 @@@ intel_dp_aux_ch(struct intel_dp *intel_
                uint8_t *send, int send_bytes,
                uint8_t *recv, int recv_size)
  {
-       uint32_t output_reg = intel_dp->output_reg;
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_device *dev = intel_dig_port->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t ch_ctl = output_reg + 0x10;
+       uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg;
        uint32_t ch_data = ch_ctl + 4;
        int i, ret, recv_bytes;
        uint32_t status;
         */
        pm_qos_update_request(&dev_priv->pm_qos, 0);
  
-       if (IS_HASWELL(dev)) {
-               switch (intel_dig_port->port) {
-               case PORT_A:
-                       ch_ctl = DPA_AUX_CH_CTL;
-                       ch_data = DPA_AUX_CH_DATA1;
-                       break;
-               case PORT_B:
-                       ch_ctl = PCH_DPB_AUX_CH_CTL;
-                       ch_data = PCH_DPB_AUX_CH_DATA1;
-                       break;
-               case PORT_C:
-                       ch_ctl = PCH_DPC_AUX_CH_CTL;
-                       ch_data = PCH_DPC_AUX_CH_DATA1;
-                       break;
-               case PORT_D:
-                       ch_ctl = PCH_DPD_AUX_CH_CTL;
-                       ch_data = PCH_DPD_AUX_CH_DATA1;
-                       break;
-               default:
-                       BUG();
-               }
-       }
        intel_dp_check_edp(intel_dp);
        /* The clock divider is based off the hrawclk,
         * and would like to run at 2MHz. So, take the
                        aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
                else
                        aux_clock_divider = 225; /* eDP input clock at 450Mhz */
-       } else if (HAS_PCH_SPLIT(dev))
+       } else if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
+               /* Workaround for non-ULT HSW */
+               aux_clock_divider = 74;
+       } else if (HAS_PCH_SPLIT(dev)) {
                aux_clock_divider = DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
-       else
+       } else {
                aux_clock_divider = intel_hrawclk(dev) / 2;
+       }
  
        if (IS_GEN6(dev))
                precharge = 3;
@@@ -732,18 -661,26 +661,26 @@@ intel_dp_i2c_init(struct intel_dp *inte
  }
  
  bool
- intel_dp_mode_fixup(struct drm_encoder *encoder,
-                   const struct drm_display_mode *mode,
-                   struct drm_display_mode *adjusted_mode)
+ intel_dp_compute_config(struct intel_encoder *encoder,
+                       struct intel_crtc_config *pipe_config)
  {
-       struct drm_device *dev = encoder->dev;
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+       struct drm_display_mode *mode = &pipe_config->requested_mode;
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        struct intel_connector *intel_connector = intel_dp->attached_connector;
        int lane_count, clock;
        int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
        int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
        int bpp, mode_rate;
        static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
+       int target_clock, link_avail, link_clock;
+       if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && !is_cpu_edp(intel_dp))
+               pipe_config->has_pch_encoder = true;
+       pipe_config->has_dp_encoder = true;
  
        if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
                intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
                                        intel_connector->panel.fitting_mode,
                                        mode, adjusted_mode);
        }
+       /* We need to take the panel's fixed mode into account. */
+       target_clock = adjusted_mode->clock;
  
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
                return false;
                      "max bw %02x pixel clock %iKHz\n",
                      max_lane_count, bws[max_clock], adjusted_mode->clock);
  
-       if (!intel_dp_adjust_dithering(intel_dp, adjusted_mode, true))
-               return false;
+       /* Walk through all bpp values. Luckily they're all nicely spaced with 2
+        * bpc in between. */
+       bpp = min_t(int, 8*3, pipe_config->pipe_bpp);
+       for (; bpp >= 6*3; bpp -= 2*3) {
+               mode_rate = intel_dp_link_required(target_clock, bpp);
+               for (clock = 0; clock <= max_clock; clock++) {
+                       for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
+                               link_clock = drm_dp_bw_code_to_link_rate(bws[clock]);
+                               link_avail = intel_dp_max_data_rate(link_clock,
+                                                                   lane_count);
+                               if (mode_rate <= link_avail) {
+                                       goto found;
+                               }
+                       }
+               }
+       }
  
-       bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
+       return false;
  
+ found:
        if (intel_dp->color_range_auto) {
                /*
                 * See:
        }
  
        if (intel_dp->color_range)
-               adjusted_mode->private_flags |= INTEL_MODE_LIMITED_COLOR_RANGE;
-       mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp);
-       for (clock = 0; clock <= max_clock; clock++) {
-               for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
-                       int link_bw_clock =
-                               drm_dp_bw_code_to_link_rate(bws[clock]);
-                       int link_avail = intel_dp_max_data_rate(link_bw_clock,
-                                                               lane_count);
-                       if (mode_rate <= link_avail) {
-                               intel_dp->link_bw = bws[clock];
-                               intel_dp->lane_count = lane_count;
-                               adjusted_mode->clock = link_bw_clock;
-                               DRM_DEBUG_KMS("DP link bw %02x lane "
-                                               "count %d clock %d bpp %d\n",
-                                      intel_dp->link_bw, intel_dp->lane_count,
-                                      adjusted_mode->clock, bpp);
-                               DRM_DEBUG_KMS("DP link bw required %i available %i\n",
-                                             mode_rate, link_avail);
-                               return true;
-                       }
-               }
-       }
-       return false;
- }
+               pipe_config->limited_color_range = true;
  
- void
- intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
-                struct drm_display_mode *adjusted_mode)
- {
-       struct drm_device *dev = crtc->dev;
-       struct intel_encoder *intel_encoder;
-       struct intel_dp *intel_dp;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int lane_count = 4;
-       struct intel_link_m_n m_n;
-       int pipe = intel_crtc->pipe;
-       enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
-       int target_clock;
+       intel_dp->link_bw = bws[clock];
+       intel_dp->lane_count = lane_count;
+       adjusted_mode->clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
+       pipe_config->pixel_target_clock = target_clock;
  
-       /*
-        * Find the lane count in the intel_encoder private
-        */
-       for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
-               intel_dp = enc_to_intel_dp(&intel_encoder->base);
+       DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n",
+                     intel_dp->link_bw, intel_dp->lane_count,
+                     adjusted_mode->clock, bpp);
+       DRM_DEBUG_KMS("DP link bw required %i available %i\n",
+                     mode_rate, link_avail);
  
-               if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
-                   intel_encoder->type == INTEL_OUTPUT_EDP)
-               {
-                       lane_count = intel_dp->lane_count;
-                       break;
-               }
-       }
-       target_clock = mode->clock;
-       for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
-               if (intel_encoder->type == INTEL_OUTPUT_EDP) {
-                       target_clock = intel_edp_target_clock(intel_encoder,
-                                                             mode);
-                       break;
-               }
-       }
+       intel_link_compute_m_n(bpp, lane_count,
+                              target_clock, adjusted_mode->clock,
+                              &pipe_config->dp_m_n);
  
        /*
-        * Compute the GMCH and Link ratios. The '3' here is
-        * the number of bytes_per_pixel post-LUT, which we always
-        * set up for 8-bits of R/G/B, or 3 bytes total.
+        * XXX: We have a strange regression where using the vbt edp bpp value
+        * for the link bw computation results in black screens, the panel only
+        * works when we do the computation at the usual 24bpp (but still
+        * requires us to use 18bpp). Until that's fully debugged, stay
+        * bug-for-bug compatible with the old code.
         */
-       intel_link_compute_m_n(intel_crtc->bpp, lane_count,
-                              target_clock, adjusted_mode->clock, &m_n);
-       if (IS_HASWELL(dev)) {
-               I915_WRITE(PIPE_DATA_M1(cpu_transcoder),
-                          TU_SIZE(m_n.tu) | m_n.gmch_m);
-               I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n);
-               I915_WRITE(PIPE_LINK_M1(cpu_transcoder), m_n.link_m);
-               I915_WRITE(PIPE_LINK_N1(cpu_transcoder), m_n.link_n);
-       } else if (HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(TRANSDATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
-               I915_WRITE(TRANSDATA_N1(pipe), m_n.gmch_n);
-               I915_WRITE(TRANSDPLINK_M1(pipe), m_n.link_m);
-               I915_WRITE(TRANSDPLINK_N1(pipe), m_n.link_n);
-       } else if (IS_VALLEYVIEW(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);
-       } else {
-               I915_WRITE(PIPE_GMCH_DATA_M(pipe),
-                          TU_SIZE(m_n.tu) | m_n.gmch_m);
-               I915_WRITE(PIPE_GMCH_DATA_N(pipe), m_n.gmch_n);
-               I915_WRITE(PIPE_DP_LINK_M(pipe), m_n.link_m);
-               I915_WRITE(PIPE_DP_LINK_N(pipe), m_n.link_n);
+       if (is_edp(intel_dp) && dev_priv->edp.bpp) {
+               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n",
+                             bpp, dev_priv->edp.bpp);
+               bpp = min_t(int, bpp, dev_priv->edp.bpp);
        }
+       pipe_config->pipe_bpp = bpp;
+       return true;
  }
  
  void intel_dp_init_link_config(struct intel_dp *intel_dp)
@@@ -994,7 -884,7 +884,7 @@@ intel_dp_mode_set(struct drm_encoder *e
                else
                        intel_dp->DP |= DP_PLL_FREQ_270MHZ;
        } else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
-               if (!HAS_PCH_SPLIT(dev))
+               if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev))
                        intel_dp->DP |= intel_dp->color_range;
  
                if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
                if (intel_crtc->pipe == 1)
                        intel_dp->DP |= DP_PIPEB_SELECT;
  
-               if (is_cpu_edp(intel_dp)) {
+               if (is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
                        /* don't miss out required setting for eDP */
                        if (adjusted_mode->clock < 200000)
                                intel_dp->DP |= DP_PLL_FREQ_160MHZ;
                intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
        }
  
-       if (is_cpu_edp(intel_dp))
+       if (is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev))
                ironlake_set_pll_edp(crtc, adjusted_mode->clock);
  }
  
@@@ -1039,16 -929,20 +929,20 @@@ static void ironlake_wait_panel_status(
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 pp_stat_reg, pp_ctrl_reg;
+       pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
+       pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
  
        DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
-                     mask, value,
-                     I915_READ(PCH_PP_STATUS),
-                     I915_READ(PCH_PP_CONTROL));
+                       mask, value,
+                       I915_READ(pp_stat_reg),
+                       I915_READ(pp_ctrl_reg));
  
-       if (_wait_for((I915_READ(PCH_PP_STATUS) & mask) == value, 5000, 10)) {
+       if (_wait_for((I915_READ(pp_stat_reg) & mask) == value, 5000, 10)) {
                DRM_ERROR("Panel status timeout: status %08x control %08x\n",
-                         I915_READ(PCH_PP_STATUS),
-                         I915_READ(PCH_PP_CONTROL));
+                               I915_READ(pp_stat_reg),
+                               I915_READ(pp_ctrl_reg));
        }
  }
  
@@@ -1075,9 -969,15 +969,15 @@@ static void ironlake_wait_panel_power_c
   * is locked
   */
  
- static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv)
+ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
  {
-       u32     control = I915_READ(PCH_PP_CONTROL);
+       struct drm_device *dev = intel_dp_to_dev(intel_dp);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 control;
+       u32 pp_ctrl_reg;
+       pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+       control = I915_READ(pp_ctrl_reg);
  
        control &= ~PANEL_UNLOCK_MASK;
        control |= PANEL_UNLOCK_REGS;
@@@ -1089,6 -989,7 +989,7 @@@ void ironlake_edp_panel_vdd_on(struct i
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 pp;
+       u32 pp_stat_reg, pp_ctrl_reg;
  
        if (!is_edp(intel_dp))
                return;
        if (!ironlake_edp_have_panel_power(intel_dp))
                ironlake_wait_panel_power_cycle(intel_dp);
  
-       pp = ironlake_get_pp_control(dev_priv);
+       pp = ironlake_get_pp_control(intel_dp);
        pp |= EDP_FORCE_VDD;
-       I915_WRITE(PCH_PP_CONTROL, pp);
-       POSTING_READ(PCH_PP_CONTROL);
-       DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
-                     I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
  
+       pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
+       pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+       I915_WRITE(pp_ctrl_reg, pp);
+       POSTING_READ(pp_ctrl_reg);
+       DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
+                       I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
        /*
         * If the panel wasn't on, delay before accessing aux channel
         */
@@@ -1128,19 -1032,23 +1032,23 @@@ static void ironlake_panel_vdd_off_sync
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 pp;
+       u32 pp_stat_reg, pp_ctrl_reg;
  
        WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
  
        if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) {
-               pp = ironlake_get_pp_control(dev_priv);
+               pp = ironlake_get_pp_control(intel_dp);
                pp &= ~EDP_FORCE_VDD;
-               I915_WRITE(PCH_PP_CONTROL, pp);
-               POSTING_READ(PCH_PP_CONTROL);
  
-               /* Make sure sequencer is idle before allowing subsequent activity */
-               DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
-                             I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
+               pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
+               pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+               I915_WRITE(pp_ctrl_reg, pp);
+               POSTING_READ(pp_ctrl_reg);
  
+               /* Make sure sequencer is idle before allowing subsequent activity */
+               DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
+               I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
                msleep(intel_dp->panel_power_down_delay);
        }
  }
@@@ -1184,6 -1092,7 +1092,7 @@@ void ironlake_edp_panel_on(struct intel
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 pp;
+       u32 pp_ctrl_reg;
  
        if (!is_edp(intel_dp))
                return;
  
        ironlake_wait_panel_power_cycle(intel_dp);
  
-       pp = ironlake_get_pp_control(dev_priv);
+       pp = ironlake_get_pp_control(intel_dp);
        if (IS_GEN5(dev)) {
                /* ILK workaround: disable reset around power sequence */
                pp &= ~PANEL_POWER_RESET;
        if (!IS_GEN5(dev))
                pp |= PANEL_POWER_RESET;
  
-       I915_WRITE(PCH_PP_CONTROL, pp);
-       POSTING_READ(PCH_PP_CONTROL);
+       pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+       I915_WRITE(pp_ctrl_reg, pp);
+       POSTING_READ(pp_ctrl_reg);
  
        ironlake_wait_panel_on(intel_dp);
  
@@@ -1226,6 -1137,7 +1137,7 @@@ void ironlake_edp_panel_off(struct inte
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 pp;
+       u32 pp_ctrl_reg;
  
        if (!is_edp(intel_dp))
                return;
  
        WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
  
-       pp = ironlake_get_pp_control(dev_priv);
+       pp = ironlake_get_pp_control(intel_dp);
        /* We need to switch off panel power _and_ force vdd, for otherwise some
         * panels get very unhappy and cease to work. */
        pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
-       I915_WRITE(PCH_PP_CONTROL, pp);
-       POSTING_READ(PCH_PP_CONTROL);
+       pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+       I915_WRITE(pp_ctrl_reg, pp);
+       POSTING_READ(pp_ctrl_reg);
  
        intel_dp->want_panel_vdd = false;
  
@@@ -1253,6 -1168,7 +1168,7 @@@ void ironlake_edp_backlight_on(struct i
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = to_intel_crtc(intel_dig_port->base.base.crtc)->pipe;
        u32 pp;
+       u32 pp_ctrl_reg;
  
        if (!is_edp(intel_dp))
                return;
         * allowing it to appear.
         */
        msleep(intel_dp->backlight_on_delay);
-       pp = ironlake_get_pp_control(dev_priv);
+       pp = ironlake_get_pp_control(intel_dp);
        pp |= EDP_BLC_ENABLE;
-       I915_WRITE(PCH_PP_CONTROL, pp);
-       POSTING_READ(PCH_PP_CONTROL);
+       pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+       I915_WRITE(pp_ctrl_reg, pp);
+       POSTING_READ(pp_ctrl_reg);
  
        intel_panel_enable_backlight(dev, pipe);
  }
@@@ -1278,6 -1197,7 +1197,7 @@@ void ironlake_edp_backlight_off(struct 
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 pp;
+       u32 pp_ctrl_reg;
  
        if (!is_edp(intel_dp))
                return;
        intel_panel_disable_backlight(dev);
  
        DRM_DEBUG_KMS("\n");
-       pp = ironlake_get_pp_control(dev_priv);
+       pp = ironlake_get_pp_control(intel_dp);
        pp &= ~EDP_BLC_ENABLE;
-       I915_WRITE(PCH_PP_CONTROL, pp);
-       POSTING_READ(PCH_PP_CONTROL);
+       pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+       I915_WRITE(pp_ctrl_reg, pp);
+       POSTING_READ(pp_ctrl_reg);
        msleep(intel_dp->backlight_off_delay);
  }
  
@@@ -1384,7 -1307,7 +1307,7 @@@ static bool intel_dp_get_hw_state(struc
        if (!(tmp & DP_PORT_EN))
                return false;
  
-       if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
+       if (is_cpu_edp(intel_dp) && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) {
                *pipe = PORT_TO_PIPE_CPT(tmp);
        } else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
                *pipe = PORT_TO_PIPE(tmp);
@@@ -1441,10 -1364,12 +1364,12 @@@ static void intel_disable_dp(struct int
  static void intel_post_disable_dp(struct intel_encoder *encoder)
  {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+       struct drm_device *dev = encoder->base.dev;
  
        if (is_cpu_edp(intel_dp)) {
                intel_dp_link_down(intel_dp);
-               ironlake_edp_pll_off(intel_dp);
+               if (!IS_VALLEYVIEW(dev))
+                       ironlake_edp_pll_off(intel_dp);
        }
  }
  
@@@ -1470,8 -1395,9 +1395,9 @@@ static void intel_enable_dp(struct inte
  static void intel_pre_enable_dp(struct intel_encoder *encoder)
  {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+       struct drm_device *dev = encoder->base.dev;
  
-       if (is_cpu_edp(intel_dp))
+       if (is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev))
                ironlake_edp_pll_on(intel_dp);
  }
  
@@@ -1548,7 -1474,7 +1474,7 @@@ intel_dp_pre_emphasis_max(struct intel_
  {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
  
-       if (IS_HASWELL(dev)) {
+       if (HAS_DDI(dev)) {
                switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
                case DP_TRAIN_VOLTAGE_SWING_400:
                        return DP_TRAIN_PRE_EMPHASIS_9_5;
@@@ -1756,7 -1682,7 +1682,7 @@@ intel_dp_set_signal_levels(struct intel
        uint32_t signal_levels, mask;
        uint8_t train_set = intel_dp->train_set[0];
  
-       if (IS_HASWELL(dev)) {
+       if (HAS_DDI(dev)) {
                signal_levels = intel_hsw_signal_levels(train_set);
                mask = DDI_BUF_EMP_MASK;
        } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
@@@ -1787,7 -1713,7 +1713,7 @@@ intel_dp_set_link_train(struct intel_d
        int ret;
        uint32_t temp;
  
-       if (IS_HASWELL(dev)) {
+       if (HAS_DDI(dev)) {
                temp = I915_READ(DP_TP_CTL(port));
  
                if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
@@@ -2028,7 -1954,7 +1954,7 @@@ intel_dp_complete_link_train(struct int
        }
  
        if (channel_eq)
 -              DRM_DEBUG_KMS("Channel EQ done. DP Training successfull\n");
 +              DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
  
        intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE);
  }
@@@ -2311,6 -2237,16 +2237,16 @@@ g4x_dp_detect(struct intel_dp *intel_dp
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        uint32_t bit;
  
+       /* Can't disconnect eDP, but you can close the lid... */
+       if (is_edp(intel_dp)) {
+               enum drm_connector_status status;
+               status = intel_panel_detect(dev);
+               if (status == connector_status_unknown)
+                       status = connector_status_connected;
+               return status;
+       }
        switch (intel_dig_port->port) {
        case PORT_B:
                bit = PORTB_HOTPLUG_LIVE_STATUS;
@@@ -2492,6 -2428,9 +2428,9 @@@ intel_dp_set_property(struct drm_connec
        }
  
        if (property == dev_priv->broadcast_rgb_property) {
+               bool old_auto = intel_dp->color_range_auto;
+               uint32_t old_range = intel_dp->color_range;
                switch (val) {
                case INTEL_BROADCAST_RGB_AUTO:
                        intel_dp->color_range_auto = true;
                default:
                        return -EINVAL;
                }
+               if (old_auto == intel_dp->color_range_auto &&
+                   old_range == intel_dp->color_range)
+                       return 0;
                goto done;
        }
  
@@@ -2538,17 -2482,14 +2482,14 @@@ done
  static void
  intel_dp_destroy(struct drm_connector *connector)
  {
-       struct drm_device *dev = connector->dev;
        struct intel_dp *intel_dp = intel_attached_dp(connector);
        struct intel_connector *intel_connector = to_intel_connector(connector);
  
        if (!IS_ERR_OR_NULL(intel_connector->edid))
                kfree(intel_connector->edid);
  
-       if (is_edp(intel_dp)) {
-               intel_panel_destroy_backlight(dev);
+       if (is_edp(intel_dp))
                intel_panel_fini(&intel_connector->panel);
-       }
  
        drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
@@@ -2573,7 -2514,6 +2514,6 @@@ void intel_dp_encoder_destroy(struct dr
  }
  
  static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
-       .mode_fixup = intel_dp_mode_fixup,
        .mode_set = intel_dp_mode_set,
  };
  
@@@ -2669,15 -2609,28 +2609,28 @@@ intel_dp_init_panel_power_sequencer(str
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct edp_power_seq cur, vbt, spec, final;
        u32 pp_on, pp_off, pp_div, pp;
+       int pp_control_reg, pp_on_reg, pp_off_reg, pp_div_reg;
+       if (HAS_PCH_SPLIT(dev)) {
+               pp_control_reg = PCH_PP_CONTROL;
+               pp_on_reg = PCH_PP_ON_DELAYS;
+               pp_off_reg = PCH_PP_OFF_DELAYS;
+               pp_div_reg = PCH_PP_DIVISOR;
+       } else {
+               pp_control_reg = PIPEA_PP_CONTROL;
+               pp_on_reg = PIPEA_PP_ON_DELAYS;
+               pp_off_reg = PIPEA_PP_OFF_DELAYS;
+               pp_div_reg = PIPEA_PP_DIVISOR;
+       }
  
        /* Workaround: Need to write PP_CONTROL with the unlock key as
         * the very first thing. */
-       pp = ironlake_get_pp_control(dev_priv);
-       I915_WRITE(PCH_PP_CONTROL, pp);
+       pp = ironlake_get_pp_control(intel_dp);
+       I915_WRITE(pp_control_reg, pp);
  
-       pp_on = I915_READ(PCH_PP_ON_DELAYS);
-       pp_off = I915_READ(PCH_PP_OFF_DELAYS);
-       pp_div = I915_READ(PCH_PP_DIVISOR);
+       pp_on = I915_READ(pp_on_reg);
+       pp_off = I915_READ(pp_off_reg);
+       pp_div = I915_READ(pp_div_reg);
  
        /* Pull timing values out of registers */
        cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
@@@ -2752,7 -2705,22 +2705,22 @@@ intel_dp_init_panel_power_sequencer_reg
                                              struct edp_power_seq *seq)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pp_on, pp_off, pp_div;
+       u32 pp_on, pp_off, pp_div, port_sel = 0;
+       int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
+       int pp_on_reg, pp_off_reg, pp_div_reg;
+       if (HAS_PCH_SPLIT(dev)) {
+               pp_on_reg = PCH_PP_ON_DELAYS;
+               pp_off_reg = PCH_PP_OFF_DELAYS;
+               pp_div_reg = PCH_PP_DIVISOR;
+       } else {
+               pp_on_reg = PIPEA_PP_ON_DELAYS;
+               pp_off_reg = PIPEA_PP_OFF_DELAYS;
+               pp_div_reg = PIPEA_PP_DIVISOR;
+       }
+       if (IS_VALLEYVIEW(dev))
+               port_sel = I915_READ(pp_on_reg) & 0xc0000000;
  
        /* And finally store the new values in the power sequencer. */
        pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
                 (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
        /* Compute the divisor for the pp clock, simply match the Bspec
         * formula. */
-       pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1)
-                       << PP_REFERENCE_DIVIDER_SHIFT;
+       pp_div = ((100 * div)/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT;
        pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
                        << PANEL_POWER_CYCLE_DELAY_SHIFT);
  
         * power sequencer any more. */
        if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
                if (is_cpu_edp(intel_dp))
-                       pp_on |= PANEL_POWER_PORT_DP_A;
+                       port_sel = PANEL_POWER_PORT_DP_A;
                else
-                       pp_on |= PANEL_POWER_PORT_DP_D;
+                       port_sel = PANEL_POWER_PORT_DP_D;
        }
  
-       I915_WRITE(PCH_PP_ON_DELAYS, pp_on);
-       I915_WRITE(PCH_PP_OFF_DELAYS, pp_off);
-       I915_WRITE(PCH_PP_DIVISOR, pp_div);
+       pp_on |= port_sel;
+       I915_WRITE(pp_on_reg, pp_on);
+       I915_WRITE(pp_off_reg, pp_off);
+       I915_WRITE(pp_div_reg, pp_div);
  
        DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
-                     I915_READ(PCH_PP_ON_DELAYS),
-                     I915_READ(PCH_PP_OFF_DELAYS),
-                     I915_READ(PCH_PP_DIVISOR));
+                     I915_READ(pp_on_reg),
+                     I915_READ(pp_off_reg),
+                     I915_READ(pp_div_reg));
  }
  
  void
@@@ -2829,7 -2798,6 +2798,6 @@@ intel_dp_init_connector(struct intel_di
        drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
        drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
  
-       connector->polled = DRM_CONNECTOR_POLL_HPD;
        connector->interlace_allowed = true;
        connector->doublescan_allowed = 0;
  
        else
                intel_connector->get_hw_state = intel_connector_get_hw_state;
  
+       intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
+       if (HAS_DDI(dev)) {
+               switch (intel_dig_port->port) {
+               case PORT_A:
+                       intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL;
+                       break;
+               case PORT_B:
+                       intel_dp->aux_ch_ctl_reg = PCH_DPB_AUX_CH_CTL;
+                       break;
+               case PORT_C:
+                       intel_dp->aux_ch_ctl_reg = PCH_DPC_AUX_CH_CTL;
+                       break;
+               case PORT_D:
+                       intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL;
+                       break;
+               default:
+                       BUG();
+               }
+       }
  
        /* Set up the DDC bus. */
        switch (port) {
        case PORT_A:
+               intel_encoder->hpd_pin = HPD_PORT_A;
                name = "DPDDC-A";
                break;
        case PORT_B:
-               dev_priv->hotplug_supported_mask |= PORTB_HOTPLUG_INT_STATUS;
+               intel_encoder->hpd_pin = HPD_PORT_B;
                name = "DPDDC-B";
                break;
        case PORT_C:
-               dev_priv->hotplug_supported_mask |= PORTC_HOTPLUG_INT_STATUS;
+               intel_encoder->hpd_pin = HPD_PORT_C;
                name = "DPDDC-C";
                break;
        case PORT_D:
-               dev_priv->hotplug_supported_mask |= PORTD_HOTPLUG_INT_STATUS;
+               intel_encoder->hpd_pin = HPD_PORT_D;
                name = "DPDDC-D";
                break;
        default:
-               WARN(1, "Invalid port %c\n", port_name(port));
-               break;
+               BUG();
        }
  
        if (is_edp(intel_dp))
@@@ -2974,6 -2961,7 +2961,7 @@@ intel_dp_init(struct drm_device *dev, i
                         DRM_MODE_ENCODER_TMDS);
        drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
  
+       intel_encoder->compute_config = intel_dp_compute_config;
        intel_encoder->enable = intel_enable_dp;
        intel_encoder->pre_enable = intel_pre_enable_dp;
        intel_encoder->disable = intel_disable_dp;
index 78d8e919509fb1e0a5b6df59d9782693593cbdae,7337013a4a0e618acd35c68c4d0ea8c961daf976..f9889658329bfd1aa613cc595a143511e9f94386
@@@ -751,6 -751,8 +751,6 @@@ static int mga_crtc_mode_set(struct drm
        int i;
        unsigned char misc = 0;
        unsigned char ext_vga[6];
 -      unsigned char ext_vga_index24;
 -      unsigned char dac_index90 = 0;
        u8 bppshift;
  
        static unsigned char dacvalue[] = {
                option2 = 0x0000b000;
                break;
        case G200_ER:
 -              dac_index90 = 0;
                break;
        }
  
                WREG_DAC(i, dacvalue[i]);
        }
  
 -      if (mdev->type == G200_ER) {
 -              WREG_DAC(0x90, dac_index90);
 -      }
 -
 +      if (mdev->type == G200_ER)
 +              WREG_DAC(0x90, 0);
  
        if (option)
                pci_write_config_dword(dev->pdev, PCI_MGA_OPTION, option);
        if (mdev->type == G200_WB)
                ext_vga[1] |= 0x88;
  
 -      ext_vga_index24 = 0x05;
 -
        /* Set pixel clocks */
        misc = 0x2d;
        WREG8(MGA_MISC_OUT, misc);
        }
  
        if (mdev->type == G200_ER)
 -              WREG_ECRT(24, ext_vga_index24);
 +              WREG_ECRT(0x24, 0x5);
  
        if (mdev->type == G200_EV) {
                WREG_ECRT(6, 0);
@@@ -1254,9 -1261,8 +1254,8 @@@ static const struct drm_crtc_helper_fun
  };
  
  /* CRTC setup */
- static void mga_crtc_init(struct drm_device *dev)
+ static void mga_crtc_init(struct mga_device *mdev)
  {
-       struct mga_device *mdev = dev->dev_private;
        struct mga_crtc *mga_crtc;
        int i;
  
        if (mga_crtc == NULL)
                return;
  
-       drm_crtc_init(dev, &mga_crtc->base, &mga_crtc_funcs);
+       drm_crtc_init(mdev->dev, &mga_crtc->base, &mga_crtc_funcs);
  
        drm_mode_crtc_set_gamma_size(&mga_crtc->base, MGAG200_LUT_SIZE);
        mdev->mode_info.crtc = mga_crtc;
@@@ -1522,7 -1528,7 +1521,7 @@@ int mgag200_modeset_init(struct mga_dev
  
        mdev->dev->mode_config.fb_base = mdev->mc.vram_base;
  
-       mga_crtc_init(mdev->dev);
+       mga_crtc_init(mdev);
  
        encoder = mga_encoder_init(mdev->dev);
        if (!encoder) {
index 1ddc03e51bf47789b65992db64a3784cf0dad424,325887390677582a09dab39d8eaf1bfb81a69313..ebf0a683305ec18aad76a31822b96334c997f53f
@@@ -479,7 -479,7 +479,7 @@@ nv50_display_flip_wait(void *data
  {
        struct nv50_display_flip *flip = data;
        if (nouveau_bo_rd32(flip->disp->sync, flip->chan->addr / 4) ==
 -                                            flip->chan->data);
 +                                            flip->chan->data)
                return true;
        usleep_range(1, 2);
        return false;
@@@ -2174,6 -2174,7 +2174,7 @@@ in
  nv50_display_create(struct drm_device *dev)
  {
        static const u16 oclass[] = {
+               NVF0_DISP_CLASS,
                NVE0_DISP_CLASS,
                NVD0_DISP_CLASS,
                NVA3_DISP_CLASS,
index 90ee49786372b5ae875a090ad60f7808acb00de1,ea963f985d764e19ebff146198f51f6fdcc4b72d..09176654fddb9ccc2aba3a697ec58192516c6245
@@@ -173,7 -173,7 +173,7 @@@ static int panel_connector_get_modes(st
                struct drm_display_mode *mode = drm_mode_create(dev);
                struct videomode vm;
  
 -              if (videomode_from_timing(timings, &vm, i))
 +              if (videomode_from_timings(timings, &vm, i))
                        break;
  
                drm_display_mode_from_videomode(&vm, mode);
@@@ -305,7 -305,7 +305,7 @@@ static const struct tilcdc_module_ops p
   */
  
  /* maybe move this somewhere common if it is needed by other outputs? */
- static struct tilcdc_panel_info * of_get_panel_info(struct device_node *np)
+ static struct tilcdc_panel_info *of_get_panel_info(struct device_node *np)
  {
        struct device_node *info_np;
        struct tilcdc_panel_info *info;
@@@ -413,7 -413,6 +413,6 @@@ static struct of_device_id panel_of_mat
                { .compatible = "ti,tilcdc,panel", },
                { },
  };
- MODULE_DEVICE_TABLE(of, panel_of_match);
  
  struct platform_driver panel_driver = {
        .probe = panel_probe,
diff --combined drivers/video/Kconfig
index 76be61701c9766023c36c4184c06776bed26ef74,3e0e3f088686a547a535920f2a7d48a45a6c03a8..ab5ba3d49e1445d3e30b67be73471a103b90f70d
@@@ -21,6 -21,8 +21,8 @@@ source "drivers/gpu/vga/Kconfig
  
  source "drivers/gpu/drm/Kconfig"
  
+ source "drivers/gpu/host1x/Kconfig"
  config VGASTATE
         tristate
         default n
@@@ -31,8 -33,26 +33,8 @@@ config VIDEO_OUTPUT_CONTRO
          This framework adds support for low-level control of the video 
          output switch.
  
 -config DISPLAY_TIMING
 -       bool
 -
 -config VIDEOMODE
 -       bool
 -
 -config OF_DISPLAY_TIMING
 -      bool "Enable device tree display timing support"
 -      depends on OF
 -      select DISPLAY_TIMING
 -      help
 -        helper to parse display timings from the devicetree
 -
 -config OF_VIDEOMODE
 -      bool "Enable device tree videomode support"
 -      depends on OF
 -      select VIDEOMODE
 -      select OF_DISPLAY_TIMING
 -      help
 -        helper to get videomodes from the devicetree
 +config VIDEOMODE_HELPERS
 +      bool
  
  config HDMI
        bool
@@@ -194,6 -214,14 +196,6 @@@ config FB_SYS_FOP
         depends on FB
         default n
  
 -config FB_WMT_GE_ROPS
 -      tristate
 -      depends on FB
 -      default n
 -      ---help---
 -        Include functions for accelerated rectangle filling and area
 -        copying using WonderMedia Graphics Engine operations.
 -
  config FB_DEFERRED_IO
        bool
        depends on FB
@@@ -1771,37 -1799,22 +1773,37 @@@ config FB_AU120
          option au1200fb:panel=<name>.
  
  config FB_VT8500
 -      bool "VT8500 LCD Driver"
 +      bool "VIA VT8500 framebuffer support"
        depends on (FB = y) && ARM && ARCH_VT8500
 -      select FB_WMT_GE_ROPS
 +      select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
 +      select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
        select FB_SYS_IMAGEBLIT
 +      select FB_MODE_HELPERS
 +      select VIDEOMODE_HELPERS
        help
          This is the framebuffer driver for VIA VT8500 integrated LCD
          controller.
  
  config FB_WM8505
 -      bool "WM8505 frame buffer support"
 +      bool "Wondermedia WM8xxx-series frame buffer support"
        depends on (FB = y) && ARM && ARCH_VT8500
 -      select FB_WMT_GE_ROPS
 +      select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
 +      select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
        select FB_SYS_IMAGEBLIT
 +      select FB_MODE_HELPERS
 +      select VIDEOMODE_HELPERS
 +      help
 +        This is the framebuffer driver for WonderMedia WM8xxx-series
 +        integrated LCD controller. This driver covers the WM8505, WM8650
 +        and WM8850 SoCs.
 +
 +config FB_WMT_GE_ROPS
 +      bool "VT8500/WM8xxx accelerated raster ops support"
 +      depends on (FB = y) && (FB_VT8500 || FB_WM8505)
 +      default n
        help
 -        This is the framebuffer driver for WonderMedia WM8505/WM8650
 -        integrated LCD controller.
 +        This adds support for accelerated raster operations on the
 +        VIA VT8500 and Wondermedia 85xx series SoCs.
  
  source "drivers/video/geode/Kconfig"
  
@@@ -2266,7 -2279,7 +2268,7 @@@ config XEN_FBDEV_FRONTEN
        select FB_SYS_IMAGEBLIT
        select FB_SYS_FOPS
        select FB_DEFERRED_IO
 -      select INPUT_XEN_KBDDEV_FRONTEND
 +      select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC
        select XEN_XENBUS_FRONTEND
        default y
        help
@@@ -2440,15 -2453,6 +2442,15 @@@ config FB_PUV3_UNIGF
          Choose this option if you want to use the Unigfx device as a
          framebuffer device. Without the support of PCI & AGP.
  
 +config FB_HYPERV
 +      tristate "Microsoft Hyper-V Synthetic Video support"
 +      depends on FB && HYPERV
 +      select FB_CFB_FILLRECT
 +      select FB_CFB_COPYAREA
 +      select FB_CFB_IMAGEBLIT
 +      help
 +        This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
 +
  source "drivers/video/omap/Kconfig"
  source "drivers/video/omap2/Kconfig"
  source "drivers/video/exynos/Kconfig"
diff --combined drivers/video/fbmem.c
index dcb669eb453299d0c7004e2353ae0e266bd368eb,ccd44b0c77a0708a584525a0d075bd5d53553922..098bfc64cfb93561e8fb0b9817531eb7412d5a27
@@@ -1373,12 -1373,15 +1373,12 @@@ fb_mmap(struct file *file, struct vm_ar
  {
        struct fb_info *info = file_fb_info(file);
        struct fb_ops *fb;
 -      unsigned long off;
 +      unsigned long mmio_pgoff;
        unsigned long start;
        u32 len;
  
        if (!info)
                return -ENODEV;
 -      if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
 -              return -EINVAL;
 -      off = vma->vm_pgoff << PAGE_SHIFT;
        fb = info->fbops;
        if (!fb)
                return -ENODEV;
                return res;
        }
  
 -      /* frame buffer memory */
 +      /*
 +       * Ugh. This can be either the frame buffer mapping, or
 +       * if pgoff points past it, the mmio mapping.
 +       */
        start = info->fix.smem_start;
 -      len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
 -      if (off >= len) {
 -              /* memory mapped io */
 -              off -= len;
 +      len = info->fix.smem_len;
 +      mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
 +      if (vma->vm_pgoff >= mmio_pgoff) {
                if (info->var.accel_flags) {
                        mutex_unlock(&info->mm_lock);
                        return -EINVAL;
                }
 +
 +              vma->vm_pgoff -= mmio_pgoff;
                start = info->fix.mmio_start;
 -              len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
 +              len = info->fix.mmio_len;
        }
        mutex_unlock(&info->mm_lock);
 -      start &= PAGE_MASK;
 -      if ((vma->vm_end - vma->vm_start + off) > len)
 -              return -EINVAL;
 -      off += start;
 -      vma->vm_pgoff = off >> PAGE_SHIFT;
 -      /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by io_remap_pfn_range()*/
 +
        vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
 -      fb_pgprotect(file, vma, off);
 -      if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
 -                           vma->vm_end - vma->vm_start, vma->vm_page_prot))
 -              return -EAGAIN;
 -      return 0;
 +      fb_pgprotect(file, vma, start);
 +
 +      return vm_iomap_memory(vma, start, len);
  }
  
  static int
@@@ -1639,6 -1645,11 +1639,11 @@@ static int do_register_framebuffer(stru
        if (!fb_info->modelist.prev || !fb_info->modelist.next)
                INIT_LIST_HEAD(&fb_info->modelist);
  
+       if (fb_info->skip_vt_switch)
+               pm_vt_switch_required(fb_info->dev, false);
+       else
+               pm_vt_switch_required(fb_info->dev, true);
        fb_var_to_videomode(&mode, &fb_info->var);
        fb_add_videomode(&mode, &fb_info->modelist);
        registered_fb[i] = fb_info;
@@@ -1673,6 -1684,8 +1678,8 @@@ static int do_unregister_framebuffer(st
        if (ret)
                return -EINVAL;
  
+       pm_vt_switch_unregister(fb_info->dev);
        unlink_framebuffer(fb_info);
        if (fb_info->pixmap.addr &&
            (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
index 717f13a9335174f502a7fbc7599fcd060ae9d583,ff00d1d8bd2649348f2e1f123933f05dfe0971e9..c84bb8a4d0c4c1b7b1433fb97f6e55796d067434
@@@ -1101,25 -1101,41 +1101,25 @@@ static int omapfb_mmap(struct fb_info *
        struct omapfb_info *ofbi = FB2OFB(fbi);
        struct fb_fix_screeninfo *fix = &fbi->fix;
        struct omapfb2_mem_region *rg;
 -      unsigned long off;
        unsigned long start;
        u32 len;
 -      int r = -EINVAL;
 -
 -      if (vma->vm_end - vma->vm_start == 0)
 -              return 0;
 -      if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
 -              return -EINVAL;
 -      off = vma->vm_pgoff << PAGE_SHIFT;
 +      int r;
  
        rg = omapfb_get_mem_region(ofbi->region);
  
        start = omapfb_get_region_paddr(ofbi);
        len = fix->smem_len;
 -      if (off >= len)
 -              goto error;
 -      if ((vma->vm_end - vma->vm_start + off) > len)
 -              goto error;
 -
 -      off += start;
  
 -      DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
 +      DBG("user mmap region start %lx, len %d, off %lx\n", start, len,
 +                      vma->vm_pgoff << PAGE_SHIFT);
  
 -      vma->vm_pgoff = off >> PAGE_SHIFT;
 -      /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
        vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
        vma->vm_ops = &mmap_user_ops;
        vma->vm_private_data = rg;
 -      if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
 -                             vma->vm_end - vma->vm_start,
 -                             vma->vm_page_prot)) {
 -              r = -EAGAIN;
 +
 +      r = vm_iomap_memory(vma, start, len);
 +      if (r)
                goto error;
 -      }
  
        /* vm_ops.open won't be called for mmap itself. */
        atomic_inc(&rg->map_count);
  
        return 0;
  
 - error:
 +error:
        omapfb_put_mem_region(ofbi->region);
  
        return r;
@@@ -2372,7 -2388,7 +2372,7 @@@ static int omapfb_init_connections(stru
                struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
                struct omap_dss_output *out = dssdev->output;
  
-               mgr = omap_dss_get_overlay_manager(dssdev->channel);
+               mgr = omap_dss_get_overlay_manager(out->dispc_channel);
  
                if (!mgr || !out)
                        continue;
        return 0;
  }
  
- static int __init omapfb_probe(struct platform_device *pdev)
+ static int omapfb_probe(struct platform_device *pdev)
  {
        struct omapfb2_device *fbdev = NULL;
        int r = 0;
  
        if (fbdev->num_displays == 0) {
                dev_err(&pdev->dev, "no displays\n");
-               r = -EINVAL;
+               r = -EPROBE_DEFER;
                goto cleanup;
        }
  
@@@ -2579,6 -2595,7 +2579,7 @@@ static int __exit omapfb_remove(struct 
  }
  
  static struct platform_driver omapfb_driver = {
+       .probe          = omapfb_probe,
        .remove         = __exit_p(omapfb_remove),
        .driver         = {
                .name   = "omapfb",
        },
  };
  
- static int __init omapfb_init(void)
- {
-       DBG("omapfb_init\n");
-       if (platform_driver_probe(&omapfb_driver, omapfb_probe)) {
-               printk(KERN_ERR "failed to register omapfb driver\n");
-               return -ENODEV;
-       }
-       return 0;
- }
- static void __exit omapfb_exit(void)
- {
-       DBG("omapfb_exit\n");
-       platform_driver_unregister(&omapfb_driver);
- }
  module_param_named(mode, def_mode, charp, 0);
  module_param_named(vram, def_vram, charp, 0);
  module_param_named(rotate, def_rotate, int, 0);
  module_param_named(vrfb, def_vrfb, bool, 0);
  module_param_named(mirror, def_mirror, bool, 0);
  
- /* late_initcall to let panel/ctrl drivers loaded first.
-  * I guess better option would be a more dynamic approach,
-  * so that omapfb reacts to new panels when they are loaded */
- late_initcall(omapfb_init);
- /*module_init(omapfb_init);*/
- module_exit(omapfb_exit);
+ module_platform_driver(omapfb_driver);
  
  MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
  MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
diff --combined include/drm/drmP.h
index 60c33f14408f31499a43dd51464d7578206d4370,f1ce786736e422b401cc74dce7d241faf36354d6..61196592152e09a3913d1989cd847a8f9457664b
@@@ -1022,7 -1022,7 +1022,7 @@@ struct drm_info_list 
  struct drm_info_node {
        struct list_head list;
        struct drm_minor *minor;
 -      struct drm_info_list *info_ent;
 +      const struct drm_info_list *info_ent;
        struct dentry *dent;
  };
  
@@@ -1546,7 -1546,8 +1546,7 @@@ extern struct idr drm_minors_idr
  extern struct drm_local_map *drm_getsarea(struct drm_device *dev);
  
                                /* Proc support (drm_proc.h) */
 -extern int drm_proc_init(struct drm_minor *minor, int minor_id,
 -                       struct proc_dir_entry *root);
 +extern int drm_proc_init(struct drm_minor *minor, struct proc_dir_entry *root);
  extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root);
  
                                /* Debugfs support */
@@@ -1592,9 -1593,8 +1592,8 @@@ extern void drm_prime_gem_destroy(struc
  
  void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
  void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
- int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
- int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
- void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
+ int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
+ void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
  
  int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj);
  int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf,
index bfc47e0de81c6ad52e50050dd2d2acdb6c746112,e96b9546c4c6ec68e26300c562bfd5620ba77e45..5951e3f38878398d36eef96e0482ebae15bf8409
@@@ -171,22 -171,6 +171,22 @@@ static inline void sg_mark_end(struct s
        sg->page_link &= ~0x01;
  }
  
 +/**
 + * sg_unmark_end - Undo setting the end of the scatterlist
 + * @sg:                SG entryScatterlist
 + *
 + * Description:
 + *   Removes the termination marker from the given entry of the scatterlist.
 + *
 + **/
 +static inline void sg_unmark_end(struct scatterlist *sg)
 +{
 +#ifdef CONFIG_DEBUG_SG
 +      BUG_ON(sg->sg_magic != SG_MAGIC);
 +#endif
 +      sg->page_link &= ~0x02;
 +}
 +
  /**
   * sg_phys - Return physical address of an sg entry
   * @sg:            SG entry
@@@ -251,13 -235,13 +251,13 @@@ size_t sg_copy_to_buffer(struct scatter
   * sg page iterator
   *
   * Iterates over sg entries page-by-page.  On each successful iteration,
-  * @piter->page points to the current page, @piter->sg to the sg holding this
-  * page and @piter->sg_pgoffset to the page's page offset within the sg. The
-  * iteration will stop either when a maximum number of sg entries was reached
-  * or a terminating sg (sg_last(sg) == true) was reached.
+  * you can call sg_page_iter_page(@piter) and sg_page_iter_dma_address(@piter)
+  * to get the current page and its dma address. @piter->sg will point to the
+  * sg holding this page and @piter->sg_pgoffset to the page's page offset
+  * within the sg. The iteration will stop either when a maximum number of sg
+  * entries was reached or a terminating sg (sg_last(sg) == true) was reached.
   */
  struct sg_page_iter {
-       struct page             *page;          /* current page */
        struct scatterlist      *sg;            /* sg holding the page */
        unsigned int            sg_pgoffset;    /* page offset within the sg */
  
@@@ -271,6 -255,24 +271,24 @@@ bool __sg_page_iter_next(struct sg_page
  void __sg_page_iter_start(struct sg_page_iter *piter,
                          struct scatterlist *sglist, unsigned int nents,
                          unsigned long pgoffset);
+ /**
+  * sg_page_iter_page - get the current page held by the page iterator
+  * @piter:    page iterator holding the page
+  */
+ static inline struct page *sg_page_iter_page(struct sg_page_iter *piter)
+ {
+       return nth_page(sg_page(piter->sg), piter->sg_pgoffset);
+ }
+ /**
+  * sg_page_iter_dma_address - get the dma address of the current page held by
+  * the page iterator.
+  * @piter:    page iterator holding the page
+  */
+ static inline dma_addr_t sg_page_iter_dma_address(struct sg_page_iter *piter)
+ {
+       return sg_dma_address(piter->sg) + (piter->sg_pgoffset << PAGE_SHIFT);
+ }
  
  /**
   * for_each_sg_page - iterate over the pages of the given sg list