2 * Copyright 2013 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Authors: Dave Airlie
27 #include "linux/crc32.h"
30 #include "qxl_object.h"
31 #include "drm_crtc_helper.h"
33 static bool qxl_head_enabled(struct qxl_head
*head
)
35 return head
->width
&& head
->height
;
38 void qxl_alloc_client_monitors_config(struct qxl_device
*qdev
, unsigned count
)
40 if (qdev
->client_monitors_config
&&
41 count
> qdev
->client_monitors_config
->count
) {
42 kfree(qdev
->client_monitors_config
);
43 qdev
->client_monitors_config
= NULL
;
45 if (!qdev
->client_monitors_config
) {
46 qdev
->client_monitors_config
= kzalloc(
47 sizeof(struct qxl_monitors_config
) +
48 sizeof(struct qxl_head
) * count
, GFP_KERNEL
);
49 if (!qdev
->client_monitors_config
) {
51 "%s: allocation failure for %u heads\n",
56 qdev
->client_monitors_config
->count
= count
;
59 static int qxl_display_copy_rom_client_monitors_config(struct qxl_device
*qdev
)
65 num_monitors
= qdev
->rom
->client_monitors_config
.count
;
66 crc
= crc32(0, (const uint8_t *)&qdev
->rom
->client_monitors_config
,
67 sizeof(qdev
->rom
->client_monitors_config
));
68 if (crc
!= qdev
->rom
->client_monitors_config_crc
) {
69 qxl_io_log(qdev
, "crc mismatch: have %X (%d) != %X\n", crc
,
70 sizeof(qdev
->rom
->client_monitors_config
),
71 qdev
->rom
->client_monitors_config_crc
);
74 if (num_monitors
> qdev
->monitors_config
->max_allowed
) {
75 DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n",
76 qdev
->monitors_config
->max_allowed
, num_monitors
);
77 num_monitors
= qdev
->monitors_config
->max_allowed
;
79 num_monitors
= qdev
->rom
->client_monitors_config
.count
;
81 qxl_alloc_client_monitors_config(qdev
, num_monitors
);
82 /* we copy max from the client but it isn't used */
83 qdev
->client_monitors_config
->max_allowed
=
84 qdev
->monitors_config
->max_allowed
;
85 for (i
= 0 ; i
< qdev
->client_monitors_config
->count
; ++i
) {
86 struct qxl_urect
*c_rect
=
87 &qdev
->rom
->client_monitors_config
.heads
[i
];
88 struct qxl_head
*client_head
=
89 &qdev
->client_monitors_config
->heads
[i
];
90 client_head
->x
= c_rect
->left
;
91 client_head
->y
= c_rect
->top
;
92 client_head
->width
= c_rect
->right
- c_rect
->left
;
93 client_head
->height
= c_rect
->bottom
- c_rect
->top
;
94 client_head
->surface_id
= 0;
96 client_head
->flags
= 0;
97 DRM_DEBUG_KMS("read %dx%d+%d+%d\n", client_head
->width
, client_head
->height
,
98 client_head
->x
, client_head
->y
);
103 void qxl_display_read_client_monitors_config(struct qxl_device
*qdev
)
106 while (qxl_display_copy_rom_client_monitors_config(qdev
)) {
107 qxl_io_log(qdev
, "failed crc check for client_monitors_config,"
110 drm_helper_hpd_irq_event(qdev
->ddev
);
113 static int qxl_add_monitors_config_modes(struct drm_connector
*connector
)
115 struct drm_device
*dev
= connector
->dev
;
116 struct qxl_device
*qdev
= dev
->dev_private
;
117 struct qxl_output
*output
= drm_connector_to_qxl_output(connector
);
118 int h
= output
->index
;
119 struct drm_display_mode
*mode
= NULL
;
120 struct qxl_head
*head
;
122 if (!qdev
->client_monitors_config
)
124 head
= &qdev
->client_monitors_config
->heads
[h
];
126 mode
= drm_cvt_mode(dev
, head
->width
, head
->height
, 60, false, false,
128 mode
->type
|= DRM_MODE_TYPE_PREFERRED
;
129 drm_mode_probed_add(connector
, mode
);
133 static int qxl_add_common_modes(struct drm_connector
*connector
)
135 struct drm_device
*dev
= connector
->dev
;
136 struct drm_display_mode
*mode
= NULL
;
161 for (i
= 0; i
< ARRAY_SIZE(common_modes
); i
++) {
162 if (common_modes
[i
].w
< 320 || common_modes
[i
].h
< 200)
165 mode
= drm_cvt_mode(dev
, common_modes
[i
].w
, common_modes
[i
].h
,
166 60, false, false, false);
167 if (common_modes
[i
].w
== 1024 && common_modes
[i
].h
== 768)
168 mode
->type
|= DRM_MODE_TYPE_PREFERRED
;
169 drm_mode_probed_add(connector
, mode
);
174 static void qxl_crtc_destroy(struct drm_crtc
*crtc
)
176 struct qxl_crtc
*qxl_crtc
= to_qxl_crtc(crtc
);
178 drm_crtc_cleanup(crtc
);
183 qxl_hide_cursor(struct qxl_device
*qdev
)
185 struct qxl_release
*release
;
186 struct qxl_cursor_cmd
*cmd
;
189 ret
= qxl_alloc_release_reserved(qdev
, sizeof(*cmd
), QXL_RELEASE_CURSOR_CMD
,
194 ret
= qxl_release_reserve_list(release
, true);
196 qxl_release_free(qdev
, release
);
200 cmd
= (struct qxl_cursor_cmd
*)qxl_release_map(qdev
, release
);
201 cmd
->type
= QXL_CURSOR_HIDE
;
202 qxl_release_unmap(qdev
, release
, &cmd
->release_info
);
204 qxl_push_cursor_ring_release(qdev
, release
, QXL_CMD_CURSOR
, false);
205 qxl_release_fence_buffer_objects(release
);
209 static int qxl_crtc_cursor_set2(struct drm_crtc
*crtc
,
210 struct drm_file
*file_priv
,
213 uint32_t height
, int32_t hot_x
, int32_t hot_y
)
215 struct drm_device
*dev
= crtc
->dev
;
216 struct qxl_device
*qdev
= dev
->dev_private
;
217 struct qxl_crtc
*qcrtc
= to_qxl_crtc(crtc
);
218 struct drm_gem_object
*obj
;
219 struct qxl_cursor
*cursor
;
220 struct qxl_cursor_cmd
*cmd
;
221 struct qxl_bo
*cursor_bo
, *user_bo
;
222 struct qxl_release
*release
;
228 return qxl_hide_cursor(qdev
);
230 obj
= drm_gem_object_lookup(crtc
->dev
, file_priv
, handle
);
232 DRM_ERROR("cannot find cursor object\n");
236 user_bo
= gem_to_qxl_bo(obj
);
238 ret
= qxl_bo_reserve(user_bo
, false);
242 ret
= qxl_bo_pin(user_bo
, QXL_GEM_DOMAIN_CPU
, NULL
);
243 qxl_bo_unreserve(user_bo
);
247 ret
= qxl_bo_kmap(user_bo
, &user_ptr
);
251 ret
= qxl_alloc_release_reserved(qdev
, sizeof(*cmd
),
252 QXL_RELEASE_CURSOR_CMD
,
257 ret
= qxl_alloc_bo_reserved(qdev
, release
, sizeof(struct qxl_cursor
) + size
,
260 goto out_free_release
;
262 ret
= qxl_release_reserve_list(release
, false);
266 ret
= qxl_bo_kmap(cursor_bo
, (void **)&cursor
);
270 cursor
->header
.unique
= 0;
271 cursor
->header
.type
= SPICE_CURSOR_TYPE_ALPHA
;
272 cursor
->header
.width
= 64;
273 cursor
->header
.height
= 64;
274 cursor
->header
.hot_spot_x
= hot_x
;
275 cursor
->header
.hot_spot_y
= hot_y
;
276 cursor
->data_size
= size
;
277 cursor
->chunk
.next_chunk
= 0;
278 cursor
->chunk
.prev_chunk
= 0;
279 cursor
->chunk
.data_size
= size
;
281 memcpy(cursor
->chunk
.data
, user_ptr
, size
);
283 qxl_bo_kunmap(cursor_bo
);
285 qxl_bo_kunmap(user_bo
);
287 cmd
= (struct qxl_cursor_cmd
*)qxl_release_map(qdev
, release
);
288 cmd
->type
= QXL_CURSOR_SET
;
289 cmd
->u
.set
.position
.x
= qcrtc
->cur_x
;
290 cmd
->u
.set
.position
.y
= qcrtc
->cur_y
;
292 cmd
->u
.set
.shape
= qxl_bo_physical_address(qdev
, cursor_bo
, 0);
294 cmd
->u
.set
.visible
= 1;
295 qxl_release_unmap(qdev
, release
, &cmd
->release_info
);
297 qxl_push_cursor_ring_release(qdev
, release
, QXL_CMD_CURSOR
, false);
298 qxl_release_fence_buffer_objects(release
);
300 /* finish with the userspace bo */
301 ret
= qxl_bo_reserve(user_bo
, false);
303 qxl_bo_unpin(user_bo
);
304 qxl_bo_unreserve(user_bo
);
306 drm_gem_object_unreference_unlocked(obj
);
308 qxl_bo_unref(&cursor_bo
);
313 qxl_release_backoff_reserve_list(release
);
315 qxl_bo_unref(&cursor_bo
);
317 qxl_release_free(qdev
, release
);
319 qxl_bo_kunmap(user_bo
);
321 qxl_bo_unpin(user_bo
);
323 drm_gem_object_unreference_unlocked(obj
);
327 static int qxl_crtc_cursor_move(struct drm_crtc
*crtc
,
330 struct drm_device
*dev
= crtc
->dev
;
331 struct qxl_device
*qdev
= dev
->dev_private
;
332 struct qxl_crtc
*qcrtc
= to_qxl_crtc(crtc
);
333 struct qxl_release
*release
;
334 struct qxl_cursor_cmd
*cmd
;
337 ret
= qxl_alloc_release_reserved(qdev
, sizeof(*cmd
), QXL_RELEASE_CURSOR_CMD
,
342 ret
= qxl_release_reserve_list(release
, true);
344 qxl_release_free(qdev
, release
);
351 cmd
= (struct qxl_cursor_cmd
*)qxl_release_map(qdev
, release
);
352 cmd
->type
= QXL_CURSOR_MOVE
;
353 cmd
->u
.position
.x
= qcrtc
->cur_x
;
354 cmd
->u
.position
.y
= qcrtc
->cur_y
;
355 qxl_release_unmap(qdev
, release
, &cmd
->release_info
);
357 qxl_push_cursor_ring_release(qdev
, release
, QXL_CMD_CURSOR
, false);
358 qxl_release_fence_buffer_objects(release
);
364 static const struct drm_crtc_funcs qxl_crtc_funcs
= {
365 .cursor_set2
= qxl_crtc_cursor_set2
,
366 .cursor_move
= qxl_crtc_cursor_move
,
367 .set_config
= drm_crtc_helper_set_config
,
368 .destroy
= qxl_crtc_destroy
,
371 static void qxl_user_framebuffer_destroy(struct drm_framebuffer
*fb
)
373 struct qxl_framebuffer
*qxl_fb
= to_qxl_framebuffer(fb
);
376 drm_gem_object_unreference_unlocked(qxl_fb
->obj
);
377 drm_framebuffer_cleanup(fb
);
381 static int qxl_framebuffer_surface_dirty(struct drm_framebuffer
*fb
,
382 struct drm_file
*file_priv
,
383 unsigned flags
, unsigned color
,
384 struct drm_clip_rect
*clips
,
387 /* TODO: vmwgfx where this was cribbed from had locking. Why? */
388 struct qxl_framebuffer
*qxl_fb
= to_qxl_framebuffer(fb
);
389 struct qxl_device
*qdev
= qxl_fb
->base
.dev
->dev_private
;
390 struct drm_clip_rect norect
;
394 qobj
= gem_to_qxl_bo(qxl_fb
->obj
);
395 /* if we aren't primary surface ignore this */
396 if (!qobj
->is_primary
)
402 norect
.x1
= norect
.y1
= 0;
403 norect
.x2
= fb
->width
;
404 norect
.y2
= fb
->height
;
405 } else if (flags
& DRM_MODE_FB_DIRTY_ANNOTATE_COPY
) {
407 inc
= 2; /* skip source rects */
410 qxl_draw_dirty_fb(qdev
, qxl_fb
, qobj
, flags
, color
,
411 clips
, num_clips
, inc
);
415 static const struct drm_framebuffer_funcs qxl_fb_funcs
= {
416 .destroy
= qxl_user_framebuffer_destroy
,
417 .dirty
= qxl_framebuffer_surface_dirty
,
419 * .create_handle = qxl_user_framebuffer_create_handle, */
423 qxl_framebuffer_init(struct drm_device
*dev
,
424 struct qxl_framebuffer
*qfb
,
425 struct drm_mode_fb_cmd2
*mode_cmd
,
426 struct drm_gem_object
*obj
)
431 ret
= drm_framebuffer_init(dev
, &qfb
->base
, &qxl_fb_funcs
);
436 drm_helper_mode_fill_fb_struct(&qfb
->base
, mode_cmd
);
440 static void qxl_crtc_dpms(struct drm_crtc
*crtc
, int mode
)
444 static bool qxl_crtc_mode_fixup(struct drm_crtc
*crtc
,
445 const struct drm_display_mode
*mode
,
446 struct drm_display_mode
*adjusted_mode
)
448 struct drm_device
*dev
= crtc
->dev
;
449 struct qxl_device
*qdev
= dev
->dev_private
;
451 qxl_io_log(qdev
, "%s: (%d,%d) => (%d,%d)\n",
453 mode
->hdisplay
, mode
->vdisplay
,
454 adjusted_mode
->hdisplay
,
455 adjusted_mode
->vdisplay
);
460 qxl_send_monitors_config(struct qxl_device
*qdev
)
464 BUG_ON(!qdev
->ram_header
->monitors_config
);
466 if (qdev
->monitors_config
->count
== 0) {
467 qxl_io_log(qdev
, "%s: 0 monitors??\n", __func__
);
470 for (i
= 0 ; i
< qdev
->monitors_config
->count
; ++i
) {
471 struct qxl_head
*head
= &qdev
->monitors_config
->heads
[i
];
473 if (head
->y
> 8192 || head
->x
> 8192 ||
474 head
->width
> 8192 || head
->height
> 8192) {
475 DRM_ERROR("head %d wrong: %dx%d+%d+%d\n",
476 i
, head
->width
, head
->height
,
481 qxl_io_monitors_config(qdev
);
484 static void qxl_monitors_config_set(struct qxl_device
*qdev
,
486 unsigned x
, unsigned y
,
487 unsigned width
, unsigned height
,
490 DRM_DEBUG_KMS("%d:%dx%d+%d+%d\n", index
, width
, height
, x
, y
);
491 qdev
->monitors_config
->heads
[index
].x
= x
;
492 qdev
->monitors_config
->heads
[index
].y
= y
;
493 qdev
->monitors_config
->heads
[index
].width
= width
;
494 qdev
->monitors_config
->heads
[index
].height
= height
;
495 qdev
->monitors_config
->heads
[index
].surface_id
= surf_id
;
499 static int qxl_crtc_mode_set(struct drm_crtc
*crtc
,
500 struct drm_display_mode
*mode
,
501 struct drm_display_mode
*adjusted_mode
,
503 struct drm_framebuffer
*old_fb
)
505 struct drm_device
*dev
= crtc
->dev
;
506 struct qxl_device
*qdev
= dev
->dev_private
;
507 struct qxl_mode
*m
= (void *)mode
->private;
508 struct qxl_framebuffer
*qfb
;
509 struct qxl_bo
*bo
, *old_bo
= NULL
;
510 struct qxl_crtc
*qcrtc
= to_qxl_crtc(crtc
);
511 uint32_t width
, height
, base_offset
;
512 bool recreate_primary
= false;
516 DRM_DEBUG_KMS("No FB bound\n");
521 qfb
= to_qxl_framebuffer(old_fb
);
522 old_bo
= gem_to_qxl_bo(qfb
->obj
);
524 qfb
= to_qxl_framebuffer(crtc
->fb
);
525 bo
= gem_to_qxl_bo(qfb
->obj
);
527 /* and do we care? */
528 DRM_DEBUG("%dx%d: not a native mode\n", x
, y
);
530 DRM_DEBUG("%dx%d: qxl id %d\n",
531 mode
->hdisplay
, mode
->vdisplay
, m
->id
);
532 DRM_DEBUG("+%d+%d (%d,%d) => (%d,%d)\n",
534 mode
->hdisplay
, mode
->vdisplay
,
535 adjusted_mode
->hdisplay
,
536 adjusted_mode
->vdisplay
);
538 if (qcrtc
->index
== 0)
539 recreate_primary
= true;
541 width
= mode
->hdisplay
;
542 height
= mode
->vdisplay
;
545 ret
= qxl_bo_reserve(bo
, false);
548 ret
= qxl_bo_pin(bo
, bo
->type
, NULL
);
550 qxl_bo_unreserve(bo
);
553 qxl_bo_unreserve(bo
);
554 if (recreate_primary
) {
555 qxl_io_destroy_primary(qdev
);
557 "recreate primary: %dx%d (was %dx%d,%d,%d)\n",
558 width
, height
, bo
->surf
.width
,
559 bo
->surf
.height
, bo
->surf
.stride
, bo
->surf
.format
);
560 qxl_io_create_primary(qdev
, base_offset
, bo
);
561 bo
->is_primary
= true;
564 surf_id
= bo
->surface_id
;
567 if (old_bo
&& old_bo
!= bo
) {
568 old_bo
->is_primary
= false;
569 ret
= qxl_bo_reserve(old_bo
, false);
570 qxl_bo_unpin(old_bo
);
571 qxl_bo_unreserve(old_bo
);
574 qxl_monitors_config_set(qdev
, qcrtc
->index
, x
, y
,
576 mode
->vdisplay
, surf_id
);
580 static void qxl_crtc_prepare(struct drm_crtc
*crtc
)
582 DRM_DEBUG("current: %dx%d+%d+%d (%d).\n",
583 crtc
->mode
.hdisplay
, crtc
->mode
.vdisplay
,
584 crtc
->x
, crtc
->y
, crtc
->enabled
);
587 static void qxl_crtc_commit(struct drm_crtc
*crtc
)
592 static void qxl_crtc_disable(struct drm_crtc
*crtc
)
594 struct qxl_crtc
*qcrtc
= to_qxl_crtc(crtc
);
595 struct drm_device
*dev
= crtc
->dev
;
596 struct qxl_device
*qdev
= dev
->dev_private
;
598 struct qxl_framebuffer
*qfb
= to_qxl_framebuffer(crtc
->fb
);
599 struct qxl_bo
*bo
= gem_to_qxl_bo(qfb
->obj
);
601 ret
= qxl_bo_reserve(bo
, false);
603 qxl_bo_unreserve(bo
);
607 qxl_monitors_config_set(qdev
, qcrtc
->index
, 0, 0, 0, 0, 0);
609 qxl_send_monitors_config(qdev
);
612 static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs
= {
613 .dpms
= qxl_crtc_dpms
,
614 .disable
= qxl_crtc_disable
,
615 .mode_fixup
= qxl_crtc_mode_fixup
,
616 .mode_set
= qxl_crtc_mode_set
,
617 .prepare
= qxl_crtc_prepare
,
618 .commit
= qxl_crtc_commit
,
621 static int qdev_crtc_init(struct drm_device
*dev
, int crtc_id
)
623 struct qxl_crtc
*qxl_crtc
;
625 qxl_crtc
= kzalloc(sizeof(struct qxl_crtc
), GFP_KERNEL
);
629 drm_crtc_init(dev
, &qxl_crtc
->base
, &qxl_crtc_funcs
);
630 qxl_crtc
->index
= crtc_id
;
631 drm_mode_crtc_set_gamma_size(&qxl_crtc
->base
, 256);
632 drm_crtc_helper_add(&qxl_crtc
->base
, &qxl_crtc_helper_funcs
);
636 static void qxl_enc_dpms(struct drm_encoder
*encoder
, int mode
)
641 static bool qxl_enc_mode_fixup(struct drm_encoder
*encoder
,
642 const struct drm_display_mode
*mode
,
643 struct drm_display_mode
*adjusted_mode
)
649 static void qxl_enc_prepare(struct drm_encoder
*encoder
)
654 static void qxl_write_monitors_config_for_encoder(struct qxl_device
*qdev
,
655 struct drm_encoder
*encoder
)
658 struct qxl_output
*output
= drm_encoder_to_qxl_output(encoder
);
659 struct qxl_head
*head
;
660 struct drm_display_mode
*mode
;
663 /* TODO: ugly, do better */
665 if (!qdev
->monitors_config
||
666 qdev
->monitors_config
->max_allowed
<= i
) {
668 "head number too large or missing monitors config: %p, %d",
669 qdev
->monitors_config
,
670 qdev
->monitors_config
?
671 qdev
->monitors_config
->max_allowed
: -1);
674 if (!encoder
->crtc
) {
675 DRM_ERROR("missing crtc on encoder %p\n", encoder
);
679 DRM_DEBUG("missing for multiple monitors: no head holes\n");
680 head
= &qdev
->monitors_config
->heads
[i
];
682 if (encoder
->crtc
->enabled
) {
683 mode
= &encoder
->crtc
->mode
;
684 head
->width
= mode
->hdisplay
;
685 head
->height
= mode
->vdisplay
;
686 head
->x
= encoder
->crtc
->x
;
687 head
->y
= encoder
->crtc
->y
;
688 if (qdev
->monitors_config
->count
< i
+ 1)
689 qdev
->monitors_config
->count
= i
+ 1;
696 DRM_DEBUG_KMS("setting head %d to +%d+%d %dx%d out of %d\n",
697 i
, head
->x
, head
->y
, head
->width
, head
->height
, qdev
->monitors_config
->count
);
699 /* TODO - somewhere else to call this for multiple monitors
700 * (config_commit?) */
701 qxl_send_monitors_config(qdev
);
704 static void qxl_enc_commit(struct drm_encoder
*encoder
)
706 struct qxl_device
*qdev
= encoder
->dev
->dev_private
;
708 qxl_write_monitors_config_for_encoder(qdev
, encoder
);
712 static void qxl_enc_mode_set(struct drm_encoder
*encoder
,
713 struct drm_display_mode
*mode
,
714 struct drm_display_mode
*adjusted_mode
)
719 static int qxl_conn_get_modes(struct drm_connector
*connector
)
722 struct qxl_device
*qdev
= connector
->dev
->dev_private
;
724 DRM_DEBUG_KMS("monitors_config=%p\n", qdev
->monitors_config
);
725 /* TODO: what should we do here? only show the configured modes for the
726 * device, or allow the full list, or both? */
727 if (qdev
->monitors_config
&& qdev
->monitors_config
->count
) {
728 ret
= qxl_add_monitors_config_modes(connector
);
732 ret
+= qxl_add_common_modes(connector
);
736 static int qxl_conn_mode_valid(struct drm_connector
*connector
,
737 struct drm_display_mode
*mode
)
739 /* TODO: is this called for user defined modes? (xrandr --add-mode)
740 * TODO: check that the mode fits in the framebuffer */
741 DRM_DEBUG("%s: %dx%d status=%d\n", mode
->name
, mode
->hdisplay
,
742 mode
->vdisplay
, mode
->status
);
746 static struct drm_encoder
*qxl_best_encoder(struct drm_connector
*connector
)
748 struct qxl_output
*qxl_output
=
749 drm_connector_to_qxl_output(connector
);
752 return &qxl_output
->enc
;
756 static const struct drm_encoder_helper_funcs qxl_enc_helper_funcs
= {
757 .dpms
= qxl_enc_dpms
,
758 .mode_fixup
= qxl_enc_mode_fixup
,
759 .prepare
= qxl_enc_prepare
,
760 .mode_set
= qxl_enc_mode_set
,
761 .commit
= qxl_enc_commit
,
764 static const struct drm_connector_helper_funcs qxl_connector_helper_funcs
= {
765 .get_modes
= qxl_conn_get_modes
,
766 .mode_valid
= qxl_conn_mode_valid
,
767 .best_encoder
= qxl_best_encoder
,
770 static void qxl_conn_save(struct drm_connector
*connector
)
775 static void qxl_conn_restore(struct drm_connector
*connector
)
780 static enum drm_connector_status
qxl_conn_detect(
781 struct drm_connector
*connector
,
784 struct qxl_output
*output
=
785 drm_connector_to_qxl_output(connector
);
786 struct drm_device
*ddev
= connector
->dev
;
787 struct qxl_device
*qdev
= ddev
->dev_private
;
790 /* The first monitor is always connected */
791 connected
= (output
->index
== 0) ||
792 (qdev
->client_monitors_config
&&
793 qdev
->client_monitors_config
->count
> output
->index
&&
794 qxl_head_enabled(&qdev
->client_monitors_config
->heads
[output
->index
]));
797 return connected
? connector_status_connected
798 : connector_status_disconnected
;
801 static int qxl_conn_set_property(struct drm_connector
*connector
,
802 struct drm_property
*property
,
809 static void qxl_conn_destroy(struct drm_connector
*connector
)
811 struct qxl_output
*qxl_output
=
812 drm_connector_to_qxl_output(connector
);
814 drm_sysfs_connector_remove(connector
);
815 drm_connector_cleanup(connector
);
819 static const struct drm_connector_funcs qxl_connector_funcs
= {
820 .dpms
= drm_helper_connector_dpms
,
821 .save
= qxl_conn_save
,
822 .restore
= qxl_conn_restore
,
823 .detect
= qxl_conn_detect
,
824 .fill_modes
= drm_helper_probe_single_connector_modes
,
825 .set_property
= qxl_conn_set_property
,
826 .destroy
= qxl_conn_destroy
,
829 static void qxl_enc_destroy(struct drm_encoder
*encoder
)
831 drm_encoder_cleanup(encoder
);
834 static const struct drm_encoder_funcs qxl_enc_funcs
= {
835 .destroy
= qxl_enc_destroy
,
838 static int qdev_output_init(struct drm_device
*dev
, int num_output
)
840 struct qxl_output
*qxl_output
;
841 struct drm_connector
*connector
;
842 struct drm_encoder
*encoder
;
844 qxl_output
= kzalloc(sizeof(struct qxl_output
), GFP_KERNEL
);
848 qxl_output
->index
= num_output
;
850 connector
= &qxl_output
->base
;
851 encoder
= &qxl_output
->enc
;
852 drm_connector_init(dev
, &qxl_output
->base
,
853 &qxl_connector_funcs
, DRM_MODE_CONNECTOR_VIRTUAL
);
855 drm_encoder_init(dev
, &qxl_output
->enc
, &qxl_enc_funcs
,
856 DRM_MODE_ENCODER_VIRTUAL
);
858 /* we get HPD via client monitors config */
859 connector
->polled
= DRM_CONNECTOR_POLL_HPD
;
860 encoder
->possible_crtcs
= 1 << num_output
;
861 drm_mode_connector_attach_encoder(&qxl_output
->base
,
863 drm_encoder_helper_add(encoder
, &qxl_enc_helper_funcs
);
864 drm_connector_helper_add(connector
, &qxl_connector_helper_funcs
);
866 drm_sysfs_connector_add(connector
);
870 static struct drm_framebuffer
*
871 qxl_user_framebuffer_create(struct drm_device
*dev
,
872 struct drm_file
*file_priv
,
873 struct drm_mode_fb_cmd2
*mode_cmd
)
875 struct drm_gem_object
*obj
;
876 struct qxl_framebuffer
*qxl_fb
;
879 obj
= drm_gem_object_lookup(dev
, file_priv
, mode_cmd
->handles
[0]);
881 qxl_fb
= kzalloc(sizeof(*qxl_fb
), GFP_KERNEL
);
885 ret
= qxl_framebuffer_init(dev
, qxl_fb
, mode_cmd
, obj
);
888 drm_gem_object_unreference_unlocked(obj
);
892 return &qxl_fb
->base
;
895 static const struct drm_mode_config_funcs qxl_mode_funcs
= {
896 .fb_create
= qxl_user_framebuffer_create
,
899 int qxl_create_monitors_object(struct qxl_device
*qdev
)
902 struct drm_gem_object
*gobj
;
903 int max_allowed
= qxl_num_crtc
;
904 int monitors_config_size
= sizeof(struct qxl_monitors_config
) +
905 max_allowed
* sizeof(struct qxl_head
);
907 ret
= qxl_gem_object_create(qdev
, monitors_config_size
, 0,
909 false, false, NULL
, &gobj
);
911 DRM_ERROR("%s: failed to create gem ret=%d\n", __func__
, ret
);
914 qdev
->monitors_config_bo
= gem_to_qxl_bo(gobj
);
916 ret
= qxl_bo_reserve(qdev
->monitors_config_bo
, false);
920 ret
= qxl_bo_pin(qdev
->monitors_config_bo
, QXL_GEM_DOMAIN_VRAM
, NULL
);
922 qxl_bo_unreserve(qdev
->monitors_config_bo
);
926 qxl_bo_unreserve(qdev
->monitors_config_bo
);
928 qxl_bo_kmap(qdev
->monitors_config_bo
, NULL
);
930 qdev
->monitors_config
= qdev
->monitors_config_bo
->kptr
;
931 qdev
->ram_header
->monitors_config
=
932 qxl_bo_physical_address(qdev
, qdev
->monitors_config_bo
, 0);
934 memset(qdev
->monitors_config
, 0, monitors_config_size
);
935 qdev
->monitors_config
->max_allowed
= max_allowed
;
939 int qxl_destroy_monitors_object(struct qxl_device
*qdev
)
943 qdev
->monitors_config
= NULL
;
944 qdev
->ram_header
->monitors_config
= 0;
946 qxl_bo_kunmap(qdev
->monitors_config_bo
);
947 ret
= qxl_bo_reserve(qdev
->monitors_config_bo
, false);
951 qxl_bo_unpin(qdev
->monitors_config_bo
);
952 qxl_bo_unreserve(qdev
->monitors_config_bo
);
954 qxl_bo_unref(&qdev
->monitors_config_bo
);
958 int qxl_modeset_init(struct qxl_device
*qdev
)
963 drm_mode_config_init(qdev
->ddev
);
965 ret
= qxl_create_monitors_object(qdev
);
969 qdev
->ddev
->mode_config
.funcs
= (void *)&qxl_mode_funcs
;
971 /* modes will be validated against the framebuffer size */
972 qdev
->ddev
->mode_config
.min_width
= 320;
973 qdev
->ddev
->mode_config
.min_height
= 200;
974 qdev
->ddev
->mode_config
.max_width
= 8192;
975 qdev
->ddev
->mode_config
.max_height
= 8192;
977 qdev
->ddev
->mode_config
.fb_base
= qdev
->vram_base
;
978 for (i
= 0 ; i
< qxl_num_crtc
; ++i
) {
979 qdev_crtc_init(qdev
->ddev
, i
);
980 qdev_output_init(qdev
->ddev
, i
);
983 qdev
->mode_info
.mode_config_initialized
= true;
985 /* primary surface must be created by this point, to allow
986 * issuing command queue commands and having them read by
988 qxl_fbdev_init(qdev
);
992 void qxl_modeset_fini(struct qxl_device
*qdev
)
994 qxl_fbdev_fini(qdev
);
996 qxl_destroy_monitors_object(qdev
);
997 if (qdev
->mode_info
.mode_config_initialized
) {
998 drm_mode_config_cleanup(qdev
->ddev
);
999 qdev
->mode_info
.mode_config_initialized
= false;