aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_fb.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fb.c74
1 files changed, 34 insertions, 40 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 8031402e7951..f2b8f0668c0c 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -237,55 +237,49 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
237 } 237 }
238} 238}
239 239
240/* Call for unpin 'a' (if not NULL), and pin 'b' (if not NULL). Although 240/* pin, prepare for scanout: */
241 * buffers to unpin are just pushed to the unpin fifo so that the 241int omap_framebuffer_pin(struct drm_framebuffer *fb)
242 * caller can defer unpin until vblank.
243 *
244 * Note if this fails (ie. something went very wrong!), all buffers are
245 * unpinned, and the caller disables the overlay. We could have tried
246 * to revert back to the previous set of pinned buffers but if things are
247 * hosed there is no guarantee that would succeed.
248 */
249int omap_framebuffer_replace(struct drm_framebuffer *a,
250 struct drm_framebuffer *b, void *arg,
251 void (*unpin)(void *arg, struct drm_gem_object *bo))
252{ 242{
253 int ret = 0, i, na, nb; 243 struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
254 struct omap_framebuffer *ofba = to_omap_framebuffer(a); 244 int ret, i, n = drm_format_num_planes(fb->pixel_format);
255 struct omap_framebuffer *ofbb = to_omap_framebuffer(b);
256 uint32_t pinned_mask = 0;
257 245
258 na = a ? drm_format_num_planes(a->pixel_format) : 0; 246 for (i = 0; i < n; i++) {
259 nb = b ? drm_format_num_planes(b->pixel_format) : 0; 247 struct plane *plane = &omap_fb->planes[i];
248 ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true);
249 if (ret)
250 goto fail;
251 omap_gem_dma_sync(plane->bo, DMA_TO_DEVICE);
252 }
260 253
261 for (i = 0; i < max(na, nb); i++) { 254 return 0;
262 struct plane *pa, *pb;
263 255
264 pa = (i < na) ? &ofba->planes[i] : NULL; 256fail:
265 pb = (i < nb) ? &ofbb->planes[i] : NULL; 257 for (i--; i >= 0; i--) {
258 struct plane *plane = &omap_fb->planes[i];
259 omap_gem_put_paddr(plane->bo);
260 plane->paddr = 0;
261 }
266 262
267 if (pa) 263 return ret;
268 unpin(arg, pa->bo); 264}
269 265
270 if (pb && !ret) { 266/* unpin, no longer being scanned out: */
271 ret = omap_gem_get_paddr(pb->bo, &pb->paddr, true); 267int omap_framebuffer_unpin(struct drm_framebuffer *fb)
272 if (!ret) { 268{
273 omap_gem_dma_sync(pb->bo, DMA_TO_DEVICE); 269 struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
274 pinned_mask |= (1 << i); 270 int ret, i, n = drm_format_num_planes(fb->pixel_format);
275 }
276 }
277 }
278 271
279 if (ret) { 272 for (i = 0; i < n; i++) {
280 /* something went wrong.. unpin what has been pinned */ 273 struct plane *plane = &omap_fb->planes[i];
281 for (i = 0; i < nb; i++) { 274 ret = omap_gem_put_paddr(plane->bo);
282 if (pinned_mask & (1 << i)) { 275 if (ret)
283 struct plane *pb = &ofba->planes[i]; 276 goto fail;
284 unpin(arg, pb->bo); 277 plane->paddr = 0;
285 }
286 }
287 } 278 }
288 279
280 return 0;
281
282fail:
289 return ret; 283 return ret;
290} 284}
291 285