diff options
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 63 |
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 | */ |
2266 | static int setplane_internal(struct drm_plane *plane, | 2266 | static 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 | |||
2350 | static 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 | /** |