diff options
Diffstat (limited to 'drivers/gpu/drm/drm_framebuffer.c')
-rw-r--r-- | drivers/gpu/drm/drm_framebuffer.c | 87 |
1 files changed, 79 insertions, 8 deletions
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 279c1035c12d..d63d4c2ac4c8 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c | |||
@@ -25,7 +25,9 @@ | |||
25 | #include <drm/drm_auth.h> | 25 | #include <drm/drm_auth.h> |
26 | #include <drm/drm_framebuffer.h> | 26 | #include <drm/drm_framebuffer.h> |
27 | #include <drm/drm_atomic.h> | 27 | #include <drm/drm_atomic.h> |
28 | #include <drm/drm_print.h> | ||
28 | 29 | ||
30 | #include "drm_internal.h" | ||
29 | #include "drm_crtc_internal.h" | 31 | #include "drm_crtc_internal.h" |
30 | 32 | ||
31 | /** | 33 | /** |
@@ -78,11 +80,12 @@ int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y, | |||
78 | src_h > fb_height || | 80 | src_h > fb_height || |
79 | src_y > fb_height - src_h) { | 81 | src_y > fb_height - src_h) { |
80 | DRM_DEBUG_KMS("Invalid source coordinates " | 82 | DRM_DEBUG_KMS("Invalid source coordinates " |
81 | "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", | 83 | "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n", |
82 | src_w >> 16, ((src_w & 0xffff) * 15625) >> 10, | 84 | src_w >> 16, ((src_w & 0xffff) * 15625) >> 10, |
83 | src_h >> 16, ((src_h & 0xffff) * 15625) >> 10, | 85 | src_h >> 16, ((src_h & 0xffff) * 15625) >> 10, |
84 | src_x >> 16, ((src_x & 0xffff) * 15625) >> 10, | 86 | src_x >> 16, ((src_x & 0xffff) * 15625) >> 10, |
85 | src_y >> 16, ((src_y & 0xffff) * 15625) >> 10); | 87 | src_y >> 16, ((src_y & 0xffff) * 15625) >> 10, |
88 | fb->width, fb->height); | ||
86 | return -ENOSPC; | 89 | return -ENOSPC; |
87 | } | 90 | } |
88 | 91 | ||
@@ -766,14 +769,18 @@ static int atomic_remove_fb(struct drm_framebuffer *fb) | |||
766 | struct drm_plane *plane; | 769 | struct drm_plane *plane; |
767 | struct drm_connector *conn; | 770 | struct drm_connector *conn; |
768 | struct drm_connector_state *conn_state; | 771 | struct drm_connector_state *conn_state; |
769 | int i, ret = 0; | 772 | int i, ret; |
770 | unsigned plane_mask; | 773 | unsigned plane_mask; |
774 | bool disable_crtcs = false; | ||
771 | 775 | ||
772 | state = drm_atomic_state_alloc(dev); | 776 | retry_disable: |
773 | if (!state) | ||
774 | return -ENOMEM; | ||
775 | |||
776 | drm_modeset_acquire_init(&ctx, 0); | 777 | drm_modeset_acquire_init(&ctx, 0); |
778 | |||
779 | state = drm_atomic_state_alloc(dev); | ||
780 | if (!state) { | ||
781 | ret = -ENOMEM; | ||
782 | goto out; | ||
783 | } | ||
777 | state->acquire_ctx = &ctx; | 784 | state->acquire_ctx = &ctx; |
778 | 785 | ||
779 | retry: | 786 | retry: |
@@ -794,7 +801,7 @@ retry: | |||
794 | goto unlock; | 801 | goto unlock; |
795 | } | 802 | } |
796 | 803 | ||
797 | if (plane_state->crtc->primary == plane) { | 804 | if (disable_crtcs && plane_state->crtc->primary == plane) { |
798 | struct drm_crtc_state *crtc_state; | 805 | struct drm_crtc_state *crtc_state; |
799 | 806 | ||
800 | crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc); | 807 | crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc); |
@@ -819,6 +826,7 @@ retry: | |||
819 | plane->old_fb = plane->fb; | 826 | plane->old_fb = plane->fb; |
820 | } | 827 | } |
821 | 828 | ||
829 | /* This list is only filled when disable_crtcs is set. */ | ||
822 | for_each_new_connector_in_state(state, conn, conn_state, i) { | 830 | for_each_new_connector_in_state(state, conn, conn_state, i) { |
823 | ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); | 831 | ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); |
824 | 832 | ||
@@ -841,9 +849,15 @@ unlock: | |||
841 | 849 | ||
842 | drm_atomic_state_put(state); | 850 | drm_atomic_state_put(state); |
843 | 851 | ||
852 | out: | ||
844 | drm_modeset_drop_locks(&ctx); | 853 | drm_modeset_drop_locks(&ctx); |
845 | drm_modeset_acquire_fini(&ctx); | 854 | drm_modeset_acquire_fini(&ctx); |
846 | 855 | ||
856 | if (ret == -EINVAL && !disable_crtcs) { | ||
857 | disable_crtcs = true; | ||
858 | goto retry_disable; | ||
859 | } | ||
860 | |||
847 | return ret; | 861 | return ret; |
848 | } | 862 | } |
849 | 863 | ||
@@ -957,3 +971,60 @@ int drm_framebuffer_plane_height(int height, | |||
957 | return fb_plane_height(height, fb->format, plane); | 971 | return fb_plane_height(height, fb->format, plane); |
958 | } | 972 | } |
959 | EXPORT_SYMBOL(drm_framebuffer_plane_height); | 973 | EXPORT_SYMBOL(drm_framebuffer_plane_height); |
974 | |||
975 | void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent, | ||
976 | const struct drm_framebuffer *fb) | ||
977 | { | ||
978 | struct drm_format_name_buf format_name; | ||
979 | unsigned int i; | ||
980 | |||
981 | drm_printf_indent(p, indent, "refcount=%u\n", | ||
982 | drm_framebuffer_read_refcount(fb)); | ||
983 | drm_printf_indent(p, indent, "format=%s\n", | ||
984 | drm_get_format_name(fb->format->format, &format_name)); | ||
985 | drm_printf_indent(p, indent, "modifier=0x%llx\n", fb->modifier); | ||
986 | drm_printf_indent(p, indent, "size=%ux%u\n", fb->width, fb->height); | ||
987 | drm_printf_indent(p, indent, "layers:\n"); | ||
988 | |||
989 | for (i = 0; i < fb->format->num_planes; i++) { | ||
990 | drm_printf_indent(p, indent + 1, "size[%u]=%dx%d\n", i, | ||
991 | drm_framebuffer_plane_width(fb->width, fb, i), | ||
992 | drm_framebuffer_plane_height(fb->height, fb, i)); | ||
993 | drm_printf_indent(p, indent + 1, "pitch[%u]=%u\n", i, fb->pitches[i]); | ||
994 | drm_printf_indent(p, indent + 1, "offset[%u]=%u\n", i, fb->offsets[i]); | ||
995 | drm_printf_indent(p, indent + 1, "obj[%u]:%s\n", i, | ||
996 | fb->obj[i] ? "" : "(null)"); | ||
997 | if (fb->obj[i]) | ||
998 | drm_gem_print_info(p, indent + 2, fb->obj[i]); | ||
999 | } | ||
1000 | } | ||
1001 | |||
1002 | #ifdef CONFIG_DEBUG_FS | ||
1003 | static int drm_framebuffer_info(struct seq_file *m, void *data) | ||
1004 | { | ||
1005 | struct drm_info_node *node = m->private; | ||
1006 | struct drm_device *dev = node->minor->dev; | ||
1007 | struct drm_printer p = drm_seq_file_printer(m); | ||
1008 | struct drm_framebuffer *fb; | ||
1009 | |||
1010 | mutex_lock(&dev->mode_config.fb_lock); | ||
1011 | drm_for_each_fb(fb, dev) { | ||
1012 | drm_printf(&p, "framebuffer[%u]:\n", fb->base.id); | ||
1013 | drm_framebuffer_print_info(&p, 1, fb); | ||
1014 | } | ||
1015 | mutex_unlock(&dev->mode_config.fb_lock); | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | static const struct drm_info_list drm_framebuffer_debugfs_list[] = { | ||
1021 | { "framebuffer", drm_framebuffer_info, 0 }, | ||
1022 | }; | ||
1023 | |||
1024 | int drm_framebuffer_debugfs_init(struct drm_minor *minor) | ||
1025 | { | ||
1026 | return drm_debugfs_create_files(drm_framebuffer_debugfs_list, | ||
1027 | ARRAY_SIZE(drm_framebuffer_debugfs_list), | ||
1028 | minor->debugfs_root, minor); | ||
1029 | } | ||
1030 | #endif | ||