Skip to content

Commit f097cd8

Browse files
tom3qrkhuangtao
authored andcommitted
UPSTREAM: drm/rockchip: Unreference framebuffers from flip work
Currently the driver waits for vblank and then unreferences old framebuffers from atomic commit code path. This is however breaking the legacy cursor API, which requires the updates to be fully asynchronous. Instead of just adding a special case for cursor, we can have actually smaller amount of code to unreference any changed framebuffer from a flip work. Signed-off-by: Tomasz Figa <tfiga@chromium.org> (cherry picked from commit 47a7eb4597775ecdc29d2630d875a991f0449bf3) Change-Id: Id36cdef1ea3962ac8c9a99549732d1810c57c4f9 Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
1 parent ffa4516 commit f097cd8

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

drivers/gpu/drm/rockchip/rockchip_drm_vop.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <drm/drm_atomic.h>
1818
#include <drm/drm_crtc.h>
1919
#include <drm/drm_crtc_helper.h>
20+
#include <drm/drm_flip_work.h>
2021
#include <drm/drm_plane_helper.h>
2122

2223
#include <linux/devfreq.h>
@@ -130,6 +131,10 @@ struct vop_zpos {
130131
int zpos;
131132
};
132133

134+
enum vop_pending {
135+
VOP_PENDING_FB_UNREF,
136+
};
137+
133138
struct vop_plane_state {
134139
struct drm_plane_state base;
135140
int format;
@@ -182,6 +187,9 @@ struct vop {
182187
struct completion wait_update_complete;
183188
struct drm_pending_vblank_event *event;
184189

190+
struct drm_flip_work fb_unref_work;
191+
unsigned long pending;
192+
185193
struct completion line_flag_completion;
186194

187195
const struct vop_data *data;
@@ -2099,7 +2107,11 @@ static void vop_wait_for_irq_handler(struct vop *vop)
20992107
static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
21002108
struct drm_crtc_state *old_crtc_state)
21012109
{
2110+
struct drm_atomic_state *old_state = old_crtc_state->state;
2111+
struct drm_plane_state *old_plane_state;
21022112
struct vop *vop = to_vop(crtc);
2113+
struct drm_plane *plane;
2114+
int i;
21032115

21042116
vop_cfg_update(crtc, old_crtc_state);
21052117

@@ -2152,6 +2164,19 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
21522164
* signalling flip completion we need to wait for it to finish.
21532165
*/
21542166
vop_wait_for_irq_handler(vop);
2167+
2168+
for_each_plane_in_state(old_state, plane, old_plane_state, i) {
2169+
if (!old_plane_state->fb)
2170+
continue;
2171+
2172+
if (old_plane_state->fb == plane->state->fb)
2173+
continue;
2174+
2175+
drm_framebuffer_reference(old_plane_state->fb);
2176+
drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb);
2177+
set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
2178+
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
2179+
}
21552180
}
21562181

21572182
static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -2336,6 +2361,15 @@ static const struct drm_crtc_funcs vop_crtc_funcs = {
23362361
.atomic_destroy_state = vop_crtc_destroy_state,
23372362
};
23382363

2364+
static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
2365+
{
2366+
struct vop *vop = container_of(work, struct vop, fb_unref_work);
2367+
struct drm_framebuffer *fb = val;
2368+
2369+
drm_crtc_vblank_put(&vop->crtc);
2370+
drm_framebuffer_unreference(fb);
2371+
}
2372+
23392373
static void vop_handle_vblank(struct vop *vop)
23402374
{
23412375
struct drm_device *drm = vop->drm_dev;
@@ -2356,6 +2390,9 @@ static void vop_handle_vblank(struct vop *vop)
23562390
}
23572391
if (!completion_done(&vop->wait_update_complete))
23582392
complete(&vop->wait_update_complete);
2393+
2394+
if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending))
2395+
drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq);
23592396
}
23602397

23612398
static irqreturn_t vop_isr(int irq, void *data)
@@ -2538,6 +2575,9 @@ static int vop_create_crtc(struct vop *vop)
25382575
goto err_cleanup_crtc;
25392576
}
25402577

2578+
drm_flip_work_init(&vop->fb_unref_work, "fb_unref",
2579+
vop_fb_unref_worker);
2580+
25412581
init_completion(&vop->dsp_hold_completion);
25422582
init_completion(&vop->wait_update_complete);
25432583
init_completion(&vop->line_flag_completion);
@@ -2621,6 +2661,7 @@ static void vop_destroy_crtc(struct vop *vop)
26212661
* references the CRTC.
26222662
*/
26232663
drm_crtc_cleanup(crtc);
2664+
drm_flip_work_cleanup(&vop->fb_unref_work);
26242665
}
26252666

26262667
/*

0 commit comments

Comments
 (0)