]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next-queued
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 18 Jan 2016 07:04:23 +0000 (08:04 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 18 Jan 2016 07:18:16 +0000 (08:18 +0100)
Pull in Dave's drm-next pull request to have a clean base for 4.6.
Also, we need the various atomic state extensions Maarten recently
created.

Conflicts are just adjacent changes that all resolve to nothing in git
diff.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
1  2 
Documentation/DocBook/gpu.tmpl
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_sprite.c

index 0061f22d126d83afddf9c4dc7ddd26601117f88a,a8669330b456eff026895af70af1121559998d2e..351e801cead9dae986cd8d3aa0f85b0002479197
      <para>
        [Insert diagram of typical DRM stack here]
      </para>
+   <sect1>
+     <title>Style Guidelines</title>
+     <para>
+       For consistency this documentation uses American English. Abbreviations
+       are written as all-uppercase, for example: DRM, KMS, IOCTL, CRTC, and so
+       on. To aid in reading, documentations make full use of the markup
+       characters kerneldoc provides: @parameter for function parameters, @member
+       for structure members, &amp;structure to reference structures and
+       function() for functions. These all get automatically hyperlinked if
+       kerneldoc for the referenced objects exists. When referencing entries in
+       function vtables please use -&gt;vfunc(). Note that kerneldoc does
+       not support referencing struct members directly, so please add a reference
+       to the vtable struct somewhere in the same paragraph or at least section.
+     </para>
+     <para>
+       Except in special situations (to separate locked from unlocked variants)
+       locking requirements for functions aren't documented in the kerneldoc.
+       Instead locking should be check at runtime using e.g.
+       <code>WARN_ON(!mutex_is_locked(...));</code>. Since it's much easier to
+       ignore documentation than runtime noise this provides more value. And on
+       top of that runtime checks do need to be updated when the locking rules
+       change, increasing the chances that they're correct. Within the
+       documentation the locking rules should be explained in the relevant
+       structures: Either in the comment for the lock explaining what it
+       protects, or data fields need a note about which lock protects them, or
+       both.
+     </para>
+     <para>
+       Functions which have a non-<code>void</code> return value should have a
+       section called "Returns" explaining the expected return values in
+       different cases and their meanings. Currently there's no consensus whether
+       that section name should be all upper-case or not, and whether it should
+       end in a colon or not. Go with the file-local style. Other common section
+       names are "Notes" with information for dangerous or tricky corner cases,
+       and "FIXME" where the interface could be cleaned up.
+     </para>
+   </sect1>
    </chapter>
  
    <!-- Internals -->
@@@ -946,12 -983,10 +983,10 @@@ int max_width, max_height;</synopsis
      <sect2>
        <title>Atomic Mode Setting Function Reference</title>
  !Edrivers/gpu/drm/drm_atomic.c
+ !Idrivers/gpu/drm/drm_atomic.c
      </sect2>
      <sect2>
-       <title>Frame Buffer Creation</title>
-       <synopsis>struct drm_framebuffer *(*fb_create)(struct drm_device *dev,
-                                    struct drm_file *file_priv,
-                                    struct drm_mode_fb_cmd2 *mode_cmd);</synopsis>
+       <title>Frame Buffer Abstraction</title>
        <para>
          Frame buffers are abstract memory objects that provide a source of
          pixels to scanout to a CRTC. Applications explicitly request the
        handles, e.g. vmwgfx directly exposes special TTM handles to userspace
        and so expects TTM handles in the create ioctl and not GEM handles.
        </para>
-       <para>
-         Drivers must first validate the requested frame buffer parameters passed
-         through the mode_cmd argument. In particular this is where invalid
-         sizes, pixel formats or pitches can be caught.
-       </para>
-       <para>
-         If the parameters are deemed valid, drivers then create, initialize and
-         return an instance of struct <structname>drm_framebuffer</structname>.
-         If desired the instance can be embedded in a larger driver-specific
-       structure. Drivers must fill its <structfield>width</structfield>,
-       <structfield>height</structfield>, <structfield>pitches</structfield>,
-         <structfield>offsets</structfield>, <structfield>depth</structfield>,
-         <structfield>bits_per_pixel</structfield> and
-         <structfield>pixel_format</structfield> fields from the values passed
-         through the <parameter>drm_mode_fb_cmd2</parameter> argument. They
-         should call the <function>drm_helper_mode_fill_fb_struct</function>
-         helper function to do so.
-       </para>
-       <para>
-       The initialization of the new framebuffer instance is finalized with a
-       call to <function>drm_framebuffer_init</function> which takes a pointer
-       to DRM frame buffer operations (struct
-       <structname>drm_framebuffer_funcs</structname>). Note that this function
-       publishes the framebuffer and so from this point on it can be accessed
-       concurrently from other threads. Hence it must be the last step in the
-       driver's framebuffer initialization sequence. Frame buffer operations
-       are
-         <itemizedlist>
-           <listitem>
-             <synopsis>int (*create_handle)(struct drm_framebuffer *fb,
-                    struct drm_file *file_priv, unsigned int *handle);</synopsis>
-             <para>
-               Create a handle to the frame buffer underlying memory object. If
-               the frame buffer uses a multi-plane format, the handle will
-               reference the memory object associated with the first plane.
-             </para>
-             <para>
-               Drivers call <function>drm_gem_handle_create</function> to create
-               the handle.
-             </para>
-           </listitem>
-           <listitem>
-             <synopsis>void (*destroy)(struct drm_framebuffer *framebuffer);</synopsis>
-             <para>
-               Destroy the frame buffer object and frees all associated
-               resources. Drivers must call
-               <function>drm_framebuffer_cleanup</function> to free resources
-               allocated by the DRM core for the frame buffer object, and must
-               make sure to unreference all memory objects associated with the
-               frame buffer. Handles created by the
-               <methodname>create_handle</methodname> operation are released by
-               the DRM core.
-             </para>
-           </listitem>
-           <listitem>
-             <synopsis>int (*dirty)(struct drm_framebuffer *framebuffer,
-            struct drm_file *file_priv, unsigned flags, unsigned color,
-            struct drm_clip_rect *clips, unsigned num_clips);</synopsis>
-             <para>
-               This optional operation notifies the driver that a region of the
-               frame buffer has changed in response to a DRM_IOCTL_MODE_DIRTYFB
-               ioctl call.
-             </para>
-           </listitem>
-         </itemizedlist>
-       </para>
        <para>
        The lifetime of a drm framebuffer is controlled with a reference count,
        drivers can grab additional references with
            pointer to CRTC functions.
          </para>
        </sect3>
-       <sect3 id="drm-kms-crtcops">
-         <title>CRTC Operations</title>
-         <sect4>
-           <title>Set Configuration</title>
-           <synopsis>int (*set_config)(struct drm_mode_set *set);</synopsis>
-           <para>
-             Apply a new CRTC configuration to the device. The configuration
-             specifies a CRTC, a frame buffer to scan out from, a (x,y) position in
-             the frame buffer, a display mode and an array of connectors to drive
-             with the CRTC if possible.
-           </para>
-           <para>
-             If the frame buffer specified in the configuration is NULL, the driver
-             must detach all encoders connected to the CRTC and all connectors
-             attached to those encoders and disable them.
-           </para>
-           <para>
-             This operation is called with the mode config lock held.
-           </para>
-           <note><para>
-           Note that the drm core has no notion of restoring the mode setting
-           state after resume, since all resume handling is in the full
-           responsibility of the driver. The common mode setting helper library
-           though provides a helper which can be used for this:
-           <function>drm_helper_resume_force_mode</function>.
-           </para></note>
-         </sect4>
-         <sect4>
-           <title>Page Flipping</title>
-           <synopsis>int (*page_flip)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
-                    struct drm_pending_vblank_event *event);</synopsis>
-           <para>
-             Schedule a page flip to the given frame buffer for the CRTC. This
-             operation is called with the mode config mutex held.
-           </para>
-           <para>
-             Page flipping is a synchronization mechanism that replaces the frame
-             buffer being scanned out by the CRTC with a new frame buffer during
-             vertical blanking, avoiding tearing. When an application requests a page
-             flip the DRM core verifies that the new frame buffer is large enough to
-             be scanned out by  the CRTC in the currently configured mode and then
-             calls the CRTC <methodname>page_flip</methodname> operation with a
-             pointer to the new frame buffer.
-           </para>
-           <para>
-             The <methodname>page_flip</methodname> operation schedules a page flip.
-             Once any pending rendering targeting the new frame buffer has
-             completed, the CRTC will be reprogrammed to display that frame buffer
-             after the next vertical refresh. The operation must return immediately
-             without waiting for rendering or page flip to complete and must block
-             any new rendering to the frame buffer until the page flip completes.
-           </para>
-           <para>
-             If a page flip can be successfully scheduled the driver must set the
-             <code>drm_crtc-&gt;fb</code> field to the new framebuffer pointed to
-             by <code>fb</code>. This is important so that the reference counting
-             on framebuffers stays balanced.
-           </para>
-           <para>
-             If a page flip is already pending, the
-             <methodname>page_flip</methodname> operation must return
-             -<errorname>EBUSY</errorname>.
-           </para>
-           <para>
-             To synchronize page flip to vertical blanking the driver will likely
-             need to enable vertical blanking interrupts. It should call
-             <function>drm_vblank_get</function> for that purpose, and call
-             <function>drm_vblank_put</function> after the page flip completes.
-           </para>
-           <para>
-             If the application has requested to be notified when page flip completes
-             the <methodname>page_flip</methodname> operation will be called with a
-             non-NULL <parameter>event</parameter> argument pointing to a
-             <structname>drm_pending_vblank_event</structname> instance. Upon page
-             flip completion the driver must call <methodname>drm_send_vblank_event</methodname>
-             to fill in the event and send to wake up any waiting processes.
-             This can be performed with
-             <programlisting><![CDATA[
-             spin_lock_irqsave(&dev->event_lock, flags);
-             ...
-             drm_send_vblank_event(dev, pipe, event);
-             spin_unlock_irqrestore(&dev->event_lock, flags);
-             ]]></programlisting>
-           </para>
-           <note><para>
-             FIXME: Could drivers that don't need to wait for rendering to complete
-             just add the event to <literal>dev-&gt;vblank_event_list</literal> and
-             let the DRM core handle everything, as for "normal" vertical blanking
-             events?
-           </para></note>
-           <para>
-             While waiting for the page flip to complete, the
-             <literal>event-&gt;base.link</literal> list head can be used freely by
-             the driver to store the pending event in a driver-specific list.
-           </para>
-           <para>
-             If the file handle is closed before the event is signaled, drivers must
-             take care to destroy the event in their
-             <methodname>preclose</methodname> operation (and, if needed, call
-             <function>drm_vblank_put</function>).
-           </para>
-         </sect4>
-         <sect4>
-           <title>Miscellaneous</title>
-           <itemizedlist>
-             <listitem>
-               <synopsis>void (*set_property)(struct drm_crtc *crtc,
-                      struct drm_property *property, uint64_t value);</synopsis>
-               <para>
-                 Set the value of the given CRTC property to
-                 <parameter>value</parameter>. See <xref linkend="drm-kms-properties"/>
-                 for more information about properties.
-               </para>
-             </listitem>
-             <listitem>
-               <synopsis>void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
-                         uint32_t start, uint32_t size);</synopsis>
-               <para>
-                 Apply a gamma table to the device. The operation is optional.
-               </para>
-             </listitem>
-             <listitem>
-               <synopsis>void (*destroy)(struct drm_crtc *crtc);</synopsis>
-               <para>
-                 Destroy the CRTC when not needed anymore. See
-                 <xref linkend="drm-kms-init"/>.
-               </para>
-             </listitem>
-           </itemizedlist>
-         </sect4>
-       </sect3>
      </sect2>
      <sect2>
        <title>Planes (struct <structname>drm_plane</structname>)</title>
          <listitem>
          DRM_PLANE_TYPE_PRIMARY represents a "main" plane for a CRTC.  Primary
          planes are the planes operated upon by CRTC modesetting and flipping
-         operations described in <xref linkend="drm-kms-crtcops"/>.
+       operations described in the page_flip hook in <structname>drm_crtc_funcs</structname>.
          </listitem>
          <listitem>
          DRM_PLANE_TYPE_CURSOR represents a "cursor" plane for a CRTC.  Cursor
            primary plane with standard capabilities.
          </para>
        </sect3>
-       <sect3>
-         <title>Plane Operations</title>
-         <itemizedlist>
-           <listitem>
-             <synopsis>int (*update_plane)(struct drm_plane *plane, struct drm_crtc *crtc,
-                         struct drm_framebuffer *fb, int crtc_x, int crtc_y,
-                         unsigned int crtc_w, unsigned int crtc_h,
-                         uint32_t src_x, uint32_t src_y,
-                         uint32_t src_w, uint32_t src_h);</synopsis>
-             <para>
-               Enable and configure the plane to use the given CRTC and frame buffer.
-             </para>
-             <para>
-               The source rectangle in frame buffer memory coordinates is given by
-               the <parameter>src_x</parameter>, <parameter>src_y</parameter>,
-               <parameter>src_w</parameter> and <parameter>src_h</parameter>
-               parameters (as 16.16 fixed point values). Devices that don't support
-               subpixel plane coordinates can ignore the fractional part.
-             </para>
-             <para>
-               The destination rectangle in CRTC coordinates is given by the
-               <parameter>crtc_x</parameter>, <parameter>crtc_y</parameter>,
-               <parameter>crtc_w</parameter> and <parameter>crtc_h</parameter>
-               parameters (as integer values). Devices scale the source rectangle to
-               the destination rectangle. If scaling is not supported, and the source
-               rectangle size doesn't match the destination rectangle size, the
-               driver must return a -<errorname>EINVAL</errorname> error.
-             </para>
-           </listitem>
-           <listitem>
-             <synopsis>int (*disable_plane)(struct drm_plane *plane);</synopsis>
-             <para>
-               Disable the plane. The DRM core calls this method in response to a
-               DRM_IOCTL_MODE_SETPLANE ioctl call with the frame buffer ID set to 0.
-               Disabled planes must not be processed by the CRTC.
-             </para>
-           </listitem>
-           <listitem>
-             <synopsis>void (*destroy)(struct drm_plane *plane);</synopsis>
-             <para>
-               Destroy the plane when not needed anymore. See
-               <xref linkend="drm-kms-init"/>.
-             </para>
-           </listitem>
-         </itemizedlist>
-       </sect3>
      </sect2>
      <sect2>
        <title>Encoders (struct <structname>drm_encoder</structname>)</title>
            encoders they want to use to a CRTC.
          </para>
        </sect3>
-       <sect3>
-         <title>Encoder Operations</title>
-         <itemizedlist>
-           <listitem>
-             <synopsis>void (*destroy)(struct drm_encoder *encoder);</synopsis>
-             <para>
-               Called to destroy the encoder when not needed anymore. See
-               <xref linkend="drm-kms-init"/>.
-             </para>
-           </listitem>
-           <listitem>
-             <synopsis>void (*set_property)(struct drm_plane *plane,
-                      struct drm_property *property, uint64_t value);</synopsis>
-             <para>
-               Set the value of the given plane property to
-               <parameter>value</parameter>. See <xref linkend="drm-kms-properties"/>
-               for more information about properties.
-             </para>
-           </listitem>
-         </itemizedlist>
-       </sect3>
      </sect2>
      <sect2>
        <title>Connectors (struct <structname>drm_connector</structname>)</title>
              connector_status_unknown.
            </para>
          </sect4>
-         <sect4>
-           <title>Miscellaneous</title>
-           <itemizedlist>
-             <listitem>
-               <synopsis>void (*set_property)(struct drm_connector *connector,
-                      struct drm_property *property, uint64_t value);</synopsis>
-               <para>
-                 Set the value of the given connector property to
-                 <parameter>value</parameter>. See <xref linkend="drm-kms-properties"/>
-                 for more information about properties.
-               </para>
-             </listitem>
-             <listitem>
-               <synopsis>void (*destroy)(struct drm_connector *connector);</synopsis>
-               <para>
-                 Destroy the connector when not needed anymore. See
-                 <xref linkend="drm-kms-init"/>.
-               </para>
-             </listitem>
-           </itemizedlist>
-         </sect4>
        </sect3>
      </sect2>
      <sect2>
@@@ -1829,462 -1578,6 +1578,6 @@@ void intel_crt_init(struct drm_device *
        To use it, a driver must provide bottom functions for all of the three KMS
        entities.
      </para>
-     <sect2>
-       <title>Helper Functions</title>
-       <itemizedlist>
-         <listitem>
-           <synopsis>int drm_crtc_helper_set_config(struct drm_mode_set *set);</synopsis>
-           <para>
-             The <function>drm_crtc_helper_set_config</function> helper function
-             is a CRTC <methodname>set_config</methodname> implementation. It
-             first tries to locate the best encoder for each connector by calling
-             the connector <methodname>best_encoder</methodname> helper
-             operation.
-           </para>
-           <para>
-             After locating the appropriate encoders, the helper function will
-             call the <methodname>mode_fixup</methodname> encoder and CRTC helper
-             operations to adjust the requested mode, or reject it completely in
-             which case an error will be returned to the application. If the new
-             configuration after mode adjustment is identical to the current
-             configuration the helper function will return without performing any
-             other operation.
-           </para>
-           <para>
-             If the adjusted mode is identical to the current mode but changes to
-             the frame buffer need to be applied, the
-             <function>drm_crtc_helper_set_config</function> function will call
-             the CRTC <methodname>mode_set_base</methodname> helper operation. If
-             the adjusted mode differs from the current mode, or if the
-             <methodname>mode_set_base</methodname> helper operation is not
-             provided, the helper function performs a full mode set sequence by
-             calling the <methodname>prepare</methodname>,
-             <methodname>mode_set</methodname> and
-             <methodname>commit</methodname> CRTC and encoder helper operations,
-             in that order.
-           </para>
-         </listitem>
-         <listitem>
-           <synopsis>void drm_helper_connector_dpms(struct drm_connector *connector, int mode);</synopsis>
-           <para>
-             The <function>drm_helper_connector_dpms</function> helper function
-             is a connector <methodname>dpms</methodname> implementation that
-             tracks power state of connectors. To use the function, drivers must
-             provide <methodname>dpms</methodname> helper operations for CRTCs
-             and encoders to apply the DPMS state to the device.
-           </para>
-           <para>
-             The mid-layer doesn't track the power state of CRTCs and encoders.
-             The <methodname>dpms</methodname> helper operations can thus be
-             called with a mode identical to the currently active mode.
-           </para>
-         </listitem>
-         <listitem>
-           <synopsis>int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
-                                             uint32_t maxX, uint32_t maxY);</synopsis>
-           <para>
-             The <function>drm_helper_probe_single_connector_modes</function> helper
-             function is a connector <methodname>fill_modes</methodname>
-             implementation that updates the connection status for the connector
-             and then retrieves a list of modes by calling the connector
-             <methodname>get_modes</methodname> helper operation.
-           </para>
-          <para>
-             If the helper operation returns no mode, and if the connector status
-             is connector_status_connected, standard VESA DMT modes up to
-             1024x768 are automatically added to the modes list by a call to
-             <function>drm_add_modes_noedid</function>.
-           </para>
-           <para>
-             The function then filters out modes larger than
-             <parameter>max_width</parameter> and <parameter>max_height</parameter>
-             if specified. It finally calls the optional connector
-             <methodname>mode_valid</methodname> helper operation for each mode in
-             the probed list to check whether the mode is valid for the connector.
-           </para>
-         </listitem>
-       </itemizedlist>
-     </sect2>
-     <sect2>
-       <title>CRTC Helper Operations</title>
-       <itemizedlist>
-         <listitem id="drm-helper-crtc-mode-fixup">
-           <synopsis>bool (*mode_fixup)(struct drm_crtc *crtc,
-                        const struct drm_display_mode *mode,
-                        struct drm_display_mode *adjusted_mode);</synopsis>
-           <para>
-             Let CRTCs adjust the requested mode or reject it completely. This
-             operation returns true if the mode is accepted (possibly after being
-             adjusted) or false if it is rejected.
-           </para>
-           <para>
-             The <methodname>mode_fixup</methodname> operation should reject the
-             mode if it can't reasonably use it. The definition of "reasonable"
-             is currently fuzzy in this context. One possible behaviour would be
-             to set the adjusted mode to the panel timings when a fixed-mode
-             panel is used with hardware capable of scaling. Another behaviour
-             would be to accept any input mode and adjust it to the closest mode
-             supported by the hardware (FIXME: This needs to be clarified).
-           </para>
-         </listitem>
-         <listitem>
-           <synopsis>int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
-                      struct drm_framebuffer *old_fb)</synopsis>
-           <para>
-             Move the CRTC on the current frame buffer (stored in
-             <literal>crtc-&gt;fb</literal>) to position (x,y). Any of the frame
-             buffer, x position or y position may have been modified.
-           </para>
-           <para>
-             This helper operation is optional. If not provided, the
-             <function>drm_crtc_helper_set_config</function> function will fall
-             back to the <methodname>mode_set</methodname> helper operation.
-           </para>
-           <note><para>
-             FIXME: Why are x and y passed as arguments, as they can be accessed
-             through <literal>crtc-&gt;x</literal> and
-             <literal>crtc-&gt;y</literal>?
-           </para></note>
-         </listitem>
-         <listitem>
-           <synopsis>void (*prepare)(struct drm_crtc *crtc);</synopsis>
-           <para>
-             Prepare the CRTC for mode setting. This operation is called after
-             validating the requested mode. Drivers use it to perform
-             device-specific operations required before setting the new mode.
-           </para>
-         </listitem>
-         <listitem>
-           <synopsis>int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
-                 struct drm_display_mode *adjusted_mode, int x, int y,
-                 struct drm_framebuffer *old_fb);</synopsis>
-           <para>
-             Set a new mode, position and frame buffer. Depending on the device
-             requirements, the mode can be stored internally by the driver and
-             applied in the <methodname>commit</methodname> operation, or
-             programmed to the hardware immediately.
-           </para>
-           <para>
-             The <methodname>mode_set</methodname> operation returns 0 on success
-           or a negative error code if an error occurs.
-           </para>
-         </listitem>
-         <listitem>
-           <synopsis>void (*commit)(struct drm_crtc *crtc);</synopsis>
-           <para>
-             Commit a mode. This operation is called after setting the new mode.
-             Upon return the device must use the new mode and be fully
-             operational.
-           </para>
-         </listitem>
-       </itemizedlist>
-     </sect2>
-     <sect2>
-       <title>Encoder Helper Operations</title>
-       <itemizedlist>
-         <listitem>
-           <synopsis>bool (*mode_fixup)(struct drm_encoder *encoder,
-                        const struct drm_display_mode *mode,
-                        struct drm_display_mode *adjusted_mode);</synopsis>
-           <para>
-             Let encoders adjust the requested mode or reject it completely. This
-             operation returns true if the mode is accepted (possibly after being
-             adjusted) or false if it is rejected. See the
-             <link linkend="drm-helper-crtc-mode-fixup">mode_fixup CRTC helper
-             operation</link> for an explanation of the allowed adjustments.
-           </para>
-         </listitem>
-         <listitem>
-           <synopsis>void (*prepare)(struct drm_encoder *encoder);</synopsis>
-           <para>
-             Prepare the encoder for mode setting. This operation is called after
-             validating the requested mode. Drivers use it to perform
-             device-specific operations required before setting the new mode.
-           </para>
-         </listitem>
-         <listitem>
-           <synopsis>void (*mode_set)(struct drm_encoder *encoder,
-                  struct drm_display_mode *mode,
-                  struct drm_display_mode *adjusted_mode);</synopsis>
-           <para>
-             Set a new mode. Depending on the device requirements, the mode can
-             be stored internally by the driver and applied in the
-             <methodname>commit</methodname> operation, or programmed to the
-             hardware immediately.
-           </para>
-         </listitem>
-         <listitem>
-           <synopsis>void (*commit)(struct drm_encoder *encoder);</synopsis>
-           <para>
-             Commit a mode. This operation is called after setting the new mode.
-             Upon return the device must use the new mode and be fully
-             operational.
-           </para>
-         </listitem>
-       </itemizedlist>
-     </sect2>
-     <sect2>
-       <title>Connector Helper Operations</title>
-       <itemizedlist>
-         <listitem>
-           <synopsis>struct drm_encoder *(*best_encoder)(struct drm_connector *connector);</synopsis>
-           <para>
-             Return a pointer to the best encoder for the connecter. Device that
-             map connectors to encoders 1:1 simply return the pointer to the
-             associated encoder. This operation is mandatory.
-           </para>
-         </listitem>
-         <listitem>
-           <synopsis>int (*get_modes)(struct drm_connector *connector);</synopsis>
-           <para>
-             Fill the connector's <structfield>probed_modes</structfield> list
-             by parsing EDID data with <function>drm_add_edid_modes</function>,
-             adding standard VESA DMT modes with <function>drm_add_modes_noedid</function>,
-             or calling <function>drm_mode_probed_add</function> directly for every
-             supported mode and return the number of modes it has detected. This
-             operation is mandatory.
-           </para>
-           <para>
-             Note that the caller function will automatically add standard VESA
-             DMT modes up to 1024x768 if the <methodname>get_modes</methodname>
-             helper operation returns no mode and if the connector status is
-             connector_status_connected. There is no need to call
-             <function>drm_add_edid_modes</function> manually in that case.
-           </para>
-           <para>
-             When adding modes manually the driver creates each mode with a call to
-             <function>drm_mode_create</function> and must fill the following fields.
-             <itemizedlist>
-               <listitem>
-                 <synopsis>__u32 type;</synopsis>
-                 <para>
-                   Mode type bitmask, a combination of
-                   <variablelist>
-                     <varlistentry>
-                       <term>DRM_MODE_TYPE_BUILTIN</term>
-                       <listitem><para>not used?</para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_TYPE_CLOCK_C</term>
-                       <listitem><para>not used?</para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_TYPE_CRTC_C</term>
-                       <listitem><para>not used?</para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>
-         DRM_MODE_TYPE_PREFERRED - The preferred mode for the connector
-                       </term>
-                       <listitem>
-                         <para>not used?</para>
-                       </listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_TYPE_DEFAULT</term>
-                       <listitem><para>not used?</para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_TYPE_USERDEF</term>
-                       <listitem><para>not used?</para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_TYPE_DRIVER</term>
-                       <listitem>
-                         <para>
-                           The mode has been created by the driver (as opposed to
-                           to user-created modes).
-                         </para>
-                       </listitem>
-                     </varlistentry>
-                   </variablelist>
-                   Drivers must set the DRM_MODE_TYPE_DRIVER bit for all modes they
-                   create, and set the DRM_MODE_TYPE_PREFERRED bit for the preferred
-                   mode.
-                 </para>
-               </listitem>
-               <listitem>
-                 <synopsis>__u32 clock;</synopsis>
-                 <para>Pixel clock frequency in kHz unit</para>
-               </listitem>
-               <listitem>
-                 <synopsis>__u16 hdisplay, hsync_start, hsync_end, htotal;
-     __u16 vdisplay, vsync_start, vsync_end, vtotal;</synopsis>
-                 <para>Horizontal and vertical timing information</para>
-                 <screen><![CDATA[
-              Active                 Front           Sync           Back
-              Region                 Porch                          Porch
-     <-----------------------><----------------><-------------><-------------->
-       //////////////////////|
-      ////////////////////// |
-     //////////////////////  |..................               ................
-                                                _______________
-     <----- [hv]display ----->
-     <------------- [hv]sync_start ------------>
-     <--------------------- [hv]sync_end --------------------->
-     <-------------------------------- [hv]total ----------------------------->
- ]]></screen>
-               </listitem>
-               <listitem>
-                 <synopsis>__u16 hskew;
-     __u16 vscan;</synopsis>
-                 <para>Unknown</para>
-               </listitem>
-               <listitem>
-                 <synopsis>__u32 flags;</synopsis>
-                 <para>
-                   Mode flags, a combination of
-                   <variablelist>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_PHSYNC</term>
-                       <listitem><para>
-                         Horizontal sync is active high
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_NHSYNC</term>
-                       <listitem><para>
-                         Horizontal sync is active low
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_PVSYNC</term>
-                       <listitem><para>
-                         Vertical sync is active high
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_NVSYNC</term>
-                       <listitem><para>
-                         Vertical sync is active low
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_INTERLACE</term>
-                       <listitem><para>
-                         Mode is interlaced
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_DBLSCAN</term>
-                       <listitem><para>
-                         Mode uses doublescan
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_CSYNC</term>
-                       <listitem><para>
-                         Mode uses composite sync
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_PCSYNC</term>
-                       <listitem><para>
-                         Composite sync is active high
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_NCSYNC</term>
-                       <listitem><para>
-                         Composite sync is active low
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_HSKEW</term>
-                       <listitem><para>
-                         hskew provided (not used?)
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_BCAST</term>
-                       <listitem><para>
-                         not used?
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_PIXMUX</term>
-                       <listitem><para>
-                         not used?
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_DBLCLK</term>
-                       <listitem><para>
-                         not used?
-                       </para></listitem>
-                     </varlistentry>
-                     <varlistentry>
-                       <term>DRM_MODE_FLAG_CLKDIV2</term>
-                       <listitem><para>
-                         ?
-                       </para></listitem>
-                     </varlistentry>
-                   </variablelist>
-                 </para>
-                 <para>
-                   Note that modes marked with the INTERLACE or DBLSCAN flags will be
-                   filtered out by
-                   <function>drm_helper_probe_single_connector_modes</function> if
-                   the connector's <structfield>interlace_allowed</structfield> or
-                   <structfield>doublescan_allowed</structfield> field is set to 0.
-                 </para>
-               </listitem>
-               <listitem>
-                 <synopsis>char name[DRM_DISPLAY_MODE_LEN];</synopsis>
-                 <para>
-                   Mode name. The driver must call
-                   <function>drm_mode_set_name</function> to fill the mode name from
-                   <structfield>hdisplay</structfield>,
-                   <structfield>vdisplay</structfield> and interlace flag after
-                   filling the corresponding fields.
-                 </para>
-               </listitem>
-             </itemizedlist>
-           </para>
-           <para>
-             The <structfield>vrefresh</structfield> value is computed by
-             <function>drm_helper_probe_single_connector_modes</function>.
-           </para>
-           <para>
-             When parsing EDID data, <function>drm_add_edid_modes</function> fills the
-             connector <structfield>display_info</structfield>
-             <structfield>width_mm</structfield> and
-             <structfield>height_mm</structfield> fields. When creating modes
-             manually the <methodname>get_modes</methodname> helper operation must
-             set the <structfield>display_info</structfield>
-             <structfield>width_mm</structfield> and
-             <structfield>height_mm</structfield> fields if they haven't been set
-             already (for instance at initialization time when a fixed-size panel is
-             attached to the connector). The mode <structfield>width_mm</structfield>
-             and <structfield>height_mm</structfield> fields are only used internally
-             during EDID parsing and should not be set when creating modes manually.
-           </para>
-         </listitem>
-         <listitem>
-           <synopsis>int (*mode_valid)(struct drm_connector *connector,
-                 struct drm_display_mode *mode);</synopsis>
-           <para>
-             Verify whether a mode is valid for the connector. Return MODE_OK for
-             supported modes and one of the enum drm_mode_status values (MODE_*)
-             for unsupported modes. This operation is optional.
-           </para>
-           <para>
-             As the mode rejection reason is currently not used beside for
-             immediately removing the unsupported mode, an implementation can
-             return MODE_BAD regardless of the exact reason why the mode is not
-             valid.
-           </para>
-           <note><para>
-             Note that the <methodname>mode_valid</methodname> helper operation is
-             only called for modes detected by the device, and
-             <emphasis>not</emphasis> for modes set by the user through the CRTC
-             <methodname>set_config</methodname> operation.
-           </para></note>
-         </listitem>
-       </itemizedlist>
-     </sect2>
      <sect2>
        <title>Atomic Modeset Helper Functions Reference</title>
        <sect3>
  !Edrivers/gpu/drm/drm_atomic_helper.c
      </sect2>
      <sect2>
-       <title>Modeset Helper Functions Reference</title>
- !Iinclude/drm/drm_crtc_helper.h
+       <title>Modeset Helper Reference for Common Vtables</title>
+ !Iinclude/drm/drm_modeset_helper_vtables.h
+ !Pinclude/drm/drm_modeset_helper_vtables.h overview
+     </sect2>
+     <sect2>
+       <title>Legacy CRTC/Modeset Helper Functions Reference</title>
  !Edrivers/gpu/drm/drm_crtc_helper.c
  !Pdrivers/gpu/drm/drm_crtc_helper.c overview
      </sect2>
@@@ -4015,92 -3312,6 +3312,6 @@@ int num_ioctls;</synopsis
        <sect2>
          <title>DPIO</title>
  !Pdrivers/gpu/drm/i915/i915_reg.h DPIO
-       <table id="dpiox2">
-         <title>Dual channel PHY (VLV/CHV/BXT)</title>
-         <tgroup cols="8">
-           <colspec colname="c0" />
-           <colspec colname="c1" />
-           <colspec colname="c2" />
-           <colspec colname="c3" />
-           <colspec colname="c4" />
-           <colspec colname="c5" />
-           <colspec colname="c6" />
-           <colspec colname="c7" />
-           <spanspec spanname="ch0" namest="c0" nameend="c3" />
-           <spanspec spanname="ch1" namest="c4" nameend="c7" />
-           <spanspec spanname="ch0pcs01" namest="c0" nameend="c1" />
-           <spanspec spanname="ch0pcs23" namest="c2" nameend="c3" />
-           <spanspec spanname="ch1pcs01" namest="c4" nameend="c5" />
-           <spanspec spanname="ch1pcs23" namest="c6" nameend="c7" />
-           <thead>
-             <row>
-               <entry spanname="ch0">CH0</entry>
-               <entry spanname="ch1">CH1</entry>
-             </row>
-           </thead>
-           <tbody valign="top" align="center">
-             <row>
-               <entry spanname="ch0">CMN/PLL/REF</entry>
-               <entry spanname="ch1">CMN/PLL/REF</entry>
-             </row>
-             <row>
-               <entry spanname="ch0pcs01">PCS01</entry>
-               <entry spanname="ch0pcs23">PCS23</entry>
-               <entry spanname="ch1pcs01">PCS01</entry>
-               <entry spanname="ch1pcs23">PCS23</entry>
-             </row>
-             <row>
-               <entry>TX0</entry>
-               <entry>TX1</entry>
-               <entry>TX2</entry>
-               <entry>TX3</entry>
-               <entry>TX0</entry>
-               <entry>TX1</entry>
-               <entry>TX2</entry>
-               <entry>TX3</entry>
-             </row>
-             <row>
-               <entry spanname="ch0">DDI0</entry>
-               <entry spanname="ch1">DDI1</entry>
-             </row>
-           </tbody>
-         </tgroup>
-       </table>
-       <table id="dpiox1">
-         <title>Single channel PHY (CHV/BXT)</title>
-         <tgroup cols="4">
-           <colspec colname="c0" />
-           <colspec colname="c1" />
-           <colspec colname="c2" />
-           <colspec colname="c3" />
-           <spanspec spanname="ch0" namest="c0" nameend="c3" />
-           <spanspec spanname="ch0pcs01" namest="c0" nameend="c1" />
-           <spanspec spanname="ch0pcs23" namest="c2" nameend="c3" />
-           <thead>
-             <row>
-               <entry spanname="ch0">CH0</entry>
-             </row>
-           </thead>
-           <tbody valign="top" align="center">
-             <row>
-               <entry spanname="ch0">CMN/PLL/REF</entry>
-             </row>
-             <row>
-               <entry spanname="ch0pcs01">PCS01</entry>
-               <entry spanname="ch0pcs23">PCS23</entry>
-             </row>
-             <row>
-               <entry>TX0</entry>
-               <entry>TX1</entry>
-               <entry>TX2</entry>
-               <entry>TX3</entry>
-             </row>
-             <row>
-               <entry spanname="ch0">DDI2</entry>
-             </row>
-           </tbody>
-         </tgroup>
-       </table>
        </sect2>
  
        <sect2>
  !Pdrivers/gpu/drm/i915/intel_csr.c csr support for dmc
  !Idrivers/gpu/drm/i915/intel_csr.c
        </sect2>
 +      <sect2>
 +      <title>Video BIOS Table (VBT)</title>
 +!Pdrivers/gpu/drm/i915/intel_bios.c Video BIOS Table (VBT)
 +!Idrivers/gpu/drm/i915/intel_bios.c
 +!Idrivers/gpu/drm/i915/intel_bios.h
 +      </sect2>
      </sect1>
  
      <sect1>
  
    <chapter id="modes_of_use">
      <title>Modes of Use</title>
-   <sect1>
-     <title>Manual switching and manual power control</title>
+     <sect1>
+       <title>Manual switching and manual power control</title>
  !Pdrivers/gpu/vga/vga_switcheroo.c Manual switching and manual power control
-   </sect1>
-   <sect1>
-     <title>Driver power control</title>
+     </sect1>
+     <sect1>
+       <title>Driver power control</title>
  !Pdrivers/gpu/vga/vga_switcheroo.c Driver power control
-   </sect1>
+     </sect1>
    </chapter>
  
-   <chapter id="pubfunctions">
-     <title>Public functions</title>
+   <chapter id="api">
+     <title>API</title>
+     <sect1>
+       <title>Public functions</title>
  !Edrivers/gpu/vga/vga_switcheroo.c
-   </chapter>
-   <chapter id="pubstructures">
-     <title>Public structures</title>
+     </sect1>
+     <sect1>
+       <title>Public structures</title>
  !Finclude/linux/vga_switcheroo.h vga_switcheroo_handler
  !Finclude/linux/vga_switcheroo.h vga_switcheroo_client_ops
-   </chapter>
-   <chapter id="pubconstants">
-     <title>Public constants</title>
+     </sect1>
+     <sect1>
+       <title>Public constants</title>
  !Finclude/linux/vga_switcheroo.h vga_switcheroo_client_id
  !Finclude/linux/vga_switcheroo.h vga_switcheroo_state
-   </chapter>
-   <chapter id="privstructures">
-     <title>Private structures</title>
+     </sect1>
+     <sect1>
+       <title>Private structures</title>
  !Fdrivers/gpu/vga/vga_switcheroo.c vgasr_priv
  !Fdrivers/gpu/vga/vga_switcheroo.c vga_switcheroo_client
+     </sect1>
+   </chapter>
+   <chapter id="handlers">
+     <title>Handlers</title>
+     <sect1>
+       <title>apple-gmux Handler</title>
+ !Pdrivers/platform/x86/apple-gmux.c Overview
+ !Pdrivers/platform/x86/apple-gmux.c Interrupt
+       <sect2>
+         <title>Graphics mux</title>
+ !Pdrivers/platform/x86/apple-gmux.c Graphics mux
+       </sect2>
+       <sect2>
+         <title>Power control</title>
+ !Pdrivers/platform/x86/apple-gmux.c Power control
+       </sect2>
+       <sect2>
+         <title>Backlight control</title>
+ !Pdrivers/platform/x86/apple-gmux.c Backlight control
+       </sect2>
+     </sect1>
    </chapter>
  
  !Cdrivers/gpu/vga/vga_switcheroo.c
  !Cinclude/linux/vga_switcheroo.h
+ !Cdrivers/platform/x86/apple-gmux.c
  </part>
  
  </book>
index 44a896ce32e6cbb2abb943a061d5eba7638f4e6f,d70d96fe553bb65515540f048bdfe224f15a48e6..a0f5659032fc15baf0c44565e26aec5aa9343aaa
@@@ -406,6 -406,8 +406,8 @@@ static int i915_load_modeset_init(struc
        if (ret)
                goto cleanup_gem_stolen;
  
+       intel_setup_gmbus(dev);
        /* Important: The output setup functions called by modeset_init need
         * working irqs for e.g. gmbus and dp aux transfers. */
        intel_modeset_init(dev);
@@@ -455,6 -457,7 +457,7 @@@ cleanup_gem
  cleanup_irq:
        intel_guc_ucode_fini(dev);
        drm_irq_uninstall(dev);
+       intel_teardown_gmbus(dev);
  cleanup_gem_stolen:
        i915_gem_cleanup_stolen(dev);
  cleanup_vga_switcheroo:
@@@ -893,7 -896,6 +896,7 @@@ int i915_driver_load(struct drm_device 
        mutex_init(&dev_priv->sb_lock);
        mutex_init(&dev_priv->modeset_restore_lock);
        mutex_init(&dev_priv->av_mutex);
 +      mutex_init(&dev_priv->wm.wm_mutex);
  
        intel_pm_setup(dev);
  
  
        /* Try to make sure MCHBAR is enabled before poking at it */
        intel_setup_mchbar(dev);
-       intel_setup_gmbus(dev);
        intel_opregion_setup(dev);
  
        i915_gem_load(dev);
@@@ -1102,7 -1103,6 +1104,6 @@@ out_gem_unload
        if (dev->pdev->msi_enabled)
                pci_disable_msi(dev->pdev);
  
-       intel_teardown_gmbus(dev);
        intel_teardown_mchbar(dev);
        pm_qos_remove_request(&dev_priv->pm_qos);
        destroy_workqueue(dev_priv->gpu_error.hangcheck_wq);
@@@ -1204,7 -1204,6 +1205,6 @@@ int i915_driver_unload(struct drm_devic
  
        intel_csr_ucode_fini(dev_priv);
  
-       intel_teardown_gmbus(dev);
        intel_teardown_mchbar(dev);
  
        destroy_workqueue(dev_priv->hotplug.dp_wq);
index 556a458d669e7c6419c8b97134f55cf06528d6a0,007ae83a4086d65ff7e4d3862f2ad2a035c74540..0a988895165fd3cde55c2b67e8876132513c95ac
@@@ -855,31 -855,31 +855,31 @@@ enum skl_disp_power_wells 
   *
   * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is
   * digital port D (CHV) or port A (BXT).
-  */
- /*
-  * Dual channel PHY (VLV/CHV/BXT)
-  * ---------------------------------
-  * |      CH0      |      CH1      |
-  * |  CMN/PLL/REF  |  CMN/PLL/REF  |
-  * |---------------|---------------| Display PHY
-  * | PCS01 | PCS23 | PCS01 | PCS23 |
-  * |-------|-------|-------|-------|
-  * |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3|
-  * ---------------------------------
-  * |     DDI0      |     DDI1      | DP/HDMI ports
-  * ---------------------------------
   *
-  * Single channel PHY (CHV/BXT)
-  * -----------------
-  * |      CH0      |
-  * |  CMN/PLL/REF  |
-  * |---------------| Display PHY
-  * | PCS01 | PCS23 |
-  * |-------|-------|
-  * |TX0|TX1|TX2|TX3|
-  * -----------------
-  * |     DDI2      | DP/HDMI port
-  * -----------------
+  *
+  *     Dual channel PHY (VLV/CHV/BXT)
+  *     ---------------------------------
+  *     |      CH0      |      CH1      |
+  *     |  CMN/PLL/REF  |  CMN/PLL/REF  |
+  *     |---------------|---------------| Display PHY
+  *     | PCS01 | PCS23 | PCS01 | PCS23 |
+  *     |-------|-------|-------|-------|
+  *     |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3|
+  *     ---------------------------------
+  *     |     DDI0      |     DDI1      | DP/HDMI ports
+  *     ---------------------------------
+  *
+  *     Single channel PHY (CHV/BXT)
+  *     -----------------
+  *     |      CH0      |
+  *     |  CMN/PLL/REF  |
+  *     |---------------| Display PHY
+  *     | PCS01 | PCS23 |
+  *     |-------|-------|
+  *     |TX0|TX1|TX2|TX3|
+  *     -----------------
+  *     |     DDI2      | DP/HDMI port
+  *     -----------------
   */
  #define DPIO_DEVFN                    0
  
  #define FPGA_DBG              _MMIO(0x42300)
  #define   FPGA_DBG_RM_NOCLAIM (1<<31)
  
 +#define CLAIM_ER              _MMIO(VLV_DISPLAY_BASE + 0x2028)
 +#define   CLAIM_ER_CLR                (1 << 31)
 +#define   CLAIM_ER_OVERFLOW   (1 << 16)
 +#define   CLAIM_ER_CTR_MASK   0xffff
 +
  #define DERRMR                _MMIO(0x44050)
  /* Note that HBLANK events are reserved on bdw+ */
  #define   DERRMR_PIPEA_SCANLINE               (1<<0)
index 25d9e5ccdebdd63c43298375c9e0f9af4ed6697d,e6408e5583d7a88af4511c6ec2334db2b7922555..1f9a3687b540610674bfb0eb1507a5a9b3c48341
@@@ -133,38 -133,38 +133,38 @@@ static const struct ddi_buf_trans skl_d
        { 0x00002016, 0x000000A0, 0x0 },
        { 0x00005012, 0x0000009B, 0x0 },
        { 0x00007011, 0x00000088, 0x0 },
 -      { 0x80009010, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
 +      { 0x80009010, 0x000000C0, 0x1 },
        { 0x00002016, 0x0000009B, 0x0 },
        { 0x00005012, 0x00000088, 0x0 },
 -      { 0x80007011, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
 +      { 0x80007011, 0x000000C0, 0x1 },
        { 0x00002016, 0x000000DF, 0x0 },
 -      { 0x80005012, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
 +      { 0x80005012, 0x000000C0, 0x1 },
  };
  
  /* Skylake U */
  static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = {
        { 0x0000201B, 0x000000A2, 0x0 },
        { 0x00005012, 0x00000088, 0x0 },
 -      { 0x00007011, 0x00000087, 0x0 },
 -      { 0x80009010, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
 +      { 0x80007011, 0x000000CD, 0x0 },
 +      { 0x80009010, 0x000000C0, 0x1 },
        { 0x0000201B, 0x0000009D, 0x0 },
 -      { 0x80005012, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
 -      { 0x80007011, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
 +      { 0x80005012, 0x000000C0, 0x1 },
 +      { 0x80007011, 0x000000C0, 0x1 },
        { 0x00002016, 0x00000088, 0x0 },
 -      { 0x80005012, 0x000000C0, 0x1 },        /* Uses I_boost level 0x1 */
 +      { 0x80005012, 0x000000C0, 0x1 },
  };
  
  /* Skylake Y */
  static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = {
        { 0x00000018, 0x000000A2, 0x0 },
        { 0x00005012, 0x00000088, 0x0 },
 -      { 0x00007011, 0x00000087, 0x0 },
 -      { 0x80009010, 0x000000C0, 0x3 },        /* Uses I_boost level 0x3 */
 +      { 0x80007011, 0x000000CD, 0x0 },
 +      { 0x80009010, 0x000000C0, 0x3 },
        { 0x00000018, 0x0000009D, 0x0 },
 -      { 0x80005012, 0x000000C0, 0x3 },        /* Uses I_boost level 0x3 */
 -      { 0x80007011, 0x000000C0, 0x3 },        /* Uses I_boost level 0x3 */
 +      { 0x80005012, 0x000000C0, 0x3 },
 +      { 0x80007011, 0x000000C0, 0x3 },
        { 0x00000018, 0x00000088, 0x0 },
 -      { 0x80005012, 0x000000C0, 0x3 },        /* Uses I_boost level 0x3 */
 +      { 0x80005012, 0x000000C0, 0x3 },
  };
  
  /*
@@@ -226,26 -226,26 +226,26 @@@ static const struct ddi_buf_trans skl_d
        { 0x00000018, 0x000000A1, 0x0 },
        { 0x00000018, 0x00000098, 0x0 },
        { 0x00004013, 0x00000088, 0x0 },
 -      { 0x00006012, 0x00000087, 0x0 },
 +      { 0x80006012, 0x000000CD, 0x1 },
        { 0x00000018, 0x000000DF, 0x0 },
 -      { 0x00003015, 0x00000087, 0x0 },        /* Default */
 -      { 0x00003015, 0x000000C7, 0x0 },
 -      { 0x00000018, 0x000000C7, 0x0 },
 +      { 0x80003015, 0x000000CD, 0x1 },        /* Default */
 +      { 0x80003015, 0x000000C0, 0x1 },
 +      { 0x80000018, 0x000000C0, 0x1 },
  };
  
  /* Skylake Y */
  static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = {
        { 0x00000018, 0x000000A1, 0x0 },
        { 0x00005012, 0x000000DF, 0x0 },
 -      { 0x00007011, 0x00000084, 0x0 },
 +      { 0x80007011, 0x000000CB, 0x3 },
        { 0x00000018, 0x000000A4, 0x0 },
        { 0x00000018, 0x0000009D, 0x0 },
        { 0x00004013, 0x00000080, 0x0 },
 -      { 0x00006013, 0x000000C7, 0x0 },
 +      { 0x80006013, 0x000000C0, 0x3 },
        { 0x00000018, 0x0000008A, 0x0 },
 -      { 0x00003015, 0x000000C7, 0x0 },        /* Default */
 -      { 0x80003015, 0x000000C7, 0x7 },        /* Uses I_boost level 0x7 */
 -      { 0x00000018, 0x000000C7, 0x0 },
 +      { 0x80003015, 0x000000C0, 0x3 },        /* Default */
 +      { 0x80003015, 0x000000C0, 0x3 },
 +      { 0x80000018, 0x000000C0, 0x3 },
  };
  
  struct bxt_ddi_buf_trans {
@@@ -301,8 -301,8 +301,8 @@@ static const struct bxt_ddi_buf_trans b
        { 154, 0x9A, 1, 128, true },    /* 9:   1200            0   */
  };
  
 -static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level,
 -                                  enum port port, int type);
 +static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv,
 +                                  u32 level, enum port port, int type);
  
  static void ddi_get_encoder_port(struct intel_encoder *intel_encoder,
                                 struct intel_digital_port **dig_port,
@@@ -342,50 -342,81 +342,50 @@@ enum port intel_ddi_get_encoder_port(st
        return port;
  }
  
 -static bool
 -intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port)
 -{
 -      return i915_mmio_reg_valid(intel_dig_port->hdmi.hdmi_reg);
 -}
 -
 -static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev,
 -                                                      int *n_entries)
 +static const struct ddi_buf_trans *
 +skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries)
  {
 -      const struct ddi_buf_trans *ddi_translations;
 -
 -      if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) {
 -              ddi_translations = skl_y_ddi_translations_dp;
 +      if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) {
                *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
 -      } else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) {
 -              ddi_translations = skl_u_ddi_translations_dp;
 +              return skl_y_ddi_translations_dp;
 +      } else if (IS_SKL_ULT(dev_priv) || IS_KBL_ULT(dev_priv)) {
                *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp);
 +              return skl_u_ddi_translations_dp;
        } else {
 -              ddi_translations = skl_ddi_translations_dp;
                *n_entries = ARRAY_SIZE(skl_ddi_translations_dp);
 +              return skl_ddi_translations_dp;
        }
 -
 -      return ddi_translations;
  }
  
 -static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev,
 -                                                       int *n_entries)
 +static const struct ddi_buf_trans *
 +skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
  {
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      const struct ddi_buf_trans *ddi_translations;
 -
 -      if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) {
 -              if (dev_priv->edp_low_vswing) {
 -                      ddi_translations = skl_y_ddi_translations_edp;
 +      if (dev_priv->edp_low_vswing) {
 +              if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) {
                        *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp);
 -              } else {
 -                      ddi_translations = skl_y_ddi_translations_dp;
 -                      *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
 -              }
 -      } else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) {
 -              if (dev_priv->edp_low_vswing) {
 -                      ddi_translations = skl_u_ddi_translations_edp;
 +                      return skl_y_ddi_translations_edp;
 +              } else if (IS_SKL_ULT(dev_priv) || IS_KBL_ULT(dev_priv)) {
                        *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp);
 +                      return skl_u_ddi_translations_edp;
                } else {
 -                      ddi_translations = skl_u_ddi_translations_dp;
 -                      *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp);
 -              }
 -      } else {
 -              if (dev_priv->edp_low_vswing) {
 -                      ddi_translations = skl_ddi_translations_edp;
                        *n_entries = ARRAY_SIZE(skl_ddi_translations_edp);
 -              } else {
 -                      ddi_translations = skl_ddi_translations_dp;
 -                      *n_entries = ARRAY_SIZE(skl_ddi_translations_dp);
 +                      return skl_ddi_translations_edp;
                }
        }
  
 -      return ddi_translations;
 +      return skl_get_buf_trans_dp(dev_priv, n_entries);
  }
  
  static const struct ddi_buf_trans *
 -skl_get_buf_trans_hdmi(struct drm_device *dev,
 -                     int *n_entries)
 +skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries)
  {
 -      const struct ddi_buf_trans *ddi_translations;
 -
 -      if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) {
 -              ddi_translations = skl_y_ddi_translations_hdmi;
 +      if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) {
                *n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi);
 +              return skl_y_ddi_translations_hdmi;
        } else {
 -              ddi_translations = skl_ddi_translations_hdmi;
                *n_entries = ARRAY_SIZE(skl_ddi_translations_hdmi);
 +              return skl_ddi_translations_hdmi;
        }
 -
 -      return ddi_translations;
  }
  
  /*
   * in either FDI or DP modes only, as HDMI connections will work with both
   * of those
   */
 -static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
 -                                    bool supports_hdmi)
 +void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
  {
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        u32 iboost_bit = 0;
        int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry,
            size;
 -      int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
 +      int hdmi_level;
 +      enum port port;
        const struct ddi_buf_trans *ddi_translations_fdi;
        const struct ddi_buf_trans *ddi_translations_dp;
        const struct ddi_buf_trans *ddi_translations_edp;
        const struct ddi_buf_trans *ddi_translations_hdmi;
        const struct ddi_buf_trans *ddi_translations;
  
 -      if (IS_BROXTON(dev)) {
 -              if (!supports_hdmi)
 +      port = intel_ddi_get_encoder_port(encoder);
 +      hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
 +
 +      if (IS_BROXTON(dev_priv)) {
 +              if (encoder->type != INTEL_OUTPUT_HDMI)
                        return;
  
                /* Vswing programming for HDMI */
 -              bxt_ddi_vswing_sequence(dev, hdmi_level, port,
 +              bxt_ddi_vswing_sequence(dev_priv, hdmi_level, port,
                                        INTEL_OUTPUT_HDMI);
                return;
 -      } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
 +      }
 +
 +      if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
                ddi_translations_fdi = NULL;
                ddi_translations_dp =
 -                              skl_get_buf_trans_dp(dev, &n_dp_entries);
 +                              skl_get_buf_trans_dp(dev_priv, &n_dp_entries);
                ddi_translations_edp =
 -                              skl_get_buf_trans_edp(dev, &n_edp_entries);
 +                              skl_get_buf_trans_edp(dev_priv, &n_edp_entries);
                ddi_translations_hdmi =
 -                              skl_get_buf_trans_hdmi(dev, &n_hdmi_entries);
 +                              skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries);
                hdmi_default_entry = 8;
                /* If we're boosting the current, set bit 31 of trans1 */
                if (dev_priv->vbt.ddi_port_info[port].hdmi_boost_level ||
                    dev_priv->vbt.ddi_port_info[port].dp_boost_level)
                        iboost_bit = 1<<31;
 -      } else if (IS_BROADWELL(dev)) {
 +
 +              if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP &&
 +                          port != PORT_A && port != PORT_E &&
 +                          n_edp_entries > 9))
 +                      n_edp_entries = 9;
 +      } else if (IS_BROADWELL(dev_priv)) {
                ddi_translations_fdi = bdw_ddi_translations_fdi;
                ddi_translations_dp = bdw_ddi_translations_dp;
                ddi_translations_edp = bdw_ddi_translations_edp;
                n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp);
                n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
                hdmi_default_entry = 7;
 -      } else if (IS_HASWELL(dev)) {
 +      } else if (IS_HASWELL(dev_priv)) {
                ddi_translations_fdi = hsw_ddi_translations_fdi;
                ddi_translations_dp = hsw_ddi_translations_dp;
                ddi_translations_edp = hsw_ddi_translations_dp;
                hdmi_default_entry = 7;
        }
  
 -      switch (port) {
 -      case PORT_A:
 +      switch (encoder->type) {
 +      case INTEL_OUTPUT_EDP:
                ddi_translations = ddi_translations_edp;
                size = n_edp_entries;
                break;
 -      case PORT_B:
 -      case PORT_C:
 +      case INTEL_OUTPUT_DISPLAYPORT:
 +      case INTEL_OUTPUT_HDMI:
                ddi_translations = ddi_translations_dp;
                size = n_dp_entries;
                break;
 -      case PORT_D:
 -              if (intel_dp_is_edp(dev, PORT_D)) {
 -                      ddi_translations = ddi_translations_edp;
 -                      size = n_edp_entries;
 -              } else {
 -                      ddi_translations = ddi_translations_dp;
 -                      size = n_dp_entries;
 -              }
 -              break;
 -      case PORT_E:
 -              if (ddi_translations_fdi)
 -                      ddi_translations = ddi_translations_fdi;
 -              else
 -                      ddi_translations = ddi_translations_dp;
 +      case INTEL_OUTPUT_ANALOG:
 +              ddi_translations = ddi_translations_fdi;
                size = n_dp_entries;
                break;
        default:
                           ddi_translations[i].trans2);
        }
  
 -      if (!supports_hdmi)
 +      if (encoder->type != INTEL_OUTPUT_HDMI)
                return;
  
        /* Choose a good default if VBT is badly populated */
                   ddi_translations_hdmi[hdmi_level].trans2);
  }
  
 -/* Program DDI buffers translations for DP. By default, program ports A-D in DP
 - * mode and port E for FDI.
 - */
 -void intel_prepare_ddi(struct drm_device *dev)
 -{
 -      struct intel_encoder *intel_encoder;
 -      bool visited[I915_MAX_PORTS] = { 0, };
 -
 -      if (!HAS_DDI(dev))
 -              return;
 -
 -      for_each_intel_encoder(dev, intel_encoder) {
 -              struct intel_digital_port *intel_dig_port;
 -              enum port port;
 -              bool supports_hdmi;
 -
 -              if (intel_encoder->type == INTEL_OUTPUT_DSI)
 -                      continue;
 -
 -              ddi_get_encoder_port(intel_encoder, &intel_dig_port, &port);
 -              if (visited[port])
 -                      continue;
 -
 -              supports_hdmi = intel_dig_port &&
 -                              intel_dig_port_supports_hdmi(intel_dig_port);
 -
 -              intel_prepare_ddi_buffers(dev, port, supports_hdmi);
 -              visited[port] = true;
 -      }
 -}
 -
  static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
                                    enum port port)
  {
@@@ -537,14 -601,8 +537,14 @@@ void hsw_fdi_link_train(struct drm_crt
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +      struct intel_encoder *encoder;
        u32 temp, i, rx_ctl_val;
  
 +      for_each_encoder_on_crtc(dev, crtc, encoder) {
 +              WARN_ON(encoder->type != INTEL_OUTPUT_ANALOG);
 +              intel_prepare_ddi_buffer(encoder);
 +      }
 +
        /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the
         * mode set "sequence for CRT port" document:
         * - TP1 to TP2 time with the default value
@@@ -2027,9 -2085,10 +2027,9 @@@ void intel_ddi_disable_pipe_clock(struc
                           TRANS_CLK_SEL_DISABLED);
  }
  
 -static void skl_ddi_set_iboost(struct drm_device *dev, u32 level,
 -                             enum port port, int type)
 +static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
 +                             u32 level, enum port port, int type)
  {
 -      struct drm_i915_private *dev_priv = dev->dev_private;
        const struct ddi_buf_trans *ddi_translations;
        uint8_t iboost;
        uint8_t dp_iboost, hdmi_iboost;
                if (dp_iboost) {
                        iboost = dp_iboost;
                } else {
 -                      ddi_translations = skl_get_buf_trans_dp(dev, &n_entries);
 +                      ddi_translations = skl_get_buf_trans_dp(dev_priv, &n_entries);
                        iboost = ddi_translations[level].i_boost;
                }
        } else if (type == INTEL_OUTPUT_EDP) {
                if (dp_iboost) {
                        iboost = dp_iboost;
                } else {
 -                      ddi_translations = skl_get_buf_trans_edp(dev, &n_entries);
 +                      ddi_translations = skl_get_buf_trans_edp(dev_priv, &n_entries);
 +
 +                      if (WARN_ON(port != PORT_A &&
 +                                  port != PORT_E && n_entries > 9))
 +                              n_entries = 9;
 +
                        iboost = ddi_translations[level].i_boost;
                }
        } else if (type == INTEL_OUTPUT_HDMI) {
                if (hdmi_iboost) {
                        iboost = hdmi_iboost;
                } else {
 -                      ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries);
 +                      ddi_translations = skl_get_buf_trans_hdmi(dev_priv, &n_entries);
                        iboost = ddi_translations[level].i_boost;
                }
        } else {
        I915_WRITE(DISPIO_CR_TX_BMU_CR0, reg);
  }
  
 -static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level,
 -                                  enum port port, int type)
 +static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv,
 +                                  u32 level, enum port port, int type)
  {
 -      struct drm_i915_private *dev_priv = dev->dev_private;
        const struct bxt_ddi_buf_trans *ddi_translations;
        u32 n_entries, i;
        uint32_t val;
@@@ -2205,7 -2260,7 +2205,7 @@@ static uint32_t translate_signal_level(
  uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
  {
        struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
 -      struct drm_device *dev = dport->base.base.dev;
 +      struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
        struct intel_encoder *encoder = &dport->base;
        uint8_t train_set = intel_dp->train_set[0];
        int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
  
        level = translate_signal_level(signal_levels);
  
 -      if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
 -              skl_ddi_set_iboost(dev, level, port, encoder->type);
 -      else if (IS_BROXTON(dev))
 -              bxt_ddi_vswing_sequence(dev, level, port, encoder->type);
 +      if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 +              skl_ddi_set_iboost(dev_priv, level, port, encoder->type);
 +      else if (IS_BROXTON(dev_priv))
 +              bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type);
  
        return DDI_BUF_TRANS_SELECT(level);
  }
@@@ -2270,12 -2325,12 +2270,12 @@@ void intel_ddi_clk_select(struct intel_
  static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
  {
        struct drm_encoder *encoder = &intel_encoder->base;
 -      struct drm_device *dev = encoder->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_i915_private *dev_priv = to_i915(encoder->dev);
        struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
        enum port port = intel_ddi_get_encoder_port(intel_encoder);
        int type = intel_encoder->type;
 -      int hdmi_level;
 +
 +      intel_prepare_ddi_buffer(intel_encoder);
  
        if (type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
  
                intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
                intel_dp_start_link_train(intel_dp);
 -              if (port != PORT_A || INTEL_INFO(dev)->gen >= 9)
 +              if (port != PORT_A || INTEL_INFO(dev_priv)->gen >= 9)
                        intel_dp_stop_link_train(intel_dp);
        } else if (type == INTEL_OUTPUT_HDMI) {
                struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
  
 -              if (IS_BROXTON(dev)) {
 -                      hdmi_level = dev_priv->vbt.
 -                              ddi_port_info[port].hdmi_level_shift;
 -                      bxt_ddi_vswing_sequence(dev, hdmi_level, port,
 -                                      INTEL_OUTPUT_HDMI);
 -              }
                intel_hdmi->set_infoframes(encoder,
                                           crtc->config->has_hdmi_sink,
                                           &crtc->config->base.adjusted_mode);
@@@ -3221,33 -3282,6 +3221,33 @@@ void intel_ddi_init(struct drm_device *
        struct intel_encoder *intel_encoder;
        struct drm_encoder *encoder;
        bool init_hdmi, init_dp;
 +      int max_lanes;
 +
 +      if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) {
 +              switch (port) {
 +              case PORT_A:
 +                      max_lanes = 4;
 +                      break;
 +              case PORT_E:
 +                      max_lanes = 0;
 +                      break;
 +              default:
 +                      max_lanes = 4;
 +                      break;
 +              }
 +      } else {
 +              switch (port) {
 +              case PORT_A:
 +                      max_lanes = 2;
 +                      break;
 +              case PORT_E:
 +                      max_lanes = 2;
 +                      break;
 +              default:
 +                      max_lanes = 4;
 +                      break;
 +              }
 +      }
  
        init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi ||
                     dev_priv->vbt.ddi_port_info[port].supports_hdmi);
        encoder = &intel_encoder->base;
  
        drm_encoder_init(dev, encoder, &intel_ddi_funcs,
-                        DRM_MODE_ENCODER_TMDS);
+                        DRM_MODE_ENCODER_TMDS, NULL);
  
        intel_encoder->compute_config = intel_ddi_compute_config;
        intel_encoder->enable = intel_enable_ddi;
        intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
                                          (DDI_BUF_PORT_REVERSAL |
                                           DDI_A_4_LANES);
 +      intel_dig_port->max_lanes = max_lanes;
  
        /*
         * Bspec says that DDI_A_4_LANES is the only supported configuration
index c532c3d605ac7d934ffa7fc69dc9c699652c4cdb,580d094bfc1e1fc7426a937b721b29062ac9fe8e..ccb3e3f474502af95da8c519b5127e4642b44794
@@@ -85,6 -85,8 +85,6 @@@ static const uint32_t intel_cursor_form
        DRM_FORMAT_ARGB8888,
  };
  
 -static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
 -
  static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
                                struct intel_crtc_state *pipe_config);
  static void ironlake_pch_clock_get(struct intel_crtc *crtc,
@@@ -1150,6 -1152,11 +1150,6 @@@ static void intel_wait_for_pipe_off(str
        }
  }
  
 -static const char *state_string(bool enabled)
 -{
 -      return enabled ? "on" : "off";
 -}
 -
  /* Only for pre-ILK configs */
  void assert_pll(struct drm_i915_private *dev_priv,
                enum pipe pipe, bool state)
        cur_state = !!(val & DPLL_VCO_ENABLE);
        I915_STATE_WARN(cur_state != state,
             "PLL state assertion failure (expected %s, current %s)\n",
 -           state_string(state), state_string(cur_state));
 +                      onoff(state), onoff(cur_state));
  }
  
  /* XXX: the dsi pll is shared between MIPI DSI ports */
@@@ -1177,7 -1184,7 +1177,7 @@@ static void assert_dsi_pll(struct drm_i
        cur_state = val & DSI_PLL_VCO_EN;
        I915_STATE_WARN(cur_state != state,
             "DSI PLL state assertion failure (expected %s, current %s)\n",
 -           state_string(state), state_string(cur_state));
 +                      onoff(state), onoff(cur_state));
  }
  #define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
  #define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
@@@ -1201,13 -1208,14 +1201,13 @@@ void assert_shared_dpll(struct drm_i915
        bool cur_state;
        struct intel_dpll_hw_state hw_state;
  
 -      if (WARN (!pll,
 -                "asserting DPLL %s with no DPLL\n", state_string(state)))
 +      if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
                return;
  
        cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
        I915_STATE_WARN(cur_state != state,
             "%s assertion failure (expected %s, current %s)\n",
 -           pll->name, state_string(state), state_string(cur_state));
 +                      pll->name, onoff(state), onoff(cur_state));
  }
  
  static void assert_fdi_tx(struct drm_i915_private *dev_priv,
        }
        I915_STATE_WARN(cur_state != state,
             "FDI TX state assertion failure (expected %s, current %s)\n",
 -           state_string(state), state_string(cur_state));
 +                      onoff(state), onoff(cur_state));
  }
  #define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true)
  #define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false)
@@@ -1242,7 -1250,7 +1242,7 @@@ static void assert_fdi_rx(struct drm_i9
        cur_state = !!(val & FDI_RX_ENABLE);
        I915_STATE_WARN(cur_state != state,
             "FDI RX state assertion failure (expected %s, current %s)\n",
 -           state_string(state), state_string(cur_state));
 +                      onoff(state), onoff(cur_state));
  }
  #define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true)
  #define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false)
@@@ -1274,7 -1282,7 +1274,7 @@@ void assert_fdi_rx_pll(struct drm_i915_
        cur_state = !!(val & FDI_RX_PLL_ENABLE);
        I915_STATE_WARN(cur_state != state,
             "FDI RX PLL assertion failure (expected %s, current %s)\n",
 -           state_string(state), state_string(cur_state));
 +                      onoff(state), onoff(cur_state));
  }
  
  void assert_panel_unlocked(struct drm_i915_private *dev_priv,
@@@ -1332,7 -1340,7 +1332,7 @@@ static void assert_cursor(struct drm_i9
  
        I915_STATE_WARN(cur_state != state,
             "cursor on pipe %c assertion failure (expected %s, current %s)\n",
 -           pipe_name(pipe), state_string(state), state_string(cur_state));
 +                      pipe_name(pipe), onoff(state), onoff(cur_state));
  }
  #define assert_cursor_enabled(d, p) assert_cursor(d, p, true)
  #define assert_cursor_disabled(d, p) assert_cursor(d, p, false)
@@@ -1359,7 -1367,7 +1359,7 @@@ void assert_pipe(struct drm_i915_privat
  
        I915_STATE_WARN(cur_state != state,
             "pipe %c assertion failure (expected %s, current %s)\n",
 -           pipe_name(pipe), state_string(state), state_string(cur_state));
 +                      pipe_name(pipe), onoff(state), onoff(cur_state));
  }
  
  static void assert_plane(struct drm_i915_private *dev_priv,
        cur_state = !!(val & DISPLAY_PLANE_ENABLE);
        I915_STATE_WARN(cur_state != state,
             "plane %c assertion failure (expected %s, current %s)\n",
 -           plane_name(plane), state_string(state), state_string(cur_state));
 +                      plane_name(plane), onoff(state), onoff(cur_state));
  }
  
  #define assert_plane_enabled(d, p) assert_plane(d, p, true)
@@@ -2145,17 -2153,6 +2145,17 @@@ static void intel_enable_pipe(struct in
  
        I915_WRITE(reg, val | PIPECONF_ENABLE);
        POSTING_READ(reg);
 +
 +      /*
 +       * Until the pipe starts DSL will read as 0, which would cause
 +       * an apparent vblank timestamp jump, which messes up also the
 +       * frame count when it's derived from the timestamps. So let's
 +       * wait for the pipe to start properly before we call
 +       * drm_crtc_vblank_on()
 +       */
 +      if (dev->max_vblank_count == 0 &&
 +          wait_for(intel_get_crtc_scanline(crtc) != crtc->scanline_offset, 50))
 +              DRM_ERROR("pipe %c didn't start\n", pipe_name(pipe));
  }
  
  /**
@@@ -2217,75 -2214,67 +2217,75 @@@ static bool need_vtd_wa(struct drm_devi
        return false;
  }
  
 -unsigned int
 -intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
 -                uint64_t fb_format_modifier, unsigned int plane)
 +static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
  {
 -      unsigned int tile_height;
 -      uint32_t pixel_bytes;
 +      return IS_GEN2(dev_priv) ? 2048 : 4096;
 +}
  
 -      switch (fb_format_modifier) {
 +static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
 +                                   uint64_t fb_modifier, unsigned int cpp)
 +{
 +      switch (fb_modifier) {
        case DRM_FORMAT_MOD_NONE:
 -              tile_height = 1;
 -              break;
 +              return cpp;
        case I915_FORMAT_MOD_X_TILED:
 -              tile_height = IS_GEN2(dev) ? 16 : 8;
 -              break;
 +              if (IS_GEN2(dev_priv))
 +                      return 128;
 +              else
 +                      return 512;
        case I915_FORMAT_MOD_Y_TILED:
 -              tile_height = 32;
 -              break;
 +              if (IS_GEN2(dev_priv) || HAS_128_BYTE_Y_TILING(dev_priv))
 +                      return 128;
 +              else
 +                      return 512;
        case I915_FORMAT_MOD_Yf_TILED:
 -              pixel_bytes = drm_format_plane_cpp(pixel_format, plane);
 -              switch (pixel_bytes) {
 -              default:
 +              switch (cpp) {
                case 1:
 -                      tile_height = 64;
 -                      break;
 +                      return 64;
                case 2:
                case 4:
 -                      tile_height = 32;
 -                      break;
 +                      return 128;
                case 8:
 -                      tile_height = 16;
 -                      break;
                case 16:
 -                      WARN_ONCE(1,
 -                                "128-bit pixels are not supported for display!");
 -                      tile_height = 16;
 -                      break;
 +                      return 256;
 +              default:
 +                      MISSING_CASE(cpp);
 +                      return cpp;
                }
                break;
        default:
 -              MISSING_CASE(fb_format_modifier);
 -              tile_height = 1;
 -              break;
 +              MISSING_CASE(fb_modifier);
 +              return cpp;
        }
 +}
  
 -      return tile_height;
 +unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
 +                             uint64_t fb_modifier, unsigned int cpp)
 +{
 +      if (fb_modifier == DRM_FORMAT_MOD_NONE)
 +              return 1;
 +      else
 +              return intel_tile_size(dev_priv) /
 +                      intel_tile_width(dev_priv, fb_modifier, cpp);
  }
  
  unsigned int
  intel_fb_align_height(struct drm_device *dev, unsigned int height,
 -                    uint32_t pixel_format, uint64_t fb_format_modifier)
 +                    uint32_t pixel_format, uint64_t fb_modifier)
  {
 -      return ALIGN(height, intel_tile_height(dev, pixel_format,
 -                                             fb_format_modifier, 0));
 +      unsigned int cpp = drm_format_plane_cpp(pixel_format, 0);
 +      unsigned int tile_height = intel_tile_height(to_i915(dev), fb_modifier, cpp);
 +
 +      return ALIGN(height, tile_height);
  }
  
  static void
  intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
                        const struct drm_plane_state *plane_state)
  {
 +      struct drm_i915_private *dev_priv = to_i915(fb->dev);
        struct intel_rotation_info *info = &view->params.rotation_info;
 -      unsigned int tile_height, tile_pitch;
 +      unsigned int tile_size, tile_width, tile_height, cpp;
  
        *view = i915_ggtt_view_normal;
  
        info->uv_offset = fb->offsets[1];
        info->fb_modifier = fb->modifier[0];
  
 -      tile_height = intel_tile_height(fb->dev, fb->pixel_format,
 -                                      fb->modifier[0], 0);
 -      tile_pitch = PAGE_SIZE / tile_height;
 -      info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
 +      tile_size = intel_tile_size(dev_priv);
 +
 +      cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 +      tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]);
 +      tile_height = tile_size / tile_width;
 +
 +      info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
        info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
 -      info->size = info->width_pages * info->height_pages * PAGE_SIZE;
 +      info->size = info->width_pages * info->height_pages * tile_size;
  
        if (info->pixel_format == DRM_FORMAT_NV12) {
 -              tile_height = intel_tile_height(fb->dev, fb->pixel_format,
 -                                              fb->modifier[0], 1);
 -              tile_pitch = PAGE_SIZE / tile_height;
 -              info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
 -              info->height_pages_uv = DIV_ROUND_UP(fb->height / 2,
 -                                                   tile_height);
 -              info->size_uv = info->width_pages_uv * info->height_pages_uv *
 -                              PAGE_SIZE;
 +              cpp = drm_format_plane_cpp(fb->pixel_format, 1);
 +              tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
 +              tile_height = tile_size / tile_width;
 +
 +              info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
 +              info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
 +              info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
        }
  }
  
 -static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
 +static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
  {
        if (INTEL_INFO(dev_priv)->gen >= 9)
                return 256 * 1024;
                return 0;
  }
  
 +static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv,
 +                                       uint64_t fb_modifier)
 +{
 +      switch (fb_modifier) {
 +      case DRM_FORMAT_MOD_NONE:
 +              return intel_linear_alignment(dev_priv);
 +      case I915_FORMAT_MOD_X_TILED:
 +              if (INTEL_INFO(dev_priv)->gen >= 9)
 +                      return 256 * 1024;
 +              return 0;
 +      case I915_FORMAT_MOD_Y_TILED:
 +      case I915_FORMAT_MOD_Yf_TILED:
 +              return 1 * 1024 * 1024;
 +      default:
 +              MISSING_CASE(fb_modifier);
 +              return 0;
 +      }
 +}
 +
  int
  intel_pin_and_fence_fb_obj(struct drm_plane *plane,
                           struct drm_framebuffer *fb,
  
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
  
 -      switch (fb->modifier[0]) {
 -      case DRM_FORMAT_MOD_NONE:
 -              alignment = intel_linear_alignment(dev_priv);
 -              break;
 -      case I915_FORMAT_MOD_X_TILED:
 -              if (INTEL_INFO(dev)->gen >= 9)
 -                      alignment = 256 * 1024;
 -              else {
 -                      /* pin() will align the object as required by fence */
 -                      alignment = 0;
 -              }
 -              break;
 -      case I915_FORMAT_MOD_Y_TILED:
 -      case I915_FORMAT_MOD_Yf_TILED:
 -              if (WARN_ONCE(INTEL_INFO(dev)->gen < 9,
 -                        "Y tiling bo slipped through, driver bug!\n"))
 -                      return -EINVAL;
 -              alignment = 1 * 1024 * 1024;
 -              break;
 -      default:
 -              MISSING_CASE(fb->modifier[0]);
 -              return -EINVAL;
 -      }
 +      alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
  
        intel_fill_fb_ggtt_view(&view, fb, plane_state);
  
@@@ -2448,27 -2438,22 +2448,27 @@@ static void intel_unpin_fb_obj(struct d
  
  /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
   * is assumed to be a power-of-two. */
 -unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
 -                                           int *x, int *y,
 -                                           unsigned int tiling_mode,
 -                                           unsigned int cpp,
 -                                           unsigned int pitch)
 -{
 -      if (tiling_mode != I915_TILING_NONE) {
 +unsigned long intel_compute_tile_offset(struct drm_i915_private *dev_priv,
 +                                      int *x, int *y,
 +                                      uint64_t fb_modifier,
 +                                      unsigned int cpp,
 +                                      unsigned int pitch)
 +{
 +      if (fb_modifier != DRM_FORMAT_MOD_NONE) {
 +              unsigned int tile_size, tile_width, tile_height;
                unsigned int tile_rows, tiles;
  
 -              tile_rows = *y / 8;
 -              *y %= 8;
 +              tile_size = intel_tile_size(dev_priv);
 +              tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
 +              tile_height = tile_size / tile_width;
 +
 +              tile_rows = *y / tile_height;
 +              *y %= tile_height;
  
 -              tiles = *x / (512/cpp);
 -              *x %= 512/cpp;
 +              tiles = *x / (tile_width/cpp);
 +              *x %= tile_width/cpp;
  
 -              return tile_rows * pitch * 8 + tiles * 4096;
 +              return tile_rows * pitch * tile_height + tiles * tile_size;
        } else {
                unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
                unsigned int offset;
@@@ -2613,8 -2598,6 +2613,8 @@@ intel_find_initial_plane_obj(struct int
        struct drm_plane_state *plane_state = primary->state;
        struct drm_crtc_state *crtc_state = intel_crtc->base.state;
        struct intel_plane *intel_plane = to_intel_plane(primary);
 +      struct intel_plane_state *intel_state =
 +              to_intel_plane_state(plane_state);
        struct drm_framebuffer *fb;
  
        if (!plane_config->fb)
@@@ -2676,15 -2659,6 +2676,15 @@@ valid_fb
        plane_state->crtc_w = fb->width;
        plane_state->crtc_h = fb->height;
  
 +      intel_state->src.x1 = plane_state->src_x;
 +      intel_state->src.y1 = plane_state->src_y;
 +      intel_state->src.x2 = plane_state->src_x + plane_state->src_w;
 +      intel_state->src.y2 = plane_state->src_y + plane_state->src_h;
 +      intel_state->dst.x1 = plane_state->crtc_x;
 +      intel_state->dst.y1 = plane_state->crtc_y;
 +      intel_state->dst.x2 = plane_state->crtc_x + plane_state->crtc_w;
 +      intel_state->dst.y2 = plane_state->crtc_y + plane_state->crtc_h;
 +
        obj = intel_fb_obj(fb);
        if (obj->tiling_mode != I915_TILING_NONE)
                dev_priv->preserve_bios_swizzle = true;
        obj->frontbuffer_bits |= to_intel_plane(primary)->frontbuffer_bit;
  }
  
 -static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 -                                    struct drm_framebuffer *fb,
 -                                    int x, int y)
 +static void i9xx_update_primary_plane(struct drm_plane *primary,
 +                                    const struct intel_crtc_state *crtc_state,
 +                                    const struct intel_plane_state *plane_state)
  {
 -      struct drm_device *dev = crtc->dev;
 +      struct drm_device *dev = primary->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      struct drm_plane *primary = crtc->primary;
 -      bool visible = to_intel_plane_state(primary->state)->visible;
 -      struct drm_i915_gem_object *obj;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
 +      struct drm_framebuffer *fb = plane_state->base.fb;
 +      struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        int plane = intel_crtc->plane;
        unsigned long linear_offset;
 +      int x = plane_state->src.x1 >> 16;
 +      int y = plane_state->src.y1 >> 16;
        u32 dspcntr;
        i915_reg_t reg = DSPCNTR(plane);
        int pixel_size;
  
 -      if (!visible || !fb) {
 -              I915_WRITE(reg, 0);
 -              if (INTEL_INFO(dev)->gen >= 4)
 -                      I915_WRITE(DSPSURF(plane), 0);
 -              else
 -                      I915_WRITE(DSPADDR(plane), 0);
 -              POSTING_READ(reg);
 -              return;
 -      }
 -
 -      obj = intel_fb_obj(fb);
 -      if (WARN_ON(obj == NULL))
 -              return;
 -
        pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
  
        dspcntr = DISPPLANE_GAMMA_ENABLE;
                 * which should always be the user's requested size.
                 */
                I915_WRITE(DSPSIZE(plane),
 -                         ((intel_crtc->config->pipe_src_h - 1) << 16) |
 -                         (intel_crtc->config->pipe_src_w - 1));
 +                         ((crtc_state->pipe_src_h - 1) << 16) |
 +                         (crtc_state->pipe_src_w - 1));
                I915_WRITE(DSPPOS(plane), 0);
        } else if (IS_CHERRYVIEW(dev) && plane == PLANE_B) {
                I915_WRITE(PRIMSIZE(plane),
 -                         ((intel_crtc->config->pipe_src_h - 1) << 16) |
 -                         (intel_crtc->config->pipe_src_w - 1));
 +                         ((crtc_state->pipe_src_h - 1) << 16) |
 +                         (crtc_state->pipe_src_w - 1));
                I915_WRITE(PRIMPOS(plane), 0);
                I915_WRITE(PRIMCNSTALPHA(plane), 0);
        }
  
        if (INTEL_INFO(dev)->gen >= 4) {
                intel_crtc->dspaddr_offset =
 -                      intel_gen4_compute_page_offset(dev_priv,
 -                                                     &x, &y, obj->tiling_mode,
 -                                                     pixel_size,
 -                                                     fb->pitches[0]);
 +                      intel_compute_tile_offset(dev_priv, &x, &y,
 +                                                fb->modifier[0],
 +                                                pixel_size,
 +                                                fb->pitches[0]);
                linear_offset -= intel_crtc->dspaddr_offset;
        } else {
                intel_crtc->dspaddr_offset = linear_offset;
        }
  
 -      if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
 +      if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
                dspcntr |= DISPPLANE_ROTATE_180;
  
 -              x += (intel_crtc->config->pipe_src_w - 1);
 -              y += (intel_crtc->config->pipe_src_h - 1);
 +              x += (crtc_state->pipe_src_w - 1);
 +              y += (crtc_state->pipe_src_h - 1);
  
                /* Finding the last pixel of the last line of the display
                data and adding to linear_offset*/
                linear_offset +=
 -                      (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
 -                      (intel_crtc->config->pipe_src_w - 1) * pixel_size;
 +                      (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
 +                      (crtc_state->pipe_src_w - 1) * pixel_size;
        }
  
        intel_crtc->adjusted_x = x;
        POSTING_READ(reg);
  }
  
 -static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 -                                        struct drm_framebuffer *fb,
 -                                        int x, int y)
 +static void i9xx_disable_primary_plane(struct drm_plane *primary,
 +                                     struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      struct drm_plane *primary = crtc->primary;
 -      bool visible = to_intel_plane_state(primary->state)->visible;
 -      struct drm_i915_gem_object *obj;
        int plane = intel_crtc->plane;
 -      unsigned long linear_offset;
 -      u32 dspcntr;
 -      i915_reg_t reg = DSPCNTR(plane);
 -      int pixel_size;
  
 -      if (!visible || !fb) {
 -              I915_WRITE(reg, 0);
 +      I915_WRITE(DSPCNTR(plane), 0);
 +      if (INTEL_INFO(dev_priv)->gen >= 4)
                I915_WRITE(DSPSURF(plane), 0);
 -              POSTING_READ(reg);
 -              return;
 -      }
 -
 -      obj = intel_fb_obj(fb);
 -      if (WARN_ON(obj == NULL))
 -              return;
 +      else
 +              I915_WRITE(DSPADDR(plane), 0);
 +      POSTING_READ(DSPCNTR(plane));
 +}
  
 -      pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 +static void ironlake_update_primary_plane(struct drm_plane *primary,
 +                                        const struct intel_crtc_state *crtc_state,
 +                                        const struct intel_plane_state *plane_state)
 +{
 +      struct drm_device *dev = primary->dev;
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
 +      struct drm_framebuffer *fb = plane_state->base.fb;
 +      struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 +      int plane = intel_crtc->plane;
 +      unsigned long linear_offset;
 +      u32 dspcntr;
 +      i915_reg_t reg = DSPCNTR(plane);
 +      int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 +      int x = plane_state->src.x1 >> 16;
 +      int y = plane_state->src.y1 >> 16;
  
        dspcntr = DISPPLANE_GAMMA_ENABLE;
 -
        dspcntr |= DISPLAY_PLANE_ENABLE;
  
        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
  
        linear_offset = y * fb->pitches[0] + x * pixel_size;
        intel_crtc->dspaddr_offset =
 -              intel_gen4_compute_page_offset(dev_priv,
 -                                             &x, &y, obj->tiling_mode,
 -                                             pixel_size,
 -                                             fb->pitches[0]);
 +              intel_compute_tile_offset(dev_priv, &x, &y,
 +                                        fb->modifier[0],
 +                                        pixel_size,
 +                                        fb->pitches[0]);
        linear_offset -= intel_crtc->dspaddr_offset;
 -      if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
 +      if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
                dspcntr |= DISPPLANE_ROTATE_180;
  
                if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
 -                      x += (intel_crtc->config->pipe_src_w - 1);
 -                      y += (intel_crtc->config->pipe_src_h - 1);
 +                      x += (crtc_state->pipe_src_w - 1);
 +                      y += (crtc_state->pipe_src_h - 1);
  
                        /* Finding the last pixel of the last line of the display
                        data and adding to linear_offset*/
                        linear_offset +=
 -                              (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
 -                              (intel_crtc->config->pipe_src_w - 1) * pixel_size;
 +                              (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
 +                              (crtc_state->pipe_src_w - 1) * pixel_size;
                }
        }
  
        POSTING_READ(reg);
  }
  
 -u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
 -                            uint32_t pixel_format)
 +u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
 +                            uint64_t fb_modifier, uint32_t pixel_format)
  {
 -      u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8;
 -
 -      /*
 -       * The stride is either expressed as a multiple of 64 bytes
 -       * chunks for linear buffers or in number of tiles for tiled
 -       * buffers.
 -       */
 -      switch (fb_modifier) {
 -      case DRM_FORMAT_MOD_NONE:
 -              return 64;
 -      case I915_FORMAT_MOD_X_TILED:
 -              if (INTEL_INFO(dev)->gen == 2)
 -                      return 128;
 -              return 512;
 -      case I915_FORMAT_MOD_Y_TILED:
 -              /* No need to check for old gens and Y tiling since this is
 -               * about the display engine and those will be blocked before
 -               * we get here.
 -               */
 -              return 128;
 -      case I915_FORMAT_MOD_Yf_TILED:
 -              if (bits_per_pixel == 8)
 -                      return 64;
 -              else
 -                      return 128;
 -      default:
 -              MISSING_CASE(fb_modifier);
 +      if (fb_modifier == DRM_FORMAT_MOD_NONE) {
                return 64;
 +      } else {
 +              int cpp = drm_format_plane_cpp(pixel_format, 0);
 +
 +              return intel_tile_width(dev_priv, fb_modifier, cpp);
        }
  }
  
@@@ -3068,30 -3074,36 +3068,30 @@@ u32 skl_plane_ctl_rotation(unsigned in
        return 0;
  }
  
 -static void skylake_update_primary_plane(struct drm_crtc *crtc,
 -                                       struct drm_framebuffer *fb,
 -                                       int x, int y)
 +static void skylake_update_primary_plane(struct drm_plane *plane,
 +                                       const struct intel_crtc_state *crtc_state,
 +                                       const struct intel_plane_state *plane_state)
  {
 -      struct drm_device *dev = crtc->dev;
 +      struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 -      struct drm_plane *plane = crtc->primary;
 -      bool visible = to_intel_plane_state(plane->state)->visible;
 -      struct drm_i915_gem_object *obj;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
 +      struct drm_framebuffer *fb = plane_state->base.fb;
 +      struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        int pipe = intel_crtc->pipe;
        u32 plane_ctl, stride_div, stride;
        u32 tile_height, plane_offset, plane_size;
 -      unsigned int rotation;
 +      unsigned int rotation = plane_state->base.rotation;
        int x_offset, y_offset;
        u32 surf_addr;
 -      struct intel_crtc_state *crtc_state = intel_crtc->config;
 -      struct intel_plane_state *plane_state;
 -      int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
 -      int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
 -      int scaler_id = -1;
 -
 -      plane_state = to_intel_plane_state(plane->state);
 -
 -      if (!visible || !fb) {
 -              I915_WRITE(PLANE_CTL(pipe, 0), 0);
 -              I915_WRITE(PLANE_SURF(pipe, 0), 0);
 -              POSTING_READ(PLANE_CTL(pipe, 0));
 -              return;
 -      }
 +      int scaler_id = plane_state->scaler_id;
 +      int src_x = plane_state->src.x1 >> 16;
 +      int src_y = plane_state->src.y1 >> 16;
 +      int src_w = drm_rect_width(&plane_state->src) >> 16;
 +      int src_h = drm_rect_height(&plane_state->src) >> 16;
 +      int dst_x = plane_state->dst.x1;
 +      int dst_y = plane_state->dst.y1;
 +      int dst_w = drm_rect_width(&plane_state->dst);
 +      int dst_h = drm_rect_height(&plane_state->dst);
  
        plane_ctl = PLANE_CTL_ENABLE |
                    PLANE_CTL_PIPE_GAMMA_ENABLE |
        plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
        plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
        plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
 -
 -      rotation = plane->state->rotation;
        plane_ctl |= skl_plane_ctl_rotation(rotation);
  
 -      obj = intel_fb_obj(fb);
 -      stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
 +      stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
                                               fb->pixel_format);
        surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
  
        WARN_ON(drm_rect_width(&plane_state->src) == 0);
  
 -      scaler_id = plane_state->scaler_id;
 -      src_x = plane_state->src.x1 >> 16;
 -      src_y = plane_state->src.y1 >> 16;
 -      src_w = drm_rect_width(&plane_state->src) >> 16;
 -      src_h = drm_rect_height(&plane_state->src) >> 16;
 -      dst_x = plane_state->dst.x1;
 -      dst_y = plane_state->dst.y1;
 -      dst_w = drm_rect_width(&plane_state->dst);
 -      dst_h = drm_rect_height(&plane_state->dst);
 -
 -      WARN_ON(x != src_x || y != src_y);
 -
        if (intel_rotation_90_or_270(rotation)) {
 +              int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 +
                /* stride = Surface height in tiles */
 -              tile_height = intel_tile_height(dev, fb->pixel_format,
 -                                              fb->modifier[0], 0);
 +              tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
                stride = DIV_ROUND_UP(fb->height, tile_height);
 -              x_offset = stride * tile_height - y - src_h;
 -              y_offset = x;
 +              x_offset = stride * tile_height - src_y - src_h;
 +              y_offset = src_x;
                plane_size = (src_w - 1) << 16 | (src_h - 1);
        } else {
                stride = fb->pitches[0] / stride_div;
 -              x_offset = x;
 -              y_offset = y;
 +              x_offset = src_x;
 +              y_offset = src_y;
                plane_size = (src_h - 1) << 16 | (src_w - 1);
        }
        plane_offset = y_offset << 16 | x_offset;
        POSTING_READ(PLANE_SURF(pipe, 0));
  }
  
 -/* Assume fb object is pinned & idle & fenced and just update base pointers */
 -static int
 -intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 -                         int x, int y, enum mode_set_atomic state)
 +static void skylake_disable_primary_plane(struct drm_plane *primary,
 +                                        struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 +      int pipe = to_intel_crtc(crtc)->pipe;
  
        if (dev_priv->fbc.deactivate)
                dev_priv->fbc.deactivate(dev_priv);
  
 -      dev_priv->display.update_primary_plane(crtc, fb, x, y);
 +      I915_WRITE(PLANE_CTL(pipe, 0), 0);
 +      I915_WRITE(PLANE_SURF(pipe, 0), 0);
 +      POSTING_READ(PLANE_SURF(pipe, 0));
 +}
  
 -      return 0;
 +/* Assume fb object is pinned & idle & fenced and just update base pointers */
 +static int
 +intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 +                         int x, int y, enum mode_set_atomic state)
 +{
 +      /* Support for kgdboc is disabled, this needs a major rework. */
 +      DRM_ERROR("legacy panic handler not supported any more.\n");
 +
 +      return -ENODEV;
  }
  
  static void intel_complete_page_flips(struct drm_device *dev)
@@@ -3203,10 -3219,8 +3203,10 @@@ static void intel_update_primary_planes
                drm_modeset_lock_crtc(crtc, &plane->base);
                plane_state = to_intel_plane_state(plane->base.state);
  
 -              if (crtc->state->active && plane_state->base.fb)
 -                      plane->commit_plane(&plane->base, plane_state);
 +              if (plane_state->visible)
 +                      plane->update_plane(&plane->base,
 +                                          to_intel_crtc_state(crtc->state),
 +                                          plane_state);
  
                drm_modeset_unlock_crtc(crtc);
        }
@@@ -4833,42 -4847,7 +4833,42 @@@ static void intel_pre_plane_update(stru
                intel_set_memory_cxsr(dev_priv, false);
        }
  
 -      if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed)
 +      /*
 +       * IVB workaround: must disable low power watermarks for at least
 +       * one frame before enabling scaling.  LP watermarks can be re-enabled
 +       * when scaling is disabled.
 +       *
 +       * WaCxSRDisabledForSpriteScaling:ivb
 +       */
 +      if (pipe_config->disable_lp_wm) {
 +              ilk_disable_lp_wm(dev);
 +              intel_wait_for_vblank(dev, crtc->pipe);
 +      }
 +
 +      /*
 +       * If we're doing a modeset, we're done.  No need to do any pre-vblank
 +       * watermark programming here.
 +       */
 +      if (needs_modeset(&pipe_config->base))
 +              return;
 +
 +      /*
 +       * For platforms that support atomic watermarks, program the
 +       * 'intermediate' watermarks immediately.  On pre-gen9 platforms, these
 +       * will be the intermediate values that are safe for both pre- and
 +       * post- vblank; when vblank happens, the 'active' values will be set
 +       * to the final 'target' values and we'll do this again to get the
 +       * optimal watermarks.  For gen9+ platforms, the values we program here
 +       * will be the final target values which will get automatically latched
 +       * at vblank time; no further programming will be necessary.
 +       *
 +       * If a platform hasn't been transitioned to atomic watermarks yet,
 +       * we'll continue to update watermarks the old way, if flags tell
 +       * us to.
 +       */
 +      if (dev_priv->display.initial_watermarks != NULL)
 +              dev_priv->display.initial_watermarks(pipe_config);
 +      else if (pipe_config->wm_changed)
                intel_update_watermarks(&crtc->base);
  }
  
@@@ -5391,7 -5370,6 +5391,7 @@@ static void modeset_put_power_domains(s
  
  static void modeset_update_crtc_power_domains(struct drm_atomic_state *state)
  {
 +      struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        struct drm_device *dev = state->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long put_domains[I915_MAX_PIPES] = {};
                                modeset_get_crtc_power_domains(crtc);
        }
  
 -      if (dev_priv->display.modeset_commit_cdclk) {
 -              unsigned int cdclk = to_intel_atomic_state(state)->cdclk;
 -
 -              if (cdclk != dev_priv->cdclk_freq &&
 -                  !WARN_ON(!state->allow_modeset))
 -                      dev_priv->display.modeset_commit_cdclk(state);
 -      }
 +      if (dev_priv->display.modeset_commit_cdclk &&
 +          intel_state->dev_cdclk != dev_priv->cdclk_freq)
 +              dev_priv->display.modeset_commit_cdclk(state);
  
        for (i = 0; i < I915_MAX_PIPES; i++)
                if (put_domains[i])
@@@ -6081,31 -6063,22 +6081,31 @@@ static int broxton_calc_cdclk(struct dr
  static int intel_mode_max_pixclk(struct drm_device *dev,
                                 struct drm_atomic_state *state)
  {
 -      struct intel_crtc *intel_crtc;
 -      struct intel_crtc_state *crtc_state;
 -      int max_pixclk = 0;
 +      struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct drm_crtc *crtc;
 +      struct drm_crtc_state *crtc_state;
 +      unsigned max_pixclk = 0, i;
 +      enum pipe pipe;
  
 -      for_each_intel_crtc(dev, intel_crtc) {
 -              crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
 -              if (IS_ERR(crtc_state))
 -                      return PTR_ERR(crtc_state);
 +      memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
 +             sizeof(intel_state->min_pixclk));
  
 -              if (!crtc_state->base.enable)
 -                      continue;
 +      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 +              int pixclk = 0;
 +
 +              if (crtc_state->enable)
 +                      pixclk = crtc_state->adjusted_mode.crtc_clock;
  
 -              max_pixclk = max(max_pixclk,
 -                               crtc_state->base.adjusted_mode.crtc_clock);
 +              intel_state->min_pixclk[i] = pixclk;
        }
  
 +      if (!intel_state->active_crtcs)
 +              return 0;
 +
 +      for_each_pipe(dev_priv, pipe)
 +              max_pixclk = max(intel_state->min_pixclk[pipe], max_pixclk);
 +
        return max_pixclk;
  }
  
@@@ -6114,18 -6087,13 +6114,18 @@@ static int valleyview_modeset_calc_cdcl
        struct drm_device *dev = state->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int max_pixclk = intel_mode_max_pixclk(dev, state);
 +      struct intel_atomic_state *intel_state =
 +              to_intel_atomic_state(state);
  
        if (max_pixclk < 0)
                return max_pixclk;
  
 -      to_intel_atomic_state(state)->cdclk =
 +      intel_state->cdclk = intel_state->dev_cdclk =
                valleyview_calc_cdclk(dev_priv, max_pixclk);
  
 +      if (!intel_state->active_crtcs)
 +              intel_state->dev_cdclk = valleyview_calc_cdclk(dev_priv, 0);
 +
        return 0;
  }
  
@@@ -6134,18 -6102,13 +6134,18 @@@ static int broxton_modeset_calc_cdclk(s
        struct drm_device *dev = state->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int max_pixclk = intel_mode_max_pixclk(dev, state);
 +      struct intel_atomic_state *intel_state =
 +              to_intel_atomic_state(state);
  
        if (max_pixclk < 0)
                return max_pixclk;
  
 -      to_intel_atomic_state(state)->cdclk =
 +      intel_state->cdclk = intel_state->dev_cdclk =
                broxton_calc_cdclk(dev_priv, max_pixclk);
  
 +      if (!intel_state->active_crtcs)
 +              intel_state->dev_cdclk = broxton_calc_cdclk(dev_priv, 0);
 +
        return 0;
  }
  
@@@ -6188,10 -6151,8 +6188,10 @@@ static void vlv_program_pfi_credits(str
  static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
  {
        struct drm_device *dev = old_state->dev;
 -      unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
        struct drm_i915_private *dev_priv = dev->dev_private;
 +      struct intel_atomic_state *old_intel_state =
 +              to_intel_atomic_state(old_state);
 +      unsigned req_cdclk = old_intel_state->dev_cdclk;
  
        /*
         * FIXME: We can end up here with all power domains off, yet
@@@ -6422,9 -6383,6 +6422,9 @@@ static void intel_crtc_disable_noatomic
        for_each_power_domain(domain, domains)
                intel_display_power_put(dev_priv, domain);
        intel_crtc->enabled_power_domains = 0;
 +
 +      dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe);
 +      dev_priv->min_pixclk[intel_crtc->pipe] = 0;
  }
  
  /*
@@@ -6534,13 -6492,11 +6534,11 @@@ static void intel_connector_check_state
  
  int intel_connector_init(struct intel_connector *connector)
  {
-       struct drm_connector_state *connector_state;
+       drm_atomic_helper_connector_reset(&connector->base);
  
-       connector_state = kzalloc(sizeof *connector_state, GFP_KERNEL);
-       if (!connector_state)
+       if (!connector->base.state)
                return -ENOMEM;
  
-       connector->base.state = connector_state;
        return 0;
  }
  
@@@ -9290,7 -9246,7 +9288,7 @@@ skylake_get_initial_plane_config(struc
        fb->width = ((val >> 0) & 0x1fff) + 1;
  
        val = I915_READ(PLANE_STRIDE(pipe, 0));
 -      stride_mult = intel_fb_stride_alignment(dev, fb->modifier[0],
 +      stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
                                                fb->pixel_format);
        fb->pitches[0] = (val & 0x3ff) * stride_mult;
  
@@@ -9706,14 -9662,14 +9704,14 @@@ void hsw_disable_pc8(struct drm_i915_pr
                val |= PCH_LP_PARTITION_LEVEL_DISABLE;
                I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
        }
 -
 -      intel_prepare_ddi(dev);
  }
  
  static void broxton_modeset_commit_cdclk(struct drm_atomic_state *old_state)
  {
        struct drm_device *dev = old_state->dev;
 -      unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
 +      struct intel_atomic_state *old_intel_state =
 +              to_intel_atomic_state(old_state);
 +      unsigned int req_cdclk = old_intel_state->dev_cdclk;
  
        broxton_set_cdclk(dev, req_cdclk);
  }
  /* compute the max rate for new configuration */
  static int ilk_max_pixel_rate(struct drm_atomic_state *state)
  {
 -      struct intel_crtc *intel_crtc;
 +      struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 +      struct drm_i915_private *dev_priv = state->dev->dev_private;
 +      struct drm_crtc *crtc;
 +      struct drm_crtc_state *cstate;
        struct intel_crtc_state *crtc_state;
 -      int max_pixel_rate = 0;
 +      unsigned max_pixel_rate = 0, i;
 +      enum pipe pipe;
  
 -      for_each_intel_crtc(state->dev, intel_crtc) {
 -              int pixel_rate;
 +      memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
 +             sizeof(intel_state->min_pixclk));
  
 -              crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
 -              if (IS_ERR(crtc_state))
 -                      return PTR_ERR(crtc_state);
 +      for_each_crtc_in_state(state, crtc, cstate, i) {
 +              int pixel_rate;
  
 -              if (!crtc_state->base.enable)
 +              crtc_state = to_intel_crtc_state(cstate);
 +              if (!crtc_state->base.enable) {
 +                      intel_state->min_pixclk[i] = 0;
                        continue;
 +              }
  
                pixel_rate = ilk_pipe_pixel_rate(crtc_state);
  
                /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
 -              if (IS_BROADWELL(state->dev) && crtc_state->ips_enabled)
 +              if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
                        pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
  
 -              max_pixel_rate = max(max_pixel_rate, pixel_rate);
 +              intel_state->min_pixclk[i] = pixel_rate;
        }
  
 +      if (!intel_state->active_crtcs)
 +              return 0;
 +
 +      for_each_pipe(dev_priv, pipe)
 +              max_pixel_rate = max(intel_state->min_pixclk[pipe], max_pixel_rate);
 +
        return max_pixel_rate;
  }
  
@@@ -9839,7 -9783,6 +9837,7 @@@ static void broadwell_set_cdclk(struct 
  static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
  {
        struct drm_i915_private *dev_priv = to_i915(state->dev);
 +      struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        int max_pixclk = ilk_max_pixel_rate(state);
        int cdclk;
  
                return -EINVAL;
        }
  
 -      to_intel_atomic_state(state)->cdclk = cdclk;
 +      intel_state->cdclk = intel_state->dev_cdclk = cdclk;
 +      if (!intel_state->active_crtcs)
 +              intel_state->dev_cdclk = 337500;
  
        return 0;
  }
  static void broadwell_modeset_commit_cdclk(struct drm_atomic_state *old_state)
  {
        struct drm_device *dev = old_state->dev;
 -      unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
 +      struct intel_atomic_state *old_intel_state =
 +              to_intel_atomic_state(old_state);
 +      unsigned req_cdclk = old_intel_state->dev_cdclk;
  
        broadwell_set_cdclk(dev, req_cdclk);
  }
@@@ -10087,17 -10026,16 +10085,17 @@@ static bool haswell_get_pipe_config(str
        return true;
  }
  
 -static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
 +static void i845_update_cursor(struct drm_crtc *crtc, u32 base,
 +                             const struct intel_plane_state *plane_state)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t cntl = 0, size = 0;
  
 -      if (on) {
 -              unsigned int width = intel_crtc->base.cursor->state->crtc_w;
 -              unsigned int height = intel_crtc->base.cursor->state->crtc_h;
 +      if (plane_state && plane_state->visible) {
 +              unsigned int width = plane_state->base.crtc_w;
 +              unsigned int height = plane_state->base.crtc_h;
                unsigned int stride = roundup_pow_of_two(width) * 4;
  
                switch (stride) {
        }
  }
  
 -static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
 +static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base,
 +                             const struct intel_plane_state *plane_state)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = intel_crtc->pipe;
        uint32_t cntl = 0;
  
 -      if (on) {
 +      if (plane_state && plane_state->visible) {
                cntl = MCURSOR_GAMMA_ENABLE;
 -              switch (intel_crtc->base.cursor->state->crtc_w) {
 +              switch (plane_state->base.crtc_w) {
                        case 64:
                                cntl |= CURSOR_MODE_64_ARGB_AX;
                                break;
                                cntl |= CURSOR_MODE_256_ARGB_AX;
                                break;
                        default:
 -                              MISSING_CASE(intel_crtc->base.cursor->state->crtc_w);
 +                              MISSING_CASE(plane_state->base.crtc_w);
                                return;
                }
                cntl |= pipe << 28; /* Connect to correct pipe */
  
                if (HAS_DDI(dev))
                        cntl |= CURSOR_PIPE_CSC_ENABLE;
 -      }
  
 -      if (crtc->cursor->state->rotation == BIT(DRM_ROTATE_180))
 -              cntl |= CURSOR_ROTATE_180;
 +              if (plane_state->base.rotation == BIT(DRM_ROTATE_180))
 +                      cntl |= CURSOR_ROTATE_180;
 +      }
  
        if (intel_crtc->cursor_cntl != cntl) {
                I915_WRITE(CURCNTR(pipe), cntl);
  
  /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
  static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 -                                   bool on)
 +                                   const struct intel_plane_state *plane_state)
  {
        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;
 -      struct drm_plane_state *cursor_state = crtc->cursor->state;
 -      int x = cursor_state->crtc_x;
 -      int y = cursor_state->crtc_y;
 -      u32 base = 0, pos = 0;
 -
 -      base = intel_crtc->cursor_addr;
 -
 -      if (x >= intel_crtc->config->pipe_src_w)
 -              on = false;
 +      u32 base = intel_crtc->cursor_addr;
 +      u32 pos = 0;
  
 -      if (y >= intel_crtc->config->pipe_src_h)
 -              on = false;
 +      if (plane_state) {
 +              int x = plane_state->base.crtc_x;
 +              int y = plane_state->base.crtc_y;
  
 -      if (x < 0) {
 -              if (x + cursor_state->crtc_w <= 0)
 -                      on = false;
 -
 -              pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
 -              x = -x;
 -      }
 -      pos |= x << CURSOR_X_SHIFT;
 +              if (x < 0) {
 +                      pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
 +                      x = -x;
 +              }
 +              pos |= x << CURSOR_X_SHIFT;
  
 -      if (y < 0) {
 -              if (y + cursor_state->crtc_h <= 0)
 -                      on = false;
 +              if (y < 0) {
 +                      pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
 +                      y = -y;
 +              }
 +              pos |= y << CURSOR_Y_SHIFT;
  
 -              pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
 -              y = -y;
 +              /* ILK+ do this automagically */
 +              if (HAS_GMCH_DISPLAY(dev) &&
 +                  plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
 +                      base += (plane_state->base.crtc_h *
 +                               plane_state->base.crtc_w - 1) * 4;
 +              }
        }
 -      pos |= y << CURSOR_Y_SHIFT;
  
        I915_WRITE(CURPOS(pipe), pos);
  
 -      /* ILK+ do this automagically */
 -      if (HAS_GMCH_DISPLAY(dev) &&
 -          crtc->cursor->state->rotation == BIT(DRM_ROTATE_180)) {
 -              base += (cursor_state->crtc_h *
 -                       cursor_state->crtc_w - 1) * 4;
 -      }
 -
        if (IS_845G(dev) || IS_I865G(dev))
 -              i845_update_cursor(crtc, base, on);
 +              i845_update_cursor(crtc, base, plane_state);
        else
 -              i9xx_update_cursor(crtc, base, on);
 +              i9xx_update_cursor(crtc, base, plane_state);
  }
  
  static bool cursor_size_ok(struct drm_device *dev,
@@@ -11371,12 -11319,13 +11369,12 @@@ static void skl_do_mmio_flip(struct int
         */
        if (intel_rotation_90_or_270(rotation)) {
                /* stride = Surface height in tiles */
 -              tile_height = intel_tile_height(dev, fb->pixel_format,
 -                                              fb->modifier[0], 0);
 +              tile_height = intel_tile_height(dev_priv, fb->modifier[0], 0);
                stride = DIV_ROUND_UP(fb->height, tile_height);
        } else {
                stride = fb->pitches[0] /
 -                              intel_fb_stride_alignment(dev, fb->modifier[0],
 -                                                        fb->pixel_format);
 +                      intel_fb_stride_alignment(dev_priv, fb->modifier[0],
 +                                                fb->pixel_format);
        }
  
        /*
@@@ -11882,13 -11831,8 +11880,13 @@@ int intel_plane_atomic_calc_changes(str
        if (!was_crtc_enabled && WARN_ON(was_visible))
                was_visible = false;
  
 -      if (!is_crtc_enabled && WARN_ON(visible))
 -              visible = false;
 +      /*
 +       * Visibility is calculated as if the crtc was on, but
 +       * after scaler setup everything depends on it being off
 +       * when the crtc isn't active.
 +       */
 +      if (!is_crtc_enabled)
 +              to_intel_plane_state(plane_state)->visible = visible = false;
  
        if (!was_visible && !visible)
                return 0;
                pipe_config->wm_changed = true;
        }
  
 +      /* Pre-gen9 platforms need two-step watermark updates */
 +      if (pipe_config->wm_changed && INTEL_INFO(dev)->gen < 9 &&
 +          dev_priv->display.optimize_watermarks)
 +              to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
 +
        if (visible || was_visible)
                intel_crtc->atomic.fb_bits |=
                        to_intel_plane(plane)->frontbuffer_bit;
@@@ -12077,29 -12016,8 +12075,29 @@@ static int intel_crtc_atomic_check(stru
        ret = 0;
        if (dev_priv->display.compute_pipe_wm) {
                ret = dev_priv->display.compute_pipe_wm(intel_crtc, state);
 -              if (ret)
 +              if (ret) {
 +                      DRM_DEBUG_KMS("Target pipe watermarks are invalid\n");
                        return ret;
 +              }
 +      }
 +
 +      if (dev_priv->display.compute_intermediate_wm &&
 +          !to_intel_atomic_state(state)->skip_intermediate_wm) {
 +              if (WARN_ON(!dev_priv->display.compute_pipe_wm))
 +                      return 0;
 +
 +              /*
 +               * Calculate 'intermediate' watermarks that satisfy both the
 +               * old state and the new state.  We can program these
 +               * immediately.
 +               */
 +              ret = dev_priv->display.compute_intermediate_wm(crtc->dev,
 +                                                              intel_crtc,
 +                                                              pipe_config);
 +              if (ret) {
 +                      DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n");
 +                      return ret;
 +              }
        }
  
        if (INTEL_INFO(dev)->gen >= 9) {
@@@ -12157,21 -12075,11 +12155,21 @@@ connected_sink_compute_bpp(struct intel
                pipe_config->pipe_bpp = connector->base.display_info.bpc*3;
        }
  
 -      /* Clamp bpp to 8 on screens without EDID 1.4 */
 -      if (connector->base.display_info.bpc == 0 && bpp > 24) {
 -              DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
 -                            bpp);
 -              pipe_config->pipe_bpp = 24;
 +      /* Clamp bpp to default limit on screens without EDID 1.4 */
 +      if (connector->base.display_info.bpc == 0) {
 +              int type = connector->base.connector_type;
 +              int clamp_bpp = 24;
 +
 +              /* Fall back to 18 bpp when DP sink capability is unknown. */
 +              if (type == DRM_MODE_CONNECTOR_DisplayPort ||
 +                  type == DRM_MODE_CONNECTOR_eDP)
 +                      clamp_bpp = 18;
 +
 +              if (bpp > clamp_bpp) {
 +                      DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of %d\n",
 +                                    bpp, clamp_bpp);
 +                      pipe_config->pipe_bpp = clamp_bpp;
 +              }
        }
  }
  
@@@ -12360,22 -12268,18 +12358,22 @@@ static void intel_dump_pipe_config(stru
  static bool check_digital_port_conflicts(struct drm_atomic_state *state)
  {
        struct drm_device *dev = state->dev;
 -      struct intel_encoder *encoder;
        struct drm_connector *connector;
 -      struct drm_connector_state *connector_state;
        unsigned int used_ports = 0;
 -      int i;
  
        /*
         * Walk the connector list instead of the encoder
         * list to detect the problem on ddi platforms
         * where there's just one encoder per digital port.
         */
 -      for_each_connector_in_state(state, connector, connector_state, i) {
 +      drm_for_each_connector(connector, dev) {
 +              struct drm_connector_state *connector_state;
 +              struct intel_encoder *encoder;
 +
 +              connector_state = drm_atomic_get_existing_connector_state(state, connector);
 +              if (!connector_state)
 +                      connector_state = connector->state;
 +
                if (!connector_state->best_encoder)
                        continue;
  
@@@ -12611,22 -12515,19 +12609,22 @@@ intel_compare_m_n(unsigned int m, unsig
  
        BUILD_BUG_ON(DATA_LINK_M_N_MASK > INT_MAX);
  
 -      if (m > m2) {
 -              while (m > m2) {
 +      if (n > n2) {
 +              while (n > n2) {
                        m2 <<= 1;
                        n2 <<= 1;
                }
 -      } else if (m < m2) {
 -              while (m < m2) {
 +      } else if (n < n2) {
 +              while (n < n2) {
                        m <<= 1;
                        n <<= 1;
                }
        }
  
 -      return m == m2 && n == n2;
 +      if (n != n2)
 +              return false;
 +
 +      return intel_fuzzy_clock_check(m, m2);
  }
  
  static bool
@@@ -13301,27 -13202,15 +13299,27 @@@ static int intel_modeset_all_pipes(stru
  
  static int intel_modeset_checks(struct drm_atomic_state *state)
  {
 -      struct drm_device *dev = state->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -      int ret;
 +      struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 +      struct drm_i915_private *dev_priv = state->dev->dev_private;
 +      struct drm_crtc *crtc;
 +      struct drm_crtc_state *crtc_state;
 +      int ret = 0, i;
  
        if (!check_digital_port_conflicts(state)) {
                DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
                return -EINVAL;
        }
  
 +      intel_state->modeset = true;
 +      intel_state->active_crtcs = dev_priv->active_crtcs;
 +
 +      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 +              if (crtc_state->active)
 +                      intel_state->active_crtcs |= 1 << i;
 +              else
 +                      intel_state->active_crtcs &= ~(1 << i);
 +      }
 +
        /*
         * See if the config requires any additional preparation, e.g.
         * to adjust global state with pipes off.  We need to do this
         * adjusted_mode bits in the crtc directly.
         */
        if (dev_priv->display.modeset_calc_cdclk) {
 -              unsigned int cdclk;
 -
                ret = dev_priv->display.modeset_calc_cdclk(state);
  
 -              cdclk = to_intel_atomic_state(state)->cdclk;
 -              if (!ret && cdclk != dev_priv->cdclk_freq)
 +              if (!ret && intel_state->dev_cdclk != dev_priv->cdclk_freq)
                        ret = intel_modeset_all_pipes(state);
  
                if (ret < 0)
                        return ret;
        } else
 -              to_intel_atomic_state(state)->cdclk = dev_priv->cdclk_freq;
 +              to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq;
  
        intel_modeset_clear_plls(state);
  
 -      if (IS_HASWELL(dev))
 +      if (IS_HASWELL(dev_priv))
                return haswell_mode_set_planes_workaround(state);
  
        return 0;
@@@ -13560,13 -13452,12 +13558,13 @@@ static int intel_atomic_commit(struct d
                               struct drm_atomic_state *state,
                               bool async)
  {
 +      struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc_state *crtc_state;
        struct drm_crtc *crtc;
 -      int ret = 0;
 -      int i;
 -      bool any_ms = false;
 +      struct intel_crtc_state *intel_cstate;
 +      int ret = 0, i;
 +      bool hw_check = intel_state->modeset;
  
        ret = intel_atomic_prepare_commit(dev, state, async);
        if (ret) {
        drm_atomic_helper_swap_state(dev, state);
        dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
  
 +      if (intel_state->modeset) {
 +              memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
 +                     sizeof(intel_state->min_pixclk));
 +              dev_priv->active_crtcs = intel_state->active_crtcs;
 +              dev_priv->atomic_cdclk_freq = intel_state->cdclk;
 +      }
 +
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  
                if (!needs_modeset(crtc->state))
                        continue;
  
 -              any_ms = true;
                intel_pre_plane_update(intel_crtc);
  
                if (crtc_state->active) {
         * update the the output configuration. */
        intel_modeset_update_crtc_state(state);
  
 -      if (any_ms) {
 +      if (intel_state->modeset) {
                intel_shared_dpll_commit(state);
  
                drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
                        put_domains = modeset_get_crtc_power_domains(crtc);
  
                        /* make sure intel_modeset_check_state runs */
 -                      any_ms = true;
 +                      hw_check = true;
                }
  
                if (!modeset)
  
        drm_atomic_helper_wait_for_vblanks(dev, state);
  
 +      /*
 +       * Now that the vblank has passed, we can go ahead and program the
 +       * optimal watermarks on platforms that need two-step watermark
 +       * programming.
 +       *
 +       * TODO: Move this (and other cleanup) to an async worker eventually.
 +       */
 +      for_each_crtc_in_state(state, crtc, crtc_state, i) {
 +              intel_cstate = to_intel_crtc_state(crtc->state);
 +
 +              if (dev_priv->display.optimize_watermarks)
 +                      dev_priv->display.optimize_watermarks(intel_cstate);
 +      }
 +
        mutex_lock(&dev->struct_mutex);
        drm_atomic_helper_cleanup_planes(dev, state);
        mutex_unlock(&dev->struct_mutex);
  
 -      if (any_ms)
 +      if (hw_check)
                intel_modeset_check_state(dev, state);
  
        drm_atomic_state_free(state);
  
 +      /* As one of the primary mmio accessors, KMS has a high likelihood
 +       * of triggering bugs in unclaimed access. After we finish
 +       * modesetting, see if an error has been flagged, and if so
 +       * enable debugging for the next modeset - and hope we catch
 +       * the culprit.
 +       *
 +       * XXX note that we assume display power is on at this point.
 +       * This might hold true now but we need to add pm helper to check
 +       * unclaimed only when the hardware is on, as atomic commits
 +       * can happen also when the device is completely off.
 +       */
 +      intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
 +
        return 0;
  }
  
@@@ -13988,7 -13846,7 +13986,7 @@@ skl_max_scale(struct intel_crtc *intel_
        struct drm_i915_private *dev_priv;
        int crtc_clock, cdclk;
  
 -      if (!intel_crtc || !crtc_state)
 +      if (!intel_crtc || !crtc_state->base.enable)
                return DRM_PLANE_HELPER_NO_SCALING;
  
        dev = intel_crtc->base.dev;
@@@ -14036,6 -13894,32 +14034,6 @@@ intel_check_primary_plane(struct drm_pl
                                             &state->visible);
  }
  
 -static void
 -intel_commit_primary_plane(struct drm_plane *plane,
 -                         struct intel_plane_state *state)
 -{
 -      struct drm_crtc *crtc = state->base.crtc;
 -      struct drm_framebuffer *fb = state->base.fb;
 -      struct drm_device *dev = plane->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -
 -      crtc = crtc ? crtc : plane->crtc;
 -
 -      dev_priv->display.update_primary_plane(crtc, fb,
 -                                             state->src.x1 >> 16,
 -                                             state->src.y1 >> 16);
 -}
 -
 -static void
 -intel_disable_primary_plane(struct drm_plane *plane,
 -                          struct drm_crtc *crtc)
 -{
 -      struct drm_device *dev = plane->dev;
 -      struct drm_i915_private *dev_priv = dev->dev_private;
 -
 -      dev_priv->display.update_primary_plane(crtc, NULL, 0, 0);
 -}
 -
  static void intel_begin_crtc_commit(struct drm_crtc *crtc,
                                    struct drm_crtc_state *old_crtc_state)
  {
@@@ -14120,39 -14004,26 +14118,39 @@@ static struct drm_plane *intel_primary_
        primary->plane = pipe;
        primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe);
        primary->check_plane = intel_check_primary_plane;
 -      primary->commit_plane = intel_commit_primary_plane;
 -      primary->disable_plane = intel_disable_primary_plane;
        if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
                primary->plane = !pipe;
  
        if (INTEL_INFO(dev)->gen >= 9) {
                intel_primary_formats = skl_primary_formats;
                num_formats = ARRAY_SIZE(skl_primary_formats);
 +
 +              primary->update_plane = skylake_update_primary_plane;
 +              primary->disable_plane = skylake_disable_primary_plane;
 +      } else if (HAS_PCH_SPLIT(dev)) {
 +              intel_primary_formats = i965_primary_formats;
 +              num_formats = ARRAY_SIZE(i965_primary_formats);
 +
 +              primary->update_plane = ironlake_update_primary_plane;
 +              primary->disable_plane = i9xx_disable_primary_plane;
        } else if (INTEL_INFO(dev)->gen >= 4) {
                intel_primary_formats = i965_primary_formats;
                num_formats = ARRAY_SIZE(i965_primary_formats);
 +
 +              primary->update_plane = i9xx_update_primary_plane;
 +              primary->disable_plane = i9xx_disable_primary_plane;
        } else {
                intel_primary_formats = i8xx_primary_formats;
                num_formats = ARRAY_SIZE(i8xx_primary_formats);
 +
 +              primary->update_plane = i9xx_update_primary_plane;
 +              primary->disable_plane = i9xx_disable_primary_plane;
        }
  
        drm_universal_plane_init(dev, &primary->base, 0,
                                 &intel_plane_funcs,
                                 intel_primary_formats, num_formats,
-                                DRM_PLANE_TYPE_PRIMARY);
+                                DRM_PLANE_TYPE_PRIMARY, NULL);
  
        if (INTEL_INFO(dev)->gen >= 4)
                intel_create_rotation_property(dev, primary);
@@@ -14245,23 -14116,22 +14243,23 @@@ static voi
  intel_disable_cursor_plane(struct drm_plane *plane,
                           struct drm_crtc *crtc)
  {
 -      intel_crtc_update_cursor(crtc, false);
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 +
 +      intel_crtc->cursor_addr = 0;
 +      intel_crtc_update_cursor(crtc, NULL);
  }
  
  static void
 -intel_commit_cursor_plane(struct drm_plane *plane,
 -                        struct intel_plane_state *state)
 +intel_update_cursor_plane(struct drm_plane *plane,
 +                        const struct intel_crtc_state *crtc_state,
 +                        const struct intel_plane_state *state)
  {
 -      struct drm_crtc *crtc = state->base.crtc;
 +      struct drm_crtc *crtc = crtc_state->base.crtc;
 +      struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_device *dev = plane->dev;
 -      struct intel_crtc *intel_crtc;
        struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
        uint32_t addr;
  
 -      crtc = crtc ? crtc : plane->crtc;
 -      intel_crtc = to_intel_crtc(crtc);
 -
        if (!obj)
                addr = 0;
        else if (!INTEL_INFO(dev)->cursor_needs_physical)
                addr = obj->phys_handle->busaddr;
  
        intel_crtc->cursor_addr = addr;
 -
 -      if (crtc->state->active)
 -              intel_crtc_update_cursor(crtc, state->visible);
 +      intel_crtc_update_cursor(crtc, state);
  }
  
  static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
        cursor->plane = pipe;
        cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe);
        cursor->check_plane = intel_check_cursor_plane;
 -      cursor->commit_plane = intel_commit_cursor_plane;
 +      cursor->update_plane = intel_update_cursor_plane;
        cursor->disable_plane = intel_disable_cursor_plane;
  
        drm_universal_plane_init(dev, &cursor->base, 0,
                                 &intel_plane_funcs,
                                 intel_cursor_formats,
                                 ARRAY_SIZE(intel_cursor_formats),
-                                DRM_PLANE_TYPE_CURSOR);
+                                DRM_PLANE_TYPE_CURSOR, NULL);
  
        if (INTEL_INFO(dev)->gen >= 4) {
                if (!dev->mode_config.rotation_property)
@@@ -14380,7 -14252,7 +14378,7 @@@ static void intel_crtc_init(struct drm_
                goto fail;
  
        ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary,
-                                       cursor, &intel_crtc_funcs);
+                                       cursor, &intel_crtc_funcs, NULL);
        if (ret)
                goto fail;
  
@@@ -14770,7 -14642,6 +14768,7 @@@ static int intel_framebuffer_init(struc
                                  struct drm_mode_fb_cmd2 *mode_cmd,
                                  struct drm_i915_gem_object *obj)
  {
 +      struct drm_i915_private *dev_priv = to_i915(dev);
        unsigned int aligned_height;
        int ret;
        u32 pitch_limit, stride_alignment;
                return -EINVAL;
        }
  
 -      stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0],
 +      stride_alignment = intel_fb_stride_alignment(dev_priv,
 +                                                   mode_cmd->modifier[0],
                                                     mode_cmd->pixel_format);
        if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
                DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
  
        drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
        intel_fb->obj = obj;
 -      intel_fb->obj->framebuffer_references++;
  
        ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
        if (ret) {
                return ret;
        }
  
 +      intel_fb->obj->framebuffer_references++;
 +
        return 0;
  }
  
@@@ -14977,6 -14846,8 +14975,6 @@@ static void intel_init_display(struct d
                        haswell_crtc_compute_clock;
                dev_priv->display.crtc_enable = haswell_crtc_enable;
                dev_priv->display.crtc_disable = haswell_crtc_disable;
 -              dev_priv->display.update_primary_plane =
 -                      skylake_update_primary_plane;
        } else if (HAS_DDI(dev)) {
                dev_priv->display.get_pipe_config = haswell_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                        haswell_crtc_compute_clock;
                dev_priv->display.crtc_enable = haswell_crtc_enable;
                dev_priv->display.crtc_disable = haswell_crtc_disable;
 -              dev_priv->display.update_primary_plane =
 -                      ironlake_update_primary_plane;
        } else if (HAS_PCH_SPLIT(dev)) {
                dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                        ironlake_crtc_compute_clock;
                dev_priv->display.crtc_enable = ironlake_crtc_enable;
                dev_priv->display.crtc_disable = ironlake_crtc_disable;
 -              dev_priv->display.update_primary_plane =
 -                      ironlake_update_primary_plane;
        } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
                dev_priv->display.crtc_enable = valleyview_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
 -              dev_priv->display.update_primary_plane =
 -                      i9xx_update_primary_plane;
        } else {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
                dev_priv->display.crtc_enable = i9xx_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
 -              dev_priv->display.update_primary_plane =
 -                      i9xx_update_primary_plane;
        }
  
        /* Returns the core display clock speed */
@@@ -15312,97 -15191,12 +15310,97 @@@ static void i915_disable_vga(struct drm
  
  void intel_modeset_init_hw(struct drm_device *dev)
  {
 +      struct drm_i915_private *dev_priv = dev->dev_private;
 +
        intel_update_cdclk(dev);
 -      intel_prepare_ddi(dev);
 +
 +      dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
 +
        intel_init_clock_gating(dev);
        intel_enable_gt_powersave(dev);
  }
  
 +/*
 + * Calculate what we think the watermarks should be for the state we've read
 + * out of the hardware and then immediately program those watermarks so that
 + * we ensure the hardware settings match our internal state.
 + *
 + * We can calculate what we think WM's should be by creating a duplicate of the
 + * current state (which was constructed during hardware readout) and running it
 + * through the atomic check code to calculate new watermark values in the
 + * state object.
 + */
 +static void sanitize_watermarks(struct drm_device *dev)
 +{
 +      struct drm_i915_private *dev_priv = to_i915(dev);
 +      struct drm_atomic_state *state;
 +      struct drm_crtc *crtc;
 +      struct drm_crtc_state *cstate;
 +      struct drm_modeset_acquire_ctx ctx;
 +      int ret;
 +      int i;
 +
 +      /* Only supported on platforms that use atomic watermark design */
 +      if (!dev_priv->display.optimize_watermarks)
 +              return;
 +
 +      /*
 +       * We need to hold connection_mutex before calling duplicate_state so
 +       * that the connector loop is protected.
 +       */
 +      drm_modeset_acquire_init(&ctx, 0);
 +retry:
 +      ret = drm_modeset_lock_all_ctx(dev, &ctx);
 +      if (ret == -EDEADLK) {
 +              drm_modeset_backoff(&ctx);
 +              goto retry;
 +      } else if (WARN_ON(ret)) {
 +              goto fail;
 +      }
 +
 +      state = drm_atomic_helper_duplicate_state(dev, &ctx);
 +      if (WARN_ON(IS_ERR(state)))
 +              goto fail;
 +
 +      /*
 +       * Hardware readout is the only time we don't want to calculate
 +       * intermediate watermarks (since we don't trust the current
 +       * watermarks).
 +       */
 +      to_intel_atomic_state(state)->skip_intermediate_wm = true;
 +
 +      ret = intel_atomic_check(dev, state);
 +      if (ret) {
 +              /*
 +               * If we fail here, it means that the hardware appears to be
 +               * programmed in a way that shouldn't be possible, given our
 +               * understanding of watermark requirements.  This might mean a
 +               * mistake in the hardware readout code or a mistake in the
 +               * watermark calculations for a given platform.  Raise a WARN
 +               * so that this is noticeable.
 +               *
 +               * If this actually happens, we'll have to just leave the
 +               * BIOS-programmed watermarks untouched and hope for the best.
 +               */
 +              WARN(true, "Could not determine valid watermarks for inherited state\n");
 +              goto fail;
 +      }
 +
 +      /* Write calculated watermark values back */
 +      to_i915(dev)->wm.config = to_intel_atomic_state(state)->wm_config;
 +      for_each_crtc_in_state(state, crtc, cstate, i) {
 +              struct intel_crtc_state *cs = to_intel_crtc_state(cstate);
 +
 +              cs->wm.need_postvbl_update = true;
 +              dev_priv->display.optimize_watermarks(cs);
 +      }
 +
 +      drm_atomic_state_free(state);
 +fail:
 +      drm_modeset_drop_locks(&ctx);
 +      drm_modeset_acquire_fini(&ctx);
 +}
 +
  void intel_modeset_init(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
                 */
                intel_find_initial_plane_obj(crtc, &plane_config);
        }
 +
 +      /*
 +       * Make sure hardware watermarks really match the state we read out.
 +       * Note that we need to do this after reconstructing the BIOS fb's
 +       * since the watermark calculation done here will use pstate->fb.
 +       */
 +      sanitize_watermarks(dev);
  }
  
  static void intel_enable_pipe_a(struct drm_device *dev)
@@@ -15659,6 -15446,7 +15657,7 @@@ static void intel_sanitize_crtc(struct 
                WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, NULL) < 0);
                crtc->base.state->active = crtc->active;
                crtc->base.enabled = crtc->active;
+               crtc->base.state->connector_mask = 0;
  
                /* Because we only establish the connector -> encoder ->
                 * crtc links if something is active, this means the
@@@ -15801,40 -15589,16 +15800,40 @@@ static void intel_modeset_readout_hw_st
        struct intel_connector *connector;
        int i;
  
 +      dev_priv->active_crtcs = 0;
 +
        for_each_intel_crtc(dev, crtc) {
 -              __drm_atomic_helper_crtc_destroy_state(&crtc->base, crtc->base.state);
 -              memset(crtc->config, 0, sizeof(*crtc->config));
 -              crtc->config->base.crtc = &crtc->base;
 +              struct intel_crtc_state *crtc_state = crtc->config;
 +              int pixclk = 0;
  
 -              crtc->active = dev_priv->display.get_pipe_config(crtc,
 -                                                               crtc->config);
 +              __drm_atomic_helper_crtc_destroy_state(&crtc->base, &crtc_state->base);
 +              memset(crtc_state, 0, sizeof(*crtc_state));
 +              crtc_state->base.crtc = &crtc->base;
  
 -              crtc->base.state->active = crtc->active;
 -              crtc->base.enabled = crtc->active;
 +              crtc_state->base.active = crtc_state->base.enable =
 +                      dev_priv->display.get_pipe_config(crtc, crtc_state);
 +
 +              crtc->base.enabled = crtc_state->base.enable;
 +              crtc->active = crtc_state->base.active;
 +
 +              if (crtc_state->base.active) {
 +                      dev_priv->active_crtcs |= 1 << crtc->pipe;
 +
 +                      if (IS_BROADWELL(dev_priv)) {
 +                              pixclk = ilk_pipe_pixel_rate(crtc_state);
 +
 +                              /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
 +                              if (crtc_state->ips_enabled)
 +                                      pixclk = DIV_ROUND_UP(pixclk * 100, 95);
 +                      } else if (IS_VALLEYVIEW(dev_priv) ||
 +                                 IS_CHERRYVIEW(dev_priv) ||
 +                                 IS_BROXTON(dev_priv))
 +                              pixclk = crtc_state->base.adjusted_mode.crtc_clock;
 +                      else
 +                              WARN_ON(dev_priv->display.modeset_calc_cdclk);
 +              }
 +
 +              dev_priv->min_pixclk[crtc->pipe] = pixclk;
  
                readout_plane_state(crtc);
  
        for_each_intel_connector(dev, connector) {
                if (connector->get_hw_state(connector)) {
                        connector->base.dpms = DRM_MODE_DPMS_ON;
-                       connector->base.encoder = &connector->encoder->base;
+                       encoder = connector->encoder;
+                       connector->base.encoder = &encoder->base;
+                       if (encoder->base.crtc &&
+                           encoder->base.crtc->state->active) {
+                               /*
+                                * This has to be done during hardware readout
+                                * because anything calling .crtc_disable may
+                                * rely on the connector_mask being accurate.
+                                */
+                               encoder->base.crtc->state->connector_mask |=
+                                       1 << drm_connector_index(&connector->base);
+                       }
                } else {
                        connector->base.dpms = DRM_MODE_DPMS_OFF;
                        connector->base.encoder = NULL;
@@@ -16130,6 -15908,8 +16143,8 @@@ void intel_modeset_cleanup(struct drm_d
        mutex_lock(&dev->struct_mutex);
        intel_cleanup_gt_powersave(dev);
        mutex_unlock(&dev->struct_mutex);
+       intel_teardown_gmbus(dev);
  }
  
  /*
@@@ -16322,7 -16102,7 +16337,7 @@@ intel_display_print_error_state(struct 
        for_each_pipe(dev_priv, i) {
                err_printf(m, "Pipe [%d]:\n", i);
                err_printf(m, "  Power: %s\n",
 -                         error->pipe[i].power_domain_on ? "on" : "off");
 +                         onoff(error->pipe[i].power_domain_on));
                err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
                err_printf(m, "  STAT: %08x\n", error->pipe[i].stat);
  
                err_printf(m, "CPU transcoder: %c\n",
                           transcoder_name(error->transcoder[i].cpu_transcoder));
                err_printf(m, "  Power: %s\n",
 -                         error->transcoder[i].power_domain_on ? "on" : "off");
 +                         onoff(error->transcoder[i].power_domain_on));
                err_printf(m, "  CONF: %08x\n", error->transcoder[i].conf);
                err_printf(m, "  HTOTAL: %08x\n", error->transcoder[i].htotal);
                err_printf(m, "  HBLANK: %08x\n", error->transcoder[i].hblank);
index 3999afa440bd508c91e9022e56334caae04a2951,796e3d313cb975efc3797a39b15beb8e55ab7f92..17612548c58d63733bfa59b6388342a719ba7e48
@@@ -157,9 -157,14 +157,9 @@@ intel_dp_max_link_bw(struct intel_dp  *
  static u8 intel_dp_max_lane_count(struct intel_dp *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;
        u8 source_max, sink_max;
  
 -      source_max = 4;
 -      if (HAS_DDI(dev) && intel_dig_port->port == PORT_A &&
 -          (intel_dig_port->saved_port_bits & DDI_A_4_LANES) == 0)
 -              source_max = 2;
 -
 +      source_max = intel_dig_port->max_lanes;
        sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
  
        return min(source_max, sink_max);
@@@ -2238,6 -2243,11 +2238,6 @@@ static void intel_edp_backlight_power(s
                _intel_edp_backlight_off(intel_dp);
  }
  
 -static const char *state_string(bool enabled)
 -{
 -      return enabled ? "on" : "off";
 -}
 -
  static void assert_dp_port(struct intel_dp *intel_dp, bool state)
  {
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
        I915_STATE_WARN(cur_state != state,
                        "DP port %c state assertion failure (expected %s, current %s)\n",
                        port_name(dig_port->port),
 -                      state_string(state), state_string(cur_state));
 +                      onoff(state), onoff(cur_state));
  }
  #define assert_dp_port_disabled(d) assert_dp_port((d), false)
  
@@@ -2257,7 -2267,7 +2257,7 @@@ static void assert_edp_pll(struct drm_i
  
        I915_STATE_WARN(cur_state != state,
                        "eDP PLL state assertion failure (expected %s, current %s)\n",
 -                      state_string(state), state_string(cur_state));
 +                      onoff(state), onoff(cur_state));
  }
  #define assert_edp_pll_enabled(d) assert_edp_pll((d), true)
  #define assert_edp_pll_disabled(d) assert_edp_pll((d), false)
@@@ -5829,11 -5839,6 +5829,11 @@@ intel_dp_init_connector(struct intel_di
        enum port port = intel_dig_port->port;
        int type, ret;
  
 +      if (WARN(intel_dig_port->max_lanes < 1,
 +               "Not enough lanes (%d) for DP on port %c\n",
 +               intel_dig_port->max_lanes, port_name(port)))
 +              return false;
 +
        intel_dp->pps_pipe = INVALID_PIPE;
  
        /* intel_dp vfuncs */
@@@ -6003,7 -6008,7 +6003,7 @@@ intel_dp_init(struct drm_device *dev
        encoder = &intel_encoder->base;
  
        if (drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
-                            DRM_MODE_ENCODER_TMDS))
+                            DRM_MODE_ENCODER_TMDS, NULL))
                goto err_encoder_init;
  
        intel_encoder->compute_config = intel_dp_compute_config;
        intel_dig_port->port = port;
        dev_priv->dig_port_map[port] = intel_encoder;
        intel_dig_port->dp.output_reg = output_reg;
 +      intel_dig_port->max_lanes = 4;
  
        intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
        if (IS_CHERRYVIEW(dev)) {
index 6f4762dc5a94be08e3eac3c09475081bd1c2595d,fa0dabf578dc51c7b2371ecc9a1f1342b345892f..2a2ab306ad8457f523c06ffdfc543e847d2ebe4a
@@@ -184,9 -184,7 +184,9 @@@ static void intel_mst_pre_enable_dp(str
        intel_mst->port = found->port;
  
        if (intel_dp->active_mst_links == 0) {
 -              intel_ddi_clk_select(encoder, intel_crtc->config);
 +              intel_prepare_ddi_buffer(&intel_dig_port->base);
 +
 +              intel_ddi_clk_select(&intel_dig_port->base, intel_crtc->config);
  
                intel_dp_set_link_params(intel_dp, intel_crtc->config);
  
@@@ -536,7 -534,7 +536,7 @@@ static void intel_dp_mst_hotplug(struc
        drm_kms_helper_hotplug_event(dev);
  }
  
- static struct drm_dp_mst_topology_cbs mst_cbs = {
+ static const struct drm_dp_mst_topology_cbs mst_cbs = {
        .add_connector = intel_dp_add_mst_connector,
        .register_connector = intel_dp_register_mst_connector,
        .destroy_connector = intel_dp_destroy_mst_connector,
@@@ -560,7 -558,7 +560,7 @@@ intel_dp_create_fake_mst_encoder(struc
        intel_mst->primary = intel_dig_port;
  
        drm_encoder_init(dev, &intel_encoder->base, &intel_dp_mst_enc_funcs,
-                        DRM_MODE_ENCODER_DPMST);
+                        DRM_MODE_ENCODER_DPMST, NULL);
  
        intel_encoder->type = INTEL_OUTPUT_DP_MST;
        intel_encoder->crtc_mask = 0x7;
index 328cd58cb5fec9fd89fe24080bcf64f025e7e9ea,44742fa2f616dd22fc25847b0f4ddb5730e550de..91cef3525c93b899382b7d8891dcb4d1d2199bf5
@@@ -702,7 -702,7 +702,7 @@@ static bool intel_dsi_get_hw_state(stru
  static void intel_dsi_get_config(struct intel_encoder *encoder,
                                 struct intel_crtc_state *pipe_config)
  {
 -      u32 pclk = 0;
 +      u32 pclk;
        DRM_DEBUG_KMS("\n");
  
        pipe_config->has_dsi_encoder = true;
         */
        pipe_config->dpll_hw_state.dpll_md = 0;
  
 -      if (IS_BROXTON(encoder->base.dev))
 -              pclk = bxt_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
 -      else if (IS_VALLEYVIEW(encoder->base.dev) ||
 -               IS_CHERRYVIEW(encoder->base.dev))
 -              pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
 -
 +      pclk = intel_dsi_get_pclk(encoder, pipe_config->pipe_bpp);
        if (!pclk)
                return;
  
@@@ -1138,7 -1143,8 +1138,8 @@@ void intel_dsi_init(struct drm_device *
  
        connector = &intel_connector->base;
  
-       drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI);
+       drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI,
+                        NULL);
  
        intel_encoder->compute_config = intel_dsi_compute_config;
        intel_encoder->pre_enable = intel_dsi_pre_enable;
index d4ed7aa9927e48238b9b41f22ad93196b9dc7583,62141751c2f09c9578fc8e3c223142c9c7277a2c..8698a643d027f70f5dd9a212c8b13eaa8f220e0e
mode 100755,100644..100755
@@@ -1392,7 -1392,7 +1392,7 @@@ intel_hdmi_detect(struct drm_connector 
  
        intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
  
 -      for (try = 0; !live_status && try < 4; try++) {
 +      for (try = 0; !live_status && try < 9; try++) {
                if (try)
                        msleep(10);
                live_status = intel_digital_port_connected(dev_priv,
@@@ -2033,11 -2033,6 +2033,11 @@@ void intel_hdmi_init_connector(struct i
        enum port port = intel_dig_port->port;
        uint8_t alternate_ddc_pin;
  
 +      if (WARN(intel_dig_port->max_lanes < 4,
 +               "Not enough lanes (%d) for HDMI on port %c\n",
 +               intel_dig_port->max_lanes, port_name(port)))
 +              return;
 +
        drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
                           DRM_MODE_CONNECTOR_HDMIA);
        drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
@@@ -2169,7 -2164,7 +2169,7 @@@ void intel_hdmi_init(struct drm_device 
        intel_encoder = &intel_dig_port->base;
  
        drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
-                        DRM_MODE_ENCODER_TMDS);
+                        DRM_MODE_ENCODER_TMDS, NULL);
  
        intel_encoder->compute_config = intel_hdmi_compute_config;
        if (HAS_PCH_SPLIT(dev)) {
        dev_priv->dig_port_map[port] = intel_encoder;
        intel_dig_port->hdmi.hdmi_reg = hdmi_reg;
        intel_dig_port->dp.output_reg = INVALID_MMIO_REG;
 +      intel_dig_port->max_lanes = 4;
  
        intel_hdmi_init_connector(intel_dig_port, intel_connector);
  }
index 22589fce9a50e70caada97e01c084e41c89256cd,4ff7a1f4183eeccf1fbcdea632ca54f3c0ab6d38..0875c8e0ec0a172cae628a85192c6014529c8ad6
@@@ -178,33 -178,28 +178,33 @@@ void intel_pipe_update_end(struct intel
  }
  
  static void
 -skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 -               struct drm_framebuffer *fb,
 -               int crtc_x, int crtc_y,
 -               unsigned int crtc_w, unsigned int crtc_h,
 -               uint32_t x, uint32_t y,
 -               uint32_t src_w, uint32_t src_h)
 +skl_update_plane(struct drm_plane *drm_plane,
 +               const struct intel_crtc_state *crtc_state,
 +               const struct intel_plane_state *plane_state)
  {
        struct drm_device *dev = drm_plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_plane *intel_plane = to_intel_plane(drm_plane);
 +      struct drm_framebuffer *fb = plane_state->base.fb;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        const int pipe = intel_plane->pipe;
        const int plane = intel_plane->plane + 1;
        u32 plane_ctl, stride_div, stride;
 -      const struct drm_intel_sprite_colorkey *key =
 -              &to_intel_plane_state(drm_plane->state)->ckey;
 +      const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
        u32 surf_addr;
        u32 tile_height, plane_offset, plane_size;
        unsigned int rotation;
        int x_offset, y_offset;
 -      struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
 -      int scaler_id;
 +      int crtc_x = plane_state->dst.x1;
 +      int crtc_y = plane_state->dst.y1;
 +      uint32_t crtc_w = drm_rect_width(&plane_state->dst);
 +      uint32_t crtc_h = drm_rect_height(&plane_state->dst);
 +      uint32_t x = plane_state->src.x1 >> 16;
 +      uint32_t y = plane_state->src.y1 >> 16;
 +      uint32_t src_w = drm_rect_width(&plane_state->src) >> 16;
 +      uint32_t src_h = drm_rect_height(&plane_state->src) >> 16;
 +      const struct intel_scaler *scaler =
 +              &crtc_state->scaler_state.scalers[plane_state->scaler_id];
  
        plane_ctl = PLANE_CTL_ENABLE |
                PLANE_CTL_PIPE_GAMMA_ENABLE |
        plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
        plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
  
 -      rotation = drm_plane->state->rotation;
 +      rotation = plane_state->base.rotation;
        plane_ctl |= skl_plane_ctl_rotation(rotation);
  
 -      stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
 +      stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
                                               fb->pixel_format);
  
 -      scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
 -
        /* Sizes are 0 based */
        src_w--;
        src_h--;
        surf_addr = intel_plane_obj_offset(intel_plane, obj, 0);
  
        if (intel_rotation_90_or_270(rotation)) {
 +              int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 +
                /* stride: Surface height in tiles */
 -              tile_height = intel_tile_height(dev, fb->pixel_format,
 -                                              fb->modifier[0], 0);
 +              tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
                stride = DIV_ROUND_UP(fb->height, tile_height);
                plane_size = (src_w << 16) | src_h;
                x_offset = stride * tile_height - y - (src_h + 1);
        I915_WRITE(PLANE_SIZE(pipe, plane), plane_size);
  
        /* program plane scaler */
 -      if (scaler_id >= 0) {
 +      if (plane_state->scaler_id >= 0) {
                uint32_t ps_ctrl = 0;
 +              int scaler_id = plane_state->scaler_id;
  
                DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n", plane,
                        PS_PLANE_SEL(plane));
 -              ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) |
 -                      crtc_state->scaler_state.scalers[scaler_id].mode;
 +              ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) | scaler->mode;
                I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
                I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
                I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
@@@ -338,29 -334,24 +338,29 @@@ chv_update_csc(struct intel_plane *inte
  }
  
  static void
 -vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 -               struct drm_framebuffer *fb,
 -               int crtc_x, int crtc_y,
 -               unsigned int crtc_w, unsigned int crtc_h,
 -               uint32_t x, uint32_t y,
 -               uint32_t src_w, uint32_t src_h)
 +vlv_update_plane(struct drm_plane *dplane,
 +               const struct intel_crtc_state *crtc_state,
 +               const struct intel_plane_state *plane_state)
  {
        struct drm_device *dev = dplane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_plane *intel_plane = to_intel_plane(dplane);
 +      struct drm_framebuffer *fb = plane_state->base.fb;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        int pipe = intel_plane->pipe;
        int plane = intel_plane->plane;
        u32 sprctl;
        unsigned long sprsurf_offset, linear_offset;
        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 -      const struct drm_intel_sprite_colorkey *key =
 -              &to_intel_plane_state(dplane->state)->ckey;
 +      const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 +      int crtc_x = plane_state->dst.x1;
 +      int crtc_y = plane_state->dst.y1;
 +      uint32_t crtc_w = drm_rect_width(&plane_state->dst);
 +      uint32_t crtc_h = drm_rect_height(&plane_state->dst);
 +      uint32_t x = plane_state->src.x1 >> 16;
 +      uint32_t y = plane_state->src.y1 >> 16;
 +      uint32_t src_w = drm_rect_width(&plane_state->src) >> 16;
 +      uint32_t src_h = drm_rect_height(&plane_state->src) >> 16;
  
        sprctl = SP_ENABLE;
  
        crtc_h--;
  
        linear_offset = y * fb->pitches[0] + x * pixel_size;
 -      sprsurf_offset = intel_gen4_compute_page_offset(dev_priv,
 -                                                      &x, &y,
 -                                                      obj->tiling_mode,
 -                                                      pixel_size,
 -                                                      fb->pitches[0]);
 +      sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
 +                                                 fb->modifier[0],
 +                                                 pixel_size,
 +                                                 fb->pitches[0]);
        linear_offset -= sprsurf_offset;
  
 -      if (dplane->state->rotation == BIT(DRM_ROTATE_180)) {
 +      if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
                sprctl |= SP_ROTATE_180;
  
                x += src_w;
@@@ -482,28 -474,23 +482,28 @@@ vlv_disable_plane(struct drm_plane *dpl
  }
  
  static void
 -ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 -               struct drm_framebuffer *fb,
 -               int crtc_x, int crtc_y,
 -               unsigned int crtc_w, unsigned int crtc_h,
 -               uint32_t x, uint32_t y,
 -               uint32_t src_w, uint32_t src_h)
 +ivb_update_plane(struct drm_plane *plane,
 +               const struct intel_crtc_state *crtc_state,
 +               const struct intel_plane_state *plane_state)
  {
        struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_plane *intel_plane = to_intel_plane(plane);
 +      struct drm_framebuffer *fb = plane_state->base.fb;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        enum pipe pipe = intel_plane->pipe;
        u32 sprctl, sprscale = 0;
        unsigned long sprsurf_offset, linear_offset;
        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 -      const struct drm_intel_sprite_colorkey *key =
 -              &to_intel_plane_state(plane->state)->ckey;
 +      const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 +      int crtc_x = plane_state->dst.x1;
 +      int crtc_y = plane_state->dst.y1;
 +      uint32_t crtc_w = drm_rect_width(&plane_state->dst);
 +      uint32_t crtc_h = drm_rect_height(&plane_state->dst);
 +      uint32_t x = plane_state->src.x1 >> 16;
 +      uint32_t y = plane_state->src.y1 >> 16;
 +      uint32_t src_w = drm_rect_width(&plane_state->src) >> 16;
 +      uint32_t src_h = drm_rect_height(&plane_state->src) >> 16;
  
        sprctl = SPRITE_ENABLE;
  
                sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
  
        linear_offset = y * fb->pitches[0] + x * pixel_size;
 -      sprsurf_offset =
 -              intel_gen4_compute_page_offset(dev_priv,
 -                                             &x, &y, obj->tiling_mode,
 -                                             pixel_size, fb->pitches[0]);
 +      sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
 +                                                 fb->modifier[0],
 +                                                 pixel_size,
 +                                                 fb->pitches[0]);
        linear_offset -= sprsurf_offset;
  
 -      if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
 +      if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
                sprctl |= SPRITE_ROTATE_180;
  
                /* HSW and BDW does this automagically in hardware */
@@@ -625,28 -612,23 +625,28 @@@ ivb_disable_plane(struct drm_plane *pla
  }
  
  static void
 -ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 -               struct drm_framebuffer *fb,
 -               int crtc_x, int crtc_y,
 -               unsigned int crtc_w, unsigned int crtc_h,
 -               uint32_t x, uint32_t y,
 -               uint32_t src_w, uint32_t src_h)
 +ilk_update_plane(struct drm_plane *plane,
 +               const struct intel_crtc_state *crtc_state,
 +               const struct intel_plane_state *plane_state)
  {
        struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_plane *intel_plane = to_intel_plane(plane);
 +      struct drm_framebuffer *fb = plane_state->base.fb;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        int pipe = intel_plane->pipe;
        unsigned long dvssurf_offset, linear_offset;
        u32 dvscntr, dvsscale;
        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 -      const struct drm_intel_sprite_colorkey *key =
 -              &to_intel_plane_state(plane->state)->ckey;
 +      const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 +      int crtc_x = plane_state->dst.x1;
 +      int crtc_y = plane_state->dst.y1;
 +      uint32_t crtc_w = drm_rect_width(&plane_state->dst);
 +      uint32_t crtc_h = drm_rect_height(&plane_state->dst);
 +      uint32_t x = plane_state->src.x1 >> 16;
 +      uint32_t y = plane_state->src.y1 >> 16;
 +      uint32_t src_w = drm_rect_width(&plane_state->src) >> 16;
 +      uint32_t src_h = drm_rect_height(&plane_state->src) >> 16;
  
        dvscntr = DVS_ENABLE;
  
                dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
  
        linear_offset = y * fb->pitches[0] + x * pixel_size;
 -      dvssurf_offset =
 -              intel_gen4_compute_page_offset(dev_priv,
 -                                             &x, &y, obj->tiling_mode,
 -                                             pixel_size, fb->pitches[0]);
 +      dvssurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
 +                                                 fb->modifier[0],
 +                                                 pixel_size,
 +                                                 fb->pitches[0]);
        linear_offset -= dvssurf_offset;
  
 -      if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
 +      if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
                dvscntr |= DVS_ROTATE_180;
  
                x += src_w;
@@@ -931,6 -913,30 +931,6 @@@ intel_check_sprite_plane(struct drm_pla
        return 0;
  }
  
 -static void
 -intel_commit_sprite_plane(struct drm_plane *plane,
 -                        struct intel_plane_state *state)
 -{
 -      struct drm_crtc *crtc = state->base.crtc;
 -      struct intel_plane *intel_plane = to_intel_plane(plane);
 -      struct drm_framebuffer *fb = state->base.fb;
 -
 -      crtc = crtc ? crtc : plane->crtc;
 -
 -      if (state->visible) {
 -              intel_plane->update_plane(plane, crtc, fb,
 -                                        state->dst.x1, state->dst.y1,
 -                                        drm_rect_width(&state->dst),
 -                                        drm_rect_height(&state->dst),
 -                                        state->src.x1 >> 16,
 -                                        state->src.y1 >> 16,
 -                                        drm_rect_width(&state->src) >> 16,
 -                                        drm_rect_height(&state->src) >> 16);
 -      } else {
 -              intel_plane->disable_plane(plane, crtc);
 -      }
 -}
 -
  int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
                              struct drm_file *file_priv)
  {
@@@ -1112,11 -1118,12 +1112,11 @@@ intel_plane_init(struct drm_device *dev
        intel_plane->plane = plane;
        intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane);
        intel_plane->check_plane = intel_check_sprite_plane;
 -      intel_plane->commit_plane = intel_commit_sprite_plane;
        possible_crtcs = (1 << pipe);
        ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
                                       &intel_plane_funcs,
                                       plane_formats, num_plane_formats,
-                                      DRM_PLANE_TYPE_OVERLAY);
+                                      DRM_PLANE_TYPE_OVERLAY, NULL);
        if (ret) {
                kfree(intel_plane);
                goto out;