diff options
Diffstat (limited to 'drivers/gpu/drm/drm_atomic.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 1d6ab371cd52..f5ea7db4a48a 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <drm/drm_atomic.h> | 30 | #include <drm/drm_atomic.h> |
31 | #include <drm/drm_mode.h> | 31 | #include <drm/drm_mode.h> |
32 | #include <drm/drm_plane_helper.h> | 32 | #include <drm/drm_plane_helper.h> |
33 | #include <drm/drm_print.h> | ||
33 | 34 | ||
34 | #include "drm_crtc_internal.h" | 35 | #include "drm_crtc_internal.h" |
35 | 36 | ||
@@ -605,6 +606,28 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc, | |||
605 | return 0; | 606 | return 0; |
606 | } | 607 | } |
607 | 608 | ||
609 | static void drm_atomic_crtc_print_state(struct drm_printer *p, | ||
610 | const struct drm_crtc_state *state) | ||
611 | { | ||
612 | struct drm_crtc *crtc = state->crtc; | ||
613 | |||
614 | drm_printf(p, "crtc[%u]: %s\n", crtc->base.id, crtc->name); | ||
615 | drm_printf(p, "\tenable=%d\n", state->enable); | ||
616 | drm_printf(p, "\tactive=%d\n", state->active); | ||
617 | drm_printf(p, "\tplanes_changed=%d\n", state->planes_changed); | ||
618 | drm_printf(p, "\tmode_changed=%d\n", state->mode_changed); | ||
619 | drm_printf(p, "\tactive_changed=%d\n", state->active_changed); | ||
620 | drm_printf(p, "\tconnectors_changed=%d\n", state->connectors_changed); | ||
621 | drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed); | ||
622 | drm_printf(p, "\tplane_mask=%x\n", state->plane_mask); | ||
623 | drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask); | ||
624 | drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask); | ||
625 | drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode)); | ||
626 | |||
627 | if (crtc->funcs->atomic_print_state) | ||
628 | crtc->funcs->atomic_print_state(p, state); | ||
629 | } | ||
630 | |||
608 | /** | 631 | /** |
609 | * drm_atomic_get_plane_state - get plane state | 632 | * drm_atomic_get_plane_state - get plane state |
610 | * @state: global atomic state object | 633 | * @state: global atomic state object |
@@ -881,6 +904,38 @@ static int drm_atomic_plane_check(struct drm_plane *plane, | |||
881 | return 0; | 904 | return 0; |
882 | } | 905 | } |
883 | 906 | ||
907 | static void drm_atomic_plane_print_state(struct drm_printer *p, | ||
908 | const struct drm_plane_state *state) | ||
909 | { | ||
910 | struct drm_plane *plane = state->plane; | ||
911 | struct drm_rect src = drm_plane_state_src(state); | ||
912 | struct drm_rect dest = drm_plane_state_dest(state); | ||
913 | |||
914 | drm_printf(p, "plane[%u]: %s\n", plane->base.id, plane->name); | ||
915 | drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)"); | ||
916 | drm_printf(p, "\tfb=%u\n", state->fb ? state->fb->base.id : 0); | ||
917 | if (state->fb) { | ||
918 | struct drm_framebuffer *fb = state->fb; | ||
919 | int i, n = drm_format_num_planes(fb->pixel_format); | ||
920 | |||
921 | drm_printf(p, "\t\tformat=%s\n", | ||
922 | drm_get_format_name(fb->pixel_format)); | ||
923 | drm_printf(p, "\t\tsize=%dx%d\n", fb->width, fb->height); | ||
924 | drm_printf(p, "\t\tlayers:\n"); | ||
925 | for (i = 0; i < n; i++) { | ||
926 | drm_printf(p, "\t\t\tpitch[%d]=%u\n", i, fb->pitches[i]); | ||
927 | drm_printf(p, "\t\t\toffset[%d]=%u\n", i, fb->offsets[i]); | ||
928 | drm_printf(p, "\t\t\tmodifier[%d]=0x%llx\n", i, fb->modifier[i]); | ||
929 | } | ||
930 | } | ||
931 | drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest)); | ||
932 | drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src)); | ||
933 | drm_printf(p, "\trotation=%x\n", state->rotation); | ||
934 | |||
935 | if (plane->funcs->atomic_print_state) | ||
936 | plane->funcs->atomic_print_state(p, state); | ||
937 | } | ||
938 | |||
884 | /** | 939 | /** |
885 | * drm_atomic_get_connector_state - get connector state | 940 | * drm_atomic_get_connector_state - get connector state |
886 | * @state: global atomic state object | 941 | * @state: global atomic state object |
@@ -996,6 +1051,18 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, | |||
996 | } | 1051 | } |
997 | EXPORT_SYMBOL(drm_atomic_connector_set_property); | 1052 | EXPORT_SYMBOL(drm_atomic_connector_set_property); |
998 | 1053 | ||
1054 | static void drm_atomic_connector_print_state(struct drm_printer *p, | ||
1055 | const struct drm_connector_state *state) | ||
1056 | { | ||
1057 | struct drm_connector *connector = state->connector; | ||
1058 | |||
1059 | drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name); | ||
1060 | drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)"); | ||
1061 | |||
1062 | if (connector->funcs->atomic_print_state) | ||
1063 | connector->funcs->atomic_print_state(p, state); | ||
1064 | } | ||
1065 | |||
999 | /** | 1066 | /** |
1000 | * drm_atomic_connector_get_property - get property value from connector state | 1067 | * drm_atomic_connector_get_property - get property value from connector state |
1001 | * @connector: the drm connector to set a property on | 1068 | * @connector: the drm connector to set a property on |
@@ -1150,6 +1217,36 @@ drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, | |||
1150 | EXPORT_SYMBOL(drm_atomic_set_fb_for_plane); | 1217 | EXPORT_SYMBOL(drm_atomic_set_fb_for_plane); |
1151 | 1218 | ||
1152 | /** | 1219 | /** |
1220 | * drm_atomic_set_fence_for_plane - set fence for plane | ||
1221 | * @plane_state: atomic state object for the plane | ||
1222 | * @fence: dma_fence to use for the plane | ||
1223 | * | ||
1224 | * Helper to setup the plane_state fence in case it is not set yet. | ||
1225 | * By using this drivers doesn't need to worry if the user choose | ||
1226 | * implicit or explicit fencing. | ||
1227 | * | ||
1228 | * This function will not set the fence to the state if it was set | ||
1229 | * via explicit fencing interfaces on the atomic ioctl. It will | ||
1230 | * all drope the reference to the fence as we not storing it | ||
1231 | * anywhere. | ||
1232 | * | ||
1233 | * Otherwise, if plane_state->fence is not set this function we | ||
1234 | * just set it with the received implict fence. | ||
1235 | */ | ||
1236 | void | ||
1237 | drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, | ||
1238 | struct dma_fence *fence) | ||
1239 | { | ||
1240 | if (plane_state->fence) { | ||
1241 | dma_fence_put(fence); | ||
1242 | return; | ||
1243 | } | ||
1244 | |||
1245 | plane_state->fence = fence; | ||
1246 | } | ||
1247 | EXPORT_SYMBOL(drm_atomic_set_fence_for_plane); | ||
1248 | |||
1249 | /** | ||
1153 | * drm_atomic_set_crtc_for_connector - set crtc for connector | 1250 | * drm_atomic_set_crtc_for_connector - set crtc for connector |
1154 | * @conn_state: atomic state object for the connector | 1251 | * @conn_state: atomic state object for the connector |
1155 | * @crtc: crtc to use for the connector | 1252 | * @crtc: crtc to use for the connector |
@@ -1460,6 +1557,92 @@ int drm_atomic_nonblocking_commit(struct drm_atomic_state *state) | |||
1460 | } | 1557 | } |
1461 | EXPORT_SYMBOL(drm_atomic_nonblocking_commit); | 1558 | EXPORT_SYMBOL(drm_atomic_nonblocking_commit); |
1462 | 1559 | ||
1560 | static void drm_atomic_print_state(const struct drm_atomic_state *state) | ||
1561 | { | ||
1562 | struct drm_printer p = drm_info_printer(state->dev->dev); | ||
1563 | struct drm_plane *plane; | ||
1564 | struct drm_plane_state *plane_state; | ||
1565 | struct drm_crtc *crtc; | ||
1566 | struct drm_crtc_state *crtc_state; | ||
1567 | struct drm_connector *connector; | ||
1568 | struct drm_connector_state *connector_state; | ||
1569 | int i; | ||
1570 | |||
1571 | DRM_DEBUG_ATOMIC("checking %p\n", state); | ||
1572 | |||
1573 | for_each_plane_in_state(state, plane, plane_state, i) | ||
1574 | drm_atomic_plane_print_state(&p, plane_state); | ||
1575 | |||
1576 | for_each_crtc_in_state(state, crtc, crtc_state, i) | ||
1577 | drm_atomic_crtc_print_state(&p, crtc_state); | ||
1578 | |||
1579 | for_each_connector_in_state(state, connector, connector_state, i) | ||
1580 | drm_atomic_connector_print_state(&p, connector_state); | ||
1581 | } | ||
1582 | |||
1583 | /** | ||
1584 | * drm_state_dump - dump entire device atomic state | ||
1585 | * @dev: the drm device | ||
1586 | * @p: where to print the state to | ||
1587 | * | ||
1588 | * Just for debugging. Drivers might want an option to dump state | ||
1589 | * to dmesg in case of error irq's. (Hint, you probably want to | ||
1590 | * ratelimit this!) | ||
1591 | * | ||
1592 | * The caller must drm_modeset_lock_all(), or if this is called | ||
1593 | * from error irq handler, it should not be enabled by default. | ||
1594 | * (Ie. if you are debugging errors you might not care that this | ||
1595 | * is racey. But calling this without all modeset locks held is | ||
1596 | * not inherently safe.) | ||
1597 | */ | ||
1598 | void drm_state_dump(struct drm_device *dev, struct drm_printer *p) | ||
1599 | { | ||
1600 | struct drm_mode_config *config = &dev->mode_config; | ||
1601 | struct drm_plane *plane; | ||
1602 | struct drm_crtc *crtc; | ||
1603 | struct drm_connector *connector; | ||
1604 | |||
1605 | if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) | ||
1606 | return; | ||
1607 | |||
1608 | list_for_each_entry(plane, &config->plane_list, head) | ||
1609 | drm_atomic_plane_print_state(p, plane->state); | ||
1610 | |||
1611 | list_for_each_entry(crtc, &config->crtc_list, head) | ||
1612 | drm_atomic_crtc_print_state(p, crtc->state); | ||
1613 | |||
1614 | list_for_each_entry(connector, &config->connector_list, head) | ||
1615 | drm_atomic_connector_print_state(p, connector->state); | ||
1616 | } | ||
1617 | EXPORT_SYMBOL(drm_state_dump); | ||
1618 | |||
1619 | #ifdef CONFIG_DEBUG_FS | ||
1620 | static int drm_state_info(struct seq_file *m, void *data) | ||
1621 | { | ||
1622 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
1623 | struct drm_device *dev = node->minor->dev; | ||
1624 | struct drm_printer p = drm_seq_file_printer(m); | ||
1625 | |||
1626 | drm_modeset_lock_all(dev); | ||
1627 | drm_state_dump(dev, &p); | ||
1628 | drm_modeset_unlock_all(dev); | ||
1629 | |||
1630 | return 0; | ||
1631 | } | ||
1632 | |||
1633 | /* any use in debugfs files to dump individual planes/crtc/etc? */ | ||
1634 | static const struct drm_info_list drm_atomic_debugfs_list[] = { | ||
1635 | {"state", drm_state_info, 0}, | ||
1636 | }; | ||
1637 | |||
1638 | int drm_atomic_debugfs_init(struct drm_minor *minor) | ||
1639 | { | ||
1640 | return drm_debugfs_create_files(drm_atomic_debugfs_list, | ||
1641 | ARRAY_SIZE(drm_atomic_debugfs_list), | ||
1642 | minor->debugfs_root, minor); | ||
1643 | } | ||
1644 | #endif | ||
1645 | |||
1463 | /* | 1646 | /* |
1464 | * The big monstor ioctl | 1647 | * The big monstor ioctl |
1465 | */ | 1648 | */ |
@@ -1749,6 +1932,9 @@ retry: | |||
1749 | } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { | 1932 | } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { |
1750 | ret = drm_atomic_nonblocking_commit(state); | 1933 | ret = drm_atomic_nonblocking_commit(state); |
1751 | } else { | 1934 | } else { |
1935 | if (unlikely(drm_debug & DRM_UT_STATE)) | ||
1936 | drm_atomic_print_state(state); | ||
1937 | |||
1752 | ret = drm_atomic_commit(state); | 1938 | ret = drm_atomic_commit(state); |
1753 | } | 1939 | } |
1754 | 1940 | ||