aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c63
1 files changed, 44 insertions, 19 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index ecd4e0b4c525..e79c8d3700d8 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2263,21 +2263,19 @@ out:
2263 * 2263 *
2264 * src_{x,y,w,h} are provided in 16.16 fixed point format 2264 * src_{x,y,w,h} are provided in 16.16 fixed point format
2265 */ 2265 */
2266static int setplane_internal(struct drm_plane *plane, 2266static int __setplane_internal(struct drm_plane *plane,
2267 struct drm_crtc *crtc, 2267 struct drm_crtc *crtc,
2268 struct drm_framebuffer *fb, 2268 struct drm_framebuffer *fb,
2269 int32_t crtc_x, int32_t crtc_y, 2269 int32_t crtc_x, int32_t crtc_y,
2270 uint32_t crtc_w, uint32_t crtc_h, 2270 uint32_t crtc_w, uint32_t crtc_h,
2271 /* src_{x,y,w,h} values are 16.16 fixed point */ 2271 /* src_{x,y,w,h} values are 16.16 fixed point */
2272 uint32_t src_x, uint32_t src_y, 2272 uint32_t src_x, uint32_t src_y,
2273 uint32_t src_w, uint32_t src_h) 2273 uint32_t src_w, uint32_t src_h)
2274{ 2274{
2275 struct drm_device *dev = plane->dev;
2276 int ret = 0; 2275 int ret = 0;
2277 unsigned int fb_width, fb_height; 2276 unsigned int fb_width, fb_height;
2278 int i; 2277 int i;
2279 2278
2280 drm_modeset_lock_all(dev);
2281 /* No fb means shut it down */ 2279 /* No fb means shut it down */
2282 if (!fb) { 2280 if (!fb) {
2283 plane->old_fb = plane->fb; 2281 plane->old_fb = plane->fb;
@@ -2345,10 +2343,28 @@ out:
2345 if (plane->old_fb) 2343 if (plane->old_fb)
2346 drm_framebuffer_unreference(plane->old_fb); 2344 drm_framebuffer_unreference(plane->old_fb);
2347 plane->old_fb = NULL; 2345 plane->old_fb = NULL;
2348 drm_modeset_unlock_all(dev);
2349 2346
2350 return ret; 2347 return ret;
2348}
2349
2350static int setplane_internal(struct drm_plane *plane,
2351 struct drm_crtc *crtc,
2352 struct drm_framebuffer *fb,
2353 int32_t crtc_x, int32_t crtc_y,
2354 uint32_t crtc_w, uint32_t crtc_h,
2355 /* src_{x,y,w,h} values are 16.16 fixed point */
2356 uint32_t src_x, uint32_t src_y,
2357 uint32_t src_w, uint32_t src_h)
2358{
2359 int ret;
2360
2361 drm_modeset_lock_all(plane->dev);
2362 ret = __setplane_internal(plane, crtc, fb,
2363 crtc_x, crtc_y, crtc_w, crtc_h,
2364 src_x, src_y, src_w, src_h);
2365 drm_modeset_unlock_all(plane->dev);
2351 2366
2367 return ret;
2352} 2368}
2353 2369
2354/** 2370/**
@@ -2714,6 +2730,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2714 int ret = 0; 2730 int ret = 0;
2715 2731
2716 BUG_ON(!crtc->cursor); 2732 BUG_ON(!crtc->cursor);
2733 WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL);
2717 2734
2718 /* 2735 /*
2719 * Obtain fb we'll be using (either new or existing) and take an extra 2736 * Obtain fb we'll be using (either new or existing) and take an extra
@@ -2733,11 +2750,9 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2733 fb = NULL; 2750 fb = NULL;
2734 } 2751 }
2735 } else { 2752 } else {
2736 mutex_lock(&dev->mode_config.mutex);
2737 fb = crtc->cursor->fb; 2753 fb = crtc->cursor->fb;
2738 if (fb) 2754 if (fb)
2739 drm_framebuffer_reference(fb); 2755 drm_framebuffer_reference(fb);
2740 mutex_unlock(&dev->mode_config.mutex);
2741 } 2756 }
2742 2757
2743 if (req->flags & DRM_MODE_CURSOR_MOVE) { 2758 if (req->flags & DRM_MODE_CURSOR_MOVE) {
@@ -2759,7 +2774,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2759 * setplane_internal will take care of deref'ing either the old or new 2774 * setplane_internal will take care of deref'ing either the old or new
2760 * framebuffer depending on success. 2775 * framebuffer depending on success.
2761 */ 2776 */
2762 ret = setplane_internal(crtc->cursor, crtc, fb, 2777 ret = __setplane_internal(crtc->cursor, crtc, fb,
2763 crtc_x, crtc_y, crtc_w, crtc_h, 2778 crtc_x, crtc_y, crtc_w, crtc_h,
2764 0, 0, src_w, src_h); 2779 0, 0, src_w, src_h);
2765 2780
@@ -2795,10 +2810,12 @@ static int drm_mode_cursor_common(struct drm_device *dev,
2795 * If this crtc has a universal cursor plane, call that plane's update 2810 * If this crtc has a universal cursor plane, call that plane's update
2796 * handler rather than using legacy cursor handlers. 2811 * handler rather than using legacy cursor handlers.
2797 */ 2812 */
2798 if (crtc->cursor)
2799 return drm_mode_cursor_universal(crtc, req, file_priv);
2800
2801 drm_modeset_lock_crtc(crtc); 2813 drm_modeset_lock_crtc(crtc);
2814 if (crtc->cursor) {
2815 ret = drm_mode_cursor_universal(crtc, req, file_priv);
2816 goto out;
2817 }
2818
2802 if (req->flags & DRM_MODE_CURSOR_BO) { 2819 if (req->flags & DRM_MODE_CURSOR_BO) {
2803 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { 2820 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
2804 ret = -ENXIO; 2821 ret = -ENXIO;
@@ -3383,7 +3400,16 @@ void drm_fb_release(struct drm_file *priv)
3383 struct drm_device *dev = priv->minor->dev; 3400 struct drm_device *dev = priv->minor->dev;
3384 struct drm_framebuffer *fb, *tfb; 3401 struct drm_framebuffer *fb, *tfb;
3385 3402
3386 mutex_lock(&priv->fbs_lock); 3403 /*
3404 * When the file gets released that means no one else can access the fb
3405 * list any more, so no need to grab fpriv->fbs_lock. And we need to to
3406 * avoid upsetting lockdep since the universal cursor code adds a
3407 * framebuffer while holding mutex locks.
3408 *
3409 * Note that a real deadlock between fpriv->fbs_lock and the modeset
3410 * locks is impossible here since no one else but this function can get
3411 * at it any more.
3412 */
3387 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { 3413 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
3388 3414
3389 mutex_lock(&dev->mode_config.fb_lock); 3415 mutex_lock(&dev->mode_config.fb_lock);
@@ -3396,7 +3422,6 @@ void drm_fb_release(struct drm_file *priv)
3396 /* This will also drop the fpriv->fbs reference. */ 3422 /* This will also drop the fpriv->fbs reference. */
3397 drm_framebuffer_remove(fb); 3423 drm_framebuffer_remove(fb);
3398 } 3424 }
3399 mutex_unlock(&priv->fbs_lock);
3400} 3425}
3401 3426
3402/** 3427/**