aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c139
1 files changed, 107 insertions, 32 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 271ffa4fdb47..ef1b22144d37 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -293,6 +293,8 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
293{ 293{
294 int ret; 294 int ret;
295 295
296 kref_init(&fb->refcount);
297
296 ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); 298 ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
297 if (ret) 299 if (ret)
298 return ret; 300 return ret;
@@ -306,6 +308,38 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
306} 308}
307EXPORT_SYMBOL(drm_framebuffer_init); 309EXPORT_SYMBOL(drm_framebuffer_init);
308 310
311static void drm_framebuffer_free(struct kref *kref)
312{
313 struct drm_framebuffer *fb =
314 container_of(kref, struct drm_framebuffer, refcount);
315 fb->funcs->destroy(fb);
316}
317
318/**
319 * drm_framebuffer_unreference - unref a framebuffer
320 *
321 * LOCKING:
322 * Caller must hold mode config lock.
323 */
324void drm_framebuffer_unreference(struct drm_framebuffer *fb)
325{
326 struct drm_device *dev = fb->dev;
327 DRM_DEBUG("FB ID: %d\n", fb->base.id);
328 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
329 kref_put(&fb->refcount, drm_framebuffer_free);
330}
331EXPORT_SYMBOL(drm_framebuffer_unreference);
332
333/**
334 * drm_framebuffer_reference - incr the fb refcnt
335 */
336void drm_framebuffer_reference(struct drm_framebuffer *fb)
337{
338 DRM_DEBUG("FB ID: %d\n", fb->base.id);
339 kref_get(&fb->refcount);
340}
341EXPORT_SYMBOL(drm_framebuffer_reference);
342
309/** 343/**
310 * drm_framebuffer_cleanup - remove a framebuffer object 344 * drm_framebuffer_cleanup - remove a framebuffer object
311 * @fb: framebuffer to remove 345 * @fb: framebuffer to remove
@@ -319,6 +353,32 @@ EXPORT_SYMBOL(drm_framebuffer_init);
319void drm_framebuffer_cleanup(struct drm_framebuffer *fb) 353void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
320{ 354{
321 struct drm_device *dev = fb->dev; 355 struct drm_device *dev = fb->dev;
356 /*
357 * This could be moved to drm_framebuffer_remove(), but for
358 * debugging is nice to keep around the list of fb's that are
359 * no longer associated w/ a drm_file but are not unreferenced
360 * yet. (i915 and omapdrm have debugfs files which will show
361 * this.)
362 */
363 drm_mode_object_put(dev, &fb->base);
364 list_del(&fb->head);
365 dev->mode_config.num_fb--;
366}
367EXPORT_SYMBOL(drm_framebuffer_cleanup);
368
369/**
370 * drm_framebuffer_remove - remove and unreference a framebuffer object
371 * @fb: framebuffer to remove
372 *
373 * LOCKING:
374 * Caller must hold mode config lock.
375 *
376 * Scans all the CRTCs and planes in @dev's mode_config. If they're
377 * using @fb, removes it, setting it to NULL.
378 */
379void drm_framebuffer_remove(struct drm_framebuffer *fb)
380{
381 struct drm_device *dev = fb->dev;
322 struct drm_crtc *crtc; 382 struct drm_crtc *crtc;
323 struct drm_plane *plane; 383 struct drm_plane *plane;
324 struct drm_mode_set set; 384 struct drm_mode_set set;
@@ -349,11 +409,11 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
349 } 409 }
350 } 410 }
351 411
352 drm_mode_object_put(dev, &fb->base); 412 list_del(&fb->filp_head);
353 list_del(&fb->head); 413
354 dev->mode_config.num_fb--; 414 drm_framebuffer_unreference(fb);
355} 415}
356EXPORT_SYMBOL(drm_framebuffer_cleanup); 416EXPORT_SYMBOL(drm_framebuffer_remove);
357 417
358/** 418/**
359 * drm_crtc_init - Initialise a new CRTC object 419 * drm_crtc_init - Initialise a new CRTC object
@@ -376,6 +436,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
376 436
377 crtc->dev = dev; 437 crtc->dev = dev;
378 crtc->funcs = funcs; 438 crtc->funcs = funcs;
439 crtc->invert_dimensions = false;
379 440
380 mutex_lock(&dev->mode_config.mutex); 441 mutex_lock(&dev->mode_config.mutex);
381 442
@@ -1030,11 +1091,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
1030 } 1091 }
1031 1092
1032 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { 1093 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
1033 fb->funcs->destroy(fb); 1094 drm_framebuffer_remove(fb);
1034 }
1035
1036 list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
1037 crtc->funcs->destroy(crtc);
1038 } 1095 }
1039 1096
1040 list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, 1097 list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
@@ -1042,6 +1099,10 @@ void drm_mode_config_cleanup(struct drm_device *dev)
1042 plane->funcs->destroy(plane); 1099 plane->funcs->destroy(plane);
1043 } 1100 }
1044 1101
1102 list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
1103 crtc->funcs->destroy(crtc);
1104 }
1105
1045 idr_remove_all(&dev->mode_config.crtc_idr); 1106 idr_remove_all(&dev->mode_config.crtc_idr);
1046 idr_destroy(&dev->mode_config.crtc_idr); 1107 idr_destroy(&dev->mode_config.crtc_idr);
1047} 1108}
@@ -1851,6 +1912,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
1851 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 1912 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
1852 1913
1853 if (crtc_req->mode_valid) { 1914 if (crtc_req->mode_valid) {
1915 int hdisplay, vdisplay;
1854 /* If we have a mode we need a framebuffer. */ 1916 /* If we have a mode we need a framebuffer. */
1855 /* If we pass -1, set the mode with the currently bound fb */ 1917 /* If we pass -1, set the mode with the currently bound fb */
1856 if (crtc_req->fb_id == -1) { 1918 if (crtc_req->fb_id == -1) {
@@ -1886,14 +1948,20 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
1886 1948
1887 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 1949 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1888 1950
1889 if (mode->hdisplay > fb->width || 1951 hdisplay = mode->hdisplay;
1890 mode->vdisplay > fb->height || 1952 vdisplay = mode->vdisplay;
1891 crtc_req->x > fb->width - mode->hdisplay || 1953
1892 crtc_req->y > fb->height - mode->vdisplay) { 1954 if (crtc->invert_dimensions)
1893 DRM_DEBUG_KMS("Invalid CRTC viewport %ux%u+%u+%u for fb size %ux%u.\n", 1955 swap(hdisplay, vdisplay);
1894 mode->hdisplay, mode->vdisplay, 1956
1895 crtc_req->x, crtc_req->y, 1957 if (hdisplay > fb->width ||
1896 fb->width, fb->height); 1958 vdisplay > fb->height ||
1959 crtc_req->x > fb->width - hdisplay ||
1960 crtc_req->y > fb->height - vdisplay) {
1961 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
1962 fb->width, fb->height,
1963 hdisplay, vdisplay, crtc_req->x, crtc_req->y,
1964 crtc->invert_dimensions ? " (inverted)" : "");
1897 ret = -ENOSPC; 1965 ret = -ENOSPC;
1898 goto out; 1966 goto out;
1899 } 1967 }
@@ -2168,6 +2236,8 @@ static int format_check(const struct drm_mode_fb_cmd2 *r)
2168 case DRM_FORMAT_NV21: 2236 case DRM_FORMAT_NV21:
2169 case DRM_FORMAT_NV16: 2237 case DRM_FORMAT_NV16:
2170 case DRM_FORMAT_NV61: 2238 case DRM_FORMAT_NV61:
2239 case DRM_FORMAT_NV24:
2240 case DRM_FORMAT_NV42:
2171 case DRM_FORMAT_YUV410: 2241 case DRM_FORMAT_YUV410:
2172 case DRM_FORMAT_YVU410: 2242 case DRM_FORMAT_YVU410:
2173 case DRM_FORMAT_YUV411: 2243 case DRM_FORMAT_YUV411:
@@ -2334,11 +2404,7 @@ int drm_mode_rmfb(struct drm_device *dev,
2334 goto out; 2404 goto out;
2335 } 2405 }
2336 2406
2337 /* TODO release all crtc connected to the framebuffer */ 2407 drm_framebuffer_remove(fb);
2338 /* TODO unhock the destructor from the buffer object */
2339
2340 list_del(&fb->filp_head);
2341 fb->funcs->destroy(fb);
2342 2408
2343out: 2409out:
2344 mutex_unlock(&dev->mode_config.mutex); 2410 mutex_unlock(&dev->mode_config.mutex);
@@ -2488,8 +2554,7 @@ void drm_fb_release(struct drm_file *priv)
2488 2554
2489 mutex_lock(&dev->mode_config.mutex); 2555 mutex_lock(&dev->mode_config.mutex);
2490 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { 2556 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
2491 list_del(&fb->filp_head); 2557 drm_framebuffer_remove(fb);
2492 fb->funcs->destroy(fb);
2493 } 2558 }
2494 mutex_unlock(&dev->mode_config.mutex); 2559 mutex_unlock(&dev->mode_config.mutex);
2495} 2560}
@@ -3488,6 +3553,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
3488 struct drm_framebuffer *fb; 3553 struct drm_framebuffer *fb;
3489 struct drm_pending_vblank_event *e = NULL; 3554 struct drm_pending_vblank_event *e = NULL;
3490 unsigned long flags; 3555 unsigned long flags;
3556 int hdisplay, vdisplay;
3491 int ret = -EINVAL; 3557 int ret = -EINVAL;
3492 3558
3493 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || 3559 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
@@ -3517,14 +3583,19 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
3517 goto out; 3583 goto out;
3518 fb = obj_to_fb(obj); 3584 fb = obj_to_fb(obj);
3519 3585
3520 if (crtc->mode.hdisplay > fb->width || 3586 hdisplay = crtc->mode.hdisplay;
3521 crtc->mode.vdisplay > fb->height || 3587 vdisplay = crtc->mode.vdisplay;
3522 crtc->x > fb->width - crtc->mode.hdisplay || 3588
3523 crtc->y > fb->height - crtc->mode.vdisplay) { 3589 if (crtc->invert_dimensions)
3524 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n", 3590 swap(hdisplay, vdisplay);
3525 fb->width, fb->height, 3591
3526 crtc->mode.hdisplay, crtc->mode.vdisplay, 3592 if (hdisplay > fb->width ||
3527 crtc->x, crtc->y); 3593 vdisplay > fb->height ||
3594 crtc->x > fb->width - hdisplay ||
3595 crtc->y > fb->height - vdisplay) {
3596 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
3597 fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y,
3598 crtc->invert_dimensions ? " (inverted)" : "");
3528 ret = -ENOSPC; 3599 ret = -ENOSPC;
3529 goto out; 3600 goto out;
3530 } 3601 }
@@ -3717,6 +3788,8 @@ int drm_format_num_planes(uint32_t format)
3717 case DRM_FORMAT_NV21: 3788 case DRM_FORMAT_NV21:
3718 case DRM_FORMAT_NV16: 3789 case DRM_FORMAT_NV16:
3719 case DRM_FORMAT_NV61: 3790 case DRM_FORMAT_NV61:
3791 case DRM_FORMAT_NV24:
3792 case DRM_FORMAT_NV42:
3720 return 2; 3793 return 2;
3721 default: 3794 default:
3722 return 1; 3795 return 1;
@@ -3750,6 +3823,8 @@ int drm_format_plane_cpp(uint32_t format, int plane)
3750 case DRM_FORMAT_NV21: 3823 case DRM_FORMAT_NV21:
3751 case DRM_FORMAT_NV16: 3824 case DRM_FORMAT_NV16:
3752 case DRM_FORMAT_NV61: 3825 case DRM_FORMAT_NV61:
3826 case DRM_FORMAT_NV24:
3827 case DRM_FORMAT_NV42:
3753 return plane ? 2 : 1; 3828 return plane ? 2 : 1;
3754 case DRM_FORMAT_YUV410: 3829 case DRM_FORMAT_YUV410:
3755 case DRM_FORMAT_YVU410: 3830 case DRM_FORMAT_YVU410: