Merge tag 'drm/tegra/for-4.16-rc1-fixes' of git://anongit.freedesktop.org/tegra/linux...
authorDave Airlie <airlied@redhat.com>
Fri, 12 Jan 2018 01:46:19 +0000 (11:46 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 12 Jan 2018 01:46:19 +0000 (11:46 +1000)
drm/tegra: Changes for v4.16-rc1

The bulk of these changes are preparation work and addition of support
for Tegra186. Currently only HDMI output (the primary output on Jetson
TX2) is supported, but the hardware is also capable of doing DSI and
DisplayPort.

Tegra DRM now also uses the atomic commit helpers instead of the open-
coded variant that was only doing half its job. As a bit of a byproduct
of the Tegra186 support the driver also gained HDMI 2.0 as well as zpos
property support.

Along the way there are also a few patches to clean up a few things and
fix minor issues.

* tag 'drm/tegra/for-4.16-rc1-fixes' of git://anongit.freedesktop.org/tegra/linux: (51 commits)
  drm/tegra: dc: Properly cleanup overlay planes
  drm/tegra: dc: Fix possible_crtcs mask for planes
  drm/tegra: dc: Restore YUV overlay support
  drm/tegra: dc: Implement legacy blending
  drm/tegra: Correct timeout in tegra_syncpt_wait
  drm/tegra: gem: Correct iommu_map_sg() error checking
  drm/tegra: dc: Link DC1 to DC0 on Tegra20
  drm/tegra: Fix non-debugfs builds
  drm/tegra: dpaux: Keep reset defaults for hybrid pad parameters
  drm/tegra: Mark Tegra186 display hub PM functions __maybe_unused
  drm/tegra: Use IOMMU groups
  gpu: host1x: Use IOMMU groups
  drm/tegra: Implement zpos property
  drm/tegra: dc: Remove redundant spinlock
  drm/tegra: dc: Use direct offset to plane registers
  drm/tegra: dc: Support more formats
  drm/tegra: fb: Force alpha formats
  drm/tegra: dpaux: Add Tegra186 support
  drm/tegra: dpaux: Implement runtime PM
  drm/tegra: sor: Support HDMI 2.0 modes
  ...

1  2 
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/drm.h
drivers/gpu/drm/tegra/fb.c

index f157bc67526946614779d29091f584c15c082fe9,ff931d3508a99f259cad5a4ab9d3dac9eca8f4da..d50bddb2e4474e456b8105d6b90b47488ff21263
@@@ -33,97 -33,91 +33,91 @@@ struct tegra_drm_file 
        struct mutex lock;
  };
  
- static void tegra_atomic_schedule(struct tegra_drm *tegra,
-                                 struct drm_atomic_state *state)
+ static int tegra_atomic_check(struct drm_device *drm,
+                             struct drm_atomic_state *state)
  {
-       tegra->commit.state = state;
-       schedule_work(&tegra->commit.work);
- }
+       int err;
  
- static void tegra_atomic_complete(struct tegra_drm *tegra,
-                                 struct drm_atomic_state *state)
- {
-       struct drm_device *drm = tegra->drm;
+       err = drm_atomic_helper_check_modeset(drm, state);
+       if (err < 0)
+               return err;
  
-       /*
-        * Everything below can be run asynchronously without the need to grab
-        * any modeset locks at all under one condition: It must be guaranteed
-        * that the asynchronous work has either been cancelled (if the driver
-        * supports it, which at least requires that the framebuffers get
-        * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
-        * before the new state gets committed on the software side with
-        * drm_atomic_helper_swap_state().
-        *
-        * This scheme allows new atomic state updates to be prepared and
-        * checked in parallel to the asynchronous completion of the previous
-        * update. Which is important since compositors need to figure out the
-        * composition of the next frame right after having submitted the
-        * current layout.
-        */
+       err = drm_atomic_normalize_zpos(drm, state);
+       if (err < 0)
+               return err;
  
-       drm_atomic_helper_commit_modeset_disables(drm, state);
-       drm_atomic_helper_commit_modeset_enables(drm, state);
-       drm_atomic_helper_commit_planes(drm, state,
-                                       DRM_PLANE_COMMIT_ACTIVE_ONLY);
+       err = drm_atomic_helper_check_planes(drm, state);
+       if (err < 0)
+               return err;
  
-       drm_atomic_helper_wait_for_vblanks(drm, state);
+       if (state->legacy_cursor_update)
+               state->async_update = !drm_atomic_helper_async_check(drm, state);
  
-       drm_atomic_helper_cleanup_planes(drm, state);
-       drm_atomic_state_put(state);
+       return 0;
  }
  
- static void tegra_atomic_work(struct work_struct *work)
+ static struct drm_atomic_state *
+ tegra_atomic_state_alloc(struct drm_device *drm)
  {
-       struct tegra_drm *tegra = container_of(work, struct tegra_drm,
-                                              commit.work);
+       struct tegra_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (!state || drm_atomic_state_init(drm, &state->base) < 0) {
+               kfree(state);
+               return NULL;
+       }
  
-       tegra_atomic_complete(tegra, tegra->commit.state);
+       return &state->base;
  }
  
- static int tegra_atomic_commit(struct drm_device *drm,
-                              struct drm_atomic_state *state, bool nonblock)
+ static void tegra_atomic_state_clear(struct drm_atomic_state *state)
  {
-       struct tegra_drm *tegra = drm->dev_private;
-       int err;
-       err = drm_atomic_helper_prepare_planes(drm, state);
-       if (err)
-               return err;
-       /* serialize outstanding nonblocking commits */
-       mutex_lock(&tegra->commit.lock);
-       flush_work(&tegra->commit.work);
-       /*
-        * This is the point of no return - everything below never fails except
-        * when the hw goes bonghits. Which means we can commit the new state on
-        * the software side now.
-        */
-       err = drm_atomic_helper_swap_state(state, true);
-       if (err) {
-               mutex_unlock(&tegra->commit.lock);
-               drm_atomic_helper_cleanup_planes(drm, state);
-               return err;
-       }
+       struct tegra_atomic_state *tegra = to_tegra_atomic_state(state);
  
-       drm_atomic_state_get(state);
-       if (nonblock)
-               tegra_atomic_schedule(tegra, state);
-       else
-               tegra_atomic_complete(tegra, state);
+       drm_atomic_state_default_clear(state);
+       tegra->clk_disp = NULL;
+       tegra->dc = NULL;
+       tegra->rate = 0;
+ }
  
-       mutex_unlock(&tegra->commit.lock);
-       return 0;
+ static void tegra_atomic_state_free(struct drm_atomic_state *state)
+ {
+       drm_atomic_state_default_release(state);
+       kfree(state);
  }
  
- static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
+ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
        .fb_create = tegra_fb_create,
  #ifdef CONFIG_DRM_FBDEV_EMULATION
 -      .output_poll_changed = tegra_fb_output_poll_changed,
 +      .output_poll_changed = drm_fb_helper_output_poll_changed,
  #endif
-       .atomic_check = drm_atomic_helper_check,
-       .atomic_commit = tegra_atomic_commit,
+       .atomic_check = tegra_atomic_check,
+       .atomic_commit = drm_atomic_helper_commit,
+       .atomic_state_alloc = tegra_atomic_state_alloc,
+       .atomic_state_clear = tegra_atomic_state_clear,
+       .atomic_state_free = tegra_atomic_state_free,
+ };
+ static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
+ {
+       struct drm_device *drm = old_state->dev;
+       struct tegra_drm *tegra = drm->dev_private;
+       if (tegra->hub) {
+               drm_atomic_helper_commit_modeset_disables(drm, old_state);
+               tegra_display_hub_atomic_commit(drm, old_state);
+               drm_atomic_helper_commit_planes(drm, old_state, 0);
+               drm_atomic_helper_commit_modeset_enables(drm, old_state);
+               drm_atomic_helper_commit_hw_done(old_state);
+               drm_atomic_helper_wait_for_vblanks(drm, old_state);
+               drm_atomic_helper_cleanup_planes(drm, old_state);
+       } else {
+               drm_atomic_helper_commit_tail_rpm(old_state);
+       }
+ }
+ static const struct drm_mode_config_helper_funcs
+ tegra_drm_mode_config_helpers = {
+       .atomic_commit_tail = tegra_atomic_commit_tail,
  };
  
  static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
index 0009f6ea21b655e55d4ff5fa8d5935cf6beed68f,da3d8c141aeef3774e29aba9b6aa58275b4f9c6f..73b661ce7086592af497b39bdaf94fe806b8860f
@@@ -188,7 -203,12 +203,8 @@@ int tegra_drm_fb_init(struct drm_devic
  void tegra_drm_fb_exit(struct drm_device *drm);
  void tegra_drm_fb_suspend(struct drm_device *drm);
  void tegra_drm_fb_resume(struct drm_device *drm);
 -#ifdef CONFIG_DRM_FBDEV_EMULATION
 -void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
 -void tegra_fb_output_poll_changed(struct drm_device *drm);
 -#endif
  
+ extern struct platform_driver tegra_display_hub_driver;
  extern struct platform_driver tegra_dc_driver;
  extern struct platform_driver tegra_hdmi_driver;
  extern struct platform_driver tegra_dsi_driver;
Simple merge