2 * Copyright (C) 2015 Red Hat, Inc.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
28 #include "virtgpu_drv.h"
29 #include <drm/drm_crtc_helper.h>
30 #include <drm/drm_atomic_helper.h>
41 static void virtio_gpu_crtc_gamma_set(struct drm_crtc
*crtc
,
42 u16
*red
, u16
*green
, u16
*blue
,
43 uint32_t start
, uint32_t size
)
49 virtio_gpu_hide_cursor(struct virtio_gpu_device
*vgdev
,
50 struct virtio_gpu_output
*output
)
52 output
->cursor
.hdr
.type
= cpu_to_le32(VIRTIO_GPU_CMD_UPDATE_CURSOR
);
53 output
->cursor
.resource_id
= 0;
54 virtio_gpu_cursor_ping(vgdev
, output
);
57 static int virtio_gpu_crtc_cursor_set(struct drm_crtc
*crtc
,
58 struct drm_file
*file_priv
,
62 int32_t hot_x
, int32_t hot_y
)
64 struct virtio_gpu_device
*vgdev
= crtc
->dev
->dev_private
;
65 struct virtio_gpu_output
*output
=
66 container_of(crtc
, struct virtio_gpu_output
, crtc
);
67 struct drm_gem_object
*gobj
= NULL
;
68 struct virtio_gpu_object
*qobj
= NULL
;
69 struct virtio_gpu_fence
*fence
= NULL
;
73 virtio_gpu_hide_cursor(vgdev
, output
);
77 /* lookup the cursor */
78 gobj
= drm_gem_object_lookup(crtc
->dev
, file_priv
, handle
);
82 qobj
= gem_to_virtio_gpu_obj(gobj
);
84 if (!qobj
->hw_res_handle
) {
89 virtio_gpu_cmd_transfer_to_host_2d(vgdev
, qobj
->hw_res_handle
, 0,
93 ret
= virtio_gpu_object_reserve(qobj
, false);
95 reservation_object_add_excl_fence(qobj
->tbo
.resv
,
98 virtio_gpu_object_unreserve(qobj
);
99 virtio_gpu_object_wait(qobj
, false);
102 output
->cursor
.hdr
.type
= cpu_to_le32(VIRTIO_GPU_CMD_UPDATE_CURSOR
);
103 output
->cursor
.resource_id
= cpu_to_le32(qobj
->hw_res_handle
);
104 output
->cursor
.hot_x
= cpu_to_le32(hot_x
);
105 output
->cursor
.hot_y
= cpu_to_le32(hot_y
);
106 virtio_gpu_cursor_ping(vgdev
, output
);
110 drm_gem_object_unreference_unlocked(gobj
);
114 static int virtio_gpu_crtc_cursor_move(struct drm_crtc
*crtc
,
117 struct virtio_gpu_device
*vgdev
= crtc
->dev
->dev_private
;
118 struct virtio_gpu_output
*output
=
119 container_of(crtc
, struct virtio_gpu_output
, crtc
);
121 output
->cursor
.hdr
.type
= cpu_to_le32(VIRTIO_GPU_CMD_MOVE_CURSOR
);
122 output
->cursor
.pos
.x
= cpu_to_le32(x
);
123 output
->cursor
.pos
.y
= cpu_to_le32(y
);
124 virtio_gpu_cursor_ping(vgdev
, output
);
128 static int virtio_gpu_page_flip(struct drm_crtc
*crtc
,
129 struct drm_framebuffer
*fb
,
130 struct drm_pending_vblank_event
*event
,
133 struct virtio_gpu_device
*vgdev
= crtc
->dev
->dev_private
;
134 struct virtio_gpu_output
*output
=
135 container_of(crtc
, struct virtio_gpu_output
, crtc
);
136 struct drm_plane
*plane
= crtc
->primary
;
137 struct virtio_gpu_framebuffer
*vgfb
;
138 struct virtio_gpu_object
*bo
;
139 unsigned long irqflags
;
143 vgfb
= to_virtio_gpu_framebuffer(plane
->fb
);
144 bo
= gem_to_virtio_gpu_obj(vgfb
->obj
);
145 handle
= bo
->hw_res_handle
;
147 DRM_DEBUG("handle 0x%x%s, crtc %dx%d\n", handle
,
148 bo
->dumb
? ", dumb" : "",
149 crtc
->mode
.hdisplay
, crtc
->mode
.vdisplay
);
151 virtio_gpu_cmd_transfer_to_host_2d
153 cpu_to_le32(crtc
->mode
.hdisplay
),
154 cpu_to_le32(crtc
->mode
.vdisplay
),
157 virtio_gpu_cmd_set_scanout(vgdev
, output
->index
, handle
,
159 crtc
->mode
.vdisplay
, 0, 0);
160 virtio_gpu_cmd_resource_flush(vgdev
, handle
, 0, 0,
162 crtc
->mode
.vdisplay
);
165 spin_lock_irqsave(&crtc
->dev
->event_lock
, irqflags
);
166 drm_send_vblank_event(crtc
->dev
, -1, event
);
167 spin_unlock_irqrestore(&crtc
->dev
->event_lock
, irqflags
);
173 static const struct drm_crtc_funcs virtio_gpu_crtc_funcs
= {
174 .cursor_set2
= virtio_gpu_crtc_cursor_set
,
175 .cursor_move
= virtio_gpu_crtc_cursor_move
,
176 .gamma_set
= virtio_gpu_crtc_gamma_set
,
177 .set_config
= drm_atomic_helper_set_config
,
178 .destroy
= drm_crtc_cleanup
,
180 .page_flip
= virtio_gpu_page_flip
,
181 .reset
= drm_atomic_helper_crtc_reset
,
182 .atomic_duplicate_state
= drm_atomic_helper_crtc_duplicate_state
,
183 .atomic_destroy_state
= drm_atomic_helper_crtc_destroy_state
,
186 static void virtio_gpu_user_framebuffer_destroy(struct drm_framebuffer
*fb
)
188 struct virtio_gpu_framebuffer
*virtio_gpu_fb
189 = to_virtio_gpu_framebuffer(fb
);
191 if (virtio_gpu_fb
->obj
)
192 drm_gem_object_unreference_unlocked(virtio_gpu_fb
->obj
);
193 drm_framebuffer_cleanup(fb
);
194 kfree(virtio_gpu_fb
);
198 virtio_gpu_framebuffer_surface_dirty(struct drm_framebuffer
*fb
,
199 struct drm_file
*file_priv
,
200 unsigned flags
, unsigned color
,
201 struct drm_clip_rect
*clips
,
204 struct virtio_gpu_framebuffer
*virtio_gpu_fb
205 = to_virtio_gpu_framebuffer(fb
);
207 return virtio_gpu_surface_dirty(virtio_gpu_fb
, clips
, num_clips
);
210 static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs
= {
211 .destroy
= virtio_gpu_user_framebuffer_destroy
,
212 .dirty
= virtio_gpu_framebuffer_surface_dirty
,
216 virtio_gpu_framebuffer_init(struct drm_device
*dev
,
217 struct virtio_gpu_framebuffer
*vgfb
,
218 struct drm_mode_fb_cmd2
*mode_cmd
,
219 struct drm_gem_object
*obj
)
222 struct virtio_gpu_object
*bo
;
225 bo
= gem_to_virtio_gpu_obj(obj
);
227 ret
= drm_framebuffer_init(dev
, &vgfb
->base
, &virtio_gpu_fb_funcs
);
232 drm_helper_mode_fill_fb_struct(&vgfb
->base
, mode_cmd
);
234 spin_lock_init(&vgfb
->dirty_lock
);
235 vgfb
->x1
= vgfb
->y1
= INT_MAX
;
236 vgfb
->x2
= vgfb
->y2
= 0;
240 static bool virtio_gpu_crtc_mode_fixup(struct drm_crtc
*crtc
,
241 const struct drm_display_mode
*mode
,
242 struct drm_display_mode
*adjusted_mode
)
247 static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc
*crtc
)
249 struct drm_device
*dev
= crtc
->dev
;
250 struct virtio_gpu_device
*vgdev
= dev
->dev_private
;
251 struct virtio_gpu_output
*output
= drm_crtc_to_virtio_gpu_output(crtc
);
253 virtio_gpu_cmd_set_scanout(vgdev
, output
->index
, 0,
255 crtc
->mode
.vdisplay
, 0, 0);
258 static void virtio_gpu_crtc_enable(struct drm_crtc
*crtc
)
262 static void virtio_gpu_crtc_disable(struct drm_crtc
*crtc
)
264 struct drm_device
*dev
= crtc
->dev
;
265 struct virtio_gpu_device
*vgdev
= dev
->dev_private
;
266 struct virtio_gpu_output
*output
= drm_crtc_to_virtio_gpu_output(crtc
);
268 virtio_gpu_cmd_set_scanout(vgdev
, output
->index
, 0, 0, 0, 0, 0);
271 static int virtio_gpu_crtc_atomic_check(struct drm_crtc
*crtc
,
272 struct drm_crtc_state
*state
)
277 static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs
= {
278 .enable
= virtio_gpu_crtc_enable
,
279 .disable
= virtio_gpu_crtc_disable
,
280 .mode_fixup
= virtio_gpu_crtc_mode_fixup
,
281 .mode_set_nofb
= virtio_gpu_crtc_mode_set_nofb
,
282 .atomic_check
= virtio_gpu_crtc_atomic_check
,
285 static bool virtio_gpu_enc_mode_fixup(struct drm_encoder
*encoder
,
286 const struct drm_display_mode
*mode
,
287 struct drm_display_mode
*adjusted_mode
)
292 static void virtio_gpu_enc_mode_set(struct drm_encoder
*encoder
,
293 struct drm_display_mode
*mode
,
294 struct drm_display_mode
*adjusted_mode
)
298 static void virtio_gpu_enc_enable(struct drm_encoder
*encoder
)
302 static void virtio_gpu_enc_disable(struct drm_encoder
*encoder
)
306 static int virtio_gpu_conn_get_modes(struct drm_connector
*connector
)
308 struct virtio_gpu_output
*output
=
309 drm_connector_to_virtio_gpu_output(connector
);
310 struct drm_display_mode
*mode
= NULL
;
311 int count
, width
, height
;
313 width
= le32_to_cpu(output
->info
.r
.width
);
314 height
= le32_to_cpu(output
->info
.r
.height
);
315 count
= drm_add_modes_noedid(connector
, XRES_MAX
, YRES_MAX
);
317 if (width
== 0 || height
== 0) {
320 drm_set_preferred_mode(connector
, XRES_DEF
, YRES_DEF
);
322 DRM_DEBUG("add mode: %dx%d\n", width
, height
);
323 mode
= drm_cvt_mode(connector
->dev
, width
, height
, 60,
324 false, false, false);
325 mode
->type
|= DRM_MODE_TYPE_PREFERRED
;
326 drm_mode_probed_add(connector
, mode
);
333 static int virtio_gpu_conn_mode_valid(struct drm_connector
*connector
,
334 struct drm_display_mode
*mode
)
336 struct virtio_gpu_output
*output
=
337 drm_connector_to_virtio_gpu_output(connector
);
340 width
= le32_to_cpu(output
->info
.r
.width
);
341 height
= le32_to_cpu(output
->info
.r
.height
);
343 if (!(mode
->type
& DRM_MODE_TYPE_PREFERRED
))
345 if (mode
->hdisplay
== XRES_DEF
&& mode
->vdisplay
== YRES_DEF
)
347 if (mode
->hdisplay
<= width
&& mode
->hdisplay
>= width
- 16 &&
348 mode
->vdisplay
<= height
&& mode
->vdisplay
>= height
- 16)
351 DRM_DEBUG("del mode: %dx%d\n", mode
->hdisplay
, mode
->vdisplay
);
355 static struct drm_encoder
*
356 virtio_gpu_best_encoder(struct drm_connector
*connector
)
358 struct virtio_gpu_output
*virtio_gpu_output
=
359 drm_connector_to_virtio_gpu_output(connector
);
361 return &virtio_gpu_output
->enc
;
364 static const struct drm_encoder_helper_funcs virtio_gpu_enc_helper_funcs
= {
365 .mode_fixup
= virtio_gpu_enc_mode_fixup
,
366 .mode_set
= virtio_gpu_enc_mode_set
,
367 .enable
= virtio_gpu_enc_enable
,
368 .disable
= virtio_gpu_enc_disable
,
371 static const struct drm_connector_helper_funcs virtio_gpu_conn_helper_funcs
= {
372 .get_modes
= virtio_gpu_conn_get_modes
,
373 .mode_valid
= virtio_gpu_conn_mode_valid
,
374 .best_encoder
= virtio_gpu_best_encoder
,
377 static void virtio_gpu_conn_save(struct drm_connector
*connector
)
382 static void virtio_gpu_conn_restore(struct drm_connector
*connector
)
387 static enum drm_connector_status
virtio_gpu_conn_detect(
388 struct drm_connector
*connector
,
391 struct virtio_gpu_output
*output
=
392 drm_connector_to_virtio_gpu_output(connector
);
394 if (output
->info
.enabled
)
395 return connector_status_connected
;
397 return connector_status_disconnected
;
400 static void virtio_gpu_conn_destroy(struct drm_connector
*connector
)
402 struct virtio_gpu_output
*virtio_gpu_output
=
403 drm_connector_to_virtio_gpu_output(connector
);
405 drm_connector_unregister(connector
);
406 drm_connector_cleanup(connector
);
407 kfree(virtio_gpu_output
);
410 static const struct drm_connector_funcs virtio_gpu_connector_funcs
= {
411 .dpms
= drm_atomic_helper_connector_dpms
,
412 .save
= virtio_gpu_conn_save
,
413 .restore
= virtio_gpu_conn_restore
,
414 .detect
= virtio_gpu_conn_detect
,
415 .fill_modes
= drm_helper_probe_single_connector_modes_nomerge
,
416 .destroy
= virtio_gpu_conn_destroy
,
417 .reset
= drm_atomic_helper_connector_reset
,
418 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
419 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
422 static const struct drm_encoder_funcs virtio_gpu_enc_funcs
= {
423 .destroy
= drm_encoder_cleanup
,
426 static int vgdev_output_init(struct virtio_gpu_device
*vgdev
, int index
)
428 struct drm_device
*dev
= vgdev
->ddev
;
429 struct virtio_gpu_output
*output
= vgdev
->outputs
+ index
;
430 struct drm_connector
*connector
= &output
->conn
;
431 struct drm_encoder
*encoder
= &output
->enc
;
432 struct drm_crtc
*crtc
= &output
->crtc
;
433 struct drm_plane
*plane
;
435 output
->index
= index
;
437 output
->info
.enabled
= cpu_to_le32(true);
438 output
->info
.r
.width
= cpu_to_le32(XRES_DEF
);
439 output
->info
.r
.height
= cpu_to_le32(YRES_DEF
);
442 plane
= virtio_gpu_plane_init(vgdev
, index
);
444 return PTR_ERR(plane
);
445 drm_crtc_init_with_planes(dev
, crtc
, plane
, NULL
,
446 &virtio_gpu_crtc_funcs
);
447 drm_mode_crtc_set_gamma_size(crtc
, 256);
448 drm_crtc_helper_add(crtc
, &virtio_gpu_crtc_helper_funcs
);
451 drm_connector_init(dev
, connector
, &virtio_gpu_connector_funcs
,
452 DRM_MODE_CONNECTOR_VIRTUAL
);
453 drm_connector_helper_add(connector
, &virtio_gpu_conn_helper_funcs
);
455 drm_encoder_init(dev
, encoder
, &virtio_gpu_enc_funcs
,
456 DRM_MODE_ENCODER_VIRTUAL
);
457 drm_encoder_helper_add(encoder
, &virtio_gpu_enc_helper_funcs
);
458 encoder
->possible_crtcs
= 1 << index
;
460 drm_mode_connector_attach_encoder(connector
, encoder
);
461 drm_connector_register(connector
);
465 static struct drm_framebuffer
*
466 virtio_gpu_user_framebuffer_create(struct drm_device
*dev
,
467 struct drm_file
*file_priv
,
468 struct drm_mode_fb_cmd2
*mode_cmd
)
470 struct drm_gem_object
*obj
= NULL
;
471 struct virtio_gpu_framebuffer
*virtio_gpu_fb
;
474 /* lookup object associated with res handle */
475 obj
= drm_gem_object_lookup(dev
, file_priv
, mode_cmd
->handles
[0]);
477 return ERR_PTR(-EINVAL
);
479 virtio_gpu_fb
= kzalloc(sizeof(*virtio_gpu_fb
), GFP_KERNEL
);
480 if (virtio_gpu_fb
== NULL
)
481 return ERR_PTR(-ENOMEM
);
483 ret
= virtio_gpu_framebuffer_init(dev
, virtio_gpu_fb
, mode_cmd
, obj
);
485 kfree(virtio_gpu_fb
);
487 drm_gem_object_unreference_unlocked(obj
);
491 return &virtio_gpu_fb
->base
;
494 static const struct drm_mode_config_funcs virtio_gpu_mode_funcs
= {
495 .fb_create
= virtio_gpu_user_framebuffer_create
,
496 .atomic_check
= drm_atomic_helper_check
,
497 .atomic_commit
= drm_atomic_helper_commit
,
500 int virtio_gpu_modeset_init(struct virtio_gpu_device
*vgdev
)
504 drm_mode_config_init(vgdev
->ddev
);
505 vgdev
->ddev
->mode_config
.funcs
= (void *)&virtio_gpu_mode_funcs
;
507 /* modes will be validated against the framebuffer size */
508 vgdev
->ddev
->mode_config
.min_width
= XRES_MIN
;
509 vgdev
->ddev
->mode_config
.min_height
= YRES_MIN
;
510 vgdev
->ddev
->mode_config
.max_width
= XRES_MAX
;
511 vgdev
->ddev
->mode_config
.max_height
= YRES_MAX
;
513 for (i
= 0 ; i
< vgdev
->num_scanouts
; ++i
)
514 vgdev_output_init(vgdev
, i
);
516 drm_mode_config_reset(vgdev
->ddev
);
520 void virtio_gpu_modeset_fini(struct virtio_gpu_device
*vgdev
)
522 virtio_gpu_fbdev_fini(vgdev
);
523 drm_mode_config_cleanup(vgdev
->ddev
);