aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-14 03:39:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-14 03:39:08 -0400
commit2d65a9f48fcdf7866aab6457bc707ca233e0c791 (patch)
treef93e5838d6ac2e59434367f4ff905f7d9c45fc2b /drivers/gpu/drm/drm_crtc.c
parentda92da3638a04894afdca8b99e973ddd20268471 (diff)
parentdfda0df3426483cf5fc7441f23f318edbabecb03 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "This is the main git pull for the drm, I pretty much froze major pulls at -rc5/6 time, and haven't had much fallout, so will probably continue doing that. Lots of changes all over, big internal header cleanup to make it clear drm features are legacy things and what are things that modern KMS drivers should be using. Also big move to use the new generic fences in all the TTM drivers. core: atomic prep work, vblank rework changes, allows immediate vblank disables major header reworking and cleanups to better delinate legacy interfaces from what KMS drivers should be using. cursor planes locking fixes ttm: move to generic fences (affects all TTM drivers) ppc64 caching fixes radeon: userptr support, uvd for old asics, reset rework for fence changes better buffer placement changes, dpm feature enablement hdmi audio support fixes intel: Cherryview work, 180 degree rotation, skylake prep work, execlist command submission full ppgtt prep work cursor improvements edid caching, vdd handling improvements nouveau: fence reworking kepler memory clock work gt21x clock work fan control improvements hdmi infoframe fixes DP audio ast: ppc64 fixes caching fix rcar: rcar-du DT support ipuv3: prep work for capture support msm: LVDS support for mdp4, new panel, gpu refactoring exynos: exynos3250 SoC support, drop bad mmap interface, mipi dsi changes, and component match support" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (640 commits) drm/mst: rework payload table allocation to conform better. drm/ast: Fix HW cursor image drm/radeon/kv: add uvd/vce info to dpm debugfs output drm/radeon/ci: add uvd/vce info to dpm debugfs output drm/radeon: export reservation_object from dmabuf to ttm drm/radeon: cope with foreign fences inside the reservation object drm/radeon: cope with foreign fences inside display drm/core: use helper to check driver features drm/radeon/cik: write gfx ucode version to ucode addr reg drm/radeon/si: print full CS when we hit a packet 0 drm/radeon: remove unecessary includes drm/radeon/combios: declare legacy_connector_convert as static drm/radeon/atombios: declare connector convert tables as static drm/radeon: drop btc_get_max_clock_from_voltage_dependency_table drm/radeon/dpm: drop clk/voltage dependency filters for BTC drm/radeon/dpm: drop clk/voltage dependency filters for CI drm/radeon/dpm: drop clk/voltage dependency filters for SI drm/radeon/dpm: drop clk/voltage dependency filters for NI drm/radeon: disable audio when we disable hdmi (v2) drm/radeon: split audio enable between eg and r600 (v2) ...
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c394
1 files changed, 227 insertions, 167 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 90e773019eac..e79c8d3700d8 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -40,106 +40,12 @@
40#include <drm/drm_modeset_lock.h> 40#include <drm/drm_modeset_lock.h>
41 41
42#include "drm_crtc_internal.h" 42#include "drm_crtc_internal.h"
43#include "drm_internal.h"
43 44
44static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, 45static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
45 struct drm_mode_fb_cmd2 *r, 46 struct drm_mode_fb_cmd2 *r,
46 struct drm_file *file_priv); 47 struct drm_file *file_priv);
47 48
48/**
49 * drm_modeset_lock_all - take all modeset locks
50 * @dev: drm device
51 *
52 * This function takes all modeset locks, suitable where a more fine-grained
53 * scheme isn't (yet) implemented. Locks must be dropped with
54 * drm_modeset_unlock_all.
55 */
56void drm_modeset_lock_all(struct drm_device *dev)
57{
58 struct drm_mode_config *config = &dev->mode_config;
59 struct drm_modeset_acquire_ctx *ctx;
60 int ret;
61
62 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
63 if (WARN_ON(!ctx))
64 return;
65
66 mutex_lock(&config->mutex);
67
68 drm_modeset_acquire_init(ctx, 0);
69
70retry:
71 ret = drm_modeset_lock(&config->connection_mutex, ctx);
72 if (ret)
73 goto fail;
74 ret = drm_modeset_lock_all_crtcs(dev, ctx);
75 if (ret)
76 goto fail;
77
78 WARN_ON(config->acquire_ctx);
79
80 /* now we hold the locks, so now that it is safe, stash the
81 * ctx for drm_modeset_unlock_all():
82 */
83 config->acquire_ctx = ctx;
84
85 drm_warn_on_modeset_not_all_locked(dev);
86
87 return;
88
89fail:
90 if (ret == -EDEADLK) {
91 drm_modeset_backoff(ctx);
92 goto retry;
93 }
94}
95EXPORT_SYMBOL(drm_modeset_lock_all);
96
97/**
98 * drm_modeset_unlock_all - drop all modeset locks
99 * @dev: device
100 *
101 * This function drop all modeset locks taken by drm_modeset_lock_all.
102 */
103void drm_modeset_unlock_all(struct drm_device *dev)
104{
105 struct drm_mode_config *config = &dev->mode_config;
106 struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
107
108 if (WARN_ON(!ctx))
109 return;
110
111 config->acquire_ctx = NULL;
112 drm_modeset_drop_locks(ctx);
113 drm_modeset_acquire_fini(ctx);
114
115 kfree(ctx);
116
117 mutex_unlock(&dev->mode_config.mutex);
118}
119EXPORT_SYMBOL(drm_modeset_unlock_all);
120
121/**
122 * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked
123 * @dev: device
124 *
125 * Useful as a debug assert.
126 */
127void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
128{
129 struct drm_crtc *crtc;
130
131 /* Locking is currently fubar in the panic handler. */
132 if (oops_in_progress)
133 return;
134
135 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
136 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
137
138 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
139 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
140}
141EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
142
143/* Avoid boilerplate. I'm tired of typing. */ 49/* Avoid boilerplate. I'm tired of typing. */
144#define DRM_ENUM_NAME_FN(fnname, list) \ 50#define DRM_ENUM_NAME_FN(fnname, list) \
145 const char *fnname(int val) \ 51 const char *fnname(int val) \
@@ -515,9 +421,6 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
515 if (ret) 421 if (ret)
516 goto out; 422 goto out;
517 423
518 /* Grab the idr reference. */
519 drm_framebuffer_reference(fb);
520
521 dev->mode_config.num_fb++; 424 dev->mode_config.num_fb++;
522 list_add(&fb->head, &dev->mode_config.fb_list); 425 list_add(&fb->head, &dev->mode_config.fb_list);
523out: 426out:
@@ -527,10 +430,34 @@ out:
527} 430}
528EXPORT_SYMBOL(drm_framebuffer_init); 431EXPORT_SYMBOL(drm_framebuffer_init);
529 432
433/* dev->mode_config.fb_lock must be held! */
434static void __drm_framebuffer_unregister(struct drm_device *dev,
435 struct drm_framebuffer *fb)
436{
437 mutex_lock(&dev->mode_config.idr_mutex);
438 idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
439 mutex_unlock(&dev->mode_config.idr_mutex);
440
441 fb->base.id = 0;
442}
443
530static void drm_framebuffer_free(struct kref *kref) 444static void drm_framebuffer_free(struct kref *kref)
531{ 445{
532 struct drm_framebuffer *fb = 446 struct drm_framebuffer *fb =
533 container_of(kref, struct drm_framebuffer, refcount); 447 container_of(kref, struct drm_framebuffer, refcount);
448 struct drm_device *dev = fb->dev;
449
450 /*
451 * The lookup idr holds a weak reference, which has not necessarily been
452 * removed at this point. Check for that.
453 */
454 mutex_lock(&dev->mode_config.fb_lock);
455 if (fb->base.id) {
456 /* Mark fb as reaped and drop idr ref. */
457 __drm_framebuffer_unregister(dev, fb);
458 }
459 mutex_unlock(&dev->mode_config.fb_lock);
460
534 fb->funcs->destroy(fb); 461 fb->funcs->destroy(fb);
535} 462}
536 463
@@ -567,8 +494,10 @@ struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
567 494
568 mutex_lock(&dev->mode_config.fb_lock); 495 mutex_lock(&dev->mode_config.fb_lock);
569 fb = __drm_framebuffer_lookup(dev, id); 496 fb = __drm_framebuffer_lookup(dev, id);
570 if (fb) 497 if (fb) {
571 drm_framebuffer_reference(fb); 498 if (!kref_get_unless_zero(&fb->refcount))
499 fb = NULL;
500 }
572 mutex_unlock(&dev->mode_config.fb_lock); 501 mutex_unlock(&dev->mode_config.fb_lock);
573 502
574 return fb; 503 return fb;
@@ -612,19 +541,6 @@ static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
612 kref_put(&fb->refcount, drm_framebuffer_free_bug); 541 kref_put(&fb->refcount, drm_framebuffer_free_bug);
613} 542}
614 543
615/* dev->mode_config.fb_lock must be held! */
616static void __drm_framebuffer_unregister(struct drm_device *dev,
617 struct drm_framebuffer *fb)
618{
619 mutex_lock(&dev->mode_config.idr_mutex);
620 idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
621 mutex_unlock(&dev->mode_config.idr_mutex);
622
623 fb->base.id = 0;
624
625 __drm_framebuffer_unreference(fb);
626}
627
628/** 544/**
629 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr 545 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
630 * @fb: fb to unregister 546 * @fb: fb to unregister
@@ -764,11 +680,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
764 crtc->funcs = funcs; 680 crtc->funcs = funcs;
765 crtc->invert_dimensions = false; 681 crtc->invert_dimensions = false;
766 682
767 drm_modeset_lock_all(dev);
768 drm_modeset_lock_init(&crtc->mutex); 683 drm_modeset_lock_init(&crtc->mutex);
769 /* dropped by _unlock_all(): */
770 drm_modeset_lock(&crtc->mutex, config->acquire_ctx);
771
772 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); 684 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
773 if (ret) 685 if (ret)
774 goto out; 686 goto out;
@@ -786,7 +698,6 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
786 cursor->possible_crtcs = 1 << drm_crtc_index(crtc); 698 cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
787 699
788 out: 700 out:
789 drm_modeset_unlock_all(dev);
790 701
791 return ret; 702 return ret;
792} 703}
@@ -853,6 +764,59 @@ static void drm_mode_remove(struct drm_connector *connector,
853} 764}
854 765
855/** 766/**
767 * drm_connector_get_cmdline_mode - reads the user's cmdline mode
768 * @connector: connector to quwery
769 * @mode: returned mode
770 *
771 * The kernel supports per-connector configration of its consoles through
772 * use of the video= parameter. This function parses that option and
773 * extracts the user's specified mode (or enable/disable status) for a
774 * particular connector. This is typically only used during the early fbdev
775 * setup.
776 */
777static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
778{
779 struct drm_cmdline_mode *mode = &connector->cmdline_mode;
780 char *option = NULL;
781
782 if (fb_get_options(connector->name, &option))
783 return;
784
785 if (!drm_mode_parse_command_line_for_connector(option,
786 connector,
787 mode))
788 return;
789
790 if (mode->force) {
791 const char *s;
792
793 switch (mode->force) {
794 case DRM_FORCE_OFF:
795 s = "OFF";
796 break;
797 case DRM_FORCE_ON_DIGITAL:
798 s = "ON - dig";
799 break;
800 default:
801 case DRM_FORCE_ON:
802 s = "ON";
803 break;
804 }
805
806 DRM_INFO("forcing %s connector %s\n", connector->name, s);
807 connector->force = mode->force;
808 }
809
810 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
811 connector->name,
812 mode->xres, mode->yres,
813 mode->refresh_specified ? mode->refresh : 60,
814 mode->rb ? " reduced blanking" : "",
815 mode->margins ? " with margins" : "",
816 mode->interlace ? " interlaced" : "");
817}
818
819/**
856 * drm_connector_init - Init a preallocated connector 820 * drm_connector_init - Init a preallocated connector
857 * @dev: DRM device 821 * @dev: DRM device
858 * @connector: the connector to init 822 * @connector: the connector to init
@@ -904,6 +868,8 @@ int drm_connector_init(struct drm_device *dev,
904 connector->edid_blob_ptr = NULL; 868 connector->edid_blob_ptr = NULL;
905 connector->status = connector_status_unknown; 869 connector->status = connector_status_unknown;
906 870
871 drm_connector_get_cmdline_mode(connector);
872
907 list_add_tail(&connector->head, &dev->mode_config.connector_list); 873 list_add_tail(&connector->head, &dev->mode_config.connector_list);
908 dev->mode_config.num_connector++; 874 dev->mode_config.num_connector++;
909 875
@@ -957,6 +923,29 @@ void drm_connector_cleanup(struct drm_connector *connector)
957EXPORT_SYMBOL(drm_connector_cleanup); 923EXPORT_SYMBOL(drm_connector_cleanup);
958 924
959/** 925/**
926 * drm_connector_index - find the index of a registered connector
927 * @connector: connector to find index for
928 *
929 * Given a registered connector, return the index of that connector within a DRM
930 * device's list of connectors.
931 */
932unsigned int drm_connector_index(struct drm_connector *connector)
933{
934 unsigned int index = 0;
935 struct drm_connector *tmp;
936
937 list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) {
938 if (tmp == connector)
939 return index;
940
941 index++;
942 }
943
944 BUG();
945}
946EXPORT_SYMBOL(drm_connector_index);
947
948/**
960 * drm_connector_register - register a connector 949 * drm_connector_register - register a connector
961 * @connector: the connector to register 950 * @connector: the connector to register
962 * 951 *
@@ -1261,6 +1250,29 @@ void drm_plane_cleanup(struct drm_plane *plane)
1261EXPORT_SYMBOL(drm_plane_cleanup); 1250EXPORT_SYMBOL(drm_plane_cleanup);
1262 1251
1263/** 1252/**
1253 * drm_plane_index - find the index of a registered plane
1254 * @plane: plane to find index for
1255 *
1256 * Given a registered plane, return the index of that CRTC within a DRM
1257 * device's list of planes.
1258 */
1259unsigned int drm_plane_index(struct drm_plane *plane)
1260{
1261 unsigned int index = 0;
1262 struct drm_plane *tmp;
1263
1264 list_for_each_entry(tmp, &plane->dev->mode_config.plane_list, head) {
1265 if (tmp == plane)
1266 return index;
1267
1268 index++;
1269 }
1270
1271 BUG();
1272}
1273EXPORT_SYMBOL(drm_plane_index);
1274
1275/**
1264 * drm_plane_force_disable - Forcibly disable a plane 1276 * drm_plane_force_disable - Forcibly disable a plane
1265 * @plane: plane to disable 1277 * @plane: plane to disable
1266 * 1278 *
@@ -1271,19 +1283,21 @@ EXPORT_SYMBOL(drm_plane_cleanup);
1271 */ 1283 */
1272void drm_plane_force_disable(struct drm_plane *plane) 1284void drm_plane_force_disable(struct drm_plane *plane)
1273{ 1285{
1274 struct drm_framebuffer *old_fb = plane->fb;
1275 int ret; 1286 int ret;
1276 1287
1277 if (!old_fb) 1288 if (!plane->fb)
1278 return; 1289 return;
1279 1290
1291 plane->old_fb = plane->fb;
1280 ret = plane->funcs->disable_plane(plane); 1292 ret = plane->funcs->disable_plane(plane);
1281 if (ret) { 1293 if (ret) {
1282 DRM_ERROR("failed to disable plane with busy fb\n"); 1294 DRM_ERROR("failed to disable plane with busy fb\n");
1295 plane->old_fb = NULL;
1283 return; 1296 return;
1284 } 1297 }
1285 /* disconnect the plane from the fb and crtc: */ 1298 /* disconnect the plane from the fb and crtc: */
1286 __drm_framebuffer_unreference(old_fb); 1299 __drm_framebuffer_unreference(plane->old_fb);
1300 plane->old_fb = NULL;
1287 plane->fb = NULL; 1301 plane->fb = NULL;
1288 plane->crtc = NULL; 1302 plane->crtc = NULL;
1289} 1303}
@@ -2249,33 +2263,29 @@ out:
2249 * 2263 *
2250 * src_{x,y,w,h} are provided in 16.16 fixed point format 2264 * src_{x,y,w,h} are provided in 16.16 fixed point format
2251 */ 2265 */
2252static int setplane_internal(struct drm_plane *plane, 2266static int __setplane_internal(struct drm_plane *plane,
2253 struct drm_crtc *crtc, 2267 struct drm_crtc *crtc,
2254 struct drm_framebuffer *fb, 2268 struct drm_framebuffer *fb,
2255 int32_t crtc_x, int32_t crtc_y, 2269 int32_t crtc_x, int32_t crtc_y,
2256 uint32_t crtc_w, uint32_t crtc_h, 2270 uint32_t crtc_w, uint32_t crtc_h,
2257 /* src_{x,y,w,h} values are 16.16 fixed point */ 2271 /* src_{x,y,w,h} values are 16.16 fixed point */
2258 uint32_t src_x, uint32_t src_y, 2272 uint32_t src_x, uint32_t src_y,
2259 uint32_t src_w, uint32_t src_h) 2273 uint32_t src_w, uint32_t src_h)
2260{ 2274{
2261 struct drm_device *dev = plane->dev;
2262 struct drm_framebuffer *old_fb = NULL;
2263 int ret = 0; 2275 int ret = 0;
2264 unsigned int fb_width, fb_height; 2276 unsigned int fb_width, fb_height;
2265 int i; 2277 int i;
2266 2278
2267 /* No fb means shut it down */ 2279 /* No fb means shut it down */
2268 if (!fb) { 2280 if (!fb) {
2269 drm_modeset_lock_all(dev); 2281 plane->old_fb = plane->fb;
2270 old_fb = plane->fb;
2271 ret = plane->funcs->disable_plane(plane); 2282 ret = plane->funcs->disable_plane(plane);
2272 if (!ret) { 2283 if (!ret) {
2273 plane->crtc = NULL; 2284 plane->crtc = NULL;
2274 plane->fb = NULL; 2285 plane->fb = NULL;
2275 } else { 2286 } else {
2276 old_fb = NULL; 2287 plane->old_fb = NULL;
2277 } 2288 }
2278 drm_modeset_unlock_all(dev);
2279 goto out; 2289 goto out;
2280 } 2290 }
2281 2291
@@ -2315,8 +2325,7 @@ static int setplane_internal(struct drm_plane *plane,
2315 goto out; 2325 goto out;
2316 } 2326 }
2317 2327
2318 drm_modeset_lock_all(dev); 2328 plane->old_fb = plane->fb;
2319 old_fb = plane->fb;
2320 ret = plane->funcs->update_plane(plane, crtc, fb, 2329 ret = plane->funcs->update_plane(plane, crtc, fb,
2321 crtc_x, crtc_y, crtc_w, crtc_h, 2330 crtc_x, crtc_y, crtc_w, crtc_h,
2322 src_x, src_y, src_w, src_h); 2331 src_x, src_y, src_w, src_h);
@@ -2325,18 +2334,37 @@ static int setplane_internal(struct drm_plane *plane,
2325 plane->fb = fb; 2334 plane->fb = fb;
2326 fb = NULL; 2335 fb = NULL;
2327 } else { 2336 } else {
2328 old_fb = NULL; 2337 plane->old_fb = NULL;
2329 } 2338 }
2330 drm_modeset_unlock_all(dev);
2331 2339
2332out: 2340out:
2333 if (fb) 2341 if (fb)
2334 drm_framebuffer_unreference(fb); 2342 drm_framebuffer_unreference(fb);
2335 if (old_fb) 2343 if (plane->old_fb)
2336 drm_framebuffer_unreference(old_fb); 2344 drm_framebuffer_unreference(plane->old_fb);
2345 plane->old_fb = NULL;
2337 2346
2338 return ret; 2347 return ret;
2348}
2349
2350static int setplane_internal(struct drm_plane *plane,
2351 struct drm_crtc *crtc,
2352 struct drm_framebuffer *fb,
2353 int32_t crtc_x, int32_t crtc_y,
2354 uint32_t crtc_w, uint32_t crtc_h,
2355 /* src_{x,y,w,h} values are 16.16 fixed point */
2356 uint32_t src_x, uint32_t src_y,
2357 uint32_t src_w, uint32_t src_h)
2358{
2359 int ret;
2360
2361 drm_modeset_lock_all(plane->dev);
2362 ret = __setplane_internal(plane, crtc, fb,
2363 crtc_x, crtc_y, crtc_w, crtc_h,
2364 src_x, src_y, src_w, src_h);
2365 drm_modeset_unlock_all(plane->dev);
2339 2366
2367 return ret;
2340} 2368}
2341 2369
2342/** 2370/**
@@ -2440,7 +2468,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
2440 * crtcs. Atomic modeset will have saner semantics ... 2468 * crtcs. Atomic modeset will have saner semantics ...
2441 */ 2469 */
2442 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) 2470 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
2443 tmp->old_fb = tmp->primary->fb; 2471 tmp->primary->old_fb = tmp->primary->fb;
2444 2472
2445 fb = set->fb; 2473 fb = set->fb;
2446 2474
@@ -2453,8 +2481,9 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
2453 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { 2481 list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
2454 if (tmp->primary->fb) 2482 if (tmp->primary->fb)
2455 drm_framebuffer_reference(tmp->primary->fb); 2483 drm_framebuffer_reference(tmp->primary->fb);
2456 if (tmp->old_fb) 2484 if (tmp->primary->old_fb)
2457 drm_framebuffer_unreference(tmp->old_fb); 2485 drm_framebuffer_unreference(tmp->primary->old_fb);
2486 tmp->primary->old_fb = NULL;
2458 } 2487 }
2459 2488
2460 return ret; 2489 return ret;
@@ -2701,6 +2730,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2701 int ret = 0; 2730 int ret = 0;
2702 2731
2703 BUG_ON(!crtc->cursor); 2732 BUG_ON(!crtc->cursor);
2733 WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL);
2704 2734
2705 /* 2735 /*
2706 * Obtain fb we'll be using (either new or existing) and take an extra 2736 * Obtain fb we'll be using (either new or existing) and take an extra
@@ -2720,11 +2750,9 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2720 fb = NULL; 2750 fb = NULL;
2721 } 2751 }
2722 } else { 2752 } else {
2723 mutex_lock(&dev->mode_config.mutex);
2724 fb = crtc->cursor->fb; 2753 fb = crtc->cursor->fb;
2725 if (fb) 2754 if (fb)
2726 drm_framebuffer_reference(fb); 2755 drm_framebuffer_reference(fb);
2727 mutex_unlock(&dev->mode_config.mutex);
2728 } 2756 }
2729 2757
2730 if (req->flags & DRM_MODE_CURSOR_MOVE) { 2758 if (req->flags & DRM_MODE_CURSOR_MOVE) {
@@ -2746,7 +2774,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2746 * setplane_internal will take care of deref'ing either the old or new 2774 * setplane_internal will take care of deref'ing either the old or new
2747 * framebuffer depending on success. 2775 * framebuffer depending on success.
2748 */ 2776 */
2749 ret = setplane_internal(crtc->cursor, crtc, fb, 2777 ret = __setplane_internal(crtc->cursor, crtc, fb,
2750 crtc_x, crtc_y, crtc_w, crtc_h, 2778 crtc_x, crtc_y, crtc_w, crtc_h,
2751 0, 0, src_w, src_h); 2779 0, 0, src_w, src_h);
2752 2780
@@ -2782,10 +2810,12 @@ static int drm_mode_cursor_common(struct drm_device *dev,
2782 * If this crtc has a universal cursor plane, call that plane's update 2810 * If this crtc has a universal cursor plane, call that plane's update
2783 * handler rather than using legacy cursor handlers. 2811 * handler rather than using legacy cursor handlers.
2784 */ 2812 */
2785 if (crtc->cursor) 2813 drm_modeset_lock_crtc(crtc);
2786 return drm_mode_cursor_universal(crtc, req, file_priv); 2814 if (crtc->cursor) {
2815 ret = drm_mode_cursor_universal(crtc, req, file_priv);
2816 goto out;
2817 }
2787 2818
2788 drm_modeset_lock(&crtc->mutex, NULL);
2789 if (req->flags & DRM_MODE_CURSOR_BO) { 2819 if (req->flags & DRM_MODE_CURSOR_BO) {
2790 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { 2820 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
2791 ret = -ENXIO; 2821 ret = -ENXIO;
@@ -2809,7 +2839,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
2809 } 2839 }
2810 } 2840 }
2811out: 2841out:
2812 drm_modeset_unlock(&crtc->mutex); 2842 drm_modeset_unlock_crtc(crtc);
2813 2843
2814 return ret; 2844 return ret;
2815 2845
@@ -3370,7 +3400,16 @@ void drm_fb_release(struct drm_file *priv)
3370 struct drm_device *dev = priv->minor->dev; 3400 struct drm_device *dev = priv->minor->dev;
3371 struct drm_framebuffer *fb, *tfb; 3401 struct drm_framebuffer *fb, *tfb;
3372 3402
3373 mutex_lock(&priv->fbs_lock); 3403 /*
3404 * When the file gets released that means no one else can access the fb
3405 * list any more, so no need to grab fpriv->fbs_lock. And we need to to
3406 * avoid upsetting lockdep since the universal cursor code adds a
3407 * framebuffer while holding mutex locks.
3408 *
3409 * Note that a real deadlock between fpriv->fbs_lock and the modeset
3410 * locks is impossible here since no one else but this function can get
3411 * at it any more.
3412 */
3374 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { 3413 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
3375 3414
3376 mutex_lock(&dev->mode_config.fb_lock); 3415 mutex_lock(&dev->mode_config.fb_lock);
@@ -3383,7 +3422,6 @@ void drm_fb_release(struct drm_file *priv)
3383 /* This will also drop the fpriv->fbs reference. */ 3422 /* This will also drop the fpriv->fbs reference. */
3384 drm_framebuffer_remove(fb); 3423 drm_framebuffer_remove(fb);
3385 } 3424 }
3386 mutex_unlock(&priv->fbs_lock);
3387} 3425}
3388 3426
3389/** 3427/**
@@ -3495,9 +3533,10 @@ EXPORT_SYMBOL(drm_property_create_enum);
3495 * @flags: flags specifying the property type 3533 * @flags: flags specifying the property type
3496 * @name: name of the property 3534 * @name: name of the property
3497 * @props: enumeration lists with property bitflags 3535 * @props: enumeration lists with property bitflags
3498 * @num_values: number of pre-defined values 3536 * @num_props: size of the @props array
3537 * @supported_bits: bitmask of all supported enumeration values
3499 * 3538 *
3500 * This creates a new generic drm property which can then be attached to a drm 3539 * This creates a new bitmask drm property which can then be attached to a drm
3501 * object with drm_object_attach_property. The returned property object must be 3540 * object with drm_object_attach_property. The returned property object must be
3502 * freed with drm_property_destroy. 3541 * freed with drm_property_destroy.
3503 * 3542 *
@@ -4157,12 +4196,25 @@ static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
4157 return ret; 4196 return ret;
4158} 4197}
4159 4198
4160static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj, 4199/**
4161 struct drm_property *property, 4200 * drm_mode_plane_set_obj_prop - set the value of a property
4162 uint64_t value) 4201 * @plane: drm plane object to set property value for
4202 * @property: property to set
4203 * @value: value the property should be set to
4204 *
4205 * This functions sets a given property on a given plane object. This function
4206 * calls the driver's ->set_property callback and changes the software state of
4207 * the property if the callback succeeds.
4208 *
4209 * Returns:
4210 * Zero on success, error code on failure.
4211 */
4212int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
4213 struct drm_property *property,
4214 uint64_t value)
4163{ 4215{
4164 int ret = -EINVAL; 4216 int ret = -EINVAL;
4165 struct drm_plane *plane = obj_to_plane(obj); 4217 struct drm_mode_object *obj = &plane->base;
4166 4218
4167 if (plane->funcs->set_property) 4219 if (plane->funcs->set_property)
4168 ret = plane->funcs->set_property(plane, property, value); 4220 ret = plane->funcs->set_property(plane, property, value);
@@ -4171,6 +4223,7 @@ static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj,
4171 4223
4172 return ret; 4224 return ret;
4173} 4225}
4226EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
4174 4227
4175/** 4228/**
4176 * drm_mode_getproperty_ioctl - get the current value of a object's property 4229 * drm_mode_getproperty_ioctl - get the current value of a object's property
@@ -4309,7 +4362,8 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
4309 ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value); 4362 ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
4310 break; 4363 break;
4311 case DRM_MODE_OBJECT_PLANE: 4364 case DRM_MODE_OBJECT_PLANE:
4312 ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value); 4365 ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj),
4366 property, arg->value);
4313 break; 4367 break;
4314 } 4368 }
4315 4369
@@ -4529,7 +4583,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4529{ 4583{
4530 struct drm_mode_crtc_page_flip *page_flip = data; 4584 struct drm_mode_crtc_page_flip *page_flip = data;
4531 struct drm_crtc *crtc; 4585 struct drm_crtc *crtc;
4532 struct drm_framebuffer *fb = NULL, *old_fb = NULL; 4586 struct drm_framebuffer *fb = NULL;
4533 struct drm_pending_vblank_event *e = NULL; 4587 struct drm_pending_vblank_event *e = NULL;
4534 unsigned long flags; 4588 unsigned long flags;
4535 int ret = -EINVAL; 4589 int ret = -EINVAL;
@@ -4545,7 +4599,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4545 if (!crtc) 4599 if (!crtc)
4546 return -ENOENT; 4600 return -ENOENT;
4547 4601
4548 drm_modeset_lock(&crtc->mutex, NULL); 4602 drm_modeset_lock_crtc(crtc);
4549 if (crtc->primary->fb == NULL) { 4603 if (crtc->primary->fb == NULL) {
4550 /* The framebuffer is currently unbound, presumably 4604 /* The framebuffer is currently unbound, presumably
4551 * due to a hotplug event, that userspace has not 4605 * due to a hotplug event, that userspace has not
@@ -4601,7 +4655,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4601 (void (*) (struct drm_pending_event *)) kfree; 4655 (void (*) (struct drm_pending_event *)) kfree;
4602 } 4656 }
4603 4657
4604 old_fb = crtc->primary->fb; 4658 crtc->primary->old_fb = crtc->primary->fb;
4605 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); 4659 ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
4606 if (ret) { 4660 if (ret) {
4607 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 4661 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
@@ -4611,7 +4665,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4611 kfree(e); 4665 kfree(e);
4612 } 4666 }
4613 /* Keep the old fb, don't unref it. */ 4667 /* Keep the old fb, don't unref it. */
4614 old_fb = NULL; 4668 crtc->primary->old_fb = NULL;
4615 } else { 4669 } else {
4616 /* 4670 /*
4617 * Warn if the driver hasn't properly updated the crtc->fb 4671 * Warn if the driver hasn't properly updated the crtc->fb
@@ -4627,9 +4681,10 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4627out: 4681out:
4628 if (fb) 4682 if (fb)
4629 drm_framebuffer_unreference(fb); 4683 drm_framebuffer_unreference(fb);
4630 if (old_fb) 4684 if (crtc->primary->old_fb)
4631 drm_framebuffer_unreference(old_fb); 4685 drm_framebuffer_unreference(crtc->primary->old_fb);
4632 drm_modeset_unlock(&crtc->mutex); 4686 crtc->primary->old_fb = NULL;
4687 drm_modeset_unlock_crtc(crtc);
4633 4688
4634 return ret; 4689 return ret;
4635} 4690}
@@ -4645,9 +4700,14 @@ out:
4645void drm_mode_config_reset(struct drm_device *dev) 4700void drm_mode_config_reset(struct drm_device *dev)
4646{ 4701{
4647 struct drm_crtc *crtc; 4702 struct drm_crtc *crtc;
4703 struct drm_plane *plane;
4648 struct drm_encoder *encoder; 4704 struct drm_encoder *encoder;
4649 struct drm_connector *connector; 4705 struct drm_connector *connector;
4650 4706
4707 list_for_each_entry(plane, &dev->mode_config.plane_list, head)
4708 if (plane->funcs->reset)
4709 plane->funcs->reset(plane);
4710
4651 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 4711 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
4652 if (crtc->funcs->reset) 4712 if (crtc->funcs->reset)
4653 crtc->funcs->reset(crtc); 4713 crtc->funcs->reset(crtc);