aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_atomic.c21
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c181
-rw-r--r--drivers/gpu/drm/drm_crtc.c76
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c14
-rw-r--r--include/drm/drm_atomic_helper.h2
-rw-r--r--include/drm/drm_crtc.h7
-rw-r--r--include/drm/drm_crtc_helper.h21
7 files changed, 301 insertions, 21 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 4c5c9c3899e0..c2e9c5283136 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -134,6 +134,7 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
134 134
135 connector->funcs->atomic_destroy_state(connector, 135 connector->funcs->atomic_destroy_state(connector,
136 state->connector_states[i]); 136 state->connector_states[i]);
137 state->connector_states[i] = NULL;
137 } 138 }
138 139
139 for (i = 0; i < config->num_crtc; i++) { 140 for (i = 0; i < config->num_crtc; i++) {
@@ -144,6 +145,7 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
144 145
145 crtc->funcs->atomic_destroy_state(crtc, 146 crtc->funcs->atomic_destroy_state(crtc,
146 state->crtc_states[i]); 147 state->crtc_states[i]);
148 state->crtc_states[i] = NULL;
147 } 149 }
148 150
149 for (i = 0; i < config->num_total_plane; i++) { 151 for (i = 0; i < config->num_total_plane; i++) {
@@ -154,6 +156,7 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
154 156
155 plane->funcs->atomic_destroy_state(plane, 157 plane->funcs->atomic_destroy_state(plane,
156 state->plane_states[i]); 158 state->plane_states[i]);
159 state->plane_states[i] = NULL;
157 } 160 }
158} 161}
159EXPORT_SYMBOL(drm_atomic_state_clear); 162EXPORT_SYMBOL(drm_atomic_state_clear);
@@ -241,7 +244,13 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
241 struct drm_crtc_state *state, struct drm_property *property, 244 struct drm_crtc_state *state, struct drm_property *property,
242 uint64_t val) 245 uint64_t val)
243{ 246{
244 if (crtc->funcs->atomic_set_property) 247 struct drm_device *dev = crtc->dev;
248 struct drm_mode_config *config = &dev->mode_config;
249
250 /* FIXME: Mode prop is missing, which also controls ->enable. */
251 if (property == config->prop_active) {
252 state->active = val;
253 } else if (crtc->funcs->atomic_set_property)
245 return crtc->funcs->atomic_set_property(crtc, state, property, val); 254 return crtc->funcs->atomic_set_property(crtc, state, property, val);
246 return -EINVAL; 255 return -EINVAL;
247} 256}
@@ -282,6 +291,13 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
282 * 291 *
283 * TODO: Add generic modeset state checks once we support those. 292 * TODO: Add generic modeset state checks once we support those.
284 */ 293 */
294
295 if (state->active && !state->enable) {
296 DRM_DEBUG_KMS("[CRTC:%d] active without enabled\n",
297 crtc->base.id);
298 return -EINVAL;
299 }
300
285 return 0; 301 return 0;
286} 302}
287 303
@@ -978,7 +994,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
978 if (!crtc) 994 if (!crtc)
979 continue; 995 continue;
980 996
981 if (crtc_state->mode_changed) { 997 if (crtc_state->mode_changed ||
998 crtc_state->active_changed) {
982 DRM_DEBUG_KMS("[CRTC:%d] requires full modeset\n", 999 DRM_DEBUG_KMS("[CRTC:%d] requires full modeset\n",
983 crtc->base.id); 1000 crtc->base.id);
984 return -EINVAL; 1001 return -EINVAL;
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 24c44c24dabe..7e3a52b97c7d 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -339,6 +339,12 @@ mode_fixup(struct drm_atomic_state *state)
339 return 0; 339 return 0;
340} 340}
341 341
342static bool
343needs_modeset(struct drm_crtc_state *state)
344{
345 return state->mode_changed || state->active_changed;
346}
347
342/** 348/**
343 * drm_atomic_helper_check - validate state object for modeset changes 349 * drm_atomic_helper_check - validate state object for modeset changes
344 * @dev: DRM device 350 * @dev: DRM device
@@ -413,12 +419,27 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
413 crtc = state->crtcs[i]; 419 crtc = state->crtcs[i];
414 crtc_state = state->crtc_states[i]; 420 crtc_state = state->crtc_states[i];
415 421
416 if (!crtc || !crtc_state->mode_changed) 422 if (!crtc)
423 continue;
424
425 /*
426 * We must set ->active_changed after walking connectors for
427 * otherwise an update that only changes active would result in
428 * a full modeset because update_connector_routing force that.
429 */
430 if (crtc->state->active != crtc_state->active) {
431 DRM_DEBUG_KMS("[CRTC:%d] active changed\n",
432 crtc->base.id);
433 crtc_state->active_changed = true;
434 }
435
436 if (!needs_modeset(crtc_state))
417 continue; 437 continue;
418 438
419 DRM_DEBUG_KMS("[CRTC:%d] needs full modeset, enable: %c\n", 439 DRM_DEBUG_KMS("[CRTC:%d] needs all connectors, enable: %c, active: %c\n",
420 crtc->base.id, 440 crtc->base.id,
421 crtc_state->enable ? 'y' : 'n'); 441 crtc_state->enable ? 'y' : 'n',
442 crtc_state->active ? 'y' : 'n');
422 443
423 ret = drm_atomic_add_affected_connectors(state, crtc); 444 ret = drm_atomic_add_affected_connectors(state, crtc);
424 if (ret != 0) 445 if (ret != 0)
@@ -554,6 +575,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
554 struct drm_connector *connector; 575 struct drm_connector *connector;
555 struct drm_encoder_helper_funcs *funcs; 576 struct drm_encoder_helper_funcs *funcs;
556 struct drm_encoder *encoder; 577 struct drm_encoder *encoder;
578 struct drm_crtc_state *old_crtc_state;
557 579
558 old_conn_state = old_state->connector_states[i]; 580 old_conn_state = old_state->connector_states[i];
559 connector = old_state->connectors[i]; 581 connector = old_state->connectors[i];
@@ -563,6 +585,11 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
563 if (!old_conn_state || !old_conn_state->crtc) 585 if (!old_conn_state || !old_conn_state->crtc)
564 continue; 586 continue;
565 587
588 old_crtc_state = old_state->crtc_states[drm_crtc_index(old_conn_state->crtc)];
589
590 if (!old_crtc_state->active)
591 continue;
592
566 encoder = old_conn_state->best_encoder; 593 encoder = old_conn_state->best_encoder;
567 594
568 /* We shouldn't get this far if we didn't previously have 595 /* We shouldn't get this far if we didn't previously have
@@ -573,6 +600,9 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
573 600
574 funcs = encoder->helper_private; 601 funcs = encoder->helper_private;
575 602
603 DRM_DEBUG_KMS("disabling [ENCODER:%d:%s]\n",
604 encoder->base.id, encoder->name);
605
576 /* 606 /*
577 * Each encoder has at most one connector (since we always steal 607 * Each encoder has at most one connector (since we always steal
578 * it away), so we won't call call disable hooks twice. 608 * it away), so we won't call call disable hooks twice.
@@ -581,7 +611,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
581 encoder->bridge->funcs->disable(encoder->bridge); 611 encoder->bridge->funcs->disable(encoder->bridge);
582 612
583 /* Right function depends upon target state. */ 613 /* Right function depends upon target state. */
584 if (connector->state->crtc) 614 if (connector->state->crtc && funcs->prepare)
585 funcs->prepare(encoder); 615 funcs->prepare(encoder);
586 else if (funcs->disable) 616 else if (funcs->disable)
587 funcs->disable(encoder); 617 funcs->disable(encoder);
@@ -595,17 +625,26 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
595 for (i = 0; i < ncrtcs; i++) { 625 for (i = 0; i < ncrtcs; i++) {
596 struct drm_crtc_helper_funcs *funcs; 626 struct drm_crtc_helper_funcs *funcs;
597 struct drm_crtc *crtc; 627 struct drm_crtc *crtc;
628 struct drm_crtc_state *old_crtc_state;
598 629
599 crtc = old_state->crtcs[i]; 630 crtc = old_state->crtcs[i];
631 old_crtc_state = old_state->crtc_states[i];
600 632
601 /* Shut down everything that needs a full modeset. */ 633 /* Shut down everything that needs a full modeset. */
602 if (!crtc || !crtc->state->mode_changed) 634 if (!crtc || !needs_modeset(crtc->state))
635 continue;
636
637 if (!old_crtc_state->active)
603 continue; 638 continue;
604 639
605 funcs = crtc->helper_private; 640 funcs = crtc->helper_private;
606 641
642 DRM_DEBUG_KMS("disabling [CRTC:%d]\n",
643 crtc->base.id);
644
645
607 /* Right function depends upon target state. */ 646 /* Right function depends upon target state. */
608 if (crtc->state->enable) 647 if (crtc->state->enable && funcs->prepare)
609 funcs->prepare(crtc); 648 funcs->prepare(crtc);
610 else if (funcs->disable) 649 else if (funcs->disable)
611 funcs->disable(crtc); 650 funcs->disable(crtc);
@@ -684,8 +723,12 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
684 723
685 funcs = crtc->helper_private; 724 funcs = crtc->helper_private;
686 725
687 if (crtc->state->enable) 726 if (crtc->state->enable) {
727 DRM_DEBUG_KMS("modeset on [CRTC:%d]\n",
728 crtc->base.id);
729
688 funcs->mode_set_nofb(crtc); 730 funcs->mode_set_nofb(crtc);
731 }
689 } 732 }
690 733
691 for (i = 0; i < old_state->num_connector; i++) { 734 for (i = 0; i < old_state->num_connector; i++) {
@@ -706,6 +749,12 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
706 mode = &new_crtc_state->mode; 749 mode = &new_crtc_state->mode;
707 adjusted_mode = &new_crtc_state->adjusted_mode; 750 adjusted_mode = &new_crtc_state->adjusted_mode;
708 751
752 if (!new_crtc_state->mode_changed)
753 continue;
754
755 DRM_DEBUG_KMS("modeset on [ENCODER:%d:%s]\n",
756 encoder->base.id, encoder->name);
757
709 /* 758 /*
710 * Each encoder has at most one connector (since we always steal 759 * Each encoder has at most one connector (since we always steal
711 * it away), so we won't call call mode_set hooks twice. 760 * it away), so we won't call call mode_set hooks twice.
@@ -758,13 +807,23 @@ void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
758 crtc = old_state->crtcs[i]; 807 crtc = old_state->crtcs[i];
759 808
760 /* Need to filter out CRTCs where only planes change. */ 809 /* Need to filter out CRTCs where only planes change. */
761 if (!crtc || !crtc->state->mode_changed) 810 if (!crtc || !needs_modeset(crtc->state))
811 continue;
812
813 if (!crtc->state->active)
762 continue; 814 continue;
763 815
764 funcs = crtc->helper_private; 816 funcs = crtc->helper_private;
765 817
766 if (crtc->state->enable) 818 if (crtc->state->enable) {
767 funcs->commit(crtc); 819 DRM_DEBUG_KMS("enabling [CRTC:%d]\n",
820 crtc->base.id);
821
822 if (funcs->enable)
823 funcs->enable(crtc);
824 else
825 funcs->commit(crtc);
826 }
768 } 827 }
769 828
770 for (i = 0; i < old_state->num_connector; i++) { 829 for (i = 0; i < old_state->num_connector; i++) {
@@ -777,9 +836,15 @@ void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
777 if (!connector || !connector->state->best_encoder) 836 if (!connector || !connector->state->best_encoder)
778 continue; 837 continue;
779 838
839 if (!connector->state->crtc->state->active)
840 continue;
841
780 encoder = connector->state->best_encoder; 842 encoder = connector->state->best_encoder;
781 funcs = encoder->helper_private; 843 funcs = encoder->helper_private;
782 844
845 DRM_DEBUG_KMS("enabling [ENCODER:%d:%s]\n",
846 encoder->base.id, encoder->name);
847
783 /* 848 /*
784 * Each encoder has at most one connector (since we always steal 849 * Each encoder has at most one connector (since we always steal
785 * it away), so we won't call call enable hooks twice. 850 * it away), so we won't call call enable hooks twice.
@@ -787,7 +852,10 @@ void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
787 if (encoder->bridge) 852 if (encoder->bridge)
788 encoder->bridge->funcs->pre_enable(encoder->bridge); 853 encoder->bridge->funcs->pre_enable(encoder->bridge);
789 854
790 funcs->commit(encoder); 855 if (funcs->enable)
856 funcs->enable(encoder);
857 else
858 funcs->commit(encoder);
791 859
792 if (encoder->bridge) 860 if (encoder->bridge)
793 encoder->bridge->funcs->enable(encoder->bridge); 861 encoder->bridge->funcs->enable(encoder->bridge);
@@ -877,6 +945,11 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
877 if (!crtc->state->enable) 945 if (!crtc->state->enable)
878 continue; 946 continue;
879 947
948 /* Legacy cursor ioctls are completely unsynced, and userspace
949 * relies on that (by doing tons of cursor updates). */
950 if (old_state->legacy_cursor_update)
951 continue;
952
880 if (!framebuffer_changed(dev, old_state, crtc)) 953 if (!framebuffer_changed(dev, old_state, crtc))
881 continue; 954 continue;
882 955
@@ -1310,6 +1383,9 @@ retry:
1310 if (ret != 0) 1383 if (ret != 0)
1311 goto fail; 1384 goto fail;
1312 1385
1386 if (plane == crtc->cursor)
1387 state->legacy_cursor_update = true;
1388
1313 /* Driver takes ownership of state on successful commit. */ 1389 /* Driver takes ownership of state on successful commit. */
1314 return 0; 1390 return 0;
1315fail: 1391fail:
@@ -1385,6 +1461,9 @@ retry:
1385 plane_state->src_h = 0; 1461 plane_state->src_h = 0;
1386 plane_state->src_w = 0; 1462 plane_state->src_w = 0;
1387 1463
1464 if (plane == plane->crtc->cursor)
1465 state->legacy_cursor_update = true;
1466
1388 ret = drm_atomic_commit(state); 1467 ret = drm_atomic_commit(state);
1389 if (ret != 0) 1468 if (ret != 0)
1390 goto fail; 1469 goto fail;
@@ -1534,6 +1613,7 @@ retry:
1534 WARN_ON(set->num_connectors); 1613 WARN_ON(set->num_connectors);
1535 1614
1536 crtc_state->enable = false; 1615 crtc_state->enable = false;
1616 crtc_state->active = false;
1537 1617
1538 ret = drm_atomic_set_crtc_for_plane(primary_state, NULL); 1618 ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
1539 if (ret != 0) 1619 if (ret != 0)
@@ -1548,6 +1628,7 @@ retry:
1548 WARN_ON(!set->num_connectors); 1628 WARN_ON(!set->num_connectors);
1549 1629
1550 crtc_state->enable = true; 1630 crtc_state->enable = true;
1631 crtc_state->active = true;
1551 drm_mode_copy(&crtc_state->mode, set->mode); 1632 drm_mode_copy(&crtc_state->mode, set->mode);
1552 1633
1553 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); 1634 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
@@ -1860,6 +1941,83 @@ backoff:
1860EXPORT_SYMBOL(drm_atomic_helper_page_flip); 1941EXPORT_SYMBOL(drm_atomic_helper_page_flip);
1861 1942
1862/** 1943/**
1944 * drm_atomic_helper_connector_dpms() - connector dpms helper implementation
1945 * @connector: affected connector
1946 * @mode: DPMS mode
1947 *
1948 * This is the main helper function provided by the atomic helper framework for
1949 * implementing the legacy DPMS connector interface. It computes the new desired
1950 * ->active state for the corresponding CRTC (if the connector is enabled) and
1951 * updates it.
1952 */
1953void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
1954 int mode)
1955{
1956 struct drm_mode_config *config = &connector->dev->mode_config;
1957 struct drm_atomic_state *state;
1958 struct drm_crtc_state *crtc_state;
1959 struct drm_crtc *crtc;
1960 struct drm_connector *tmp_connector;
1961 int ret;
1962 bool active = false;
1963
1964 if (mode != DRM_MODE_DPMS_ON)
1965 mode = DRM_MODE_DPMS_OFF;
1966
1967 connector->dpms = mode;
1968 crtc = connector->state->crtc;
1969
1970 if (!crtc)
1971 return;
1972
1973 /* FIXME: ->dpms has no return value so can't forward the -ENOMEM. */
1974 state = drm_atomic_state_alloc(connector->dev);
1975 if (!state)
1976 return;
1977
1978 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
1979retry:
1980 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1981 if (IS_ERR(crtc_state))
1982 return;
1983
1984 WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
1985
1986 list_for_each_entry(tmp_connector, &config->connector_list, head) {
1987 if (connector->state->crtc != crtc)
1988 continue;
1989
1990 if (connector->dpms == DRM_MODE_DPMS_ON) {
1991 active = true;
1992 break;
1993 }
1994 }
1995 crtc_state->active = active;
1996
1997 ret = drm_atomic_commit(state);
1998 if (ret != 0)
1999 goto fail;
2000
2001 /* Driver takes ownership of state on successful async commit. */
2002 return;
2003fail:
2004 if (ret == -EDEADLK)
2005 goto backoff;
2006
2007 drm_atomic_state_free(state);
2008
2009 WARN(1, "Driver bug: Changing ->active failed with ret=%i\n", ret);
2010
2011 return;
2012backoff:
2013 drm_atomic_state_clear(state);
2014 drm_atomic_legacy_backoff(state);
2015
2016 goto retry;
2017}
2018EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
2019
2020/**
1863 * DOC: atomic state reset and initialization 2021 * DOC: atomic state reset and initialization
1864 * 2022 *
1865 * Both the drm core and the atomic helpers assume that there is always the full 2023 * Both the drm core and the atomic helpers assume that there is always the full
@@ -1910,6 +2068,7 @@ drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
1910 2068
1911 if (state) { 2069 if (state) {
1912 state->mode_changed = false; 2070 state->mode_changed = false;
2071 state->active_changed = false;
1913 state->planes_changed = false; 2072 state->planes_changed = false;
1914 state->event = NULL; 2073 state->event = NULL;
1915 } 2074 }
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index ad2934ba0bd2..b459888f6310 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -691,6 +691,10 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
691 if (cursor) 691 if (cursor)
692 cursor->possible_crtcs = 1 << drm_crtc_index(crtc); 692 cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
693 693
694 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
695 drm_object_attach_property(&crtc->base, config->prop_active, 0);
696 }
697
694 return 0; 698 return 0;
695} 699}
696EXPORT_SYMBOL(drm_crtc_init_with_planes); 700EXPORT_SYMBOL(drm_crtc_init_with_planes);
@@ -1481,6 +1485,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
1481 return -ENOMEM; 1485 return -ENOMEM;
1482 dev->mode_config.prop_crtc_id = prop; 1486 dev->mode_config.prop_crtc_id = prop;
1483 1487
1488 prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
1489 "ACTIVE");
1490 if (!prop)
1491 return -ENOMEM;
1492 dev->mode_config.prop_active = prop;
1493
1484 return 0; 1494 return 0;
1485} 1495}
1486 1496
@@ -3810,7 +3820,7 @@ static struct drm_property *property_create_range(struct drm_device *dev,
3810} 3820}
3811 3821
3812/** 3822/**
3813 * drm_property_create_range - create a new ranged property type 3823 * drm_property_create_range - create a new unsigned ranged property type
3814 * @dev: drm device 3824 * @dev: drm device
3815 * @flags: flags specifying the property type 3825 * @flags: flags specifying the property type
3816 * @name: name of the property 3826 * @name: name of the property
@@ -3821,8 +3831,8 @@ static struct drm_property *property_create_range(struct drm_device *dev,
3821 * object with drm_object_attach_property. The returned property object must be 3831 * object with drm_object_attach_property. The returned property object must be
3822 * freed with drm_property_destroy. 3832 * freed with drm_property_destroy.
3823 * 3833 *
3824 * Userspace is allowed to set any integer value in the (min, max) range 3834 * Userspace is allowed to set any unsigned integer value in the (min, max)
3825 * inclusive. 3835 * range inclusive.
3826 * 3836 *
3827 * Returns: 3837 * Returns:
3828 * A pointer to the newly created property on success, NULL on failure. 3838 * A pointer to the newly created property on success, NULL on failure.
@@ -3836,6 +3846,24 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags
3836} 3846}
3837EXPORT_SYMBOL(drm_property_create_range); 3847EXPORT_SYMBOL(drm_property_create_range);
3838 3848
3849/**
3850 * drm_property_create_signed_range - create a new signed ranged property type
3851 * @dev: drm device
3852 * @flags: flags specifying the property type
3853 * @name: name of the property
3854 * @min: minimum value of the property
3855 * @max: maximum value of the property
3856 *
3857 * This creates a new generic drm property which can then be attached to a drm
3858 * object with drm_object_attach_property. The returned property object must be
3859 * freed with drm_property_destroy.
3860 *
3861 * Userspace is allowed to set any signed integer value in the (min, max)
3862 * range inclusive.
3863 *
3864 * Returns:
3865 * A pointer to the newly created property on success, NULL on failure.
3866 */
3839struct drm_property *drm_property_create_signed_range(struct drm_device *dev, 3867struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
3840 int flags, const char *name, 3868 int flags, const char *name,
3841 int64_t min, int64_t max) 3869 int64_t min, int64_t max)
@@ -3845,6 +3873,23 @@ struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
3845} 3873}
3846EXPORT_SYMBOL(drm_property_create_signed_range); 3874EXPORT_SYMBOL(drm_property_create_signed_range);
3847 3875
3876/**
3877 * drm_property_create_object - create a new object property type
3878 * @dev: drm device
3879 * @flags: flags specifying the property type
3880 * @name: name of the property
3881 * @type: object type from DRM_MODE_OBJECT_* defines
3882 *
3883 * This creates a new generic drm property which can then be attached to a drm
3884 * object with drm_object_attach_property. The returned property object must be
3885 * freed with drm_property_destroy.
3886 *
3887 * Userspace is only allowed to set this to any property value of the given
3888 * @type. Only useful for atomic properties, which is enforced.
3889 *
3890 * Returns:
3891 * A pointer to the newly created property on success, NULL on failure.
3892 */
3848struct drm_property *drm_property_create_object(struct drm_device *dev, 3893struct drm_property *drm_property_create_object(struct drm_device *dev,
3849 int flags, const char *name, uint32_t type) 3894 int flags, const char *name, uint32_t type)
3850{ 3895{
@@ -3852,6 +3897,9 @@ struct drm_property *drm_property_create_object(struct drm_device *dev,
3852 3897
3853 flags |= DRM_MODE_PROP_OBJECT; 3898 flags |= DRM_MODE_PROP_OBJECT;
3854 3899
3900 if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
3901 return NULL;
3902
3855 property = drm_property_create(dev, flags, name, 1); 3903 property = drm_property_create(dev, flags, name, 1);
3856 if (!property) 3904 if (!property)
3857 return NULL; 3905 return NULL;
@@ -3863,6 +3911,28 @@ struct drm_property *drm_property_create_object(struct drm_device *dev,
3863EXPORT_SYMBOL(drm_property_create_object); 3911EXPORT_SYMBOL(drm_property_create_object);
3864 3912
3865/** 3913/**
3914 * drm_property_create_bool - create a new boolean property type
3915 * @dev: drm device
3916 * @flags: flags specifying the property type
3917 * @name: name of the property
3918 *
3919 * This creates a new generic drm property which can then be attached to a drm
3920 * object with drm_object_attach_property. The returned property object must be
3921 * freed with drm_property_destroy.
3922 *
3923 * This is implemented as a ranged property with only {0, 1} as valid values.
3924 *
3925 * Returns:
3926 * A pointer to the newly created property on success, NULL on failure.
3927 */
3928struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
3929 const char *name)
3930{
3931 return drm_property_create_range(dev, flags, name, 0, 1);
3932}
3933EXPORT_SYMBOL(drm_property_create_bool);
3934
3935/**
3866 * drm_property_add_enum - add a possible value to an enumeration property 3936 * drm_property_add_enum - add a possible value to an enumeration property
3867 * @property: enumeration property to change 3937 * @property: enumeration property to change
3868 * @index: index of the new enumeration 3938 * @index: index of the new enumeration
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 4dcdcad9f16d..5ba5792bfdba 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -435,7 +435,8 @@ int drm_plane_helper_commit(struct drm_plane *plane,
435 goto out; 435 goto out;
436 } 436 }
437 437
438 if (plane_funcs->prepare_fb && plane_state->fb) { 438 if (plane_funcs->prepare_fb && plane_state->fb &&
439 plane_state->fb != old_fb) {
439 ret = plane_funcs->prepare_fb(plane, plane_state->fb); 440 ret = plane_funcs->prepare_fb(plane, plane_state->fb);
440 if (ret) 441 if (ret)
441 goto out; 442 goto out;
@@ -464,6 +465,13 @@ int drm_plane_helper_commit(struct drm_plane *plane,
464 crtc_funcs[i]->atomic_flush(crtc[i]); 465 crtc_funcs[i]->atomic_flush(crtc[i]);
465 } 466 }
466 467
468 /*
469 * If we only moved the plane and didn't change fb's, there's no need to
470 * wait for vblank.
471 */
472 if (plane->state->fb == old_fb)
473 goto out;
474
467 for (i = 0; i < 2; i++) { 475 for (i = 0; i < 2; i++) {
468 if (!crtc[i]) 476 if (!crtc[i])
469 continue; 477 continue;
@@ -492,7 +500,7 @@ out:
492} 500}
493 501
494/** 502/**
495 * drm_plane_helper_update() - Helper for primary plane update 503 * drm_plane_helper_update() - Transitional helper for plane update
496 * @plane: plane object to update 504 * @plane: plane object to update
497 * @crtc: owning CRTC of owning plane 505 * @crtc: owning CRTC of owning plane
498 * @fb: framebuffer to flip onto plane 506 * @fb: framebuffer to flip onto plane
@@ -549,7 +557,7 @@ int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
549EXPORT_SYMBOL(drm_plane_helper_update); 557EXPORT_SYMBOL(drm_plane_helper_update);
550 558
551/** 559/**
552 * drm_plane_helper_disable() - Helper for primary plane disable 560 * drm_plane_helper_disable() - Transitional helper for plane disable
553 * @plane: plane to disable 561 * @plane: plane to disable
554 * 562 *
555 * Provides a default plane disable handler using the atomic plane update 563 * Provides a default plane disable handler using the atomic plane update
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index a0ea4ded3cb5..8039d54a7441 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -82,6 +82,8 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
82 struct drm_framebuffer *fb, 82 struct drm_framebuffer *fb,
83 struct drm_pending_vblank_event *event, 83 struct drm_pending_vblank_event *event,
84 uint32_t flags); 84 uint32_t flags);
85void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
86 int mode);
85 87
86/* default implementations for state handling */ 88/* default implementations for state handling */
87void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); 89void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0ebd9286b332..02614170c034 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -253,6 +253,7 @@ struct drm_atomic_state;
253 * @enable: whether the CRTC should be enabled, gates all other state 253 * @enable: whether the CRTC should be enabled, gates all other state
254 * @active: whether the CRTC is actively displaying (used for DPMS) 254 * @active: whether the CRTC is actively displaying (used for DPMS)
255 * @mode_changed: for use by helpers and drivers when computing state updates 255 * @mode_changed: for use by helpers and drivers when computing state updates
256 * @active_changed: for use by helpers and drivers when computing state updates
256 * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes 257 * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
257 * @last_vblank_count: for helpers and drivers to capture the vblank of the 258 * @last_vblank_count: for helpers and drivers to capture the vblank of the
258 * update to ensure framebuffer cleanup isn't done too early 259 * update to ensure framebuffer cleanup isn't done too early
@@ -278,6 +279,7 @@ struct drm_crtc_state {
278 /* computed state bits used by helpers and drivers */ 279 /* computed state bits used by helpers and drivers */
279 bool planes_changed : 1; 280 bool planes_changed : 1;
280 bool mode_changed : 1; 281 bool mode_changed : 1;
282 bool active_changed : 1;
281 283
282 /* attached planes bitmask: 284 /* attached planes bitmask:
283 * WARNING: transitional helpers do not maintain plane_mask so 285 * WARNING: transitional helpers do not maintain plane_mask so
@@ -910,6 +912,7 @@ struct drm_bridge {
910 * struct struct drm_atomic_state - the global state object for atomic updates 912 * struct struct drm_atomic_state - the global state object for atomic updates
911 * @dev: parent DRM device 913 * @dev: parent DRM device
912 * @allow_modeset: allow full modeset 914 * @allow_modeset: allow full modeset
915 * @legacy_cursor_update: hint to enforce legacy cursor ioctl semantics
913 * @planes: pointer to array of plane pointers 916 * @planes: pointer to array of plane pointers
914 * @plane_states: pointer to array of plane states pointers 917 * @plane_states: pointer to array of plane states pointers
915 * @crtcs: pointer to array of CRTC pointers 918 * @crtcs: pointer to array of CRTC pointers
@@ -922,6 +925,7 @@ struct drm_bridge {
922struct drm_atomic_state { 925struct drm_atomic_state {
923 struct drm_device *dev; 926 struct drm_device *dev;
924 bool allow_modeset : 1; 927 bool allow_modeset : 1;
928 bool legacy_cursor_update : 1;
925 struct drm_plane **planes; 929 struct drm_plane **planes;
926 struct drm_plane_state **plane_states; 930 struct drm_plane_state **plane_states;
927 struct drm_crtc **crtcs; 931 struct drm_crtc **crtcs;
@@ -1117,6 +1121,7 @@ struct drm_mode_config {
1117 struct drm_property *prop_crtc_h; 1121 struct drm_property *prop_crtc_h;
1118 struct drm_property *prop_fb_id; 1122 struct drm_property *prop_fb_id;
1119 struct drm_property *prop_crtc_id; 1123 struct drm_property *prop_crtc_id;
1124 struct drm_property *prop_active;
1120 1125
1121 /* DVI-I properties */ 1126 /* DVI-I properties */
1122 struct drm_property *dvi_i_subconnector_property; 1127 struct drm_property *dvi_i_subconnector_property;
@@ -1349,6 +1354,8 @@ struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
1349 int64_t min, int64_t max); 1354 int64_t min, int64_t max);
1350struct drm_property *drm_property_create_object(struct drm_device *dev, 1355struct drm_property *drm_property_create_object(struct drm_device *dev,
1351 int flags, const char *name, uint32_t type); 1356 int flags, const char *name, uint32_t type);
1357struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
1358 const char *name);
1352extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property); 1359extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
1353extern int drm_property_add_enum(struct drm_property *property, int index, 1360extern int drm_property_add_enum(struct drm_property *property, int index,
1354 uint64_t value, const char *name); 1361 uint64_t value, const char *name);
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 5810c027acdc..c250a22b39ab 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -58,11 +58,19 @@ enum mode_set_atomic {
58 * @mode_set_base_atomic: non-blocking mode set (used for kgdb support) 58 * @mode_set_base_atomic: non-blocking mode set (used for kgdb support)
59 * @load_lut: load color palette 59 * @load_lut: load color palette
60 * @disable: disable CRTC when no longer in use 60 * @disable: disable CRTC when no longer in use
61 * @enable: enable CRTC
61 * @atomic_check: check for validity of an atomic state 62 * @atomic_check: check for validity of an atomic state
62 * @atomic_begin: begin atomic update 63 * @atomic_begin: begin atomic update
63 * @atomic_flush: flush atomic update 64 * @atomic_flush: flush atomic update
64 * 65 *
65 * The helper operations are called by the mid-layer CRTC helper. 66 * The helper operations are called by the mid-layer CRTC helper.
67 *
68 * Note that with atomic helpers @dpms, @prepare and @commit hooks are
69 * deprecated. Used @enable and @disable instead exclusively.
70 *
71 * With legacy crtc helpers there's a big semantic difference between @disable
72 * and the other hooks: @disable also needs to release any resources acquired in
73 * @mode_set (like shared PLLs).
66 */ 74 */
67struct drm_crtc_helper_funcs { 75struct drm_crtc_helper_funcs {
68 /* 76 /*
@@ -93,8 +101,8 @@ struct drm_crtc_helper_funcs {
93 /* reload the current crtc LUT */ 101 /* reload the current crtc LUT */
94 void (*load_lut)(struct drm_crtc *crtc); 102 void (*load_lut)(struct drm_crtc *crtc);
95 103
96 /* disable crtc when not in use - more explicit than dpms off */
97 void (*disable)(struct drm_crtc *crtc); 104 void (*disable)(struct drm_crtc *crtc);
105 void (*enable)(struct drm_crtc *crtc);
98 106
99 /* atomic helpers */ 107 /* atomic helpers */
100 int (*atomic_check)(struct drm_crtc *crtc, 108 int (*atomic_check)(struct drm_crtc *crtc,
@@ -115,9 +123,17 @@ struct drm_crtc_helper_funcs {
115 * @get_crtc: return CRTC that the encoder is currently attached to 123 * @get_crtc: return CRTC that the encoder is currently attached to
116 * @detect: connection status detection 124 * @detect: connection status detection
117 * @disable: disable encoder when not in use (overrides DPMS off) 125 * @disable: disable encoder when not in use (overrides DPMS off)
126 * @enable: enable encoder
118 * @atomic_check: check for validity of an atomic update 127 * @atomic_check: check for validity of an atomic update
119 * 128 *
120 * The helper operations are called by the mid-layer CRTC helper. 129 * The helper operations are called by the mid-layer CRTC helper.
130 *
131 * Note that with atomic helpers @dpms, @prepare and @commit hooks are
132 * deprecated. Used @enable and @disable instead exclusively.
133 *
134 * With legacy crtc helpers there's a big semantic difference between @disable
135 * and the other hooks: @disable also needs to release any resources acquired in
136 * @mode_set (like shared PLLs).
121 */ 137 */
122struct drm_encoder_helper_funcs { 138struct drm_encoder_helper_funcs {
123 void (*dpms)(struct drm_encoder *encoder, int mode); 139 void (*dpms)(struct drm_encoder *encoder, int mode);
@@ -136,9 +152,10 @@ struct drm_encoder_helper_funcs {
136 /* detect for DAC style encoders */ 152 /* detect for DAC style encoders */
137 enum drm_connector_status (*detect)(struct drm_encoder *encoder, 153 enum drm_connector_status (*detect)(struct drm_encoder *encoder,
138 struct drm_connector *connector); 154 struct drm_connector *connector);
139 /* disable encoder when not in use - more explicit than dpms off */
140 void (*disable)(struct drm_encoder *encoder); 155 void (*disable)(struct drm_encoder *encoder);
141 156
157 void (*enable)(struct drm_encoder *encoder);
158
142 /* atomic helpers */ 159 /* atomic helpers */
143 int (*atomic_check)(struct drm_encoder *encoder, 160 int (*atomic_check)(struct drm_encoder *encoder,
144 struct drm_crtc_state *crtc_state, 161 struct drm_crtc_state *crtc_state,