diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_fb.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_fb.c | 74 |
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 | 241 | int 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 | */ | ||
249 | int 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; | 256 | fail: |
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); | 267 | int 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 | |||
282 | fail: | ||
289 | return ret; | 283 | return ret; |
290 | } | 284 | } |
291 | 285 | ||