Merge tag 'v4.3-rc2' into topic/drm-misc
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 22 Sep 2015 09:02:18 +0000 (11:02 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 24 Sep 2015 15:18:41 +0000 (17:18 +0200)
Backmerge Linux 4.3-rc2 because of conflicts in the dp helper code
between bugfixes and new code. Just adjacent lines really.

On top of that there's a silent conflict in the new fsl-dcu driver
merged into 4.3 and

commit 844f9111f6f54f88eb2f0fac121b82ce77193866
Author: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Date:   Wed Sep 2 10:42:40 2015 +0200

    drm/atomic: Make prepare_fb/cleanup_fb only take state, v3.

which Thierry Reding spotted and provided a fixup for.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
1  2 
Documentation/kernel-parameters.txt
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
drivers/gpu/drm/i915/intel_audio.c
drivers/gpu/drm/i915/intel_display.c

@@@ -910,6 -910,8 +910,8 @@@ bytes respectively. Such letter suffixe
                        Disable PIN 1 of APIC timer
                        Can be useful to work around chipset bugs.
  
+       dis_ucode_ldr   [X86] Disable the microcode loader.
        dma_debug=off   If the kernel is compiled with DMA_API_DEBUG support,
                        this option disables the debugging code at boot.
  
                        The filter can be disabled or changed to another
                        driver later using sysfs.
  
 -      drm_kms_helper.edid_firmware=[<connector>:]<file>
 -                      Broken monitors, graphic adapters and KVMs may
 -                      send no or incorrect EDID data sets. This parameter
 -                      allows to specify an EDID data set in the
 -                      /lib/firmware directory that is used instead.
 +      drm_kms_helper.edid_firmware=[<connector>:]<file>[,[<connector>:]<file>]
 +                      Broken monitors, graphic adapters, KVMs and EDIDless
 +                      panels may send no or incorrect EDID data sets.
 +                      This parameter allows to specify an EDID data sets
 +                      in the /lib/firmware directory that are used instead.
                        Generic built-in EDID data sets are used, if one of
                        edid/1024x768.bin, edid/1280x1024.bin,
                        edid/1680x1050.bin, or edid/1920x1080.bin is given
                        available in Documentation/EDID/HOWTO.txt. An EDID
                        data set will only be used for a particular connector,
                        if its name and a colon are prepended to the EDID
 -                      name.
 +                      name. Each connector may use a unique EDID data
 +                      set by separating the files with a comma.  An EDID
 +                      data set with no connector name will be used for
 +                      any connectors not explicitly specified.
  
        dscc4.setup=    [NET]
  
                             <bus_id>,<clkrate>
  
        i8042.debug     [HW] Toggle i8042 debug mode
+       i8042.unmask_kbd_data
+                       [HW] Enable printing of interrupt data from the KBD port
+                            (disabled by default, and as a pre-condition
+                            requires that i8042.debug=1 be enabled)
        i8042.direct    [HW] Put keyboard port into non-translated mode
        i8042.dumbkbd   [HW] Pretend that controller can only read data from
                             keyboard and cannot control its state
                        The default parameter value of '0' causes the kernel
                        not to attempt recovery of lost locks.
  
+       nfs4.layoutstats_timer =
+                       [NFSv4.2] Change the rate at which the kernel sends
+                       layoutstats to the pNFS metadata server.
+                       Setting this to value to 0 causes the kernel to use
+                       whatever value is the default set by the layout
+                       driver. A non-zero value sets the minimum interval
+                       in seconds between layoutstats transmissions.
        nfsd.nfs4_disable_idmapping=
                        [NFSv4] When set to the default of '1', the NFSv4
                        server will return only numeric uids and gids to
                        in a given burst of a callback-flood test.
  
        rcutorture.fqs_duration= [KNL]
-                       Set duration of force_quiescent_state bursts.
+                       Set duration of force_quiescent_state bursts
+                       in microseconds.
  
        rcutorture.fqs_holdoff= [KNL]
-                       Set holdoff time within force_quiescent_state bursts.
+                       Set holdoff time within force_quiescent_state bursts
+                       in microseconds.
  
        rcutorture.fqs_stutter= [KNL]
-                       Set wait time between force_quiescent_state bursts.
+                       Set wait time between force_quiescent_state bursts
+                       in seconds.
+       rcutorture.gp_cond= [KNL]
+                       Use conditional/asynchronous update-side
+                       primitives, if available.
  
        rcutorture.gp_exp= [KNL]
-                       Use expedited update-side primitives.
+                       Use expedited update-side primitives, if available.
  
        rcutorture.gp_normal= [KNL]
-                       Use normal (non-expedited) update-side primitives.
-                       If both gp_exp and gp_normal are set, do both.
-                       If neither gp_exp nor gp_normal are set, still
-                       do both.
+                       Use normal (non-expedited) asynchronous
+                       update-side primitives, if available.
+       rcutorture.gp_sync= [KNL]
+                       Use normal (non-expedited) synchronous
+                       update-side primitives, if available.  If all
+                       of rcutorture.gp_cond=, rcutorture.gp_exp=,
+                       rcutorture.gp_normal=, and rcutorture.gp_sync=
+                       are zero, rcutorture acts as if is interpreted
+                       they are all non-zero.
  
        rcutorture.n_barrier_cbs= [KNL]
                        Set callbacks/threads for rcu_barrier() testing.
                        Set time (s) between CPU-hotplug operations, or
                        zero to disable CPU-hotplug testing.
  
-       rcutorture.torture_runnable= [BOOT]
-                       Start rcutorture running at boot time.
        rcutorture.shuffle_interval= [KNL]
                        Set task-shuffle interval (s).  Shuffling tasks
                        allows some CPUs to go into dyntick-idle mode
                        Test RCU's dyntick-idle handling.  See also the
                        rcutorture.shuffle_interval parameter.
  
+       rcutorture.torture_runnable= [BOOT]
+                       Start rcutorture running at boot time.
        rcutorture.torture_type= [KNL]
                        Specify the RCU implementation to test.
  
                        plus one apbt timer for broadcast timer.
                        x86_intel_mid_timer=apbt_only | lapic_and_apbt
  
+       xen_512gb_limit         [KNL,X86-64,XEN]
+                       Restricts the kernel running paravirtualized under Xen
+                       to use only up to 512 GB of RAM. The reason to do so is
+                       crash analysis tools and Xen tools for doing domain
+                       save/restore/migration must be enabled to handle larger
+                       domains.
        xen_emul_unplug=                [HW,X86,XEN]
                        Unplug Xen emulated devices
                        Format: [unplug0,][unplug1]
@@@ -663,25 -663,6 +663,25 @@@ drm_atomic_plane_get_property(struct dr
        return 0;
  }
  
 +static bool
 +plane_switching_crtc(struct drm_atomic_state *state,
 +                   struct drm_plane *plane,
 +                   struct drm_plane_state *plane_state)
 +{
 +      if (!plane->state->crtc || !plane_state->crtc)
 +              return false;
 +
 +      if (plane->state->crtc == plane_state->crtc)
 +              return false;
 +
 +      /* This could be refined, but currently there's no helper or driver code
 +       * to implement direct switching of active planes nor userspace to take
 +       * advantage of more direct plane switching without the intermediate
 +       * full OFF state.
 +       */
 +      return true;
 +}
 +
  /**
   * drm_atomic_plane_check - check plane state
   * @plane: plane to check
@@@ -753,12 -734,6 +753,12 @@@ static int drm_atomic_plane_check(struc
                return -ENOSPC;
        }
  
 +      if (plane_switching_crtc(state->state, plane, state)) {
 +              DRM_DEBUG_ATOMIC("[PLANE:%d] switching CRTC directly\n",
 +                               plane->base.id);
 +              return -EINVAL;
 +      }
 +
        return 0;
  }
  
@@@ -1540,7 -1515,8 +1540,8 @@@ retry
                        copied_props++;
                }
  
-               if (obj->type == DRM_MODE_OBJECT_PLANE && count_props) {
+               if (obj->type == DRM_MODE_OBJECT_PLANE && count_props &&
+                   !(arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
                        plane = obj_to_plane(obj);
                        plane_mask |= (1 << drm_plane_index(plane));
                        plane->old_fb = plane->fb;
        }
  
        if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
+               /*
+                * Unlike commit, check_only does not clean up state.
+                * Below we call drm_atomic_state_free for it.
+                */
                ret = drm_atomic_check_only(state);
-               /* _check_only() does not free state, unlike _commit() */
-               if (!ret)
-                       drm_atomic_state_free(state);
        } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
                ret = drm_atomic_async_commit(state);
        } else {
                plane->old_fb = NULL;
        }
  
+       if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+               /*
+                * TEST_ONLY and PAGE_FLIP_EVENT are mutually exclusive,
+                * if they weren't, this code should be called on success
+                * for TEST_ONLY too.
+                */
+               for_each_crtc_in_state(state, crtc, crtc_state, i) {
+                       if (!crtc_state->event)
+                               continue;
+                       destroy_vblank_event(dev, file_priv,
+                                            crtc_state->event);
+               }
+       }
        if (ret == -EDEADLK) {
                drm_atomic_state_clear(state);
                drm_modeset_backoff(&ctx);
                goto retry;
        }
  
-       if (ret) {
-               if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
-                       for_each_crtc_in_state(state, crtc, crtc_state, i) {
-                               if (!crtc_state->event)
-                                       continue;
-                               destroy_vblank_event(dev, file_priv,
-                                                    crtc_state->event);
-                       }
-               }
+       if (ret || arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
                drm_atomic_state_free(state);
-       }
  
        drm_modeset_drop_locks(&ctx);
        drm_modeset_acquire_fini(&ctx);
   * add their own additional internal state.
   *
   * This library also provides default implementations for the check callback in
 - * drm_atomic_helper_check and for the commit callback with
 - * drm_atomic_helper_commit. But the individual stages and callbacks are expose
 - * to allow drivers to mix and match and e.g. use the plane helpers only
 + * drm_atomic_helper_check() and for the commit callback with
 + * drm_atomic_helper_commit(). But the individual stages and callbacks are
 + * exposed to allow drivers to mix and match and e.g. use the plane helpers only
   * together with a driver private modeset implementation.
   *
   * This library also provides implementations for all the legacy driver
 - * interfaces on top of the atomic interface. See drm_atomic_helper_set_config,
 - * drm_atomic_helper_disable_plane, drm_atomic_helper_disable_plane and the
 + * interfaces on top of the atomic interface. See drm_atomic_helper_set_config(),
 + * drm_atomic_helper_disable_plane(), drm_atomic_helper_disable_plane() and the
   * various functions to implement set_property callbacks. New drivers must not
   * implement these functions themselves but must use the provided helpers.
   */
@@@ -790,7 -790,7 +790,7 @@@ crtc_set_mode(struct drm_device *dev, s
   * This function shuts down all the outputs that need to be shut down and
   * prepares them (if required) with the new mode.
   *
-  * For compatability with legacy crtc helpers this should be called before
+  * For compatibility with legacy crtc helpers this should be called before
   * drm_atomic_helper_commit_planes(), which is what the default commit function
   * does. But drivers with different needs can group the modeset commits together
   * and do the plane commits at the end. This is useful for drivers doing runtime
@@@ -815,7 -815,7 +815,7 @@@ EXPORT_SYMBOL(drm_atomic_helper_commit_
   * This function enables all the outputs with the new configuration which had to
   * be turned off for the update.
   *
-  * For compatability with legacy crtc helpers this should be called after
+  * For compatibility with legacy crtc helpers this should be called after
   * drm_atomic_helper_commit_planes(), which is what the default commit function
   * does. But drivers with different needs can group the modeset commits together
   * and do the plane commits at the end. This is useful for drivers doing runtime
@@@ -993,22 -993,6 +993,22 @@@ EXPORT_SYMBOL(drm_atomic_helper_wait_fo
   * object. This can still fail when e.g. the framebuffer reservation fails. For
   * now this doesn't implement asynchronous commits.
   *
 + * Note that right now this function does not support async commits, and hence
 + * driver writers must implement their own version for now. Also note that the
 + * default ordering of how the various stages are called is to match the legacy
 + * modeset helper library closest. One peculiarity of that is that it doesn't
 + * mesh well with runtime PM at all.
 + *
 + * For drivers supporting runtime PM the recommended sequence is
 + *
 + *     drm_atomic_helper_commit_modeset_disables(dev, state);
 + *
 + *     drm_atomic_helper_commit_modeset_enables(dev, state);
 + *
 + *     drm_atomic_helper_commit_planes(dev, state, true);
 + *
 + * See the kerneldoc entries for these three functions for more details.
 + *
   * RETURNS
   * Zero for success or -errno.
   */
@@@ -1053,7 -1037,7 +1053,7 @@@ int drm_atomic_helper_commit(struct drm
  
        drm_atomic_helper_commit_modeset_disables(dev, state);
  
 -      drm_atomic_helper_commit_planes(dev, state);
 +      drm_atomic_helper_commit_planes(dev, state, false);
  
        drm_atomic_helper_commit_modeset_enables(dev, state);
  
@@@ -1093,7 -1077,7 +1093,7 @@@ EXPORT_SYMBOL(drm_atomic_helper_commit)
   * work item, which allows nice concurrent updates on disjoint sets of crtcs.
   *
   * 3. The software state is updated synchronously with
 - * drm_atomic_helper_swap_state. Doing this under the protection of all modeset
 + * drm_atomic_helper_swap_state(). Doing this under the protection of all modeset
   * locks means concurrent callers never see inconsistent state. And doing this
   * while it's guaranteed that no relevant async worker runs means that async
   * workers do not need grab any locks. Actually they must not grab locks, for
@@@ -1127,14 -1111,17 +1127,14 @@@ int drm_atomic_helper_prepare_planes(st
                const struct drm_plane_helper_funcs *funcs;
                struct drm_plane *plane = state->planes[i];
                struct drm_plane_state *plane_state = state->plane_states[i];
 -              struct drm_framebuffer *fb;
  
                if (!plane)
                        continue;
  
                funcs = plane->helper_private;
  
 -              fb = plane_state->fb;
 -
 -              if (fb && funcs->prepare_fb) {
 -                      ret = funcs->prepare_fb(plane, fb, plane_state);
 +              if (funcs->prepare_fb) {
 +                      ret = funcs->prepare_fb(plane, plane_state);
                        if (ret)
                                goto fail;
                }
@@@ -1147,14 -1134,17 +1147,14 @@@ fail
                const struct drm_plane_helper_funcs *funcs;
                struct drm_plane *plane = state->planes[i];
                struct drm_plane_state *plane_state = state->plane_states[i];
 -              struct drm_framebuffer *fb;
  
                if (!plane)
                        continue;
  
                funcs = plane->helper_private;
  
 -              fb = state->plane_states[i]->fb;
 -
 -              if (fb && funcs->cleanup_fb)
 -                      funcs->cleanup_fb(plane, fb, plane_state);
 +              if (funcs->cleanup_fb)
 +                      funcs->cleanup_fb(plane, plane_state);
  
        }
  
  }
  EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
  
 +bool plane_crtc_active(struct drm_plane_state *state)
 +{
 +      return state->crtc && state->crtc->state->active;
 +}
 +
  /**
   * drm_atomic_helper_commit_planes - commit plane state
   * @dev: DRM device
   * @old_state: atomic state object with old state structures
 + * @active_only: Only commit on active CRTC if set
   *
   * This function commits the new plane state using the plane and atomic helper
   * functions for planes and crtcs. It assumes that the atomic state has already
   * Note that this function does all plane updates across all CRTCs in one step.
   * If the hardware can't support this approach look at
   * drm_atomic_helper_commit_planes_on_crtc() instead.
 + *
 + * Plane parameters can be updated by applications while the associated CRTC is
 + * disabled. The DRM/KMS core will store the parameters in the plane state,
 + * which will be available to the driver when the CRTC is turned on. As a result
 + * most drivers don't need to be immediately notified of plane updates for a
 + * disabled CRTC.
 + *
 + * Unless otherwise needed, drivers are advised to set the @active_only
 + * parameters to true in order not to receive plane update notifications related
 + * to a disabled CRTC. This avoids the need to manually ignore plane updates in
 + * driver code when the driver and/or hardware can't or just don't need to deal
 + * with updates on disabled CRTCs, for example when supporting runtime PM.
 + *
 + * The drm_atomic_helper_commit() default implementation only sets @active_only
 + * to false to most closely match the behaviour of the legacy helpers. This should
 + * not be copied blindly by drivers.
   */
  void drm_atomic_helper_commit_planes(struct drm_device *dev,
 -                                   struct drm_atomic_state *old_state)
 +                                   struct drm_atomic_state *old_state,
 +                                   bool active_only)
  {
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state;
                if (!funcs || !funcs->atomic_begin)
                        continue;
  
 +              if (active_only && !crtc->state->active)
 +                      continue;
 +
                funcs->atomic_begin(crtc, old_crtc_state);
        }
  
        for_each_plane_in_state(old_state, plane, old_plane_state, i) {
                const struct drm_plane_helper_funcs *funcs;
 +              bool disabling;
  
                funcs = plane->helper_private;
  
                if (!funcs)
                        continue;
  
 +              disabling = drm_atomic_plane_disabling(plane, old_plane_state);
 +
 +              if (active_only) {
 +                      /*
 +                       * Skip planes related to inactive CRTCs. If the plane
 +                       * is enabled use the state of the current CRTC. If the
 +                       * plane is being disabled use the state of the old
 +                       * CRTC to avoid skipping planes being disabled on an
 +                       * active CRTC.
 +                       */
 +                      if (!disabling && !plane_crtc_active(plane->state))
 +                              continue;
 +                      if (disabling && !plane_crtc_active(old_plane_state))
 +                              continue;
 +              }
 +
                /*
                 * Special-case disabling the plane if drivers support it.
                 */
 -              if (drm_atomic_plane_disabling(plane, old_plane_state) &&
 -                  funcs->atomic_disable)
 +              if (disabling && funcs->atomic_disable)
                        funcs->atomic_disable(plane, old_plane_state);
 -              else if (plane->state->crtc ||
 -                       drm_atomic_plane_disabling(plane, old_plane_state))
 +              else if (plane->state->crtc || disabling)
                        funcs->atomic_update(plane, old_plane_state);
        }
  
                if (!funcs || !funcs->atomic_flush)
                        continue;
  
 +              if (active_only && !crtc->state->active)
 +                      continue;
 +
                funcs->atomic_flush(crtc, old_crtc_state);
        }
  }
@@@ -1354,11 -1300,14 +1354,11 @@@ void drm_atomic_helper_cleanup_planes(s
  
        for_each_plane_in_state(old_state, plane, plane_state, i) {
                const struct drm_plane_helper_funcs *funcs;
 -              struct drm_framebuffer *old_fb;
  
                funcs = plane->helper_private;
  
 -              old_fb = plane_state->fb;
 -
 -              if (old_fb && funcs->cleanup_fb)
 -                      funcs->cleanup_fb(plane, old_fb, plane_state);
 +              if (funcs->cleanup_fb)
 +                      funcs->cleanup_fb(plane, plane_state);
        }
  }
  EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
   *
   * 4. Actually commit the hardware state.
   *
 - * 5. Call drm_atomic_helper_cleanup_planes with @state, which since step 3
 + * 5. Call drm_atomic_helper_cleanup_planes() with @state, which since step 3
   * contains the old state. Also do any other cleanup required with that state.
   */
  void drm_atomic_helper_swap_state(struct drm_device *dev,
@@@ -1553,9 -1502,21 +1553,9 @@@ retry
                goto fail;
        }
  
 -      ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
 +      ret = __drm_atomic_helper_disable_plane(plane, plane_state);
        if (ret != 0)
                goto fail;
 -      drm_atomic_set_fb_for_plane(plane_state, NULL);
 -      plane_state->crtc_x = 0;
 -      plane_state->crtc_y = 0;
 -      plane_state->crtc_h = 0;
 -      plane_state->crtc_w = 0;
 -      plane_state->src_x = 0;
 -      plane_state->src_y = 0;
 -      plane_state->src_h = 0;
 -      plane_state->src_w = 0;
 -
 -      if (plane == plane->crtc->cursor)
 -              state->legacy_cursor_update = true;
  
        ret = drm_atomic_commit(state);
        if (ret != 0)
@@@ -1585,32 -1546,6 +1585,32 @@@ backoff
  }
  EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
  
 +/* just used from fb-helper and atomic-helper: */
 +int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
 +              struct drm_plane_state *plane_state)
 +{
 +      int ret;
 +
 +      ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
 +      if (ret != 0)
 +              return ret;
 +
 +      drm_atomic_set_fb_for_plane(plane_state, NULL);
 +      plane_state->crtc_x = 0;
 +      plane_state->crtc_y = 0;
 +      plane_state->crtc_h = 0;
 +      plane_state->crtc_w = 0;
 +      plane_state->src_x = 0;
 +      plane_state->src_y = 0;
 +      plane_state->src_h = 0;
 +      plane_state->src_w = 0;
 +
 +      if (plane->crtc && (plane == plane->crtc->cursor))
 +              plane_state->state->legacy_cursor_update = true;
 +
 +      return 0;
 +}
 +
  static int update_output_state(struct drm_atomic_state *state,
                               struct drm_mode_set *set)
  {
@@@ -1694,6 -1629,8 +1694,6 @@@ int drm_atomic_helper_set_config(struc
  {
        struct drm_atomic_state *state;
        struct drm_crtc *crtc = set->crtc;
 -      struct drm_crtc_state *crtc_state;
 -      struct drm_plane_state *primary_state;
        int ret = 0;
  
        state = drm_atomic_state_alloc(crtc->dev);
  
        state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
  retry:
 -      crtc_state = drm_atomic_get_crtc_state(state, crtc);
 -      if (IS_ERR(crtc_state)) {
 -              ret = PTR_ERR(crtc_state);
 +      ret = __drm_atomic_helper_set_config(set, state);
 +      if (ret != 0)
                goto fail;
 -      }
  
 -      primary_state = drm_atomic_get_plane_state(state, crtc->primary);
 -      if (IS_ERR(primary_state)) {
 -              ret = PTR_ERR(primary_state);
 +      ret = drm_atomic_commit(state);
 +      if (ret != 0)
                goto fail;
 -      }
 +
 +      /* Driver takes ownership of state on successful commit. */
 +      return 0;
 +fail:
 +      if (ret == -EDEADLK)
 +              goto backoff;
 +
 +      drm_atomic_state_free(state);
 +
 +      return ret;
 +backoff:
 +      drm_atomic_state_clear(state);
 +      drm_atomic_legacy_backoff(state);
 +
 +      /*
 +       * Someone might have exchanged the framebuffer while we dropped locks
 +       * in the backoff code. We need to fix up the fb refcount tracking the
 +       * core does for us.
 +       */
 +      crtc->primary->old_fb = crtc->primary->fb;
 +
 +      goto retry;
 +}
 +EXPORT_SYMBOL(drm_atomic_helper_set_config);
 +
 +/* just used from fb-helper and atomic-helper: */
 +int __drm_atomic_helper_set_config(struct drm_mode_set *set,
 +              struct drm_atomic_state *state)
 +{
 +      struct drm_crtc_state *crtc_state;
 +      struct drm_plane_state *primary_state;
 +      struct drm_crtc *crtc = set->crtc;
 +      int ret;
 +
 +      crtc_state = drm_atomic_get_crtc_state(state, crtc);
 +      if (IS_ERR(crtc_state))
 +              return PTR_ERR(crtc_state);
 +
 +      primary_state = drm_atomic_get_plane_state(state, crtc->primary);
 +      if (IS_ERR(primary_state))
 +              return PTR_ERR(primary_state);
  
        if (!set->mode) {
                WARN_ON(set->fb);
  
                ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
                if (ret != 0)
 -                      goto fail;
 +                      return ret;
  
                crtc_state->active = false;
  
                ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
                if (ret != 0)
 -                      goto fail;
 +                      return ret;
  
                drm_atomic_set_fb_for_plane(primary_state, NULL);
  
  
        ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
        if (ret != 0)
 -              goto fail;
 +              return ret;
  
        crtc_state->active = true;
  
        ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
        if (ret != 0)
 -              goto fail;
 +              return ret;
 +
        drm_atomic_set_fb_for_plane(primary_state, set->fb);
        primary_state->crtc_x = 0;
        primary_state->crtc_y = 0;
  commit:
        ret = update_output_state(state, set);
        if (ret)
 -              goto fail;
 -
 -      ret = drm_atomic_commit(state);
 -      if (ret != 0)
 -              goto fail;
 +              return ret;
  
 -      /* Driver takes ownership of state on successful commit. */
        return 0;
 -fail:
 -      if (ret == -EDEADLK)
 -              goto backoff;
 -
 -      drm_atomic_state_free(state);
 -
 -      return ret;
 -backoff:
 -      drm_atomic_state_clear(state);
 -      drm_atomic_legacy_backoff(state);
 -
 -      /*
 -       * Someone might have exchanged the framebuffer while we dropped locks
 -       * in the backoff code. We need to fix up the fb refcount tracking the
 -       * core does for us.
 -       */
 -      crtc->primary->old_fb = crtc->primary->fb;
 -
 -      goto retry;
  }
 -EXPORT_SYMBOL(drm_atomic_helper_set_config);
  
  /**
   * drm_atomic_helper_crtc_set_property - helper for crtc properties
@@@ -2409,84 -2333,6 +2409,84 @@@ drm_atomic_helper_connector_duplicate_s
  EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
  
  /**
 + * drm_atomic_helper_duplicate_state - duplicate an atomic state object
 + * @dev: DRM device
 + * @ctx: lock acquisition context
 + *
 + * Makes a copy of the current atomic state by looping over all objects and
 + * duplicating their respective states.
 + *
 + * Note that this treats atomic state as persistent between save and restore.
 + * Drivers must make sure that this is possible and won't result in confusion
 + * or erroneous behaviour.
 + *
 + * Note that if callers haven't already acquired all modeset locks this might
 + * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
 + *
 + * Returns:
 + * A pointer to the copy of the atomic state object on success or an
 + * ERR_PTR()-encoded error code on failure.
 + */
 +struct drm_atomic_state *
 +drm_atomic_helper_duplicate_state(struct drm_device *dev,
 +                                struct drm_modeset_acquire_ctx *ctx)
 +{
 +      struct drm_atomic_state *state;
 +      struct drm_connector *conn;
 +      struct drm_plane *plane;
 +      struct drm_crtc *crtc;
 +      int err = 0;
 +
 +      state = drm_atomic_state_alloc(dev);
 +      if (!state)
 +              return ERR_PTR(-ENOMEM);
 +
 +      state->acquire_ctx = ctx;
 +
 +      drm_for_each_crtc(crtc, dev) {
 +              struct drm_crtc_state *crtc_state;
 +
 +              crtc_state = drm_atomic_get_crtc_state(state, crtc);
 +              if (IS_ERR(crtc_state)) {
 +                      err = PTR_ERR(crtc_state);
 +                      goto free;
 +              }
 +      }
 +
 +      drm_for_each_plane(plane, dev) {
 +              struct drm_plane_state *plane_state;
 +
 +              plane_state = drm_atomic_get_plane_state(state, plane);
 +              if (IS_ERR(plane_state)) {
 +                      err = PTR_ERR(plane_state);
 +                      goto free;
 +              }
 +      }
 +
 +      drm_for_each_connector(conn, dev) {
 +              struct drm_connector_state *conn_state;
 +
 +              conn_state = drm_atomic_get_connector_state(state, conn);
 +              if (IS_ERR(conn_state)) {
 +                      err = PTR_ERR(conn_state);
 +                      goto free;
 +              }
 +      }
 +
 +      /* clear the acquire context so that it isn't accidentally reused */
 +      state->acquire_ctx = NULL;
 +
 +free:
 +      if (err < 0) {
 +              drm_atomic_state_free(state);
 +              state = ERR_PTR(err);
 +      }
 +
 +      return state;
 +}
 +EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
 +
 +/**
   * __drm_atomic_helper_connector_destroy_state - release connector state
   * @connector: connector object
   * @state: connector state object to release
@@@ -159,6 -159,8 +159,8 @@@ int drm_dp_bw_code_to_link_rate(u8 link
  }
  EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
  
+ #define AUX_RETRY_INTERVAL 500 /* us */
  /**
   * DOC: dp helpers
   *
@@@ -213,7 -215,7 +215,7 @@@ static int drm_dp_dpcd_access(struct dr
                        return -EIO;
  
                case DP_AUX_NATIVE_REPLY_DEFER:
-                       usleep_range(400, 500);
+                       usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
                        break;
                }
        }
@@@ -422,19 -424,90 +424,103 @@@ static u32 drm_dp_i2c_functionality(str
               I2C_FUNC_10BIT_ADDR;
  }
  
 +static void drm_dp_i2c_msg_write_status_update(struct drm_dp_aux_msg *msg)
 +{
 +      /*
 +       * In case of i2c defer or short i2c ack reply to a write,
 +       * we need to switch to WRITE_STATUS_UPDATE to drain the
 +       * rest of the message
 +       */
 +      if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE) {
 +              msg->request &= DP_AUX_I2C_MOT;
 +              msg->request |= DP_AUX_I2C_WRITE_STATUS_UPDATE;
 +      }
 +}
 +
+ #define AUX_PRECHARGE_LEN 10 /* 10 to 16 */
+ #define AUX_SYNC_LEN (16 + 4) /* preamble + AUX_SYNC_END */
+ #define AUX_STOP_LEN 4
+ #define AUX_CMD_LEN 4
+ #define AUX_ADDRESS_LEN 20
+ #define AUX_REPLY_PAD_LEN 4
+ #define AUX_LENGTH_LEN 8
+ /*
+  * Calculate the duration of the AUX request/reply in usec. Gives the
+  * "best" case estimate, ie. successful while as short as possible.
+  */
+ static int drm_dp_aux_req_duration(const struct drm_dp_aux_msg *msg)
+ {
+       int len = AUX_PRECHARGE_LEN + AUX_SYNC_LEN + AUX_STOP_LEN +
+               AUX_CMD_LEN + AUX_ADDRESS_LEN + AUX_LENGTH_LEN;
+       if ((msg->request & DP_AUX_I2C_READ) == 0)
+               len += msg->size * 8;
+       return len;
+ }
+ static int drm_dp_aux_reply_duration(const struct drm_dp_aux_msg *msg)
+ {
+       int len = AUX_PRECHARGE_LEN + AUX_SYNC_LEN + AUX_STOP_LEN +
+               AUX_CMD_LEN + AUX_REPLY_PAD_LEN;
+       /*
+        * For read we expect what was asked. For writes there will
+        * be 0 or 1 data bytes. Assume 0 for the "best" case.
+        */
+       if (msg->request & DP_AUX_I2C_READ)
+               len += msg->size * 8;
+       return len;
+ }
+ #define I2C_START_LEN 1
+ #define I2C_STOP_LEN 1
+ #define I2C_ADDR_LEN 9 /* ADDRESS + R/W + ACK/NACK */
+ #define I2C_DATA_LEN 9 /* DATA + ACK/NACK */
+ /*
+  * Calculate the length of the i2c transfer in usec, assuming
+  * the i2c bus speed is as specified. Gives the the "worst"
+  * case estimate, ie. successful while as long as possible.
+  * Doesn't account the the "MOT" bit, and instead assumes each
+  * message includes a START, ADDRESS and STOP. Neither does it
+  * account for additional random variables such as clock stretching.
+  */
+ static int drm_dp_i2c_msg_duration(const struct drm_dp_aux_msg *msg,
+                                  int i2c_speed_khz)
+ {
+       /* AUX bitrate is 1MHz, i2c bitrate as specified */
+       return DIV_ROUND_UP((I2C_START_LEN + I2C_ADDR_LEN +
+                            msg->size * I2C_DATA_LEN +
+                            I2C_STOP_LEN) * 1000, i2c_speed_khz);
+ }
+ /*
+  * Deterine how many retries should be attempted to successfully transfer
+  * the specified message, based on the estimated durations of the
+  * i2c and AUX transfers.
+  */
+ static int drm_dp_i2c_retry_count(const struct drm_dp_aux_msg *msg,
+                             int i2c_speed_khz)
+ {
+       int aux_time_us = drm_dp_aux_req_duration(msg) +
+               drm_dp_aux_reply_duration(msg);
+       int i2c_time_us = drm_dp_i2c_msg_duration(msg, i2c_speed_khz);
+       return DIV_ROUND_UP(i2c_time_us, aux_time_us + AUX_RETRY_INTERVAL);
+ }
+ /*
+  * FIXME currently assumes 10 kHz as some real world devices seem
+  * to require it. We should query/set the speed via DPCD if supported.
+  */
+ static int dp_aux_i2c_speed_khz __read_mostly = 10;
+ module_param_unsafe(dp_aux_i2c_speed_khz, int, 0644);
+ MODULE_PARM_DESC(dp_aux_i2c_speed_khz,
+                "Assumed speed of the i2c bus in kHz, (1-400, default 10)");
  /*
   * Transfer a single I2C-over-AUX message and handle various error conditions,
   * retrying the transaction as appropriate.  It is assumed that the
@@@ -447,13 -520,16 +533,16 @@@ static int drm_dp_i2c_do_msg(struct drm
  {
        unsigned int retry, defer_i2c;
        int ret;
        /*
         * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device
         * is required to retry at least seven times upon receiving AUX_DEFER
         * before giving up the AUX transaction.
+        *
+        * We also try to account for the i2c bus speed.
         */
-       for (retry = 0, defer_i2c = 0; retry < (7 + defer_i2c); retry++) {
+       int max_retries = max(7, drm_dp_i2c_retry_count(msg, dp_aux_i2c_speed_khz));
+       for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c); retry++) {
                mutex_lock(&aux->hw_mutex);
                ret = aux->transfer(aux, msg);
                mutex_unlock(&aux->hw_mutex);
                         * For now just defer for long enough to hopefully be
                         * safe for all use-cases.
                         */
-                       usleep_range(500, 600);
+                       usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
                        continue;
  
                default:
                         * Both native ACK and I2C ACK replies received. We
                         * can assume the transfer was successful.
                         */
 +                      if (ret != msg->size)
 +                              drm_dp_i2c_msg_write_status_update(msg);
                        return ret;
  
                case DP_AUX_I2C_REPLY_NACK:
                        aux->i2c_defer_count++;
                        if (defer_i2c < 7)
                                defer_i2c++;
-                       usleep_range(400, 500);
+                       usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
 +                      drm_dp_i2c_msg_write_status_update(msg);
++
                        continue;
  
                default:
        return -EREMOTEIO;
  }
  
 +static void drm_dp_i2c_msg_set_request(struct drm_dp_aux_msg *msg,
 +                                     const struct i2c_msg *i2c_msg)
 +{
 +      msg->request = (i2c_msg->flags & I2C_M_RD) ?
 +              DP_AUX_I2C_READ : DP_AUX_I2C_WRITE;
 +      msg->request |= DP_AUX_I2C_MOT;
 +}
 +
  /*
   * Keep retrying drm_dp_i2c_do_msg until all data has been transferred.
   *
@@@ -596,7 -661,10 +686,7 @@@ static int drm_dp_i2c_xfer(struct i2c_a
  
        for (i = 0; i < num; i++) {
                msg.address = msgs[i].addr;
 -              msg.request = (msgs[i].flags & I2C_M_RD) ?
 -                      DP_AUX_I2C_READ :
 -                      DP_AUX_I2C_WRITE;
 -              msg.request |= DP_AUX_I2C_MOT;
 +              drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
                /* Send a bare address packet to start the transaction.
                 * Zero sized messages specify an address only (bare
                 * address) transaction.
                msg.buffer = NULL;
                msg.size = 0;
                err = drm_dp_i2c_do_msg(aux, &msg);
 +
 +              /*
 +               * Reset msg.request in case in case it got
 +               * changed into a WRITE_STATUS_UPDATE.
 +               */
 +              drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
 +
                if (err < 0)
                        break;
                /* We want each transaction to be as large as possible, but
                        msg.size = min(transfer_size, msgs[i].len - j);
  
                        err = drm_dp_i2c_drain_msg(aux, &msg);
 +
 +                      /*
 +                       * Reset msg.request in case in case it got
 +                       * changed into a WRITE_STATUS_UPDATE.
 +                       */
 +                      drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
 +
                        if (err < 0)
                                break;
                        transfer_size = err;
@@@ -190,14 -190,14 +190,12 @@@ set_failed
  
  static void
  fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
--                           struct drm_framebuffer *fb,
                             const struct drm_plane_state *new_state)
  {
  }
  
  static int
  fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
--                           struct drm_framebuffer *fb,
                             const struct drm_plane_state *new_state)
  {
        return 0;
@@@ -400,8 -400,11 +400,11 @@@ void intel_audio_codec_enable(struct in
        struct drm_connector *connector;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_audio_component *acomp = dev_priv->audio_component;
+       struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+       enum port port = intel_dig_port->port;
  
 -      connector = drm_select_eld(encoder, mode);
 +      connector = drm_select_eld(encoder);
        if (!connector)
                return;
  
  
        if (dev_priv->display.audio_codec_enable)
                dev_priv->display.audio_codec_enable(connector, intel_encoder, mode);
+       if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
+               acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
  }
  
  /**
   * The disable sequences must be performed before disabling the transcoder or
   * port.
   */
- void intel_audio_codec_disable(struct intel_encoder *encoder)
+ void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
  {
-       struct drm_device *dev = encoder->base.dev;
+       struct drm_encoder *encoder = &intel_encoder->base;
+       struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_audio_component *acomp = dev_priv->audio_component;
+       struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+       enum port port = intel_dig_port->port;
  
        if (dev_priv->display.audio_codec_disable)
-               dev_priv->display.audio_codec_disable(encoder);
+               dev_priv->display.audio_codec_disable(intel_encoder);
+       if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
+               acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
  }
  
  /**
@@@ -526,12 -539,16 +539,16 @@@ static int i915_audio_component_bind(st
                                     struct device *hda_dev, void *data)
  {
        struct i915_audio_component *acomp = data;
+       struct drm_i915_private *dev_priv = dev_to_i915(i915_dev);
  
        if (WARN_ON(acomp->ops || acomp->dev))
                return -EEXIST;
  
+       drm_modeset_lock_all(dev_priv->dev);
        acomp->ops = &i915_audio_component_ops;
        acomp->dev = i915_dev;
+       dev_priv->audio_component = acomp;
+       drm_modeset_unlock_all(dev_priv->dev);
  
        return 0;
  }
@@@ -540,9 -557,13 +557,13 @@@ static void i915_audio_component_unbind
                                        struct device *hda_dev, void *data)
  {
        struct i915_audio_component *acomp = data;
+       struct drm_i915_private *dev_priv = dev_to_i915(i915_dev);
  
+       drm_modeset_lock_all(dev_priv->dev);
        acomp->ops = NULL;
        acomp->dev = NULL;
+       dev_priv->audio_component = NULL;
+       drm_modeset_unlock_all(dev_priv->dev);
  }
  
  static const struct component_ops i915_audio_component_bind_ops = {
@@@ -6305,7 -6305,7 +6305,7 @@@ static void intel_connector_check_state
                      connector->base.name);
  
        if (connector->get_hw_state(connector)) {
-               struct drm_encoder *encoder = &connector->encoder->base;
+               struct intel_encoder *encoder = connector->encoder;
                struct drm_connector_state *conn_state = connector->base.state;
  
                I915_STATE_WARN(!crtc,
                I915_STATE_WARN(!crtc->state->active,
                      "connector is active, but attached crtc isn't\n");
  
-               if (!encoder)
+               if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST)
                        return;
  
-               I915_STATE_WARN(conn_state->best_encoder != encoder,
+               I915_STATE_WARN(conn_state->best_encoder != &encoder->base,
                        "atomic encoder doesn't match attached encoder\n");
  
-               I915_STATE_WARN(conn_state->crtc != encoder->crtc,
+               I915_STATE_WARN(conn_state->crtc != encoder->base.crtc,
                        "attached encoder crtc differs from connector crtc\n");
        } else {
                I915_STATE_WARN(crtc && crtc->state->active,
@@@ -13313,10 -13313,10 +13313,10 @@@ static void intel_shared_dpll_init(stru
   */
  int
  intel_prepare_plane_fb(struct drm_plane *plane,
 -                     struct drm_framebuffer *fb,
                       const struct drm_plane_state *new_state)
  {
        struct drm_device *dev = plane->dev;
 +      struct drm_framebuffer *fb = new_state->fb;
        struct intel_plane *intel_plane = to_intel_plane(plane);
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
   */
  void
  intel_cleanup_plane_fb(struct drm_plane *plane,
 -                     struct drm_framebuffer *fb,
                       const struct drm_plane_state *old_state)
  {
        struct drm_device *dev = plane->dev;
 -      struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 +      struct drm_i915_gem_object *obj = intel_fb_obj(old_state->fb);
  
 -      if (WARN_ON(!obj))
 +      if (!obj)
                return;
  
        if (plane->type != DRM_PLANE_TYPE_CURSOR ||
            !INTEL_INFO(dev)->cursor_needs_physical) {
                mutex_lock(&dev->struct_mutex);
 -              intel_unpin_fb_obj(fb, old_state);
 +              intel_unpin_fb_obj(old_state->fb, old_state);
                mutex_unlock(&dev->struct_mutex);
        }
  }