aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-04 02:29:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-04 02:29:23 -0400
commit612a9aab56a93533e76e3ad91642db7033e03b69 (patch)
tree8402096973f67af941f9392f7da06cca03e0b58a /drivers/gpu/drm/drm_crtc.c
parent3a494318b14b1bc0f59d2d6ce84c505c74d82d2a (diff)
parent268d28371cd326be4dfcd7eba5917bf4b9d30c8f (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm merge (part 1) from Dave Airlie: "So first of all my tree and uapi stuff has a conflict mess, its my fault as the nouveau stuff didn't hit -next as were trying to rebase regressions out of it before we merged. Highlights: - SH mobile modesetting driver and associated helpers - some DRM core documentation - i915 modesetting rework, haswell hdmi, haswell and vlv fixes, write combined pte writing, ilk rc6 support, - nouveau: major driver rework into a hw core driver, makes features like SLI a lot saner to implement, - psb: add eDP/DP support for Cedarview - radeon: 2 layer page tables, async VM pte updates, better PLL selection for > 2 screens, better ACPI interactions The rest is general grab bag of fixes. So why part 1? well I have the exynos pull req which came in a bit late but was waiting for me to do something they shouldn't have and it looks fairly safe, and David Howells has some more header cleanups he'd like me to pull, that seem like a good idea, but I'd like to get this merge out of the way so -next dosen't get blocked." Tons of conflicts mostly due to silly include line changes, but mostly mindless. A few other small semantic conflicts too, noted from Dave's pre-merged branch. * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (447 commits) drm/nv98/crypt: fix fuc build with latest envyas drm/nouveau/devinit: fixup various issues with subdev ctor/init ordering drm/nv41/vm: fix and enable use of "real" pciegart drm/nv44/vm: fix and enable use of "real" pciegart drm/nv04/dmaobj: fixup vm target handling in preparation for nv4x pcie drm/nouveau: store supported dma mask in vmmgr drm/nvc0/ibus: initial implementation of subdev drm/nouveau/therm: add support for fan-control modes drm/nouveau/hwmon: rename pwm0* to pmw1* to follow hwmon's rules drm/nouveau/therm: calculate the pwm divisor on nv50+ drm/nouveau/fan: rewrite the fan tachometer driver to get more precision, faster drm/nouveau/therm: move thermal-related functions to the therm subdev drm/nouveau/bios: parse the pwm divisor from the perf table drm/nouveau/therm: use the EXTDEV table to detect i2c monitoring devices drm/nouveau/therm: rework thermal table parsing drm/nouveau/gpio: expose the PWM/TOGGLE parameter found in the gpio vbios table drm/nouveau: fix pm initialization order drm/nouveau/bios: check that fixed tvdac gpio data is valid before using it drm/nouveau: log channel debug/error messages from client object rather than drm client drm/nouveau: have drm debugging macros build on top of core macros ...
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: