Signed-off-by: Rob Clark <robdclark at gmail.com>
---
 drivers/gpu/drm/drm_fb_helper.c | 59 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 3549b1f..eef1687 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1192,6 +1192,59 @@ int drm_fb_helper_set_par(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_set_par);

+static int pan_display_atomic(struct fb_var_screeninfo *var,
+               struct fb_info *info)
+{
+       struct drm_fb_helper *fb_helper = info->par;
+       struct drm_device *dev = fb_helper->dev;
+       struct drm_atomic_state *state;
+       int i, ret;
+
+       state = drm_atomic_state_alloc(dev);
+       if (!state)
+               return -ENOMEM;
+
+       state->acquire_ctx = dev->mode_config.acquire_ctx;
+retry:
+       for(i = 0; i < fb_helper->crtc_count; i++) {
+               struct drm_mode_set *mode_set;
+
+               mode_set = &fb_helper->crtc_info[i].mode_set;
+
+               mode_set->x = var->xoffset;
+               mode_set->y = var->yoffset;
+
+               ret = drm_atomic_helper_set_config_impl(mode_set, state);
+               if (ret != 0)
+                       goto fail;
+       }
+
+       ret = drm_atomic_commit(state);
+       if (ret != 0)
+               goto fail;
+
+       // XXX if fail, revert modeset[i]->x,y?? legacy path doesn't seem to do 
it either..
+
+       info->var.xoffset = var->xoffset;
+       info->var.yoffset = var->yoffset;
+
+       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);
+
+       goto retry;
+}
+
 /**
  * drm_fb_helper_pan_display - implementation for ->fb_pan_display
  * @var: updated screen information
@@ -1215,6 +1268,11 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo 
*var,
                return -EBUSY;
        }

+       if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
+               ret = pan_display_atomic(var, info);
+               goto unlock;
+       }
+
        for (i = 0; i < fb_helper->crtc_count; i++) {
                modeset = &fb_helper->crtc_info[i].mode_set;

@@ -1229,6 +1287,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo 
*var,
                        }
                }
        }
+unlock:
        drm_modeset_unlock_all(dev);
        return ret;
 }
-- 
2.4.3

Reply via email to