aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2015-01-22 10:36:21 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-01-27 04:02:18 -0500
commiteab3bbeffd152125ae0f90863b8e9bc8eef49423 (patch)
tree544f11ec5b22e8c941b638761aeddf0431117943 /drivers
parent960cd9d4fef6dd9e235c0e5c0d4ed027f8a48025 (diff)
drm/atomic: Add drm_crtc_state->active
This is the infrastructure for DPMS ported to the atomic world. Fundamental changes compare to legacy DPMS are: - No more per-connector dpms state, instead there's just one per each display pipeline. So if you clone either you have to unclone first if you only want to switch off one screen, or you just switch of everything (like all desktops do). This massively reduces complexity for cloning since now there's no more half-enabled cloned configs to consider. - Only on/off, dpms standby/suspend are as dead as real CRTs. Again reduces complexity a lot. Now especially for backwards compat the really important part for dpms support is that dpms on always succeeds (except for hw death and unplugged cables ofc). Which means everything that could fail (like configuration checking, resources assignments and buffer management) must be done irrespective from ->active. ->active is really only a toggle to change the hardware state. More precisely: - Drivers MUST NOT look at ->active in their ->atomic_check callbacks. Changes to ->active MUST always suceed if nothing else changes. - Drivers using the atomic helpers MUST NOT look at ->active anywhere, period. The helpers will take care of calling the respective enable/modeset/disable hooks as necessary. As before the helpers will carefully keep track of the state and not call any hooks unecessarily, so still no double-disables or enables like with crtc helpers. - ->mode_set hooks are only called when the mode or output configuration changes, not for changes in ->active state. - Drivers which reconstruct the state objects in their ->reset hooks or through some other hw state readout infrastructure must ensure that ->active reflects actual hw state. This just implements the core bits and helper logic, a subsequent patch will implement the helper code to implement legacy dpms with this. v2: Rebase on top of the drm ioctl work: - Move crtc checks to the core check function. - Also check for ->active_changed when deciding whether a modeset might happen (for the ALLOW_MODESET mode). - Expose the ->active state with an atomic prop. v3: Review from Rob - Spelling fix in comment. - Extract needs_modeset helper to consolidate the ->mode_changed || ->active_changed checks. v4: Fixup fumble between crtc->state and crtc_state. Cc: Rob Clark <robdclark@gmail.com> Reviewed-by: Thierry Reding <treding@nvidia.com> Tested-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_atomic.c18
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c54
-rw-r--r--drivers/gpu/drm/drm_crtc.c10
3 files changed, 75 insertions, 7 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 1e38dfc8e462..ee68267bb326 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -241,7 +241,13 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
241 struct drm_crtc_state *state, struct drm_property *property, 241 struct drm_crtc_state *state, struct drm_property *property,
242 uint64_t val) 242 uint64_t val)
243{ 243{
244 if (crtc->funcs->atomic_set_property) 244 struct drm_device *dev = crtc->dev;
245 struct drm_mode_config *config = &dev->mode_config;
246
247 /* FIXME: Mode prop is missing, which also controls ->enable. */
248 if (property == config->prop_active) {
249 state->active = val;
250 } else if (crtc->funcs->atomic_set_property)
245 return crtc->funcs->atomic_set_property(crtc, state, property, val); 251 return crtc->funcs->atomic_set_property(crtc, state, property, val);
246 return -EINVAL; 252 return -EINVAL;
247} 253}
@@ -282,6 +288,13 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
282 * 288 *
283 * TODO: Add generic modeset state checks once we support those. 289 * TODO: Add generic modeset state checks once we support those.
284 */ 290 */
291
292 if (state->active && !state->enable) {
293 DRM_DEBUG_KMS("[CRTC:%d] active without enabled\n",
294 crtc->base.id);
295 return -EINVAL;
296 }
297
285 return 0; 298 return 0;
286} 299}
287 300
@@ -976,7 +989,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
976 if (!crtc) 989 if (!crtc)
977 continue; 990 continue;
978 991
979 if (crtc_state->mode_changed) { 992 if (crtc_state->mode_changed ||
993 crtc_state->active_changed) {
980 DRM_DEBUG_KMS("[CRTC:%d] requires full modeset\n", 994 DRM_DEBUG_KMS("[CRTC:%d] requires full modeset\n",
981 crtc->base.id); 995 crtc->base.id);
982 return -EINVAL; 996 return -EINVAL;
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 541ba833ed36..3f17933b1d2c 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -330,6 +330,12 @@ mode_fixup(struct drm_atomic_state *state)
330 return 0; 330 return 0;
331} 331}
332 332
333static bool
334needs_modeset(struct drm_crtc_state *state)
335{
336 return state->mode_changed || state->active_changed;
337}
338
333/** 339/**
334 * drm_atomic_helper_check - validate state object for modeset changes 340 * drm_atomic_helper_check - validate state object for modeset changes
335 * @dev: DRM device 341 * @dev: DRM device
@@ -404,12 +410,27 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
404 crtc = state->crtcs[i]; 410 crtc = state->crtcs[i];
405 crtc_state = state->crtc_states[i]; 411 crtc_state = state->crtc_states[i];
406 412
407 if (!crtc || !crtc_state->mode_changed) 413 if (!crtc)
408 continue; 414 continue;
409 415
410 DRM_DEBUG_KMS("[CRTC:%d] needs full modeset, enable: %c\n", 416 /*
417 * We must set ->active_changed after walking connectors for
418 * otherwise an update that only changes active would result in
419 * a full modeset because update_connector_routing force that.
420 */
421 if (crtc->state->active != crtc_state->active) {
422 DRM_DEBUG_KMS("[CRTC:%d] active changed\n",
423 crtc->base.id);
424 crtc_state->active_changed = true;
425 }
426
427 if (!needs_modeset(crtc_state))
428 continue;
429
430 DRM_DEBUG_KMS("[CRTC:%d] needs all connectors, enable: %c, active: %c\n",
411 crtc->base.id, 431 crtc->base.id,
412 crtc_state->enable ? 'y' : 'n'); 432 crtc_state->enable ? 'y' : 'n',
433 crtc_state->active ? 'y' : 'n');
413 434
414 ret = drm_atomic_add_affected_connectors(state, crtc); 435 ret = drm_atomic_add_affected_connectors(state, crtc);
415 if (ret != 0) 436 if (ret != 0)
@@ -545,6 +566,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
545 struct drm_connector *connector; 566 struct drm_connector *connector;
546 struct drm_encoder_helper_funcs *funcs; 567 struct drm_encoder_helper_funcs *funcs;
547 struct drm_encoder *encoder; 568 struct drm_encoder *encoder;
569 struct drm_crtc_state *old_crtc_state;
548 570
549 old_conn_state = old_state->connector_states[i]; 571 old_conn_state = old_state->connector_states[i];
550 connector = old_state->connectors[i]; 572 connector = old_state->connectors[i];
@@ -554,6 +576,11 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
554 if (!old_conn_state || !old_conn_state->crtc) 576 if (!old_conn_state || !old_conn_state->crtc)
555 continue; 577 continue;
556 578
579 old_crtc_state = old_state->crtc_states[drm_crtc_index(old_conn_state->crtc)];
580
581 if (!old_crtc_state->active)
582 continue;
583
557 encoder = old_conn_state->best_encoder; 584 encoder = old_conn_state->best_encoder;
558 585
559 /* We shouldn't get this far if we didn't previously have 586 /* We shouldn't get this far if we didn't previously have
@@ -586,11 +613,16 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
586 for (i = 0; i < ncrtcs; i++) { 613 for (i = 0; i < ncrtcs; i++) {
587 struct drm_crtc_helper_funcs *funcs; 614 struct drm_crtc_helper_funcs *funcs;
588 struct drm_crtc *crtc; 615 struct drm_crtc *crtc;
616 struct drm_crtc_state *old_crtc_state;
589 617
590 crtc = old_state->crtcs[i]; 618 crtc = old_state->crtcs[i];
619 old_crtc_state = old_state->crtc_states[i];
591 620
592 /* Shut down everything that needs a full modeset. */ 621 /* Shut down everything that needs a full modeset. */
593 if (!crtc || !crtc->state->mode_changed) 622 if (!crtc || !needs_modeset(crtc->state))
623 continue;
624
625 if (!old_crtc_state->active)
594 continue; 626 continue;
595 627
596 funcs = crtc->helper_private; 628 funcs = crtc->helper_private;
@@ -697,6 +729,9 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
697 mode = &new_crtc_state->mode; 729 mode = &new_crtc_state->mode;
698 adjusted_mode = &new_crtc_state->adjusted_mode; 730 adjusted_mode = &new_crtc_state->adjusted_mode;
699 731
732 if (!new_crtc_state->mode_changed)
733 continue;
734
700 /* 735 /*
701 * Each encoder has at most one connector (since we always steal 736 * Each encoder has at most one connector (since we always steal
702 * it away), so we won't call call mode_set hooks twice. 737 * it away), so we won't call call mode_set hooks twice.
@@ -749,7 +784,10 @@ void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
749 crtc = old_state->crtcs[i]; 784 crtc = old_state->crtcs[i];
750 785
751 /* Need to filter out CRTCs where only planes change. */ 786 /* Need to filter out CRTCs where only planes change. */
752 if (!crtc || !crtc->state->mode_changed) 787 if (!crtc || !needs_modeset(crtc->state))
788 continue;
789
790 if (!crtc->state->active)
753 continue; 791 continue;
754 792
755 funcs = crtc->helper_private; 793 funcs = crtc->helper_private;
@@ -768,6 +806,9 @@ void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
768 if (!connector || !connector->state->best_encoder) 806 if (!connector || !connector->state->best_encoder)
769 continue; 807 continue;
770 808
809 if (!connector->state->crtc->state->active)
810 continue;
811
771 encoder = connector->state->best_encoder; 812 encoder = connector->state->best_encoder;
772 funcs = encoder->helper_private; 813 funcs = encoder->helper_private;
773 814
@@ -1518,6 +1559,7 @@ retry:
1518 WARN_ON(set->num_connectors); 1559 WARN_ON(set->num_connectors);
1519 1560
1520 crtc_state->enable = false; 1561 crtc_state->enable = false;
1562 crtc_state->active = false;
1521 1563
1522 ret = drm_atomic_set_crtc_for_plane(primary_state, NULL); 1564 ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
1523 if (ret != 0) 1565 if (ret != 0)
@@ -1532,6 +1574,7 @@ retry:
1532 WARN_ON(!set->num_connectors); 1574 WARN_ON(!set->num_connectors);
1533 1575
1534 crtc_state->enable = true; 1576 crtc_state->enable = true;
1577 crtc_state->active = true;
1535 drm_mode_copy(&crtc_state->mode, set->mode); 1578 drm_mode_copy(&crtc_state->mode, set->mode);
1536 1579
1537 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); 1580 ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
@@ -1894,6 +1937,7 @@ drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
1894 1937
1895 if (state) { 1938 if (state) {
1896 state->mode_changed = false; 1939 state->mode_changed = false;
1940 state->active_changed = false;
1897 state->planes_changed = false; 1941 state->planes_changed = false;
1898 state->event = NULL; 1942 state->event = NULL;
1899 } 1943 }
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index c0bbb00beba7..419f9d915c78 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