1 /* 2 * Copyright 2013 Red Hat Inc. 3 * 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: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 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. 21 * 22 * Authors: Dave Airlie 23 * Alon Levy 24 */ 25 26 27 #include "linux/crc32.h" 28 29 #include "qxl_drv.h" 30 #include "qxl_object.h" 31 #include "drm_crtc_helper.h" 32 33 static void qxl_crtc_set_to_mode(struct qxl_device *qdev, 34 struct drm_connector *connector, 35 struct qxl_head *head) 36 { 37 struct drm_device *dev = connector->dev; 38 struct drm_display_mode *mode, *t; 39 int width = head->width; 40 int height = head->height; 41 42 if (width < 320 || height < 240) { 43 qxl_io_log(qdev, "%s: bad head: %dx%d", width, height); 44 width = 1024; 45 height = 768; 46 } 47 if (width * height * 4 > 16*1024*1024) { 48 width = 1024; 49 height = 768; 50 } 51 /* TODO: go over regular modes and removed preferred? */ 52 list_for_each_entry_safe(mode, t, &connector->probed_modes, head) 53 drm_mode_remove(connector, mode); 54 mode = drm_cvt_mode(dev, width, height, 60, false, false, false); 55 mode->type |= DRM_MODE_TYPE_PREFERRED; 56 mode->status = MODE_OK; 57 drm_mode_probed_add(connector, mode); 58 qxl_io_log(qdev, "%s: %d x %d\n", __func__, width, height); 59 } 60 61 void qxl_crtc_set_from_monitors_config(struct qxl_device *qdev) 62 { 63 struct drm_connector *connector; 64 int i; 65 struct drm_device *dev = qdev->ddev; 66 67 i = 0; 68 qxl_io_log(qdev, "%s: %d, %d\n", __func__, 69 dev->mode_config.num_connector, 70 qdev->monitors_config->count); 71 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 72 if (i > qdev->monitors_config->count) { 73 /* crtc will be reported as disabled */ 74 continue; 75 } 76 qxl_crtc_set_to_mode(qdev, connector, 77 &qdev->monitors_config->heads[i]); 78 ++i; 79 } 80 } 81 82 void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned count) 83 { 84 if (qdev->client_monitors_config && 85 count > qdev->client_monitors_config->count) { 86 kfree(qdev->client_monitors_config); 87 qdev->client_monitors_config = NULL; 88 } 89 if (!qdev->client_monitors_config) { 90 qdev->client_monitors_config = kzalloc( 91 sizeof(struct qxl_monitors_config) + 92 sizeof(struct qxl_head) * count, GFP_KERNEL); 93 if (!qdev->client_monitors_config) { 94 qxl_io_log(qdev, 95 "%s: allocation failure for %u heads\n", 96 __func__, count); 97 return; 98 } 99 } 100 qdev->client_monitors_config->count = count; 101 } 102 103 static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) 104 { 105 int i; 106 int num_monitors; 107 uint32_t crc; 108 109 BUG_ON(!qdev->monitors_config); 110 num_monitors = qdev->rom->client_monitors_config.count; 111 crc = crc32(0, (const uint8_t *)&qdev->rom->client_monitors_config, 112 sizeof(qdev->rom->client_monitors_config)); 113 if (crc != qdev->rom->client_monitors_config_crc) { 114 qxl_io_log(qdev, "crc mismatch: have %X (%d) != %X\n", crc, 115 sizeof(qdev->rom->client_monitors_config), 116 qdev->rom->client_monitors_config_crc); 117 return 1; 118 } 119 if (num_monitors > qdev->monitors_config->max_allowed) { 120 DRM_INFO("client monitors list will be truncated: %d < %d\n", 121 qdev->monitors_config->max_allowed, num_monitors); 122 num_monitors = qdev->monitors_config->max_allowed; 123 } else { 124 num_monitors = qdev->rom->client_monitors_config.count; 125 } 126 qxl_alloc_client_monitors_config(qdev, num_monitors); 127 /* we copy max from the client but it isn't used */ 128 qdev->client_monitors_config->max_allowed = 129 qdev->monitors_config->max_allowed; 130 for (i = 0 ; i < qdev->client_monitors_config->count ; ++i) { 131 struct qxl_urect *c_rect = 132 &qdev->rom->client_monitors_config.heads[i]; 133 struct qxl_head *client_head = 134 &qdev->client_monitors_config->heads[i]; 135 struct qxl_head *head = &qdev->monitors_config->heads[i]; 136 client_head->x = head->x = c_rect->left; 137 client_head->y = head->y = c_rect->top; 138 client_head->width = head->width = 139 c_rect->right - c_rect->left; 140 client_head->height = head->height = 141 c_rect->bottom - c_rect->top; 142 client_head->surface_id = head->surface_id = 0; 143 client_head->id = head->id = i; 144 client_head->flags = head->flags = 0; 145 QXL_DEBUG(qdev, "read %dx%d+%d+%d\n", head->width, head->height, 146 head->x, head->y); 147 } 148 return 0; 149 } 150 151 void qxl_display_read_client_monitors_config(struct qxl_device *qdev) 152 { 153 154 while (qxl_display_copy_rom_client_monitors_config(qdev)) { 155 qxl_io_log(qdev, "failed crc check for client_monitors_config," 156 " retrying\n"); 157 } 158 qxl_crtc_set_from_monitors_config(qdev); 159 /* fire off a uevent and let userspace tell us what to do */ 160 qxl_io_log(qdev, "calling drm_sysfs_hotplug_event\n"); 161 drm_sysfs_hotplug_event(qdev->ddev); 162 } 163 164 static int qxl_add_monitors_config_modes(struct drm_connector *connector) 165 { 166 struct drm_device *dev = connector->dev; 167 struct qxl_device *qdev = dev->dev_private; 168 struct qxl_output *output = drm_connector_to_qxl_output(connector); 169 int h = output->index; 170 struct drm_display_mode *mode = NULL; 171 struct qxl_head *head; 172 173 if (!qdev->monitors_config) 174 return 0; 175 head = &qdev->monitors_config->heads[h]; 176 177 mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false, 178 false); 179 mode->type |= DRM_MODE_TYPE_PREFERRED; 180 drm_mode_probed_add(connector, mode); 181 return 1; 182 } 183 184 static int qxl_add_common_modes(struct drm_connector *connector) 185 { 186 struct drm_device *dev = connector->dev; 187 struct drm_display_mode *mode = NULL; 188 int i; 189 struct mode_size { 190 int w; 191 int h; 192 } common_modes[] = { 193 { 640, 480}, 194 { 720, 480}, 195 { 800, 600}, 196 { 848, 480}, 197 {1024, 768}, 198 {1152, 768}, 199 {1280, 720}, 200 {1280, 800}, 201 {1280, 854}, 202 {1280, 960}, 203 {1280, 1024}, 204 {1440, 900}, 205 {1400, 1050}, 206 {1680, 1050}, 207 {1600, 1200}, 208 {1920, 1080}, 209 {1920, 1200} 210 }; 211 212 for (i = 0; i < ARRAY_SIZE(common_modes); i++) { 213 if (common_modes[i].w < 320 || common_modes[i].h < 200) 214 continue; 215 216 mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 217 60, false, false, false); 218 if (common_modes[i].w == 1024 && common_modes[i].h == 768) 219 mode->type |= DRM_MODE_TYPE_PREFERRED; 220 drm_mode_probed_add(connector, mode); 221 } 222 return i - 1; 223 } 224 225 static void qxl_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 226 u16 *blue, uint32_t start, uint32_t size) 227 { 228 /* TODO */ 229 } 230 231 static void qxl_crtc_destroy(struct drm_crtc *crtc) 232 { 233 struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc); 234 235 drm_crtc_cleanup(crtc); 236 kfree(qxl_crtc); 237 } 238 239 static void 240 qxl_hide_cursor(struct qxl_device *qdev) 241 { 242 struct qxl_release *release; 243 struct qxl_cursor_cmd *cmd; 244 int ret; 245 246 ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD, 247 &release, NULL); 248 249 cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); 250 cmd->type = QXL_CURSOR_HIDE; 251 qxl_release_unmap(qdev, release, &cmd->release_info); 252 253 qxl_fence_releaseable(qdev, release); 254 qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); 255 qxl_release_unreserve(qdev, release); 256 } 257 258 static int qxl_crtc_cursor_set(struct drm_crtc *crtc, 259 struct drm_file *file_priv, 260 uint32_t handle, 261 uint32_t width, 262 uint32_t height) 263 { 264 struct drm_device *dev = crtc->dev; 265 struct qxl_device *qdev = dev->dev_private; 266 struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); 267 struct drm_gem_object *obj; 268 struct qxl_cursor *cursor; 269 struct qxl_cursor_cmd *cmd; 270 struct qxl_bo *cursor_bo, *user_bo; 271 struct qxl_release *release; 272 void *user_ptr; 273 274 int size = 64*64*4; 275 int ret = 0; 276 if (!handle) { 277 qxl_hide_cursor(qdev); 278 return 0; 279 } 280 281 obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); 282 if (!obj) { 283 DRM_ERROR("cannot find cursor object\n"); 284 return -ENOENT; 285 } 286 287 user_bo = gem_to_qxl_bo(obj); 288 289 ret = qxl_bo_reserve(user_bo, false); 290 if (ret) 291 goto out_unref; 292 293 ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL); 294 if (ret) 295 goto out_unreserve; 296 297 ret = qxl_bo_kmap(user_bo, &user_ptr); 298 if (ret) 299 goto out_unpin; 300 301 ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), 302 QXL_RELEASE_CURSOR_CMD, 303 &release, NULL); 304 if (ret) 305 goto out_kunmap; 306 ret = qxl_alloc_bo_reserved(qdev, sizeof(struct qxl_cursor) + size, 307 &cursor_bo); 308 if (ret) 309 goto out_free_release; 310 ret = qxl_bo_kmap(cursor_bo, (void **)&cursor); 311 if (ret) 312 goto out_free_bo; 313 314 cursor->header.unique = 0; 315 cursor->header.type = SPICE_CURSOR_TYPE_ALPHA; 316 cursor->header.width = 64; 317 cursor->header.height = 64; 318 cursor->header.hot_spot_x = 0; 319 cursor->header.hot_spot_y = 0; 320 cursor->data_size = size; 321 cursor->chunk.next_chunk = 0; 322 cursor->chunk.prev_chunk = 0; 323 cursor->chunk.data_size = size; 324 325 memcpy(cursor->chunk.data, user_ptr, size); 326 327 qxl_bo_kunmap(cursor_bo); 328 329 /* finish with the userspace bo */ 330 qxl_bo_kunmap(user_bo); 331 qxl_bo_unpin(user_bo); 332 qxl_bo_unreserve(user_bo); 333 drm_gem_object_unreference_unlocked(obj); 334 335 cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); 336 cmd->type = QXL_CURSOR_SET; 337 cmd->u.set.position.x = qcrtc->cur_x; 338 cmd->u.set.position.y = qcrtc->cur_y; 339 340 cmd->u.set.shape = qxl_bo_physical_address(qdev, cursor_bo, 0); 341 qxl_release_add_res(qdev, release, cursor_bo); 342 343 cmd->u.set.visible = 1; 344 qxl_release_unmap(qdev, release, &cmd->release_info); 345 346 qxl_fence_releaseable(qdev, release); 347 qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); 348 qxl_release_unreserve(qdev, release); 349 350 qxl_bo_unreserve(cursor_bo); 351 qxl_bo_unref(&cursor_bo); 352 353 return ret; 354 out_free_bo: 355 qxl_bo_unref(&cursor_bo); 356 out_free_release: 357 qxl_release_unreserve(qdev, release); 358 qxl_release_free(qdev, release); 359 out_kunmap: 360 qxl_bo_kunmap(user_bo); 361 out_unpin: 362 qxl_bo_unpin(user_bo); 363 out_unreserve: 364 qxl_bo_unreserve(user_bo); 365 out_unref: 366 drm_gem_object_unreference_unlocked(obj); 367 return ret; 368 } 369 370 static int qxl_crtc_cursor_move(struct drm_crtc *crtc, 371 int x, int y) 372 { 373 struct drm_device *dev = crtc->dev; 374 struct qxl_device *qdev = dev->dev_private; 375 struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); 376 struct qxl_release *release; 377 struct qxl_cursor_cmd *cmd; 378 int ret; 379 380 ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD, 381 &release, NULL); 382 383 qcrtc->cur_x = x; 384 qcrtc->cur_y = y; 385 386 cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); 387 cmd->type = QXL_CURSOR_MOVE; 388 cmd->u.position.x = qcrtc->cur_x; 389 cmd->u.position.y = qcrtc->cur_y; 390 qxl_release_unmap(qdev, release, &cmd->release_info); 391 392 qxl_fence_releaseable(qdev, release); 393 qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); 394 qxl_release_unreserve(qdev, release); 395 return 0; 396 } 397 398 399 static const struct drm_crtc_funcs qxl_crtc_funcs = { 400 .cursor_set = qxl_crtc_cursor_set, 401 .cursor_move = qxl_crtc_cursor_move, 402 .gamma_set = qxl_crtc_gamma_set, 403 .set_config = drm_crtc_helper_set_config, 404 .destroy = qxl_crtc_destroy, 405 }; 406 407 static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) 408 { 409 struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb); 410 411 if (qxl_fb->obj) 412 drm_gem_object_unreference_unlocked(qxl_fb->obj); 413 drm_framebuffer_cleanup(fb); 414 kfree(qxl_fb); 415 } 416 417 static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, 418 struct drm_file *file_priv, 419 unsigned flags, unsigned color, 420 struct drm_clip_rect *clips, 421 unsigned num_clips) 422 { 423 /* TODO: vmwgfx where this was cribbed from had locking. Why? */ 424 struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb); 425 struct qxl_device *qdev = qxl_fb->base.dev->dev_private; 426 struct drm_clip_rect norect; 427 struct qxl_bo *qobj; 428 int inc = 1; 429 430 qobj = gem_to_qxl_bo(qxl_fb->obj); 431 /* if we aren't primary surface ignore this */ 432 if (!qobj->is_primary) 433 return 0; 434 435 if (!num_clips) { 436 num_clips = 1; 437 clips = &norect; 438 norect.x1 = norect.y1 = 0; 439 norect.x2 = fb->width; 440 norect.y2 = fb->height; 441 } else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) { 442 num_clips /= 2; 443 inc = 2; /* skip source rects */ 444 } 445 446 qxl_draw_dirty_fb(qdev, qxl_fb, qobj, flags, color, 447 clips, num_clips, inc); 448 return 0; 449 } 450 451 static const struct drm_framebuffer_funcs qxl_fb_funcs = { 452 .destroy = qxl_user_framebuffer_destroy, 453 .dirty = qxl_framebuffer_surface_dirty, 454 /* TODO? 455 * .create_handle = qxl_user_framebuffer_create_handle, */ 456 }; 457 458 int 459 qxl_framebuffer_init(struct drm_device *dev, 460 struct qxl_framebuffer *qfb, 461 struct drm_mode_fb_cmd2 *mode_cmd, 462 struct drm_gem_object *obj) 463 { 464 int ret; 465 466 qfb->obj = obj; 467 ret = drm_framebuffer_init(dev, &qfb->base, &qxl_fb_funcs); 468 if (ret) { 469 qfb->obj = NULL; 470 return ret; 471 } 472 drm_helper_mode_fill_fb_struct(&qfb->base, mode_cmd); 473 return 0; 474 } 475 476 static void qxl_crtc_dpms(struct drm_crtc *crtc, int mode) 477 { 478 } 479 480 static bool qxl_crtc_mode_fixup(struct drm_crtc *crtc, 481 const struct drm_display_mode *mode, 482 struct drm_display_mode *adjusted_mode) 483 { 484 struct drm_device *dev = crtc->dev; 485 struct qxl_device *qdev = dev->dev_private; 486 487 qxl_io_log(qdev, "%s: (%d,%d) => (%d,%d)\n", 488 __func__, 489 mode->hdisplay, mode->vdisplay, 490 adjusted_mode->hdisplay, 491 adjusted_mode->vdisplay); 492 return true; 493 } 494 495 void 496 qxl_send_monitors_config(struct qxl_device *qdev) 497 { 498 int i; 499 500 BUG_ON(!qdev->ram_header->monitors_config); 501 502 if (qdev->monitors_config->count == 0) { 503 qxl_io_log(qdev, "%s: 0 monitors??\n", __func__); 504 return; 505 } 506 for (i = 0 ; i < qdev->monitors_config->count ; ++i) { 507 struct qxl_head *head = &qdev->monitors_config->heads[i]; 508 509 if (head->y > 8192 || head->y < head->x || 510 head->width > 8192 || head->height > 8192) { 511 DRM_ERROR("head %d wrong: %dx%d+%d+%d\n", 512 i, head->width, head->height, 513 head->x, head->y); 514 return; 515 } 516 } 517 qxl_io_monitors_config(qdev); 518 } 519 520 static void qxl_monitors_config_set_single(struct qxl_device *qdev, 521 unsigned x, unsigned y, 522 unsigned width, unsigned height) 523 { 524 DRM_DEBUG("%dx%d+%d+%d\n", width, height, x, y); 525 qdev->monitors_config->count = 1; 526 qdev->monitors_config->heads[0].x = x; 527 qdev->monitors_config->heads[0].y = y; 528 qdev->monitors_config->heads[0].width = width; 529 qdev->monitors_config->heads[0].height = height; 530 } 531 532 static int qxl_crtc_mode_set(struct drm_crtc *crtc, 533 struct drm_display_mode *mode, 534 struct drm_display_mode *adjusted_mode, 535 int x, int y, 536 struct drm_framebuffer *old_fb) 537 { 538 struct drm_device *dev = crtc->dev; 539 struct qxl_device *qdev = dev->dev_private; 540 struct qxl_mode *m = (void *)mode->private; 541 struct qxl_framebuffer *qfb; 542 struct qxl_bo *bo, *old_bo = NULL; 543 uint32_t width, height, base_offset; 544 bool recreate_primary = false; 545 int ret; 546 547 if (!crtc->fb) { 548 DRM_DEBUG_KMS("No FB bound\n"); 549 return 0; 550 } 551 552 if (old_fb) { 553 qfb = to_qxl_framebuffer(old_fb); 554 old_bo = gem_to_qxl_bo(qfb->obj); 555 } 556 qfb = to_qxl_framebuffer(crtc->fb); 557 bo = gem_to_qxl_bo(qfb->obj); 558 if (!m) 559 /* and do we care? */ 560 DRM_DEBUG("%dx%d: not a native mode\n", x, y); 561 else 562 DRM_DEBUG("%dx%d: qxl id %d\n", 563 mode->hdisplay, mode->vdisplay, m->id); 564 DRM_DEBUG("+%d+%d (%d,%d) => (%d,%d)\n", 565 x, y, 566 mode->hdisplay, mode->vdisplay, 567 adjusted_mode->hdisplay, 568 adjusted_mode->vdisplay); 569 570 recreate_primary = true; 571 572 width = mode->hdisplay; 573 height = mode->vdisplay; 574 base_offset = 0; 575 576 ret = qxl_bo_reserve(bo, false); 577 if (ret != 0) 578 return ret; 579 ret = qxl_bo_pin(bo, bo->type, NULL); 580 if (ret != 0) { 581 qxl_bo_unreserve(bo); 582 return -EINVAL; 583 } 584 qxl_bo_unreserve(bo); 585 if (recreate_primary) { 586 qxl_io_destroy_primary(qdev); 587 qxl_io_log(qdev, 588 "recreate primary: %dx%d (was %dx%d,%d,%d)\n", 589 width, height, bo->surf.width, 590 bo->surf.height, bo->surf.stride, bo->surf.format); 591 qxl_io_create_primary(qdev, width, height, base_offset, bo); 592 bo->is_primary = true; 593 } 594 595 if (old_bo && old_bo != bo) { 596 old_bo->is_primary = false; 597 ret = qxl_bo_reserve(old_bo, false); 598 qxl_bo_unpin(old_bo); 599 qxl_bo_unreserve(old_bo); 600 } 601 602 if (qdev->monitors_config->count == 0) { 603 qxl_monitors_config_set_single(qdev, x, y, 604 mode->hdisplay, 605 mode->vdisplay); 606 } 607 return 0; 608 } 609 610 static void qxl_crtc_prepare(struct drm_crtc *crtc) 611 { 612 DRM_DEBUG("current: %dx%d+%d+%d (%d).\n", 613 crtc->mode.hdisplay, crtc->mode.vdisplay, 614 crtc->x, crtc->y, crtc->enabled); 615 } 616 617 static void qxl_crtc_commit(struct drm_crtc *crtc) 618 { 619 DRM_DEBUG("\n"); 620 } 621 622 static void qxl_crtc_load_lut(struct drm_crtc *crtc) 623 { 624 DRM_DEBUG("\n"); 625 } 626 627 static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { 628 .dpms = qxl_crtc_dpms, 629 .mode_fixup = qxl_crtc_mode_fixup, 630 .mode_set = qxl_crtc_mode_set, 631 .prepare = qxl_crtc_prepare, 632 .commit = qxl_crtc_commit, 633 .load_lut = qxl_crtc_load_lut, 634 }; 635 636 static int qdev_crtc_init(struct drm_device *dev, int num_crtc) 637 { 638 struct qxl_crtc *qxl_crtc; 639 640 qxl_crtc = kzalloc(sizeof(struct qxl_crtc), GFP_KERNEL); 641 if (!qxl_crtc) 642 return -ENOMEM; 643 644 drm_crtc_init(dev, &qxl_crtc->base, &qxl_crtc_funcs); 645 646 drm_mode_crtc_set_gamma_size(&qxl_crtc->base, 256); 647 drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs); 648 return 0; 649 } 650 651 static void qxl_enc_dpms(struct drm_encoder *encoder, int mode) 652 { 653 DRM_DEBUG("\n"); 654 } 655 656 static bool qxl_enc_mode_fixup(struct drm_encoder *encoder, 657 const struct drm_display_mode *mode, 658 struct drm_display_mode *adjusted_mode) 659 { 660 DRM_DEBUG("\n"); 661 return true; 662 } 663 664 static void qxl_enc_prepare(struct drm_encoder *encoder) 665 { 666 DRM_DEBUG("\n"); 667 } 668 669 static void qxl_write_monitors_config_for_encoder(struct qxl_device *qdev, 670 struct drm_encoder *encoder) 671 { 672 int i; 673 struct qxl_head *head; 674 struct drm_display_mode *mode; 675 676 BUG_ON(!encoder); 677 /* TODO: ugly, do better */ 678 for (i = 0 ; (encoder->possible_crtcs != (1 << i)) && i < 32; ++i) 679 ; 680 if (encoder->possible_crtcs != (1 << i)) { 681 DRM_ERROR("encoder has wrong possible_crtcs: %x\n", 682 encoder->possible_crtcs); 683 return; 684 } 685 if (!qdev->monitors_config || 686 qdev->monitors_config->max_allowed <= i) { 687 DRM_ERROR( 688 "head number too large or missing monitors config: %p, %d", 689 qdev->monitors_config, 690 qdev->monitors_config ? 691 qdev->monitors_config->max_allowed : -1); 692 return; 693 } 694 if (!encoder->crtc) { 695 DRM_ERROR("missing crtc on encoder %p\n", encoder); 696 return; 697 } 698 if (i != 0) 699 DRM_DEBUG("missing for multiple monitors: no head holes\n"); 700 head = &qdev->monitors_config->heads[i]; 701 head->id = i; 702 head->surface_id = 0; 703 if (encoder->crtc->enabled) { 704 mode = &encoder->crtc->mode; 705 head->width = mode->hdisplay; 706 head->height = mode->vdisplay; 707 head->x = encoder->crtc->x; 708 head->y = encoder->crtc->y; 709 if (qdev->monitors_config->count < i + 1) 710 qdev->monitors_config->count = i + 1; 711 } else { 712 head->width = 0; 713 head->height = 0; 714 head->x = 0; 715 head->y = 0; 716 } 717 DRM_DEBUG("setting head %d to +%d+%d %dx%d\n", 718 i, head->x, head->y, head->width, head->height); 719 head->flags = 0; 720 /* TODO - somewhere else to call this for multiple monitors 721 * (config_commit?) */ 722 qxl_send_monitors_config(qdev); 723 } 724 725 static void qxl_enc_commit(struct drm_encoder *encoder) 726 { 727 struct qxl_device *qdev = encoder->dev->dev_private; 728 729 qxl_write_monitors_config_for_encoder(qdev, encoder); 730 DRM_DEBUG("\n"); 731 } 732 733 static void qxl_enc_mode_set(struct drm_encoder *encoder, 734 struct drm_display_mode *mode, 735 struct drm_display_mode *adjusted_mode) 736 { 737 DRM_DEBUG("\n"); 738 } 739 740 static int qxl_conn_get_modes(struct drm_connector *connector) 741 { 742 int ret = 0; 743 struct qxl_device *qdev = connector->dev->dev_private; 744 745 DRM_DEBUG_KMS("monitors_config=%p\n", qdev->monitors_config); 746 /* TODO: what should we do here? only show the configured modes for the 747 * device, or allow the full list, or both? */ 748 if (qdev->monitors_config && qdev->monitors_config->count) { 749 ret = qxl_add_monitors_config_modes(connector); 750 if (ret < 0) 751 return ret; 752 } 753 ret += qxl_add_common_modes(connector); 754 return ret; 755 } 756 757 static int qxl_conn_mode_valid(struct drm_connector *connector, 758 struct drm_display_mode *mode) 759 { 760 /* TODO: is this called for user defined modes? (xrandr --add-mode) 761 * TODO: check that the mode fits in the framebuffer */ 762 DRM_DEBUG("%s: %dx%d status=%d\n", mode->name, mode->hdisplay, 763 mode->vdisplay, mode->status); 764 return MODE_OK; 765 } 766 767 static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector) 768 { 769 struct qxl_output *qxl_output = 770 drm_connector_to_qxl_output(connector); 771 772 DRM_DEBUG("\n"); 773 return &qxl_output->enc; 774 } 775 776 777 static const struct drm_encoder_helper_funcs qxl_enc_helper_funcs = { 778 .dpms = qxl_enc_dpms, 779 .mode_fixup = qxl_enc_mode_fixup, 780 .prepare = qxl_enc_prepare, 781 .mode_set = qxl_enc_mode_set, 782 .commit = qxl_enc_commit, 783 }; 784 785 static const struct drm_connector_helper_funcs qxl_connector_helper_funcs = { 786 .get_modes = qxl_conn_get_modes, 787 .mode_valid = qxl_conn_mode_valid, 788 .best_encoder = qxl_best_encoder, 789 }; 790 791 static void qxl_conn_save(struct drm_connector *connector) 792 { 793 DRM_DEBUG("\n"); 794 } 795 796 static void qxl_conn_restore(struct drm_connector *connector) 797 { 798 DRM_DEBUG("\n"); 799 } 800 801 static enum drm_connector_status qxl_conn_detect( 802 struct drm_connector *connector, 803 bool force) 804 { 805 struct qxl_output *output = 806 drm_connector_to_qxl_output(connector); 807 struct drm_device *ddev = connector->dev; 808 struct qxl_device *qdev = ddev->dev_private; 809 int connected; 810 811 /* The first monitor is always connected */ 812 connected = (output->index == 0) || 813 (qdev->monitors_config && 814 qdev->monitors_config->count > output->index); 815 816 DRM_DEBUG("\n"); 817 return connected ? connector_status_connected 818 : connector_status_disconnected; 819 } 820 821 static int qxl_conn_set_property(struct drm_connector *connector, 822 struct drm_property *property, 823 uint64_t value) 824 { 825 DRM_DEBUG("\n"); 826 return 0; 827 } 828 829 static void qxl_conn_destroy(struct drm_connector *connector) 830 { 831 struct qxl_output *qxl_output = 832 drm_connector_to_qxl_output(connector); 833 834 drm_sysfs_connector_remove(connector); 835 drm_connector_cleanup(connector); 836 kfree(qxl_output); 837 } 838 839 static const struct drm_connector_funcs qxl_connector_funcs = { 840 .dpms = drm_helper_connector_dpms, 841 .save = qxl_conn_save, 842 .restore = qxl_conn_restore, 843 .detect = qxl_conn_detect, 844 .fill_modes = drm_helper_probe_single_connector_modes, 845 .set_property = qxl_conn_set_property, 846 .destroy = qxl_conn_destroy, 847 }; 848 849 static void qxl_enc_destroy(struct drm_encoder *encoder) 850 { 851 drm_encoder_cleanup(encoder); 852 } 853 854 static const struct drm_encoder_funcs qxl_enc_funcs = { 855 .destroy = qxl_enc_destroy, 856 }; 857 858 static int qdev_output_init(struct drm_device *dev, int num_output) 859 { 860 struct qxl_output *qxl_output; 861 struct drm_connector *connector; 862 struct drm_encoder *encoder; 863 864 qxl_output = kzalloc(sizeof(struct qxl_output), GFP_KERNEL); 865 if (!qxl_output) 866 return -ENOMEM; 867 868 qxl_output->index = num_output; 869 870 connector = &qxl_output->base; 871 encoder = &qxl_output->enc; 872 drm_connector_init(dev, &qxl_output->base, 873 &qxl_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL); 874 875 drm_encoder_init(dev, &qxl_output->enc, &qxl_enc_funcs, 876 DRM_MODE_ENCODER_VIRTUAL); 877 878 encoder->possible_crtcs = 1 << num_output; 879 drm_mode_connector_attach_encoder(&qxl_output->base, 880 &qxl_output->enc); 881 drm_encoder_helper_add(encoder, &qxl_enc_helper_funcs); 882 drm_connector_helper_add(connector, &qxl_connector_helper_funcs); 883 884 drm_sysfs_connector_add(connector); 885 return 0; 886 } 887 888 static struct drm_framebuffer * 889 qxl_user_framebuffer_create(struct drm_device *dev, 890 struct drm_file *file_priv, 891 struct drm_mode_fb_cmd2 *mode_cmd) 892 { 893 struct drm_gem_object *obj; 894 struct qxl_framebuffer *qxl_fb; 895 int ret; 896 897 obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); 898 899 qxl_fb = kzalloc(sizeof(*qxl_fb), GFP_KERNEL); 900 if (qxl_fb == NULL) 901 return NULL; 902 903 ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj); 904 if (ret) { 905 kfree(qxl_fb); 906 drm_gem_object_unreference_unlocked(obj); 907 return NULL; 908 } 909 910 return &qxl_fb->base; 911 } 912 913 static const struct drm_mode_config_funcs qxl_mode_funcs = { 914 .fb_create = qxl_user_framebuffer_create, 915 }; 916 917 int qxl_modeset_init(struct qxl_device *qdev) 918 { 919 int i; 920 int ret; 921 struct drm_gem_object *gobj; 922 int max_allowed = QXL_NUM_OUTPUTS; 923 int monitors_config_size = sizeof(struct qxl_monitors_config) + 924 max_allowed * sizeof(struct qxl_head); 925 926 drm_mode_config_init(qdev->ddev); 927 ret = qxl_gem_object_create(qdev, monitors_config_size, 0, 928 QXL_GEM_DOMAIN_VRAM, 929 false, false, NULL, &gobj); 930 if (ret) { 931 DRM_ERROR("%s: failed to create gem ret=%d\n", __func__, ret); 932 return -ENOMEM; 933 } 934 qdev->monitors_config_bo = gem_to_qxl_bo(gobj); 935 qxl_bo_kmap(qdev->monitors_config_bo, NULL); 936 qdev->monitors_config = qdev->monitors_config_bo->kptr; 937 qdev->ram_header->monitors_config = 938 qxl_bo_physical_address(qdev, qdev->monitors_config_bo, 0); 939 940 memset(qdev->monitors_config, 0, monitors_config_size); 941 qdev->monitors_config->max_allowed = max_allowed; 942 943 qdev->ddev->mode_config.funcs = (void *)&qxl_mode_funcs; 944 945 /* modes will be validated against the framebuffer size */ 946 qdev->ddev->mode_config.min_width = 320; 947 qdev->ddev->mode_config.min_height = 200; 948 qdev->ddev->mode_config.max_width = 8192; 949 qdev->ddev->mode_config.max_height = 8192; 950 951 qdev->ddev->mode_config.fb_base = qdev->vram_base; 952 for (i = 0 ; i < QXL_NUM_OUTPUTS; ++i) { 953 qdev_crtc_init(qdev->ddev, i); 954 qdev_output_init(qdev->ddev, i); 955 } 956 957 qdev->mode_info.mode_config_initialized = true; 958 959 /* primary surface must be created by this point, to allow 960 * issuing command queue commands and having them read by 961 * spice server. */ 962 qxl_fbdev_init(qdev); 963 return 0; 964 } 965 966 void qxl_modeset_fini(struct qxl_device *qdev) 967 { 968 qxl_fbdev_fini(qdev); 969 if (qdev->mode_info.mode_config_initialized) { 970 drm_mode_config_cleanup(qdev->ddev); 971 qdev->mode_info.mode_config_initialized = false; 972 } 973 } 974