aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorTomasz Figa <tfiga@chromium.org>2016-09-14 08:54:58 -0400
committerSean Paul <seanpaul@chromium.org>2016-09-21 09:55:51 -0400
commit81c248f75a130c1ce46c67e8b05b37e8ffbbb33e (patch)
treefd273595e615342a52f964d7e77890c2d753a60e /drivers/gpu
parent47a7eb4597775ecdc29d2630d875a991f0449bf3 (diff)
drm/rockchip: Replace custom wait_for_vblanks with helper
Currently the driver uses a custom function to wait for flip to complete after an atomic commit. It was needed before because of two problems: - there is no hardware vblank counter, so the original helper would have a race condition with the vblank interrupt, - the driver didn't support unreferencing cursor framebuffers asynchronously to the commit, which was what the helper expected. Since both problems have been solved by previous patches, we can now make the driver use the generic helper and remove custom waiting code. Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.h1
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fb.c64
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c14
3 files changed, 1 insertions, 78 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 5c698456aa1c..fb6226cf84b7 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -39,7 +39,6 @@ struct drm_connector;
39struct rockchip_crtc_funcs { 39struct rockchip_crtc_funcs {
40 int (*enable_vblank)(struct drm_crtc *crtc); 40 int (*enable_vblank)(struct drm_crtc *crtc);
41 void (*disable_vblank)(struct drm_crtc *crtc); 41 void (*disable_vblank)(struct drm_crtc *crtc);
42 void (*wait_for_update)(struct drm_crtc *crtc);
43}; 42};
44 43
45struct rockchip_crtc_state { 44struct rockchip_crtc_state {
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 9890eccadd3b..0f6eda023bd0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -174,68 +174,6 @@ static void rockchip_drm_output_poll_changed(struct drm_device *dev)
174 drm_fb_helper_hotplug_event(fb_helper); 174 drm_fb_helper_hotplug_event(fb_helper);
175} 175}
176 176
177static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc)
178{
179 struct rockchip_drm_private *priv = crtc->dev->dev_private;
180 int pipe = drm_crtc_index(crtc);
181 const struct rockchip_crtc_funcs *crtc_funcs = priv->crtc_funcs[pipe];
182
183 if (crtc_funcs && crtc_funcs->wait_for_update)
184 crtc_funcs->wait_for_update(crtc);
185}
186
187/*
188 * We can't use drm_atomic_helper_wait_for_vblanks() because rk3288 and rk3066
189 * have hardware counters for neither vblanks nor scanlines, which results in
190 * a race where:
191 * | <-- HW vsync irq and reg take effect
192 * plane_commit --> |
193 * get_vblank and wait --> |
194 * | <-- handle_vblank, vblank->count + 1
195 * cleanup_fb --> |
196 * iommu crash --> |
197 * | <-- HW vsync irq and reg take effect
198 *
199 * This function is equivalent but uses rockchip_crtc_wait_for_update() instead
200 * of waiting for vblank_count to change.
201 */
202static void
203rockchip_atomic_wait_for_complete(struct drm_device *dev, struct drm_atomic_state *old_state)
204{
205 struct drm_crtc_state *old_crtc_state;
206 struct drm_crtc *crtc;
207 int i, ret;
208
209 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
210 /* No one cares about the old state, so abuse it for tracking
211 * and store whether we hold a vblank reference (and should do a
212 * vblank wait) in the ->enable boolean.
213 */
214 old_crtc_state->enable = false;
215
216 if (!crtc->state->active)
217 continue;
218
219 if (!drm_atomic_helper_framebuffer_changed(dev,
220 old_state, crtc))
221 continue;
222
223 ret = drm_crtc_vblank_get(crtc);
224 if (ret != 0)
225 continue;
226
227 old_crtc_state->enable = true;
228 }
229
230 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
231 if (!old_crtc_state->enable)
232 continue;
233
234 rockchip_crtc_wait_for_update(crtc);
235 drm_crtc_vblank_put(crtc);
236 }
237}
238
239static void 177static void
240rockchip_atomic_commit_tail(struct drm_atomic_state *state) 178rockchip_atomic_commit_tail(struct drm_atomic_state *state)
241{ 179{
@@ -250,7 +188,7 @@ rockchip_atomic_commit_tail(struct drm_atomic_state *state)
250 188
251 drm_atomic_helper_commit_hw_done(state); 189 drm_atomic_helper_commit_hw_done(state);
252 190
253 rockchip_atomic_wait_for_complete(dev, state); 191 drm_atomic_helper_wait_for_vblanks(dev, state);
254 192
255 drm_atomic_helper_cleanup_planes(dev, state); 193 drm_atomic_helper_cleanup_planes(dev, state);
256} 194}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 82dafcdd9056..b6d47dda691a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -122,7 +122,6 @@ struct vop {
122 struct mutex vsync_mutex; 122 struct mutex vsync_mutex;
123 bool vsync_work_pending; 123 bool vsync_work_pending;
124 struct completion dsp_hold_completion; 124 struct completion dsp_hold_completion;
125 struct completion wait_update_complete;
126 125
127 /* protected by dev->event_lock */ 126 /* protected by dev->event_lock */
128 struct drm_pending_vblank_event *event; 127 struct drm_pending_vblank_event *event;
@@ -933,18 +932,9 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
933 spin_unlock_irqrestore(&vop->irq_lock, flags); 932 spin_unlock_irqrestore(&vop->irq_lock, flags);
934} 933}
935 934
936static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
937{
938 struct vop *vop = to_vop(crtc);
939
940 reinit_completion(&vop->wait_update_complete);
941 WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100));
942}
943
944static const struct rockchip_crtc_funcs private_crtc_funcs = { 935static const struct rockchip_crtc_funcs private_crtc_funcs = {
945 .enable_vblank = vop_crtc_enable_vblank, 936 .enable_vblank = vop_crtc_enable_vblank,
946 .disable_vblank = vop_crtc_disable_vblank, 937 .disable_vblank = vop_crtc_disable_vblank,
947 .wait_for_update = vop_crtc_wait_for_update,
948}; 938};
949 939
950static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, 940static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -1251,9 +1241,6 @@ static void vop_handle_vblank(struct vop *vop)
1251 } 1241 }
1252 spin_unlock_irqrestore(&drm->event_lock, flags); 1242 spin_unlock_irqrestore(&drm->event_lock, flags);
1253 1243
1254 if (!completion_done(&vop->wait_update_complete))
1255 complete(&vop->wait_update_complete);
1256
1257 if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending)) 1244 if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending))
1258 drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq); 1245 drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq);
1259} 1246}
@@ -1398,7 +1385,6 @@ static int vop_create_crtc(struct vop *vop)
1398 vop_fb_unref_worker); 1385 vop_fb_unref_worker);
1399 1386
1400 init_completion(&vop->dsp_hold_completion); 1387 init_completion(&vop->dsp_hold_completion);
1401 init_completion(&vop->wait_update_complete);
1402 init_completion(&vop->line_flag_completion); 1388 init_completion(&vop->line_flag_completion);
1403 crtc->port = port; 1389 crtc->port = port;
1404 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs); 1390 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);