aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/virtio/virtgpu_plane.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/virtio/virtgpu_plane.c')
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_plane.c150
1 files changed, 127 insertions, 23 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
index 70b44a2345ab..925ca25209df 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -38,6 +38,10 @@ static const uint32_t virtio_gpu_formats[] = {
38 DRM_FORMAT_ABGR8888, 38 DRM_FORMAT_ABGR8888,
39}; 39};
40 40
41static const uint32_t virtio_gpu_cursor_formats[] = {
42 DRM_FORMAT_ARGB8888,
43};
44
41static void virtio_gpu_plane_destroy(struct drm_plane *plane) 45static void virtio_gpu_plane_destroy(struct drm_plane *plane)
42{ 46{
43 kfree(plane); 47 kfree(plane);
@@ -58,16 +62,22 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
58 return 0; 62 return 0;
59} 63}
60 64
61static void virtio_gpu_plane_atomic_update(struct drm_plane *plane, 65static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
62 struct drm_plane_state *old_state) 66 struct drm_plane_state *old_state)
63{ 67{
64 struct drm_device *dev = plane->dev; 68 struct drm_device *dev = plane->dev;
65 struct virtio_gpu_device *vgdev = dev->dev_private; 69 struct virtio_gpu_device *vgdev = dev->dev_private;
66 struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(plane->crtc); 70 struct virtio_gpu_output *output = NULL;
67 struct virtio_gpu_framebuffer *vgfb; 71 struct virtio_gpu_framebuffer *vgfb;
68 struct virtio_gpu_object *bo; 72 struct virtio_gpu_object *bo;
69 uint32_t handle; 73 uint32_t handle;
70 74
75 if (plane->state->crtc)
76 output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
77 if (old_state->crtc)
78 output = drm_crtc_to_virtio_gpu_output(old_state->crtc);
79 WARN_ON(!output);
80
71 if (plane->state->fb) { 81 if (plane->state->fb) {
72 vgfb = to_virtio_gpu_framebuffer(plane->state->fb); 82 vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
73 bo = gem_to_virtio_gpu_obj(vgfb->obj); 83 bo = gem_to_virtio_gpu_obj(vgfb->obj);
@@ -75,55 +85,149 @@ static void virtio_gpu_plane_atomic_update(struct drm_plane *plane,
75 if (bo->dumb) { 85 if (bo->dumb) {
76 virtio_gpu_cmd_transfer_to_host_2d 86 virtio_gpu_cmd_transfer_to_host_2d
77 (vgdev, handle, 0, 87 (vgdev, handle, 0,
78 cpu_to_le32(plane->state->crtc_w), 88 cpu_to_le32(plane->state->src_w >> 16),
79 cpu_to_le32(plane->state->crtc_h), 89 cpu_to_le32(plane->state->src_h >> 16),
80 plane->state->crtc_x, plane->state->crtc_y, NULL); 90 plane->state->src_x >> 16,
91 plane->state->src_y >> 16, NULL);
81 } 92 }
82 } else { 93 } else {
83 handle = 0; 94 handle = 0;
84 } 95 }
85 96
86 DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d\n", handle, 97 DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", handle,
87 plane->state->crtc_w, plane->state->crtc_h, 98 plane->state->crtc_w, plane->state->crtc_h,
88 plane->state->crtc_x, plane->state->crtc_y); 99 plane->state->crtc_x, plane->state->crtc_y,
100 plane->state->src_w >> 16,
101 plane->state->src_h >> 16,
102 plane->state->src_x >> 16,
103 plane->state->src_y >> 16);
89 virtio_gpu_cmd_set_scanout(vgdev, output->index, handle, 104 virtio_gpu_cmd_set_scanout(vgdev, output->index, handle,
90 plane->state->crtc_w, 105 plane->state->src_w >> 16,
91 plane->state->crtc_h, 106 plane->state->src_h >> 16,
92 plane->state->crtc_x, 107 plane->state->src_x >> 16,
93 plane->state->crtc_y); 108 plane->state->src_y >> 16);
94 virtio_gpu_cmd_resource_flush(vgdev, handle, 109 virtio_gpu_cmd_resource_flush(vgdev, handle,
95 plane->state->crtc_x, 110 plane->state->src_x >> 16,
96 plane->state->crtc_y, 111 plane->state->src_y >> 16,
97 plane->state->crtc_w, 112 plane->state->src_w >> 16,
98 plane->state->crtc_h); 113 plane->state->src_h >> 16);
99} 114}
100 115
116static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
117 struct drm_plane_state *old_state)
118{
119 struct drm_device *dev = plane->dev;
120 struct virtio_gpu_device *vgdev = dev->dev_private;
121 struct virtio_gpu_output *output = NULL;
122 struct virtio_gpu_framebuffer *vgfb;
123 struct virtio_gpu_fence *fence = NULL;
124 struct virtio_gpu_object *bo = NULL;
125 uint32_t handle;
126 int ret = 0;
101 127
102static const struct drm_plane_helper_funcs virtio_gpu_plane_helper_funcs = { 128 if (plane->state->crtc)
129 output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
130 if (old_state->crtc)
131 output = drm_crtc_to_virtio_gpu_output(old_state->crtc);
132 WARN_ON(!output);
133
134 if (plane->state->fb) {
135 vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
136 bo = gem_to_virtio_gpu_obj(vgfb->obj);
137 handle = bo->hw_res_handle;
138 } else {
139 handle = 0;
140 }
141
142 if (bo && bo->dumb && (plane->state->fb != old_state->fb)) {
143 /* new cursor -- update & wait */
144 virtio_gpu_cmd_transfer_to_host_2d
145 (vgdev, handle, 0,
146 cpu_to_le32(plane->state->crtc_w),
147 cpu_to_le32(plane->state->crtc_h),
148 0, 0, &fence);
149 ret = virtio_gpu_object_reserve(bo, false);
150 if (!ret) {
151 reservation_object_add_excl_fence(bo->tbo.resv,
152 &fence->f);
153 fence_put(&fence->f);
154 fence = NULL;
155 virtio_gpu_object_unreserve(bo);
156 virtio_gpu_object_wait(bo, false);
157 }
158 }
159
160 if (plane->state->fb != old_state->fb) {
161 DRM_DEBUG("update, handle %d, pos +%d+%d, hot %d,%d\n", handle,
162 plane->state->crtc_x,
163 plane->state->crtc_y,
164 plane->state->fb ? plane->state->fb->hot_x : 0,
165 plane->state->fb ? plane->state->fb->hot_y : 0);
166 output->cursor.hdr.type =
167 cpu_to_le32(VIRTIO_GPU_CMD_UPDATE_CURSOR);
168 output->cursor.resource_id = cpu_to_le32(handle);
169 if (plane->state->fb) {
170 output->cursor.hot_x =
171 cpu_to_le32(plane->state->fb->hot_x);
172 output->cursor.hot_y =
173 cpu_to_le32(plane->state->fb->hot_y);
174 } else {
175 output->cursor.hot_x = cpu_to_le32(0);
176 output->cursor.hot_y = cpu_to_le32(0);
177 }
178 } else {
179 DRM_DEBUG("move +%d+%d\n",
180 plane->state->crtc_x,
181 plane->state->crtc_y);
182 output->cursor.hdr.type =
183 cpu_to_le32(VIRTIO_GPU_CMD_MOVE_CURSOR);
184 }
185 output->cursor.pos.x = cpu_to_le32(plane->state->crtc_x);
186 output->cursor.pos.y = cpu_to_le32(plane->state->crtc_y);
187 virtio_gpu_cursor_ping(vgdev, output);
188}
189
190static const struct drm_plane_helper_funcs virtio_gpu_primary_helper_funcs = {
191 .atomic_check = virtio_gpu_plane_atomic_check,
192 .atomic_update = virtio_gpu_primary_plane_update,
193};
194
195static const struct drm_plane_helper_funcs virtio_gpu_cursor_helper_funcs = {
103 .atomic_check = virtio_gpu_plane_atomic_check, 196 .atomic_check = virtio_gpu_plane_atomic_check,
104 .atomic_update = virtio_gpu_plane_atomic_update, 197 .atomic_update = virtio_gpu_cursor_plane_update,
105}; 198};
106 199
107struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev, 200struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
201 enum drm_plane_type type,
108 int index) 202 int index)
109{ 203{
110 struct drm_device *dev = vgdev->ddev; 204 struct drm_device *dev = vgdev->ddev;
205 const struct drm_plane_helper_funcs *funcs;
111 struct drm_plane *plane; 206 struct drm_plane *plane;
112 int ret; 207 const uint32_t *formats;
208 int ret, nformats;
113 209
114 plane = kzalloc(sizeof(*plane), GFP_KERNEL); 210 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
115 if (!plane) 211 if (!plane)
116 return ERR_PTR(-ENOMEM); 212 return ERR_PTR(-ENOMEM);
117 213
214 if (type == DRM_PLANE_TYPE_CURSOR) {
215 formats = virtio_gpu_cursor_formats;
216 nformats = ARRAY_SIZE(virtio_gpu_cursor_formats);
217 funcs = &virtio_gpu_cursor_helper_funcs;
218 } else {
219 formats = virtio_gpu_formats;
220 nformats = ARRAY_SIZE(virtio_gpu_formats);
221 funcs = &virtio_gpu_primary_helper_funcs;
222 }
118 ret = drm_universal_plane_init(dev, plane, 1 << index, 223 ret = drm_universal_plane_init(dev, plane, 1 << index,
119 &virtio_gpu_plane_funcs, 224 &virtio_gpu_plane_funcs,
120 virtio_gpu_formats, 225 formats, nformats,
121 ARRAY_SIZE(virtio_gpu_formats), 226 type, NULL);
122 DRM_PLANE_TYPE_PRIMARY, NULL);
123 if (ret) 227 if (ret)
124 goto err_plane_init; 228 goto err_plane_init;
125 229
126 drm_plane_helper_add(plane, &virtio_gpu_plane_helper_funcs); 230 drm_plane_helper_add(plane, funcs);
127 return plane; 231 return plane;
128 232
129err_plane_init: 233err_plane_init: