1 /* 2 * Copyright (c) 2006-2009 Red Hat Inc. 3 * Copyright (c) 2006-2008 Intel Corporation 4 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 5 * 6 * DRM framebuffer helper functions 7 * 8 * Permission to use, copy, modify, distribute, and sell this software and its 9 * documentation for any purpose is hereby granted without fee, provided that 10 * the above copyright notice appear in all copies and that both that copyright 11 * notice and this permission notice appear in supporting documentation, and 12 * that the name of the copyright holders not be used in advertising or 13 * publicity pertaining to distribution of the software without specific, 14 * written prior permission. The copyright holders make no representations 15 * about the suitability of this software for any purpose. It is provided "as 16 * is" without express or implied warranty. 17 * 18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 24 * OF THIS SOFTWARE. 25 * 26 * Authors: 27 * Dave Airlie <airlied@linux.ie> 28 * Jesse Barnes <jesse.barnes@intel.com> 29 */ 30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 31 32 #include <linux/console.h> 33 #include <linux/dma-buf.h> 34 #include <linux/kernel.h> 35 #include <linux/sysrq.h> 36 #include <linux/slab.h> 37 #include <linux/module.h> 38 #include <drm/drmP.h> 39 #include <drm/drm_crtc.h> 40 #include <drm/drm_fb_helper.h> 41 #include <drm/drm_crtc_helper.h> 42 #include <drm/drm_atomic.h> 43 #include <drm/drm_atomic_helper.h> 44 45 #include "drm_crtc_internal.h" 46 #include "drm_crtc_helper_internal.h" 47 48 static bool drm_fbdev_emulation = true; 49 module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600); 50 MODULE_PARM_DESC(fbdev_emulation, 51 "Enable legacy fbdev emulation [default=true]"); 52 53 static int drm_fbdev_overalloc = CONFIG_DRM_FBDEV_OVERALLOC; 54 module_param(drm_fbdev_overalloc, int, 0444); 55 MODULE_PARM_DESC(drm_fbdev_overalloc, 56 "Overallocation of the fbdev buffer (%) [default=" 57 __MODULE_STRING(CONFIG_DRM_FBDEV_OVERALLOC) "]"); 58 59 static LIST_HEAD(kernel_fb_helper_list); 60 static DEFINE_MUTEX(kernel_fb_helper_lock); 61 62 /** 63 * DOC: fbdev helpers 64 * 65 * The fb helper functions are useful to provide an fbdev on top of a drm kernel 66 * mode setting driver. They can be used mostly independently from the crtc 67 * helper functions used by many drivers to implement the kernel mode setting 68 * interfaces. 69 * 70 * Drivers that support a dumb buffer with a virtual address and mmap support, 71 * should try out the generic fbdev emulation using drm_fbdev_generic_setup(). 72 * 73 * Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it 74 * down by calling drm_fb_helper_fbdev_teardown(). 75 * 76 * Drivers that need to handle connector hotplugging (e.g. dp mst) can't use 77 * the setup helper and will need to do the whole four-step setup process with 78 * drm_fb_helper_prepare(), drm_fb_helper_init(), 79 * drm_fb_helper_single_add_all_connectors(), enable hotplugging and 80 * drm_fb_helper_initial_config() to avoid a possible race window. 81 * 82 * At runtime drivers should restore the fbdev console by using 83 * drm_fb_helper_lastclose() as their &drm_driver.lastclose callback. 84 * They should also notify the fb helper code from updates to the output 85 * configuration by using drm_fb_helper_output_poll_changed() as their 86 * &drm_mode_config_funcs.output_poll_changed callback. 87 * 88 * For suspend/resume consider using drm_mode_config_helper_suspend() and 89 * drm_mode_config_helper_resume() which takes care of fbdev as well. 90 * 91 * All other functions exported by the fb helper library can be used to 92 * implement the fbdev driver interface by the driver. 93 * 94 * It is possible, though perhaps somewhat tricky, to implement race-free 95 * hotplug detection using the fbdev helpers. The drm_fb_helper_prepare() 96 * helper must be called first to initialize the minimum required to make 97 * hotplug detection work. Drivers also need to make sure to properly set up 98 * the &drm_mode_config.funcs member. After calling drm_kms_helper_poll_init() 99 * it is safe to enable interrupts and start processing hotplug events. At the 100 * same time, drivers should initialize all modeset objects such as CRTCs, 101 * encoders and connectors. To finish up the fbdev helper initialization, the 102 * drm_fb_helper_init() function is called. To probe for all attached displays 103 * and set up an initial configuration using the detected hardware, drivers 104 * should call drm_fb_helper_single_add_all_connectors() followed by 105 * drm_fb_helper_initial_config(). 106 * 107 * If &drm_framebuffer_funcs.dirty is set, the 108 * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will 109 * accumulate changes and schedule &drm_fb_helper.dirty_work to run right 110 * away. This worker then calls the dirty() function ensuring that it will 111 * always run in process context since the fb_*() function could be running in 112 * atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io 113 * callback it will also schedule dirty_work with the damage collected from the 114 * mmap page writes. Drivers can use drm_fb_helper_defio_init() to setup 115 * deferred I/O (coupled with drm_fb_helper_fbdev_teardown()). 116 */ 117 118 #define drm_fb_helper_for_each_connector(fbh, i__) \ 119 for (({ lockdep_assert_held(&(fbh)->lock); }), \ 120 i__ = 0; i__ < (fbh)->connector_count; i__++) 121 122 static int __drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, 123 struct drm_connector *connector) 124 { 125 struct drm_fb_helper_connector *fb_conn; 126 struct drm_fb_helper_connector **temp; 127 unsigned int count; 128 129 if (!drm_fbdev_emulation) 130 return 0; 131 132 lockdep_assert_held(&fb_helper->lock); 133 134 count = fb_helper->connector_count + 1; 135 136 if (count > fb_helper->connector_info_alloc_count) { 137 size_t size = count * sizeof(fb_conn); 138 139 temp = krealloc(fb_helper->connector_info, size, GFP_KERNEL); 140 if (!temp) 141 return -ENOMEM; 142 143 fb_helper->connector_info_alloc_count = count; 144 fb_helper->connector_info = temp; 145 } 146 147 fb_conn = kzalloc(sizeof(*fb_conn), GFP_KERNEL); 148 if (!fb_conn) 149 return -ENOMEM; 150 151 drm_connector_get(connector); 152 fb_conn->connector = connector; 153 fb_helper->connector_info[fb_helper->connector_count++] = fb_conn; 154 155 return 0; 156 } 157 158 int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, 159 struct drm_connector *connector) 160 { 161 int err; 162 163 if (!fb_helper) 164 return 0; 165 166 mutex_lock(&fb_helper->lock); 167 err = __drm_fb_helper_add_one_connector(fb_helper, connector); 168 mutex_unlock(&fb_helper->lock); 169 170 return err; 171 } 172 EXPORT_SYMBOL(drm_fb_helper_add_one_connector); 173 174 /** 175 * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev 176 * emulation helper 177 * @fb_helper: fbdev initialized with drm_fb_helper_init, can be NULL 178 * 179 * This functions adds all the available connectors for use with the given 180 * fb_helper. This is a separate step to allow drivers to freely assign 181 * connectors to the fbdev, e.g. if some are reserved for special purposes or 182 * not adequate to be used for the fbcon. 183 * 184 * This function is protected against concurrent connector hotadds/removals 185 * using drm_fb_helper_add_one_connector() and 186 * drm_fb_helper_remove_one_connector(). 187 */ 188 int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) 189 { 190 struct drm_device *dev; 191 struct drm_connector *connector; 192 struct drm_connector_list_iter conn_iter; 193 int i, ret = 0; 194 195 if (!drm_fbdev_emulation || !fb_helper) 196 return 0; 197 198 dev = fb_helper->dev; 199 200 mutex_lock(&fb_helper->lock); 201 drm_connector_list_iter_begin(dev, &conn_iter); 202 drm_for_each_connector_iter(connector, &conn_iter) { 203 ret = __drm_fb_helper_add_one_connector(fb_helper, connector); 204 if (ret) 205 goto fail; 206 } 207 goto out; 208 209 fail: 210 drm_fb_helper_for_each_connector(fb_helper, i) { 211 struct drm_fb_helper_connector *fb_helper_connector = 212 fb_helper->connector_info[i]; 213 214 drm_connector_put(fb_helper_connector->connector); 215 216 kfree(fb_helper_connector); 217 fb_helper->connector_info[i] = NULL; 218 } 219 fb_helper->connector_count = 0; 220 out: 221 drm_connector_list_iter_end(&conn_iter); 222 mutex_unlock(&fb_helper->lock); 223 224 return ret; 225 } 226 EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); 227 228 static int __drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, 229 struct drm_connector *connector) 230 { 231 struct drm_fb_helper_connector *fb_helper_connector; 232 int i, j; 233 234 if (!drm_fbdev_emulation) 235 return 0; 236 237 lockdep_assert_held(&fb_helper->lock); 238 239 drm_fb_helper_for_each_connector(fb_helper, i) { 240 if (fb_helper->connector_info[i]->connector == connector) 241 break; 242 } 243 244 if (i == fb_helper->connector_count) 245 return -EINVAL; 246 fb_helper_connector = fb_helper->connector_info[i]; 247 drm_connector_put(fb_helper_connector->connector); 248 249 for (j = i + 1; j < fb_helper->connector_count; j++) 250 fb_helper->connector_info[j - 1] = fb_helper->connector_info[j]; 251 252 fb_helper->connector_count--; 253 kfree(fb_helper_connector); 254 255 return 0; 256 } 257 258 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, 259 struct drm_connector *connector) 260 { 261 int err; 262 263 if (!fb_helper) 264 return 0; 265 266 mutex_lock(&fb_helper->lock); 267 err = __drm_fb_helper_remove_one_connector(fb_helper, connector); 268 mutex_unlock(&fb_helper->lock); 269 270 return err; 271 } 272 EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); 273 274 static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) 275 { 276 uint16_t *r_base, *g_base, *b_base; 277 278 if (crtc->funcs->gamma_set == NULL) 279 return; 280 281 r_base = crtc->gamma_store; 282 g_base = r_base + crtc->gamma_size; 283 b_base = g_base + crtc->gamma_size; 284 285 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 286 crtc->gamma_size, NULL); 287 } 288 289 /** 290 * drm_fb_helper_debug_enter - implementation for &fb_ops.fb_debug_enter 291 * @info: fbdev registered by the helper 292 */ 293 int drm_fb_helper_debug_enter(struct fb_info *info) 294 { 295 struct drm_fb_helper *helper = info->par; 296 const struct drm_crtc_helper_funcs *funcs; 297 int i; 298 299 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { 300 for (i = 0; i < helper->crtc_count; i++) { 301 struct drm_mode_set *mode_set = 302 &helper->crtc_info[i].mode_set; 303 304 if (!mode_set->crtc->enabled) 305 continue; 306 307 funcs = mode_set->crtc->helper_private; 308 if (funcs->mode_set_base_atomic == NULL) 309 continue; 310 311 if (drm_drv_uses_atomic_modeset(mode_set->crtc->dev)) 312 continue; 313 314 funcs->mode_set_base_atomic(mode_set->crtc, 315 mode_set->fb, 316 mode_set->x, 317 mode_set->y, 318 ENTER_ATOMIC_MODE_SET); 319 } 320 } 321 322 return 0; 323 } 324 EXPORT_SYMBOL(drm_fb_helper_debug_enter); 325 326 /** 327 * drm_fb_helper_debug_leave - implementation for &fb_ops.fb_debug_leave 328 * @info: fbdev registered by the helper 329 */ 330 int drm_fb_helper_debug_leave(struct fb_info *info) 331 { 332 struct drm_fb_helper *helper = info->par; 333 struct drm_crtc *crtc; 334 const struct drm_crtc_helper_funcs *funcs; 335 struct drm_framebuffer *fb; 336 int i; 337 338 for (i = 0; i < helper->crtc_count; i++) { 339 struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; 340 341 crtc = mode_set->crtc; 342 if (drm_drv_uses_atomic_modeset(crtc->dev)) 343 continue; 344 345 funcs = crtc->helper_private; 346 fb = crtc->primary->fb; 347 348 if (!crtc->enabled) 349 continue; 350 351 if (!fb) { 352 DRM_ERROR("no fb to restore??\n"); 353 continue; 354 } 355 356 if (funcs->mode_set_base_atomic == NULL) 357 continue; 358 359 drm_fb_helper_restore_lut_atomic(mode_set->crtc); 360 funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x, 361 crtc->y, LEAVE_ATOMIC_MODE_SET); 362 } 363 364 return 0; 365 } 366 EXPORT_SYMBOL(drm_fb_helper_debug_leave); 367 368 static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active) 369 { 370 struct drm_device *dev = fb_helper->dev; 371 struct drm_plane_state *plane_state; 372 struct drm_plane *plane; 373 struct drm_atomic_state *state; 374 int i, ret; 375 struct drm_modeset_acquire_ctx ctx; 376 377 drm_modeset_acquire_init(&ctx, 0); 378 379 state = drm_atomic_state_alloc(dev); 380 if (!state) { 381 ret = -ENOMEM; 382 goto out_ctx; 383 } 384 385 state->acquire_ctx = &ctx; 386 retry: 387 drm_for_each_plane(plane, dev) { 388 plane_state = drm_atomic_get_plane_state(state, plane); 389 if (IS_ERR(plane_state)) { 390 ret = PTR_ERR(plane_state); 391 goto out_state; 392 } 393 394 plane_state->rotation = DRM_MODE_ROTATE_0; 395 396 /* disable non-primary: */ 397 if (plane->type == DRM_PLANE_TYPE_PRIMARY) 398 continue; 399 400 ret = __drm_atomic_helper_disable_plane(plane, plane_state); 401 if (ret != 0) 402 goto out_state; 403 } 404 405 for (i = 0; i < fb_helper->crtc_count; i++) { 406 struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; 407 struct drm_plane *primary = mode_set->crtc->primary; 408 409 /* Cannot fail as we've already gotten the plane state above */ 410 plane_state = drm_atomic_get_new_plane_state(state, primary); 411 plane_state->rotation = fb_helper->crtc_info[i].rotation; 412 413 ret = __drm_atomic_helper_set_config(mode_set, state); 414 if (ret != 0) 415 goto out_state; 416 417 /* 418 * __drm_atomic_helper_set_config() sets active when a 419 * mode is set, unconditionally clear it if we force DPMS off 420 */ 421 if (!active) { 422 struct drm_crtc *crtc = mode_set->crtc; 423 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 424 425 crtc_state->active = false; 426 } 427 } 428 429 ret = drm_atomic_commit(state); 430 431 out_state: 432 if (ret == -EDEADLK) 433 goto backoff; 434 435 drm_atomic_state_put(state); 436 out_ctx: 437 drm_modeset_drop_locks(&ctx); 438 drm_modeset_acquire_fini(&ctx); 439 440 return ret; 441 442 backoff: 443 drm_atomic_state_clear(state); 444 drm_modeset_backoff(&ctx); 445 446 goto retry; 447 } 448 449 static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper) 450 { 451 struct drm_device *dev = fb_helper->dev; 452 struct drm_plane *plane; 453 int i, ret = 0; 454 455 drm_modeset_lock_all(fb_helper->dev); 456 drm_for_each_plane(plane, dev) { 457 if (plane->type != DRM_PLANE_TYPE_PRIMARY) 458 drm_plane_force_disable(plane); 459 460 if (plane->rotation_property) 461 drm_mode_plane_set_obj_prop(plane, 462 plane->rotation_property, 463 DRM_MODE_ROTATE_0); 464 } 465 466 for (i = 0; i < fb_helper->crtc_count; i++) { 467 struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; 468 struct drm_crtc *crtc = mode_set->crtc; 469 470 if (crtc->funcs->cursor_set2) { 471 ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0); 472 if (ret) 473 goto out; 474 } else if (crtc->funcs->cursor_set) { 475 ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0); 476 if (ret) 477 goto out; 478 } 479 480 ret = drm_mode_set_config_internal(mode_set); 481 if (ret) 482 goto out; 483 } 484 out: 485 drm_modeset_unlock_all(fb_helper->dev); 486 487 return ret; 488 } 489 490 static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) 491 { 492 struct drm_device *dev = fb_helper->dev; 493 494 if (drm_drv_uses_atomic_modeset(dev)) 495 return restore_fbdev_mode_atomic(fb_helper, true); 496 else 497 return restore_fbdev_mode_legacy(fb_helper); 498 } 499 500 /** 501 * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration 502 * @fb_helper: driver-allocated fbdev helper, can be NULL 503 * 504 * This should be called from driver's drm &drm_driver.lastclose callback 505 * when implementing an fbcon on top of kms using this helper. This ensures that 506 * the user isn't greeted with a black screen when e.g. X dies. 507 * 508 * RETURNS: 509 * Zero if everything went ok, negative error code otherwise. 510 */ 511 int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) 512 { 513 bool do_delayed; 514 int ret; 515 516 if (!drm_fbdev_emulation || !fb_helper) 517 return -ENODEV; 518 519 if (READ_ONCE(fb_helper->deferred_setup)) 520 return 0; 521 522 mutex_lock(&fb_helper->lock); 523 ret = restore_fbdev_mode(fb_helper); 524 525 do_delayed = fb_helper->delayed_hotplug; 526 if (do_delayed) 527 fb_helper->delayed_hotplug = false; 528 mutex_unlock(&fb_helper->lock); 529 530 if (do_delayed) 531 drm_fb_helper_hotplug_event(fb_helper); 532 533 return ret; 534 } 535 EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked); 536 537 static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) 538 { 539 struct drm_device *dev = fb_helper->dev; 540 struct drm_crtc *crtc; 541 int bound = 0, crtcs_bound = 0; 542 543 /* 544 * Sometimes user space wants everything disabled, so don't steal the 545 * display if there's a master. 546 */ 547 if (READ_ONCE(dev->master)) 548 return false; 549 550 drm_for_each_crtc(crtc, dev) { 551 drm_modeset_lock(&crtc->mutex, NULL); 552 if (crtc->primary->fb) 553 crtcs_bound++; 554 if (crtc->primary->fb == fb_helper->fb) 555 bound++; 556 drm_modeset_unlock(&crtc->mutex); 557 } 558 559 if (bound < crtcs_bound) 560 return false; 561 562 return true; 563 } 564 565 #ifdef CONFIG_MAGIC_SYSRQ 566 /* 567 * restore fbcon display for all kms driver's using this helper, used for sysrq 568 * and panic handling. 569 */ 570 static bool drm_fb_helper_force_kernel_mode(void) 571 { 572 bool ret, error = false; 573 struct drm_fb_helper *helper; 574 575 if (list_empty(&kernel_fb_helper_list)) 576 return false; 577 578 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { 579 struct drm_device *dev = helper->dev; 580 581 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) 582 continue; 583 584 mutex_lock(&helper->lock); 585 ret = restore_fbdev_mode(helper); 586 if (ret) 587 error = true; 588 mutex_unlock(&helper->lock); 589 } 590 return error; 591 } 592 593 static void drm_fb_helper_restore_work_fn(struct work_struct *ignored) 594 { 595 bool ret; 596 597 ret = drm_fb_helper_force_kernel_mode(); 598 if (ret == true) 599 DRM_ERROR("Failed to restore crtc configuration\n"); 600 } 601 static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn); 602 603 static void drm_fb_helper_sysrq(int dummy1) 604 { 605 schedule_work(&drm_fb_helper_restore_work); 606 } 607 608 static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { 609 .handler = drm_fb_helper_sysrq, 610 .help_msg = "force-fb(V)", 611 .action_msg = "Restore framebuffer console", 612 }; 613 #else 614 static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { }; 615 #endif 616 617 static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode) 618 { 619 struct drm_device *dev = fb_helper->dev; 620 struct drm_crtc *crtc; 621 struct drm_connector *connector; 622 int i, j; 623 624 drm_modeset_lock_all(dev); 625 for (i = 0; i < fb_helper->crtc_count; i++) { 626 crtc = fb_helper->crtc_info[i].mode_set.crtc; 627 628 if (!crtc->enabled) 629 continue; 630 631 /* Walk the connectors & encoders on this fb turning them on/off */ 632 drm_fb_helper_for_each_connector(fb_helper, j) { 633 connector = fb_helper->connector_info[j]->connector; 634 connector->funcs->dpms(connector, dpms_mode); 635 drm_object_property_set_value(&connector->base, 636 dev->mode_config.dpms_property, dpms_mode); 637 } 638 } 639 drm_modeset_unlock_all(dev); 640 } 641 642 static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) 643 { 644 struct drm_fb_helper *fb_helper = info->par; 645 646 /* 647 * For each CRTC in this fb, turn the connectors on/off. 648 */ 649 mutex_lock(&fb_helper->lock); 650 if (!drm_fb_helper_is_bound(fb_helper)) { 651 mutex_unlock(&fb_helper->lock); 652 return; 653 } 654 655 if (drm_drv_uses_atomic_modeset(fb_helper->dev)) 656 restore_fbdev_mode_atomic(fb_helper, dpms_mode == DRM_MODE_DPMS_ON); 657 else 658 dpms_legacy(fb_helper, dpms_mode); 659 mutex_unlock(&fb_helper->lock); 660 } 661 662 /** 663 * drm_fb_helper_blank - implementation for &fb_ops.fb_blank 664 * @blank: desired blanking state 665 * @info: fbdev registered by the helper 666 */ 667 int drm_fb_helper_blank(int blank, struct fb_info *info) 668 { 669 if (oops_in_progress) 670 return -EBUSY; 671 672 switch (blank) { 673 /* Display: On; HSync: On, VSync: On */ 674 case FB_BLANK_UNBLANK: 675 drm_fb_helper_dpms(info, DRM_MODE_DPMS_ON); 676 break; 677 /* Display: Off; HSync: On, VSync: On */ 678 case FB_BLANK_NORMAL: 679 drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY); 680 break; 681 /* Display: Off; HSync: Off, VSync: On */ 682 case FB_BLANK_HSYNC_SUSPEND: 683 drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY); 684 break; 685 /* Display: Off; HSync: On, VSync: Off */ 686 case FB_BLANK_VSYNC_SUSPEND: 687 drm_fb_helper_dpms(info, DRM_MODE_DPMS_SUSPEND); 688 break; 689 /* Display: Off; HSync: Off, VSync: Off */ 690 case FB_BLANK_POWERDOWN: 691 drm_fb_helper_dpms(info, DRM_MODE_DPMS_OFF); 692 break; 693 } 694 return 0; 695 } 696 EXPORT_SYMBOL(drm_fb_helper_blank); 697 698 static void drm_fb_helper_modeset_release(struct drm_fb_helper *helper, 699 struct drm_mode_set *modeset) 700 { 701 int i; 702 703 for (i = 0; i < modeset->num_connectors; i++) { 704 drm_connector_put(modeset->connectors[i]); 705 modeset->connectors[i] = NULL; 706 } 707 modeset->num_connectors = 0; 708 709 drm_mode_destroy(helper->dev, modeset->mode); 710 modeset->mode = NULL; 711 712 /* FIXME should hold a ref? */ 713 modeset->fb = NULL; 714 } 715 716 static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) 717 { 718 int i; 719 720 for (i = 0; i < helper->connector_count; i++) { 721 drm_connector_put(helper->connector_info[i]->connector); 722 kfree(helper->connector_info[i]); 723 } 724 kfree(helper->connector_info); 725 726 for (i = 0; i < helper->crtc_count; i++) { 727 struct drm_mode_set *modeset = &helper->crtc_info[i].mode_set; 728 729 drm_fb_helper_modeset_release(helper, modeset); 730 kfree(modeset->connectors); 731 } 732 kfree(helper->crtc_info); 733 } 734 735 static void drm_fb_helper_resume_worker(struct work_struct *work) 736 { 737 struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper, 738 resume_work); 739 740 console_lock(); 741 fb_set_suspend(helper->fbdev, 0); 742 console_unlock(); 743 } 744 745 static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper, 746 struct drm_clip_rect *clip) 747 { 748 struct drm_framebuffer *fb = fb_helper->fb; 749 unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0); 750 size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp; 751 void *src = fb_helper->fbdev->screen_buffer + offset; 752 void *dst = fb_helper->buffer->vaddr + offset; 753 size_t len = (clip->x2 - clip->x1) * cpp; 754 unsigned int y; 755 756 for (y = clip->y1; y < clip->y2; y++) { 757 memcpy(dst, src, len); 758 src += fb->pitches[0]; 759 dst += fb->pitches[0]; 760 } 761 } 762 763 static void drm_fb_helper_dirty_work(struct work_struct *work) 764 { 765 struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper, 766 dirty_work); 767 struct drm_clip_rect *clip = &helper->dirty_clip; 768 struct drm_clip_rect clip_copy; 769 unsigned long flags; 770 771 spin_lock_irqsave(&helper->dirty_lock, flags); 772 clip_copy = *clip; 773 clip->x1 = clip->y1 = ~0; 774 clip->x2 = clip->y2 = 0; 775 spin_unlock_irqrestore(&helper->dirty_lock, flags); 776 777 /* call dirty callback only when it has been really touched */ 778 if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2) { 779 /* Generic fbdev uses a shadow buffer */ 780 if (helper->buffer) 781 drm_fb_helper_dirty_blit_real(helper, &clip_copy); 782 helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1); 783 } 784 } 785 786 /** 787 * drm_fb_helper_prepare - setup a drm_fb_helper structure 788 * @dev: DRM device 789 * @helper: driver-allocated fbdev helper structure to set up 790 * @funcs: pointer to structure of functions associate with this helper 791 * 792 * Sets up the bare minimum to make the framebuffer helper usable. This is 793 * useful to implement race-free initialization of the polling helpers. 794 */ 795 void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, 796 const struct drm_fb_helper_funcs *funcs) 797 { 798 INIT_LIST_HEAD(&helper->kernel_fb_list); 799 spin_lock_init(&helper->dirty_lock); 800 INIT_WORK(&helper->resume_work, drm_fb_helper_resume_worker); 801 INIT_WORK(&helper->dirty_work, drm_fb_helper_dirty_work); 802 helper->dirty_clip.x1 = helper->dirty_clip.y1 = ~0; 803 mutex_init(&helper->lock); 804 helper->funcs = funcs; 805 helper->dev = dev; 806 } 807 EXPORT_SYMBOL(drm_fb_helper_prepare); 808 809 /** 810 * drm_fb_helper_init - initialize a &struct drm_fb_helper 811 * @dev: drm device 812 * @fb_helper: driver-allocated fbdev helper structure to initialize 813 * @max_conn_count: max connector count 814 * 815 * This allocates the structures for the fbdev helper with the given limits. 816 * Note that this won't yet touch the hardware (through the driver interfaces) 817 * nor register the fbdev. This is only done in drm_fb_helper_initial_config() 818 * to allow driver writes more control over the exact init sequence. 819 * 820 * Drivers must call drm_fb_helper_prepare() before calling this function. 821 * 822 * RETURNS: 823 * Zero if everything went ok, nonzero otherwise. 824 */ 825 int drm_fb_helper_init(struct drm_device *dev, 826 struct drm_fb_helper *fb_helper, 827 int max_conn_count) 828 { 829 struct drm_crtc *crtc; 830 struct drm_mode_config *config = &dev->mode_config; 831 int i; 832 833 if (!drm_fbdev_emulation) { 834 dev->fb_helper = fb_helper; 835 return 0; 836 } 837 838 if (!max_conn_count) 839 return -EINVAL; 840 841 fb_helper->crtc_info = kcalloc(config->num_crtc, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); 842 if (!fb_helper->crtc_info) 843 return -ENOMEM; 844 845 fb_helper->crtc_count = config->num_crtc; 846 fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL); 847 if (!fb_helper->connector_info) { 848 kfree(fb_helper->crtc_info); 849 return -ENOMEM; 850 } 851 fb_helper->connector_info_alloc_count = dev->mode_config.num_connector; 852 fb_helper->connector_count = 0; 853 854 for (i = 0; i < fb_helper->crtc_count; i++) { 855 fb_helper->crtc_info[i].mode_set.connectors = 856 kcalloc(max_conn_count, 857 sizeof(struct drm_connector *), 858 GFP_KERNEL); 859 860 if (!fb_helper->crtc_info[i].mode_set.connectors) 861 goto out_free; 862 fb_helper->crtc_info[i].mode_set.num_connectors = 0; 863 fb_helper->crtc_info[i].rotation = DRM_MODE_ROTATE_0; 864 } 865 866 i = 0; 867 drm_for_each_crtc(crtc, dev) { 868 fb_helper->crtc_info[i].mode_set.crtc = crtc; 869 i++; 870 } 871 872 dev->fb_helper = fb_helper; 873 874 return 0; 875 out_free: 876 drm_fb_helper_crtc_free(fb_helper); 877 return -ENOMEM; 878 } 879 EXPORT_SYMBOL(drm_fb_helper_init); 880 881 /** 882 * drm_fb_helper_alloc_fbi - allocate fb_info and some of its members 883 * @fb_helper: driver-allocated fbdev helper 884 * 885 * A helper to alloc fb_info and the members cmap and apertures. Called 886 * by the driver within the fb_probe fb_helper callback function. Drivers do not 887 * need to release the allocated fb_info structure themselves, this is 888 * automatically done when calling drm_fb_helper_fini(). 889 * 890 * RETURNS: 891 * fb_info pointer if things went okay, pointer containing error code 892 * otherwise 893 */ 894 struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper) 895 { 896 struct device *dev = fb_helper->dev->dev; 897 struct fb_info *info; 898 int ret; 899 900 info = framebuffer_alloc(0, dev); 901 if (!info) 902 return ERR_PTR(-ENOMEM); 903 904 ret = fb_alloc_cmap(&info->cmap, 256, 0); 905 if (ret) 906 goto err_release; 907 908 info->apertures = alloc_apertures(1); 909 if (!info->apertures) { 910 ret = -ENOMEM; 911 goto err_free_cmap; 912 } 913 914 fb_helper->fbdev = info; 915 916 return info; 917 918 err_free_cmap: 919 fb_dealloc_cmap(&info->cmap); 920 err_release: 921 framebuffer_release(info); 922 return ERR_PTR(ret); 923 } 924 EXPORT_SYMBOL(drm_fb_helper_alloc_fbi); 925 926 /** 927 * drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device 928 * @fb_helper: driver-allocated fbdev helper, can be NULL 929 * 930 * A wrapper around unregister_framebuffer, to release the fb_info 931 * framebuffer device. This must be called before releasing all resources for 932 * @fb_helper by calling drm_fb_helper_fini(). 933 */ 934 void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper) 935 { 936 if (fb_helper && fb_helper->fbdev) 937 unregister_framebuffer(fb_helper->fbdev); 938 } 939 EXPORT_SYMBOL(drm_fb_helper_unregister_fbi); 940 941 /** 942 * drm_fb_helper_fini - finialize a &struct drm_fb_helper 943 * @fb_helper: driver-allocated fbdev helper, can be NULL 944 * 945 * This cleans up all remaining resources associated with @fb_helper. Must be 946 * called after drm_fb_helper_unlink_fbi() was called. 947 */ 948 void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) 949 { 950 struct fb_info *info; 951 952 if (!fb_helper) 953 return; 954 955 fb_helper->dev->fb_helper = NULL; 956 957 if (!drm_fbdev_emulation) 958 return; 959 960 cancel_work_sync(&fb_helper->resume_work); 961 cancel_work_sync(&fb_helper->dirty_work); 962 963 info = fb_helper->fbdev; 964 if (info) { 965 if (info->cmap.len) 966 fb_dealloc_cmap(&info->cmap); 967 framebuffer_release(info); 968 } 969 fb_helper->fbdev = NULL; 970 971 mutex_lock(&kernel_fb_helper_lock); 972 if (!list_empty(&fb_helper->kernel_fb_list)) { 973 list_del(&fb_helper->kernel_fb_list); 974 if (list_empty(&kernel_fb_helper_list)) 975 unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); 976 } 977 mutex_unlock(&kernel_fb_helper_lock); 978 979 mutex_destroy(&fb_helper->lock); 980 drm_fb_helper_crtc_free(fb_helper); 981 982 } 983 EXPORT_SYMBOL(drm_fb_helper_fini); 984 985 /** 986 * drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer 987 * @fb_helper: driver-allocated fbdev helper, can be NULL 988 * 989 * A wrapper around unlink_framebuffer implemented by fbdev core 990 */ 991 void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper) 992 { 993 if (fb_helper && fb_helper->fbdev) 994 unlink_framebuffer(fb_helper->fbdev); 995 } 996 EXPORT_SYMBOL(drm_fb_helper_unlink_fbi); 997 998 static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y, 999 u32 width, u32 height) 1000 { 1001 struct drm_fb_helper *helper = info->par; 1002 struct drm_clip_rect *clip = &helper->dirty_clip; 1003 unsigned long flags; 1004 1005 if (!helper->fb->funcs->dirty) 1006 return; 1007 1008 spin_lock_irqsave(&helper->dirty_lock, flags); 1009 clip->x1 = min_t(u32, clip->x1, x); 1010 clip->y1 = min_t(u32, clip->y1, y); 1011 clip->x2 = max_t(u32, clip->x2, x + width); 1012 clip->y2 = max_t(u32, clip->y2, y + height); 1013 spin_unlock_irqrestore(&helper->dirty_lock, flags); 1014 1015 schedule_work(&helper->dirty_work); 1016 } 1017 1018 /** 1019 * drm_fb_helper_deferred_io() - fbdev deferred_io callback function 1020 * @info: fb_info struct pointer 1021 * @pagelist: list of dirty mmap framebuffer pages 1022 * 1023 * This function is used as the &fb_deferred_io.deferred_io 1024 * callback function for flushing the fbdev mmap writes. 1025 */ 1026 void drm_fb_helper_deferred_io(struct fb_info *info, 1027 struct list_head *pagelist) 1028 { 1029 unsigned long start, end, min, max; 1030 struct page *page; 1031 u32 y1, y2; 1032 1033 min = ULONG_MAX; 1034 max = 0; 1035 list_for_each_entry(page, pagelist, lru) { 1036 start = page->index << PAGE_SHIFT; 1037 end = start + PAGE_SIZE - 1; 1038 min = min(min, start); 1039 max = max(max, end); 1040 } 1041 1042 if (min < max) { 1043 y1 = min / info->fix.line_length; 1044 y2 = min_t(u32, DIV_ROUND_UP(max, info->fix.line_length), 1045 info->var.yres); 1046 drm_fb_helper_dirty(info, 0, y1, info->var.xres, y2 - y1); 1047 } 1048 } 1049 EXPORT_SYMBOL(drm_fb_helper_deferred_io); 1050 1051 /** 1052 * drm_fb_helper_defio_init - fbdev deferred I/O initialization 1053 * @fb_helper: driver-allocated fbdev helper 1054 * 1055 * This function allocates &fb_deferred_io, sets callback to 1056 * drm_fb_helper_deferred_io(), delay to 50ms and calls fb_deferred_io_init(). 1057 * It should be called from the &drm_fb_helper_funcs->fb_probe callback. 1058 * drm_fb_helper_fbdev_teardown() cleans up deferred I/O. 1059 * 1060 * NOTE: A copy of &fb_ops is made and assigned to &info->fbops. This is done 1061 * because fb_deferred_io_cleanup() clears &fbops->fb_mmap and would thereby 1062 * affect other instances of that &fb_ops. 1063 * 1064 * Returns: 1065 * 0 on success or a negative error code on failure. 1066 */ 1067 int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper) 1068 { 1069 struct fb_info *info = fb_helper->fbdev; 1070 struct fb_deferred_io *fbdefio; 1071 struct fb_ops *fbops; 1072 1073 fbdefio = kzalloc(sizeof(*fbdefio), GFP_KERNEL); 1074 fbops = kzalloc(sizeof(*fbops), GFP_KERNEL); 1075 if (!fbdefio || !fbops) { 1076 kfree(fbdefio); 1077 kfree(fbops); 1078 return -ENOMEM; 1079 } 1080 1081 info->fbdefio = fbdefio; 1082 fbdefio->delay = msecs_to_jiffies(50); 1083 fbdefio->deferred_io = drm_fb_helper_deferred_io; 1084 1085 *fbops = *info->fbops; 1086 info->fbops = fbops; 1087 1088 fb_deferred_io_init(info); 1089 1090 return 0; 1091 } 1092 EXPORT_SYMBOL(drm_fb_helper_defio_init); 1093 1094 /** 1095 * drm_fb_helper_sys_read - wrapper around fb_sys_read 1096 * @info: fb_info struct pointer 1097 * @buf: userspace buffer to read from framebuffer memory 1098 * @count: number of bytes to read from framebuffer memory 1099 * @ppos: read offset within framebuffer memory 1100 * 1101 * A wrapper around fb_sys_read implemented by fbdev core 1102 */ 1103 ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf, 1104 size_t count, loff_t *ppos) 1105 { 1106 return fb_sys_read(info, buf, count, ppos); 1107 } 1108 EXPORT_SYMBOL(drm_fb_helper_sys_read); 1109 1110 /** 1111 * drm_fb_helper_sys_write - wrapper around fb_sys_write 1112 * @info: fb_info struct pointer 1113 * @buf: userspace buffer to write to framebuffer memory 1114 * @count: number of bytes to write to framebuffer memory 1115 * @ppos: write offset within framebuffer memory 1116 * 1117 * A wrapper around fb_sys_write implemented by fbdev core 1118 */ 1119 ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf, 1120 size_t count, loff_t *ppos) 1121 { 1122 ssize_t ret; 1123 1124 ret = fb_sys_write(info, buf, count, ppos); 1125 if (ret > 0) 1126 drm_fb_helper_dirty(info, 0, 0, info->var.xres, 1127 info->var.yres); 1128 1129 return ret; 1130 } 1131 EXPORT_SYMBOL(drm_fb_helper_sys_write); 1132 1133 /** 1134 * drm_fb_helper_sys_fillrect - wrapper around sys_fillrect 1135 * @info: fbdev registered by the helper 1136 * @rect: info about rectangle to fill 1137 * 1138 * A wrapper around sys_fillrect implemented by fbdev core 1139 */ 1140 void drm_fb_helper_sys_fillrect(struct fb_info *info, 1141 const struct fb_fillrect *rect) 1142 { 1143 sys_fillrect(info, rect); 1144 drm_fb_helper_dirty(info, rect->dx, rect->dy, 1145 rect->width, rect->height); 1146 } 1147 EXPORT_SYMBOL(drm_fb_helper_sys_fillrect); 1148 1149 /** 1150 * drm_fb_helper_sys_copyarea - wrapper around sys_copyarea 1151 * @info: fbdev registered by the helper 1152 * @area: info about area to copy 1153 * 1154 * A wrapper around sys_copyarea implemented by fbdev core 1155 */ 1156 void drm_fb_helper_sys_copyarea(struct fb_info *info, 1157 const struct fb_copyarea *area) 1158 { 1159 sys_copyarea(info, area); 1160 drm_fb_helper_dirty(info, area->dx, area->dy, 1161 area->width, area->height); 1162 } 1163 EXPORT_SYMBOL(drm_fb_helper_sys_copyarea); 1164 1165 /** 1166 * drm_fb_helper_sys_imageblit - wrapper around sys_imageblit 1167 * @info: fbdev registered by the helper 1168 * @image: info about image to blit 1169 * 1170 * A wrapper around sys_imageblit implemented by fbdev core 1171 */ 1172 void drm_fb_helper_sys_imageblit(struct fb_info *info, 1173 const struct fb_image *image) 1174 { 1175 sys_imageblit(info, image); 1176 drm_fb_helper_dirty(info, image->dx, image->dy, 1177 image->width, image->height); 1178 } 1179 EXPORT_SYMBOL(drm_fb_helper_sys_imageblit); 1180 1181 /** 1182 * drm_fb_helper_cfb_fillrect - wrapper around cfb_fillrect 1183 * @info: fbdev registered by the helper 1184 * @rect: info about rectangle to fill 1185 * 1186 * A wrapper around cfb_fillrect implemented by fbdev core 1187 */ 1188 void drm_fb_helper_cfb_fillrect(struct fb_info *info, 1189 const struct fb_fillrect *rect) 1190 { 1191 cfb_fillrect(info, rect); 1192 drm_fb_helper_dirty(info, rect->dx, rect->dy, 1193 rect->width, rect->height); 1194 } 1195 EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect); 1196 1197 /** 1198 * drm_fb_helper_cfb_copyarea - wrapper around cfb_copyarea 1199 * @info: fbdev registered by the helper 1200 * @area: info about area to copy 1201 * 1202 * A wrapper around cfb_copyarea implemented by fbdev core 1203 */ 1204 void drm_fb_helper_cfb_copyarea(struct fb_info *info, 1205 const struct fb_copyarea *area) 1206 { 1207 cfb_copyarea(info, area); 1208 drm_fb_helper_dirty(info, area->dx, area->dy, 1209 area->width, area->height); 1210 } 1211 EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea); 1212 1213 /** 1214 * drm_fb_helper_cfb_imageblit - wrapper around cfb_imageblit 1215 * @info: fbdev registered by the helper 1216 * @image: info about image to blit 1217 * 1218 * A wrapper around cfb_imageblit implemented by fbdev core 1219 */ 1220 void drm_fb_helper_cfb_imageblit(struct fb_info *info, 1221 const struct fb_image *image) 1222 { 1223 cfb_imageblit(info, image); 1224 drm_fb_helper_dirty(info, image->dx, image->dy, 1225 image->width, image->height); 1226 } 1227 EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit); 1228 1229 /** 1230 * drm_fb_helper_set_suspend - wrapper around fb_set_suspend 1231 * @fb_helper: driver-allocated fbdev helper, can be NULL 1232 * @suspend: whether to suspend or resume 1233 * 1234 * A wrapper around fb_set_suspend implemented by fbdev core. 1235 * Use drm_fb_helper_set_suspend_unlocked() if you don't need to take 1236 * the lock yourself 1237 */ 1238 void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend) 1239 { 1240 if (fb_helper && fb_helper->fbdev) 1241 fb_set_suspend(fb_helper->fbdev, suspend); 1242 } 1243 EXPORT_SYMBOL(drm_fb_helper_set_suspend); 1244 1245 /** 1246 * drm_fb_helper_set_suspend_unlocked - wrapper around fb_set_suspend that also 1247 * takes the console lock 1248 * @fb_helper: driver-allocated fbdev helper, can be NULL 1249 * @suspend: whether to suspend or resume 1250 * 1251 * A wrapper around fb_set_suspend() that takes the console lock. If the lock 1252 * isn't available on resume, a worker is tasked with waiting for the lock 1253 * to become available. The console lock can be pretty contented on resume 1254 * due to all the printk activity. 1255 * 1256 * This function can be called multiple times with the same state since 1257 * &fb_info.state is checked to see if fbdev is running or not before locking. 1258 * 1259 * Use drm_fb_helper_set_suspend() if you need to take the lock yourself. 1260 */ 1261 void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, 1262 bool suspend) 1263 { 1264 if (!fb_helper || !fb_helper->fbdev) 1265 return; 1266 1267 /* make sure there's no pending/ongoing resume */ 1268 flush_work(&fb_helper->resume_work); 1269 1270 if (suspend) { 1271 if (fb_helper->fbdev->state != FBINFO_STATE_RUNNING) 1272 return; 1273 1274 console_lock(); 1275 1276 } else { 1277 if (fb_helper->fbdev->state == FBINFO_STATE_RUNNING) 1278 return; 1279 1280 if (!console_trylock()) { 1281 schedule_work(&fb_helper->resume_work); 1282 return; 1283 } 1284 } 1285 1286 fb_set_suspend(fb_helper->fbdev, suspend); 1287 console_unlock(); 1288 } 1289 EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked); 1290 1291 static int setcmap_pseudo_palette(struct fb_cmap *cmap, struct fb_info *info) 1292 { 1293 u32 *palette = (u32 *)info->pseudo_palette; 1294 int i; 1295 1296 if (cmap->start + cmap->len > 16) 1297 return -EINVAL; 1298 1299 for (i = 0; i < cmap->len; ++i) { 1300 u16 red = cmap->red[i]; 1301 u16 green = cmap->green[i]; 1302 u16 blue = cmap->blue[i]; 1303 u32 value; 1304 1305 red >>= 16 - info->var.red.length; 1306 green >>= 16 - info->var.green.length; 1307 blue >>= 16 - info->var.blue.length; 1308 value = (red << info->var.red.offset) | 1309 (green << info->var.green.offset) | 1310 (blue << info->var.blue.offset); 1311 if (info->var.transp.length > 0) { 1312 u32 mask = (1 << info->var.transp.length) - 1; 1313 1314 mask <<= info->var.transp.offset; 1315 value |= mask; 1316 } 1317 palette[cmap->start + i] = value; 1318 } 1319 1320 return 0; 1321 } 1322 1323 static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info) 1324 { 1325 struct drm_fb_helper *fb_helper = info->par; 1326 struct drm_crtc *crtc; 1327 u16 *r, *g, *b; 1328 int i, ret = 0; 1329 1330 drm_modeset_lock_all(fb_helper->dev); 1331 for (i = 0; i < fb_helper->crtc_count; i++) { 1332 crtc = fb_helper->crtc_info[i].mode_set.crtc; 1333 if (!crtc->funcs->gamma_set || !crtc->gamma_size) 1334 return -EINVAL; 1335 1336 if (cmap->start + cmap->len > crtc->gamma_size) 1337 return -EINVAL; 1338 1339 r = crtc->gamma_store; 1340 g = r + crtc->gamma_size; 1341 b = g + crtc->gamma_size; 1342 1343 memcpy(r + cmap->start, cmap->red, cmap->len * sizeof(*r)); 1344 memcpy(g + cmap->start, cmap->green, cmap->len * sizeof(*g)); 1345 memcpy(b + cmap->start, cmap->blue, cmap->len * sizeof(*b)); 1346 1347 ret = crtc->funcs->gamma_set(crtc, r, g, b, 1348 crtc->gamma_size, NULL); 1349 if (ret) 1350 return ret; 1351 } 1352 drm_modeset_unlock_all(fb_helper->dev); 1353 1354 return ret; 1355 } 1356 1357 static struct drm_property_blob *setcmap_new_gamma_lut(struct drm_crtc *crtc, 1358 struct fb_cmap *cmap) 1359 { 1360 struct drm_device *dev = crtc->dev; 1361 struct drm_property_blob *gamma_lut; 1362 struct drm_color_lut *lut; 1363 int size = crtc->gamma_size; 1364 int i; 1365 1366 if (!size || cmap->start + cmap->len > size) 1367 return ERR_PTR(-EINVAL); 1368 1369 gamma_lut = drm_property_create_blob(dev, sizeof(*lut) * size, NULL); 1370 if (IS_ERR(gamma_lut)) 1371 return gamma_lut; 1372 1373 lut = gamma_lut->data; 1374 if (cmap->start || cmap->len != size) { 1375 u16 *r = crtc->gamma_store; 1376 u16 *g = r + crtc->gamma_size; 1377 u16 *b = g + crtc->gamma_size; 1378 1379 for (i = 0; i < cmap->start; i++) { 1380 lut[i].red = r[i]; 1381 lut[i].green = g[i]; 1382 lut[i].blue = b[i]; 1383 } 1384 for (i = cmap->start + cmap->len; i < size; i++) { 1385 lut[i].red = r[i]; 1386 lut[i].green = g[i]; 1387 lut[i].blue = b[i]; 1388 } 1389 } 1390 1391 for (i = 0; i < cmap->len; i++) { 1392 lut[cmap->start + i].red = cmap->red[i]; 1393 lut[cmap->start + i].green = cmap->green[i]; 1394 lut[cmap->start + i].blue = cmap->blue[i]; 1395 } 1396 1397 return gamma_lut; 1398 } 1399 1400 static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info) 1401 { 1402 struct drm_fb_helper *fb_helper = info->par; 1403 struct drm_device *dev = fb_helper->dev; 1404 struct drm_property_blob *gamma_lut = NULL; 1405 struct drm_modeset_acquire_ctx ctx; 1406 struct drm_crtc_state *crtc_state; 1407 struct drm_atomic_state *state; 1408 struct drm_crtc *crtc; 1409 u16 *r, *g, *b; 1410 int i, ret = 0; 1411 bool replaced; 1412 1413 drm_modeset_acquire_init(&ctx, 0); 1414 1415 state = drm_atomic_state_alloc(dev); 1416 if (!state) { 1417 ret = -ENOMEM; 1418 goto out_ctx; 1419 } 1420 1421 state->acquire_ctx = &ctx; 1422 retry: 1423 for (i = 0; i < fb_helper->crtc_count; i++) { 1424 crtc = fb_helper->crtc_info[i].mode_set.crtc; 1425 1426 if (!gamma_lut) 1427 gamma_lut = setcmap_new_gamma_lut(crtc, cmap); 1428 if (IS_ERR(gamma_lut)) { 1429 ret = PTR_ERR(gamma_lut); 1430 gamma_lut = NULL; 1431 goto out_state; 1432 } 1433 1434 crtc_state = drm_atomic_get_crtc_state(state, crtc); 1435 if (IS_ERR(crtc_state)) { 1436 ret = PTR_ERR(crtc_state); 1437 goto out_state; 1438 } 1439 1440 replaced = drm_property_replace_blob(&crtc_state->degamma_lut, 1441 NULL); 1442 replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL); 1443 replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, 1444 gamma_lut); 1445 crtc_state->color_mgmt_changed |= replaced; 1446 } 1447 1448 ret = drm_atomic_commit(state); 1449 if (ret) 1450 goto out_state; 1451 1452 for (i = 0; i < fb_helper->crtc_count; i++) { 1453 crtc = fb_helper->crtc_info[i].mode_set.crtc; 1454 1455 r = crtc->gamma_store; 1456 g = r + crtc->gamma_size; 1457 b = g + crtc->gamma_size; 1458 1459 memcpy(r + cmap->start, cmap->red, cmap->len * sizeof(*r)); 1460 memcpy(g + cmap->start, cmap->green, cmap->len * sizeof(*g)); 1461 memcpy(b + cmap->start, cmap->blue, cmap->len * sizeof(*b)); 1462 } 1463 1464 out_state: 1465 if (ret == -EDEADLK) 1466 goto backoff; 1467 1468 drm_property_blob_put(gamma_lut); 1469 drm_atomic_state_put(state); 1470 out_ctx: 1471 drm_modeset_drop_locks(&ctx); 1472 drm_modeset_acquire_fini(&ctx); 1473 1474 return ret; 1475 1476 backoff: 1477 drm_atomic_state_clear(state); 1478 drm_modeset_backoff(&ctx); 1479 goto retry; 1480 } 1481 1482 /** 1483 * drm_fb_helper_setcmap - implementation for &fb_ops.fb_setcmap 1484 * @cmap: cmap to set 1485 * @info: fbdev registered by the helper 1486 */ 1487 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) 1488 { 1489 struct drm_fb_helper *fb_helper = info->par; 1490 int ret; 1491 1492 if (oops_in_progress) 1493 return -EBUSY; 1494 1495 mutex_lock(&fb_helper->lock); 1496 1497 if (!drm_fb_helper_is_bound(fb_helper)) { 1498 ret = -EBUSY; 1499 goto out; 1500 } 1501 1502 if (info->fix.visual == FB_VISUAL_TRUECOLOR) 1503 ret = setcmap_pseudo_palette(cmap, info); 1504 else if (drm_drv_uses_atomic_modeset(fb_helper->dev)) 1505 ret = setcmap_atomic(cmap, info); 1506 else 1507 ret = setcmap_legacy(cmap, info); 1508 1509 out: 1510 mutex_unlock(&fb_helper->lock); 1511 1512 return ret; 1513 } 1514 EXPORT_SYMBOL(drm_fb_helper_setcmap); 1515 1516 /** 1517 * drm_fb_helper_ioctl - legacy ioctl implementation 1518 * @info: fbdev registered by the helper 1519 * @cmd: ioctl command 1520 * @arg: ioctl argument 1521 * 1522 * A helper to implement the standard fbdev ioctl. Only 1523 * FBIO_WAITFORVSYNC is implemented for now. 1524 */ 1525 int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, 1526 unsigned long arg) 1527 { 1528 struct drm_fb_helper *fb_helper = info->par; 1529 struct drm_mode_set *mode_set; 1530 struct drm_crtc *crtc; 1531 int ret = 0; 1532 1533 mutex_lock(&fb_helper->lock); 1534 if (!drm_fb_helper_is_bound(fb_helper)) { 1535 ret = -EBUSY; 1536 goto unlock; 1537 } 1538 1539 switch (cmd) { 1540 case FBIO_WAITFORVSYNC: 1541 /* 1542 * Only consider the first CRTC. 1543 * 1544 * This ioctl is supposed to take the CRTC number as 1545 * an argument, but in fbdev times, what that number 1546 * was supposed to be was quite unclear, different 1547 * drivers were passing that argument differently 1548 * (some by reference, some by value), and most of the 1549 * userspace applications were just hardcoding 0 as an 1550 * argument. 1551 * 1552 * The first CRTC should be the integrated panel on 1553 * most drivers, so this is the best choice we can 1554 * make. If we're not smart enough here, one should 1555 * just consider switch the userspace to KMS. 1556 */ 1557 mode_set = &fb_helper->crtc_info[0].mode_set; 1558 crtc = mode_set->crtc; 1559 1560 /* 1561 * Only wait for a vblank event if the CRTC is 1562 * enabled, otherwise just don't do anythintg, 1563 * not even report an error. 1564 */ 1565 ret = drm_crtc_vblank_get(crtc); 1566 if (!ret) { 1567 drm_crtc_wait_one_vblank(crtc); 1568 drm_crtc_vblank_put(crtc); 1569 } 1570 1571 ret = 0; 1572 goto unlock; 1573 default: 1574 ret = -ENOTTY; 1575 } 1576 1577 unlock: 1578 mutex_unlock(&fb_helper->lock); 1579 return ret; 1580 } 1581 EXPORT_SYMBOL(drm_fb_helper_ioctl); 1582 1583 /** 1584 * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var 1585 * @var: screeninfo to check 1586 * @info: fbdev registered by the helper 1587 */ 1588 int drm_fb_helper_check_var(struct fb_var_screeninfo *var, 1589 struct fb_info *info) 1590 { 1591 struct drm_fb_helper *fb_helper = info->par; 1592 struct drm_framebuffer *fb = fb_helper->fb; 1593 int depth; 1594 1595 if (var->pixclock != 0 || in_dbg_master()) 1596 return -EINVAL; 1597 1598 /* 1599 * Changes struct fb_var_screeninfo are currently not pushed back 1600 * to KMS, hence fail if different settings are requested. 1601 */ 1602 if (var->bits_per_pixel != fb->format->cpp[0] * 8 || 1603 var->xres > fb->width || var->yres > fb->height || 1604 var->xres_virtual > fb->width || var->yres_virtual > fb->height) { 1605 DRM_DEBUG("fb requested width/height/bpp can't fit in current fb " 1606 "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n", 1607 var->xres, var->yres, var->bits_per_pixel, 1608 var->xres_virtual, var->yres_virtual, 1609 fb->width, fb->height, fb->format->cpp[0] * 8); 1610 return -EINVAL; 1611 } 1612 1613 switch (var->bits_per_pixel) { 1614 case 16: 1615 depth = (var->green.length == 6) ? 16 : 15; 1616 break; 1617 case 32: 1618 depth = (var->transp.length > 0) ? 32 : 24; 1619 break; 1620 default: 1621 depth = var->bits_per_pixel; 1622 break; 1623 } 1624 1625 switch (depth) { 1626 case 8: 1627 var->red.offset = 0; 1628 var->green.offset = 0; 1629 var->blue.offset = 0; 1630 var->red.length = 8; 1631 var->green.length = 8; 1632 var->blue.length = 8; 1633 var->transp.length = 0; 1634 var->transp.offset = 0; 1635 break; 1636 case 15: 1637 var->red.offset = 10; 1638 var->green.offset = 5; 1639 var->blue.offset = 0; 1640 var->red.length = 5; 1641 var->green.length = 5; 1642 var->blue.length = 5; 1643 var->transp.length = 1; 1644 var->transp.offset = 15; 1645 break; 1646 case 16: 1647 var->red.offset = 11; 1648 var->green.offset = 5; 1649 var->blue.offset = 0; 1650 var->red.length = 5; 1651 var->green.length = 6; 1652 var->blue.length = 5; 1653 var->transp.length = 0; 1654 var->transp.offset = 0; 1655 break; 1656 case 24: 1657 var->red.offset = 16; 1658 var->green.offset = 8; 1659 var->blue.offset = 0; 1660 var->red.length = 8; 1661 var->green.length = 8; 1662 var->blue.length = 8; 1663 var->transp.length = 0; 1664 var->transp.offset = 0; 1665 break; 1666 case 32: 1667 var->red.offset = 16; 1668 var->green.offset = 8; 1669 var->blue.offset = 0; 1670 var->red.length = 8; 1671 var->green.length = 8; 1672 var->blue.length = 8; 1673 var->transp.length = 8; 1674 var->transp.offset = 24; 1675 break; 1676 default: 1677 return -EINVAL; 1678 } 1679 return 0; 1680 } 1681 EXPORT_SYMBOL(drm_fb_helper_check_var); 1682 1683 /** 1684 * drm_fb_helper_set_par - implementation for &fb_ops.fb_set_par 1685 * @info: fbdev registered by the helper 1686 * 1687 * This will let fbcon do the mode init and is called at initialization time by 1688 * the fbdev core when registering the driver, and later on through the hotplug 1689 * callback. 1690 */ 1691 int drm_fb_helper_set_par(struct fb_info *info) 1692 { 1693 struct drm_fb_helper *fb_helper = info->par; 1694 struct fb_var_screeninfo *var = &info->var; 1695 1696 if (oops_in_progress) 1697 return -EBUSY; 1698 1699 if (var->pixclock != 0) { 1700 DRM_ERROR("PIXEL CLOCK SET\n"); 1701 return -EINVAL; 1702 } 1703 1704 drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper); 1705 1706 return 0; 1707 } 1708 EXPORT_SYMBOL(drm_fb_helper_set_par); 1709 1710 static void pan_set(struct drm_fb_helper *fb_helper, int x, int y) 1711 { 1712 int i; 1713 1714 for (i = 0; i < fb_helper->crtc_count; i++) { 1715 struct drm_mode_set *mode_set; 1716 1717 mode_set = &fb_helper->crtc_info[i].mode_set; 1718 1719 mode_set->x = x; 1720 mode_set->y = y; 1721 } 1722 } 1723 1724 static int pan_display_atomic(struct fb_var_screeninfo *var, 1725 struct fb_info *info) 1726 { 1727 struct drm_fb_helper *fb_helper = info->par; 1728 int ret; 1729 1730 pan_set(fb_helper, var->xoffset, var->yoffset); 1731 1732 ret = restore_fbdev_mode_atomic(fb_helper, true); 1733 if (!ret) { 1734 info->var.xoffset = var->xoffset; 1735 info->var.yoffset = var->yoffset; 1736 } else 1737 pan_set(fb_helper, info->var.xoffset, info->var.yoffset); 1738 1739 return ret; 1740 } 1741 1742 static int pan_display_legacy(struct fb_var_screeninfo *var, 1743 struct fb_info *info) 1744 { 1745 struct drm_fb_helper *fb_helper = info->par; 1746 struct drm_mode_set *modeset; 1747 int ret = 0; 1748 int i; 1749 1750 drm_modeset_lock_all(fb_helper->dev); 1751 for (i = 0; i < fb_helper->crtc_count; i++) { 1752 modeset = &fb_helper->crtc_info[i].mode_set; 1753 1754 modeset->x = var->xoffset; 1755 modeset->y = var->yoffset; 1756 1757 if (modeset->num_connectors) { 1758 ret = drm_mode_set_config_internal(modeset); 1759 if (!ret) { 1760 info->var.xoffset = var->xoffset; 1761 info->var.yoffset = var->yoffset; 1762 } 1763 } 1764 } 1765 drm_modeset_unlock_all(fb_helper->dev); 1766 1767 return ret; 1768 } 1769 1770 /** 1771 * drm_fb_helper_pan_display - implementation for &fb_ops.fb_pan_display 1772 * @var: updated screen information 1773 * @info: fbdev registered by the helper 1774 */ 1775 int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, 1776 struct fb_info *info) 1777 { 1778 struct drm_fb_helper *fb_helper = info->par; 1779 struct drm_device *dev = fb_helper->dev; 1780 int ret; 1781 1782 if (oops_in_progress) 1783 return -EBUSY; 1784 1785 mutex_lock(&fb_helper->lock); 1786 if (!drm_fb_helper_is_bound(fb_helper)) { 1787 mutex_unlock(&fb_helper->lock); 1788 return -EBUSY; 1789 } 1790 1791 if (drm_drv_uses_atomic_modeset(dev)) 1792 ret = pan_display_atomic(var, info); 1793 else 1794 ret = pan_display_legacy(var, info); 1795 mutex_unlock(&fb_helper->lock); 1796 1797 return ret; 1798 } 1799 EXPORT_SYMBOL(drm_fb_helper_pan_display); 1800 1801 /* 1802 * Allocates the backing storage and sets up the fbdev info structure through 1803 * the ->fb_probe callback. 1804 */ 1805 static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, 1806 int preferred_bpp) 1807 { 1808 int ret = 0; 1809 int crtc_count = 0; 1810 int i; 1811 struct drm_fb_helper_surface_size sizes; 1812 int gamma_size = 0; 1813 1814 memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size)); 1815 sizes.surface_depth = 24; 1816 sizes.surface_bpp = 32; 1817 sizes.fb_width = (u32)-1; 1818 sizes.fb_height = (u32)-1; 1819 1820 /* if driver picks 8 or 16 by default use that for both depth/bpp */ 1821 if (preferred_bpp != sizes.surface_bpp) 1822 sizes.surface_depth = sizes.surface_bpp = preferred_bpp; 1823 1824 /* first up get a count of crtcs now in use and new min/maxes width/heights */ 1825 drm_fb_helper_for_each_connector(fb_helper, i) { 1826 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; 1827 struct drm_cmdline_mode *cmdline_mode; 1828 1829 cmdline_mode = &fb_helper_conn->connector->cmdline_mode; 1830 1831 if (cmdline_mode->bpp_specified) { 1832 switch (cmdline_mode->bpp) { 1833 case 8: 1834 sizes.surface_depth = sizes.surface_bpp = 8; 1835 break; 1836 case 15: 1837 sizes.surface_depth = 15; 1838 sizes.surface_bpp = 16; 1839 break; 1840 case 16: 1841 sizes.surface_depth = sizes.surface_bpp = 16; 1842 break; 1843 case 24: 1844 sizes.surface_depth = sizes.surface_bpp = 24; 1845 break; 1846 case 32: 1847 sizes.surface_depth = 24; 1848 sizes.surface_bpp = 32; 1849 break; 1850 } 1851 break; 1852 } 1853 } 1854 1855 crtc_count = 0; 1856 for (i = 0; i < fb_helper->crtc_count; i++) { 1857 struct drm_display_mode *desired_mode; 1858 struct drm_mode_set *mode_set; 1859 int x, y, j; 1860 /* in case of tile group, are we the last tile vert or horiz? 1861 * If no tile group you are always the last one both vertically 1862 * and horizontally 1863 */ 1864 bool lastv = true, lasth = true; 1865 1866 desired_mode = fb_helper->crtc_info[i].desired_mode; 1867 mode_set = &fb_helper->crtc_info[i].mode_set; 1868 1869 if (!desired_mode) 1870 continue; 1871 1872 crtc_count++; 1873 1874 x = fb_helper->crtc_info[i].x; 1875 y = fb_helper->crtc_info[i].y; 1876 1877 if (gamma_size == 0) 1878 gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size; 1879 1880 sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width); 1881 sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height); 1882 1883 for (j = 0; j < mode_set->num_connectors; j++) { 1884 struct drm_connector *connector = mode_set->connectors[j]; 1885 1886 if (connector->has_tile) { 1887 lasth = (connector->tile_h_loc == (connector->num_h_tile - 1)); 1888 lastv = (connector->tile_v_loc == (connector->num_v_tile - 1)); 1889 /* cloning to multiple tiles is just crazy-talk, so: */ 1890 break; 1891 } 1892 } 1893 1894 if (lasth) 1895 sizes.fb_width = min_t(u32, desired_mode->hdisplay + x, sizes.fb_width); 1896 if (lastv) 1897 sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height); 1898 } 1899 1900 if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { 1901 DRM_INFO("Cannot find any crtc or sizes\n"); 1902 1903 /* First time: disable all crtc's.. */ 1904 if (!fb_helper->deferred_setup && !READ_ONCE(fb_helper->dev->master)) 1905 restore_fbdev_mode(fb_helper); 1906 return -EAGAIN; 1907 } 1908 1909 /* Handle our overallocation */ 1910 sizes.surface_height *= drm_fbdev_overalloc; 1911 sizes.surface_height /= 100; 1912 1913 /* push down into drivers */ 1914 ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes); 1915 if (ret < 0) 1916 return ret; 1917 1918 strcpy(fb_helper->fb->comm, "[fbcon]"); 1919 return 0; 1920 } 1921 1922 /** 1923 * drm_fb_helper_fill_fix - initializes fixed fbdev information 1924 * @info: fbdev registered by the helper 1925 * @pitch: desired pitch 1926 * @depth: desired depth 1927 * 1928 * Helper to fill in the fixed fbdev information useful for a non-accelerated 1929 * fbdev emulations. Drivers which support acceleration methods which impose 1930 * additional constraints need to set up their own limits. 1931 * 1932 * Drivers should call this (or their equivalent setup code) from their 1933 * &drm_fb_helper_funcs.fb_probe callback. 1934 */ 1935 void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, 1936 uint32_t depth) 1937 { 1938 info->fix.type = FB_TYPE_PACKED_PIXELS; 1939 info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR : 1940 FB_VISUAL_TRUECOLOR; 1941 info->fix.mmio_start = 0; 1942 info->fix.mmio_len = 0; 1943 info->fix.type_aux = 0; 1944 info->fix.xpanstep = 1; /* doing it in hw */ 1945 info->fix.ypanstep = 1; /* doing it in hw */ 1946 info->fix.ywrapstep = 0; 1947 info->fix.accel = FB_ACCEL_NONE; 1948 1949 info->fix.line_length = pitch; 1950 } 1951 EXPORT_SYMBOL(drm_fb_helper_fill_fix); 1952 1953 /** 1954 * drm_fb_helper_fill_var - initalizes variable fbdev information 1955 * @info: fbdev instance to set up 1956 * @fb_helper: fb helper instance to use as template 1957 * @fb_width: desired fb width 1958 * @fb_height: desired fb height 1959 * 1960 * Sets up the variable fbdev metainformation from the given fb helper instance 1961 * and the drm framebuffer allocated in &drm_fb_helper.fb. 1962 * 1963 * Drivers should call this (or their equivalent setup code) from their 1964 * &drm_fb_helper_funcs.fb_probe callback after having allocated the fbdev 1965 * backing storage framebuffer. 1966 */ 1967 void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, 1968 uint32_t fb_width, uint32_t fb_height) 1969 { 1970 struct drm_framebuffer *fb = fb_helper->fb; 1971 1972 info->pseudo_palette = fb_helper->pseudo_palette; 1973 info->var.xres_virtual = fb->width; 1974 info->var.yres_virtual = fb->height; 1975 info->var.bits_per_pixel = fb->format->cpp[0] * 8; 1976 info->var.accel_flags = FB_ACCELF_TEXT; 1977 info->var.xoffset = 0; 1978 info->var.yoffset = 0; 1979 info->var.activate = FB_ACTIVATE_NOW; 1980 1981 switch (fb->format->depth) { 1982 case 8: 1983 info->var.red.offset = 0; 1984 info->var.green.offset = 0; 1985 info->var.blue.offset = 0; 1986 info->var.red.length = 8; /* 8bit DAC */ 1987 info->var.green.length = 8; 1988 info->var.blue.length = 8; 1989 info->var.transp.offset = 0; 1990 info->var.transp.length = 0; 1991 break; 1992 case 15: 1993 info->var.red.offset = 10; 1994 info->var.green.offset = 5; 1995 info->var.blue.offset = 0; 1996 info->var.red.length = 5; 1997 info->var.green.length = 5; 1998 info->var.blue.length = 5; 1999 info->var.transp.offset = 15; 2000 info->var.transp.length = 1; 2001 break; 2002 case 16: 2003 info->var.red.offset = 11; 2004 info->var.green.offset = 5; 2005 info->var.blue.offset = 0; 2006 info->var.red.length = 5; 2007 info->var.green.length = 6; 2008 info->var.blue.length = 5; 2009 info->var.transp.offset = 0; 2010 break; 2011 case 24: 2012 info->var.red.offset = 16; 2013 info->var.green.offset = 8; 2014 info->var.blue.offset = 0; 2015 info->var.red.length = 8; 2016 info->var.green.length = 8; 2017 info->var.blue.length = 8; 2018 info->var.transp.offset = 0; 2019 info->var.transp.length = 0; 2020 break; 2021 case 32: 2022 info->var.red.offset = 16; 2023 info->var.green.offset = 8; 2024 info->var.blue.offset = 0; 2025 info->var.red.length = 8; 2026 info->var.green.length = 8; 2027 info->var.blue.length = 8; 2028 info->var.transp.offset = 24; 2029 info->var.transp.length = 8; 2030 break; 2031 default: 2032 break; 2033 } 2034 2035 info->var.xres = fb_width; 2036 info->var.yres = fb_height; 2037 } 2038 EXPORT_SYMBOL(drm_fb_helper_fill_var); 2039 2040 static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper, 2041 uint32_t maxX, 2042 uint32_t maxY) 2043 { 2044 struct drm_connector *connector; 2045 int i, count = 0; 2046 2047 drm_fb_helper_for_each_connector(fb_helper, i) { 2048 connector = fb_helper->connector_info[i]->connector; 2049 count += connector->funcs->fill_modes(connector, maxX, maxY); 2050 } 2051 2052 return count; 2053 } 2054 2055 struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height) 2056 { 2057 struct drm_display_mode *mode; 2058 2059 list_for_each_entry(mode, &fb_connector->connector->modes, head) { 2060 if (mode->hdisplay > width || 2061 mode->vdisplay > height) 2062 continue; 2063 if (mode->type & DRM_MODE_TYPE_PREFERRED) 2064 return mode; 2065 } 2066 return NULL; 2067 } 2068 EXPORT_SYMBOL(drm_has_preferred_mode); 2069 2070 static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) 2071 { 2072 return fb_connector->connector->cmdline_mode.specified; 2073 } 2074 2075 struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn) 2076 { 2077 struct drm_cmdline_mode *cmdline_mode; 2078 struct drm_display_mode *mode; 2079 bool prefer_non_interlace; 2080 2081 cmdline_mode = &fb_helper_conn->connector->cmdline_mode; 2082 if (cmdline_mode->specified == false) 2083 return NULL; 2084 2085 /* attempt to find a matching mode in the list of modes 2086 * we have gotten so far, if not add a CVT mode that conforms 2087 */ 2088 if (cmdline_mode->rb || cmdline_mode->margins) 2089 goto create_mode; 2090 2091 prefer_non_interlace = !cmdline_mode->interlace; 2092 again: 2093 list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { 2094 /* check width/height */ 2095 if (mode->hdisplay != cmdline_mode->xres || 2096 mode->vdisplay != cmdline_mode->yres) 2097 continue; 2098 2099 if (cmdline_mode->refresh_specified) { 2100 if (mode->vrefresh != cmdline_mode->refresh) 2101 continue; 2102 } 2103 2104 if (cmdline_mode->interlace) { 2105 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) 2106 continue; 2107 } else if (prefer_non_interlace) { 2108 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 2109 continue; 2110 } 2111 return mode; 2112 } 2113 2114 if (prefer_non_interlace) { 2115 prefer_non_interlace = false; 2116 goto again; 2117 } 2118 2119 create_mode: 2120 mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev, 2121 cmdline_mode); 2122 list_add(&mode->head, &fb_helper_conn->connector->modes); 2123 return mode; 2124 } 2125 EXPORT_SYMBOL(drm_pick_cmdline_mode); 2126 2127 static bool drm_connector_enabled(struct drm_connector *connector, bool strict) 2128 { 2129 bool enable; 2130 2131 if (connector->display_info.non_desktop) 2132 return false; 2133 2134 if (strict) 2135 enable = connector->status == connector_status_connected; 2136 else 2137 enable = connector->status != connector_status_disconnected; 2138 2139 return enable; 2140 } 2141 2142 static void drm_enable_connectors(struct drm_fb_helper *fb_helper, 2143 bool *enabled) 2144 { 2145 bool any_enabled = false; 2146 struct drm_connector *connector; 2147 int i = 0; 2148 2149 drm_fb_helper_for_each_connector(fb_helper, i) { 2150 connector = fb_helper->connector_info[i]->connector; 2151 enabled[i] = drm_connector_enabled(connector, true); 2152 DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, 2153 connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no"); 2154 2155 any_enabled |= enabled[i]; 2156 } 2157 2158 if (any_enabled) 2159 return; 2160 2161 drm_fb_helper_for_each_connector(fb_helper, i) { 2162 connector = fb_helper->connector_info[i]->connector; 2163 enabled[i] = drm_connector_enabled(connector, false); 2164 } 2165 } 2166 2167 static bool drm_target_cloned(struct drm_fb_helper *fb_helper, 2168 struct drm_display_mode **modes, 2169 struct drm_fb_offset *offsets, 2170 bool *enabled, int width, int height) 2171 { 2172 int count, i, j; 2173 bool can_clone = false; 2174 struct drm_fb_helper_connector *fb_helper_conn; 2175 struct drm_display_mode *dmt_mode, *mode; 2176 2177 /* only contemplate cloning in the single crtc case */ 2178 if (fb_helper->crtc_count > 1) 2179 return false; 2180 2181 count = 0; 2182 drm_fb_helper_for_each_connector(fb_helper, i) { 2183 if (enabled[i]) 2184 count++; 2185 } 2186 2187 /* only contemplate cloning if more than one connector is enabled */ 2188 if (count <= 1) 2189 return false; 2190 2191 /* check the command line or if nothing common pick 1024x768 */ 2192 can_clone = true; 2193 drm_fb_helper_for_each_connector(fb_helper, i) { 2194 if (!enabled[i]) 2195 continue; 2196 fb_helper_conn = fb_helper->connector_info[i]; 2197 modes[i] = drm_pick_cmdline_mode(fb_helper_conn); 2198 if (!modes[i]) { 2199 can_clone = false; 2200 break; 2201 } 2202 for (j = 0; j < i; j++) { 2203 if (!enabled[j]) 2204 continue; 2205 if (!drm_mode_match(modes[j], modes[i], 2206 DRM_MODE_MATCH_TIMINGS | 2207 DRM_MODE_MATCH_CLOCK | 2208 DRM_MODE_MATCH_FLAGS | 2209 DRM_MODE_MATCH_3D_FLAGS)) 2210 can_clone = false; 2211 } 2212 } 2213 2214 if (can_clone) { 2215 DRM_DEBUG_KMS("can clone using command line\n"); 2216 return true; 2217 } 2218 2219 /* try and find a 1024x768 mode on each connector */ 2220 can_clone = true; 2221 dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false); 2222 2223 drm_fb_helper_for_each_connector(fb_helper, i) { 2224 if (!enabled[i]) 2225 continue; 2226 2227 fb_helper_conn = fb_helper->connector_info[i]; 2228 list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { 2229 if (drm_mode_match(mode, dmt_mode, 2230 DRM_MODE_MATCH_TIMINGS | 2231 DRM_MODE_MATCH_CLOCK | 2232 DRM_MODE_MATCH_FLAGS | 2233 DRM_MODE_MATCH_3D_FLAGS)) 2234 modes[i] = mode; 2235 } 2236 if (!modes[i]) 2237 can_clone = false; 2238 } 2239 2240 if (can_clone) { 2241 DRM_DEBUG_KMS("can clone using 1024x768\n"); 2242 return true; 2243 } 2244 DRM_INFO("kms: can't enable cloning when we probably wanted to.\n"); 2245 return false; 2246 } 2247 2248 static int drm_get_tile_offsets(struct drm_fb_helper *fb_helper, 2249 struct drm_display_mode **modes, 2250 struct drm_fb_offset *offsets, 2251 int idx, 2252 int h_idx, int v_idx) 2253 { 2254 struct drm_fb_helper_connector *fb_helper_conn; 2255 int i; 2256 int hoffset = 0, voffset = 0; 2257 2258 drm_fb_helper_for_each_connector(fb_helper, i) { 2259 fb_helper_conn = fb_helper->connector_info[i]; 2260 if (!fb_helper_conn->connector->has_tile) 2261 continue; 2262 2263 if (!modes[i] && (h_idx || v_idx)) { 2264 DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i, 2265 fb_helper_conn->connector->base.id); 2266 continue; 2267 } 2268 if (fb_helper_conn->connector->tile_h_loc < h_idx) 2269 hoffset += modes[i]->hdisplay; 2270 2271 if (fb_helper_conn->connector->tile_v_loc < v_idx) 2272 voffset += modes[i]->vdisplay; 2273 } 2274 offsets[idx].x = hoffset; 2275 offsets[idx].y = voffset; 2276 DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx); 2277 return 0; 2278 } 2279 2280 static bool drm_target_preferred(struct drm_fb_helper *fb_helper, 2281 struct drm_display_mode **modes, 2282 struct drm_fb_offset *offsets, 2283 bool *enabled, int width, int height) 2284 { 2285 struct drm_fb_helper_connector *fb_helper_conn; 2286 const u64 mask = BIT_ULL(fb_helper->connector_count) - 1; 2287 u64 conn_configured = 0; 2288 int tile_pass = 0; 2289 int i; 2290 2291 retry: 2292 drm_fb_helper_for_each_connector(fb_helper, i) { 2293 fb_helper_conn = fb_helper->connector_info[i]; 2294 2295 if (conn_configured & BIT_ULL(i)) 2296 continue; 2297 2298 if (enabled[i] == false) { 2299 conn_configured |= BIT_ULL(i); 2300 continue; 2301 } 2302 2303 /* first pass over all the untiled connectors */ 2304 if (tile_pass == 0 && fb_helper_conn->connector->has_tile) 2305 continue; 2306 2307 if (tile_pass == 1) { 2308 if (fb_helper_conn->connector->tile_h_loc != 0 || 2309 fb_helper_conn->connector->tile_v_loc != 0) 2310 continue; 2311 2312 } else { 2313 if (fb_helper_conn->connector->tile_h_loc != tile_pass - 1 && 2314 fb_helper_conn->connector->tile_v_loc != tile_pass - 1) 2315 /* if this tile_pass doesn't cover any of the tiles - keep going */ 2316 continue; 2317 2318 /* 2319 * find the tile offsets for this pass - need to find 2320 * all tiles left and above 2321 */ 2322 drm_get_tile_offsets(fb_helper, modes, offsets, 2323 i, fb_helper_conn->connector->tile_h_loc, fb_helper_conn->connector->tile_v_loc); 2324 } 2325 DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", 2326 fb_helper_conn->connector->base.id); 2327 2328 /* got for command line mode first */ 2329 modes[i] = drm_pick_cmdline_mode(fb_helper_conn); 2330 if (!modes[i]) { 2331 DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n", 2332 fb_helper_conn->connector->base.id, fb_helper_conn->connector->tile_group ? fb_helper_conn->connector->tile_group->id : 0); 2333 modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height); 2334 } 2335 /* No preferred modes, pick one off the list */ 2336 if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) { 2337 list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head) 2338 break; 2339 } 2340 DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : 2341 "none"); 2342 conn_configured |= BIT_ULL(i); 2343 } 2344 2345 if ((conn_configured & mask) != mask) { 2346 tile_pass++; 2347 goto retry; 2348 } 2349 return true; 2350 } 2351 2352 static bool connector_has_possible_crtc(struct drm_connector *connector, 2353 struct drm_crtc *crtc) 2354 { 2355 struct drm_encoder *encoder; 2356 int i; 2357 2358 drm_connector_for_each_possible_encoder(connector, encoder, i) { 2359 if (encoder->possible_crtcs & drm_crtc_mask(crtc)) 2360 return true; 2361 } 2362 2363 return false; 2364 } 2365 2366 static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, 2367 struct drm_fb_helper_crtc **best_crtcs, 2368 struct drm_display_mode **modes, 2369 int n, int width, int height) 2370 { 2371 int c, o; 2372 struct drm_connector *connector; 2373 int my_score, best_score, score; 2374 struct drm_fb_helper_crtc **crtcs, *crtc; 2375 struct drm_fb_helper_connector *fb_helper_conn; 2376 2377 if (n == fb_helper->connector_count) 2378 return 0; 2379 2380 fb_helper_conn = fb_helper->connector_info[n]; 2381 connector = fb_helper_conn->connector; 2382 2383 best_crtcs[n] = NULL; 2384 best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height); 2385 if (modes[n] == NULL) 2386 return best_score; 2387 2388 crtcs = kcalloc(fb_helper->connector_count, 2389 sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); 2390 if (!crtcs) 2391 return best_score; 2392 2393 my_score = 1; 2394 if (connector->status == connector_status_connected) 2395 my_score++; 2396 if (drm_has_cmdline_mode(fb_helper_conn)) 2397 my_score++; 2398 if (drm_has_preferred_mode(fb_helper_conn, width, height)) 2399 my_score++; 2400 2401 /* 2402 * select a crtc for this connector and then attempt to configure 2403 * remaining connectors 2404 */ 2405 for (c = 0; c < fb_helper->crtc_count; c++) { 2406 crtc = &fb_helper->crtc_info[c]; 2407 2408 if (!connector_has_possible_crtc(connector, 2409 crtc->mode_set.crtc)) 2410 continue; 2411 2412 for (o = 0; o < n; o++) 2413 if (best_crtcs[o] == crtc) 2414 break; 2415 2416 if (o < n) { 2417 /* ignore cloning unless only a single crtc */ 2418 if (fb_helper->crtc_count > 1) 2419 continue; 2420 2421 if (!drm_mode_equal(modes[o], modes[n])) 2422 continue; 2423 } 2424 2425 crtcs[n] = crtc; 2426 memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *)); 2427 score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1, 2428 width, height); 2429 if (score > best_score) { 2430 best_score = score; 2431 memcpy(best_crtcs, crtcs, 2432 fb_helper->connector_count * 2433 sizeof(struct drm_fb_helper_crtc *)); 2434 } 2435 } 2436 2437 kfree(crtcs); 2438 return best_score; 2439 } 2440 2441 /* 2442 * This function checks if rotation is necessary because of panel orientation 2443 * and if it is, if it is supported. 2444 * If rotation is necessary and supported, its gets set in fb_crtc.rotation. 2445 * If rotation is necessary but not supported, a DRM_MODE_ROTATE_* flag gets 2446 * or-ed into fb_helper->sw_rotations. In drm_setup_crtcs_fb() we check if only 2447 * one bit is set and then we set fb_info.fbcon_rotate_hint to make fbcon do 2448 * the unsupported rotation. 2449 */ 2450 static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper, 2451 struct drm_fb_helper_crtc *fb_crtc, 2452 struct drm_connector *connector) 2453 { 2454 struct drm_plane *plane = fb_crtc->mode_set.crtc->primary; 2455 uint64_t valid_mask = 0; 2456 int i, rotation; 2457 2458 fb_crtc->rotation = DRM_MODE_ROTATE_0; 2459 2460 switch (connector->display_info.panel_orientation) { 2461 case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: 2462 rotation = DRM_MODE_ROTATE_180; 2463 break; 2464 case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: 2465 rotation = DRM_MODE_ROTATE_90; 2466 break; 2467 case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: 2468 rotation = DRM_MODE_ROTATE_270; 2469 break; 2470 default: 2471 rotation = DRM_MODE_ROTATE_0; 2472 } 2473 2474 /* 2475 * TODO: support 90 / 270 degree hardware rotation, 2476 * depending on the hardware this may require the framebuffer 2477 * to be in a specific tiling format. 2478 */ 2479 if (rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) { 2480 fb_helper->sw_rotations |= rotation; 2481 return; 2482 } 2483 2484 for (i = 0; i < plane->rotation_property->num_values; i++) 2485 valid_mask |= (1ULL << plane->rotation_property->values[i]); 2486 2487 if (!(rotation & valid_mask)) { 2488 fb_helper->sw_rotations |= rotation; 2489 return; 2490 } 2491 2492 fb_crtc->rotation = rotation; 2493 /* Rotating in hardware, fbcon should not rotate */ 2494 fb_helper->sw_rotations |= DRM_MODE_ROTATE_0; 2495 } 2496 2497 static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, 2498 u32 width, u32 height) 2499 { 2500 struct drm_device *dev = fb_helper->dev; 2501 struct drm_fb_helper_crtc **crtcs; 2502 struct drm_display_mode **modes; 2503 struct drm_fb_offset *offsets; 2504 bool *enabled; 2505 int i; 2506 2507 DRM_DEBUG_KMS("\n"); 2508 /* prevent concurrent modification of connector_count by hotplug */ 2509 lockdep_assert_held(&fb_helper->lock); 2510 2511 crtcs = kcalloc(fb_helper->connector_count, 2512 sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); 2513 modes = kcalloc(fb_helper->connector_count, 2514 sizeof(struct drm_display_mode *), GFP_KERNEL); 2515 offsets = kcalloc(fb_helper->connector_count, 2516 sizeof(struct drm_fb_offset), GFP_KERNEL); 2517 enabled = kcalloc(fb_helper->connector_count, 2518 sizeof(bool), GFP_KERNEL); 2519 if (!crtcs || !modes || !enabled || !offsets) { 2520 DRM_ERROR("Memory allocation failed\n"); 2521 goto out; 2522 } 2523 2524 mutex_lock(&fb_helper->dev->mode_config.mutex); 2525 if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0) 2526 DRM_DEBUG_KMS("No connectors reported connected with modes\n"); 2527 drm_enable_connectors(fb_helper, enabled); 2528 2529 if (!(fb_helper->funcs->initial_config && 2530 fb_helper->funcs->initial_config(fb_helper, crtcs, modes, 2531 offsets, 2532 enabled, width, height))) { 2533 memset(modes, 0, fb_helper->connector_count*sizeof(modes[0])); 2534 memset(crtcs, 0, fb_helper->connector_count*sizeof(crtcs[0])); 2535 memset(offsets, 0, fb_helper->connector_count*sizeof(offsets[0])); 2536 2537 if (!drm_target_cloned(fb_helper, modes, offsets, 2538 enabled, width, height) && 2539 !drm_target_preferred(fb_helper, modes, offsets, 2540 enabled, width, height)) 2541 DRM_ERROR("Unable to find initial modes\n"); 2542 2543 DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", 2544 width, height); 2545 2546 drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height); 2547 } 2548 mutex_unlock(&fb_helper->dev->mode_config.mutex); 2549 2550 /* need to set the modesets up here for use later */ 2551 /* fill out the connector<->crtc mappings into the modesets */ 2552 for (i = 0; i < fb_helper->crtc_count; i++) 2553 drm_fb_helper_modeset_release(fb_helper, 2554 &fb_helper->crtc_info[i].mode_set); 2555 2556 fb_helper->sw_rotations = 0; 2557 drm_fb_helper_for_each_connector(fb_helper, i) { 2558 struct drm_display_mode *mode = modes[i]; 2559 struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; 2560 struct drm_fb_offset *offset = &offsets[i]; 2561 2562 if (mode && fb_crtc) { 2563 struct drm_mode_set *modeset = &fb_crtc->mode_set; 2564 struct drm_connector *connector = 2565 fb_helper->connector_info[i]->connector; 2566 2567 DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n", 2568 mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y); 2569 2570 fb_crtc->desired_mode = mode; 2571 fb_crtc->x = offset->x; 2572 fb_crtc->y = offset->y; 2573 modeset->mode = drm_mode_duplicate(dev, 2574 fb_crtc->desired_mode); 2575 drm_connector_get(connector); 2576 drm_setup_crtc_rotation(fb_helper, fb_crtc, connector); 2577 modeset->connectors[modeset->num_connectors++] = connector; 2578 modeset->x = offset->x; 2579 modeset->y = offset->y; 2580 } 2581 } 2582 out: 2583 kfree(crtcs); 2584 kfree(modes); 2585 kfree(offsets); 2586 kfree(enabled); 2587 } 2588 2589 /* 2590 * This is a continuation of drm_setup_crtcs() that sets up anything related 2591 * to the framebuffer. During initialization, drm_setup_crtcs() is called before 2592 * the framebuffer has been allocated (fb_helper->fb and fb_helper->fbdev). 2593 * So, any setup that touches those fields needs to be done here instead of in 2594 * drm_setup_crtcs(). 2595 */ 2596 static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) 2597 { 2598 struct fb_info *info = fb_helper->fbdev; 2599 int i; 2600 2601 for (i = 0; i < fb_helper->crtc_count; i++) 2602 if (fb_helper->crtc_info[i].mode_set.num_connectors) 2603 fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; 2604 2605 mutex_lock(&fb_helper->dev->mode_config.mutex); 2606 drm_fb_helper_for_each_connector(fb_helper, i) { 2607 struct drm_connector *connector = 2608 fb_helper->connector_info[i]->connector; 2609 2610 /* use first connected connector for the physical dimensions */ 2611 if (connector->status == connector_status_connected) { 2612 info->var.width = connector->display_info.width_mm; 2613 info->var.height = connector->display_info.height_mm; 2614 break; 2615 } 2616 } 2617 mutex_unlock(&fb_helper->dev->mode_config.mutex); 2618 2619 switch (fb_helper->sw_rotations) { 2620 case DRM_MODE_ROTATE_0: 2621 info->fbcon_rotate_hint = FB_ROTATE_UR; 2622 break; 2623 case DRM_MODE_ROTATE_90: 2624 info->fbcon_rotate_hint = FB_ROTATE_CCW; 2625 break; 2626 case DRM_MODE_ROTATE_180: 2627 info->fbcon_rotate_hint = FB_ROTATE_UD; 2628 break; 2629 case DRM_MODE_ROTATE_270: 2630 info->fbcon_rotate_hint = FB_ROTATE_CW; 2631 break; 2632 default: 2633 /* 2634 * Multiple bits are set / multiple rotations requested 2635 * fbcon cannot handle separate rotation settings per 2636 * output, so fallback to unrotated. 2637 */ 2638 info->fbcon_rotate_hint = FB_ROTATE_UR; 2639 } 2640 } 2641 2642 /* Note: Drops fb_helper->lock before returning. */ 2643 static int 2644 __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper, 2645 int bpp_sel) 2646 { 2647 struct drm_device *dev = fb_helper->dev; 2648 struct fb_info *info; 2649 unsigned int width, height; 2650 int ret; 2651 2652 width = dev->mode_config.max_width; 2653 height = dev->mode_config.max_height; 2654 2655 drm_setup_crtcs(fb_helper, width, height); 2656 ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); 2657 if (ret < 0) { 2658 if (ret == -EAGAIN) { 2659 fb_helper->preferred_bpp = bpp_sel; 2660 fb_helper->deferred_setup = true; 2661 ret = 0; 2662 } 2663 mutex_unlock(&fb_helper->lock); 2664 2665 return ret; 2666 } 2667 drm_setup_crtcs_fb(fb_helper); 2668 2669 fb_helper->deferred_setup = false; 2670 2671 info = fb_helper->fbdev; 2672 info->var.pixclock = 0; 2673 2674 /* Need to drop locks to avoid recursive deadlock in 2675 * register_framebuffer. This is ok because the only thing left to do is 2676 * register the fbdev emulation instance in kernel_fb_helper_list. */ 2677 mutex_unlock(&fb_helper->lock); 2678 2679 ret = register_framebuffer(info); 2680 if (ret < 0) 2681 return ret; 2682 2683 dev_info(dev->dev, "fb%d: %s frame buffer device\n", 2684 info->node, info->fix.id); 2685 2686 mutex_lock(&kernel_fb_helper_lock); 2687 if (list_empty(&kernel_fb_helper_list)) 2688 register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); 2689 2690 list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); 2691 mutex_unlock(&kernel_fb_helper_lock); 2692 2693 return 0; 2694 } 2695 2696 /** 2697 * drm_fb_helper_initial_config - setup a sane initial connector configuration 2698 * @fb_helper: fb_helper device struct 2699 * @bpp_sel: bpp value to use for the framebuffer configuration 2700 * 2701 * Scans the CRTCs and connectors and tries to put together an initial setup. 2702 * At the moment, this is a cloned configuration across all heads with 2703 * a new framebuffer object as the backing store. 2704 * 2705 * Note that this also registers the fbdev and so allows userspace to call into 2706 * the driver through the fbdev interfaces. 2707 * 2708 * This function will call down into the &drm_fb_helper_funcs.fb_probe callback 2709 * to let the driver allocate and initialize the fbdev info structure and the 2710 * drm framebuffer used to back the fbdev. drm_fb_helper_fill_var() and 2711 * drm_fb_helper_fill_fix() are provided as helpers to setup simple default 2712 * values for the fbdev info structure. 2713 * 2714 * HANG DEBUGGING: 2715 * 2716 * When you have fbcon support built-in or already loaded, this function will do 2717 * a full modeset to setup the fbdev console. Due to locking misdesign in the 2718 * VT/fbdev subsystem that entire modeset sequence has to be done while holding 2719 * console_lock. Until console_unlock is called no dmesg lines will be sent out 2720 * to consoles, not even serial console. This means when your driver crashes, 2721 * you will see absolutely nothing else but a system stuck in this function, 2722 * with no further output. Any kind of printk() you place within your own driver 2723 * or in the drm core modeset code will also never show up. 2724 * 2725 * Standard debug practice is to run the fbcon setup without taking the 2726 * console_lock as a hack, to be able to see backtraces and crashes on the 2727 * serial line. This can be done by setting the fb.lockless_register_fb=1 kernel 2728 * cmdline option. 2729 * 2730 * The other option is to just disable fbdev emulation since very likely the 2731 * first modeset from userspace will crash in the same way, and is even easier 2732 * to debug. This can be done by setting the drm_kms_helper.fbdev_emulation=0 2733 * kernel cmdline option. 2734 * 2735 * RETURNS: 2736 * Zero if everything went ok, nonzero otherwise. 2737 */ 2738 int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) 2739 { 2740 int ret; 2741 2742 if (!drm_fbdev_emulation) 2743 return 0; 2744 2745 mutex_lock(&fb_helper->lock); 2746 ret = __drm_fb_helper_initial_config_and_unlock(fb_helper, bpp_sel); 2747 2748 return ret; 2749 } 2750 EXPORT_SYMBOL(drm_fb_helper_initial_config); 2751 2752 /** 2753 * drm_fb_helper_hotplug_event - respond to a hotplug notification by 2754 * probing all the outputs attached to the fb 2755 * @fb_helper: driver-allocated fbdev helper, can be NULL 2756 * 2757 * Scan the connectors attached to the fb_helper and try to put together a 2758 * setup after notification of a change in output configuration. 2759 * 2760 * Called at runtime, takes the mode config locks to be able to check/change the 2761 * modeset configuration. Must be run from process context (which usually means 2762 * either the output polling work or a work item launched from the driver's 2763 * hotplug interrupt). 2764 * 2765 * Note that drivers may call this even before calling 2766 * drm_fb_helper_initial_config but only after drm_fb_helper_init. This allows 2767 * for a race-free fbcon setup and will make sure that the fbdev emulation will 2768 * not miss any hotplug events. 2769 * 2770 * RETURNS: 2771 * 0 on success and a non-zero error code otherwise. 2772 */ 2773 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) 2774 { 2775 int err = 0; 2776 2777 if (!drm_fbdev_emulation || !fb_helper) 2778 return 0; 2779 2780 mutex_lock(&fb_helper->lock); 2781 if (fb_helper->deferred_setup) { 2782 err = __drm_fb_helper_initial_config_and_unlock(fb_helper, 2783 fb_helper->preferred_bpp); 2784 return err; 2785 } 2786 2787 if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) { 2788 fb_helper->delayed_hotplug = true; 2789 mutex_unlock(&fb_helper->lock); 2790 return err; 2791 } 2792 2793 DRM_DEBUG_KMS("\n"); 2794 2795 drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height); 2796 drm_setup_crtcs_fb(fb_helper); 2797 mutex_unlock(&fb_helper->lock); 2798 2799 drm_fb_helper_set_par(fb_helper->fbdev); 2800 2801 return 0; 2802 } 2803 EXPORT_SYMBOL(drm_fb_helper_hotplug_event); 2804 2805 /** 2806 * drm_fb_helper_fbdev_setup() - Setup fbdev emulation 2807 * @dev: DRM device 2808 * @fb_helper: fbdev helper structure to set up 2809 * @funcs: fbdev helper functions 2810 * @preferred_bpp: Preferred bits per pixel for the device. 2811 * @dev->mode_config.preferred_depth is used if this is zero. 2812 * @max_conn_count: Maximum number of connectors. 2813 * @dev->mode_config.num_connector is used if this is zero. 2814 * 2815 * This function sets up fbdev emulation and registers fbdev for access by 2816 * userspace. If all connectors are disconnected, setup is deferred to the next 2817 * time drm_fb_helper_hotplug_event() is called. 2818 * The caller must to provide a &drm_fb_helper_funcs->fb_probe callback 2819 * function. 2820 * 2821 * See also: drm_fb_helper_initial_config() 2822 * 2823 * Returns: 2824 * Zero on success or negative error code on failure. 2825 */ 2826 int drm_fb_helper_fbdev_setup(struct drm_device *dev, 2827 struct drm_fb_helper *fb_helper, 2828 const struct drm_fb_helper_funcs *funcs, 2829 unsigned int preferred_bpp, 2830 unsigned int max_conn_count) 2831 { 2832 int ret; 2833 2834 if (!preferred_bpp) 2835 preferred_bpp = dev->mode_config.preferred_depth; 2836 if (!preferred_bpp) 2837 preferred_bpp = 32; 2838 2839 if (!max_conn_count) 2840 max_conn_count = dev->mode_config.num_connector; 2841 if (!max_conn_count) { 2842 DRM_DEV_ERROR(dev->dev, "No connectors\n"); 2843 return -EINVAL; 2844 } 2845 2846 drm_fb_helper_prepare(dev, fb_helper, funcs); 2847 2848 ret = drm_fb_helper_init(dev, fb_helper, max_conn_count); 2849 if (ret < 0) { 2850 DRM_DEV_ERROR(dev->dev, "Failed to initialize fbdev helper\n"); 2851 return ret; 2852 } 2853 2854 ret = drm_fb_helper_single_add_all_connectors(fb_helper); 2855 if (ret < 0) { 2856 DRM_DEV_ERROR(dev->dev, "Failed to add connectors\n"); 2857 goto err_drm_fb_helper_fini; 2858 } 2859 2860 if (!drm_drv_uses_atomic_modeset(dev)) 2861 drm_helper_disable_unused_functions(dev); 2862 2863 ret = drm_fb_helper_initial_config(fb_helper, preferred_bpp); 2864 if (ret < 0) { 2865 DRM_DEV_ERROR(dev->dev, "Failed to set fbdev configuration\n"); 2866 goto err_drm_fb_helper_fini; 2867 } 2868 2869 return 0; 2870 2871 err_drm_fb_helper_fini: 2872 drm_fb_helper_fini(fb_helper); 2873 2874 return ret; 2875 } 2876 EXPORT_SYMBOL(drm_fb_helper_fbdev_setup); 2877 2878 /** 2879 * drm_fb_helper_fbdev_teardown - Tear down fbdev emulation 2880 * @dev: DRM device 2881 * 2882 * This function unregisters fbdev if not already done and cleans up the 2883 * associated resources including the &drm_framebuffer. 2884 * The driver is responsible for freeing the &drm_fb_helper structure which is 2885 * stored in &drm_device->fb_helper. Do note that this pointer has been cleared 2886 * when this function returns. 2887 * 2888 * In order to support device removal/unplug while file handles are still open, 2889 * drm_fb_helper_unregister_fbi() should be called on device removal and 2890 * drm_fb_helper_fbdev_teardown() in the &drm_driver->release callback when 2891 * file handles are closed. 2892 */ 2893 void drm_fb_helper_fbdev_teardown(struct drm_device *dev) 2894 { 2895 struct drm_fb_helper *fb_helper = dev->fb_helper; 2896 struct fb_ops *fbops = NULL; 2897 2898 if (!fb_helper) 2899 return; 2900 2901 /* Unregister if it hasn't been done already */ 2902 if (fb_helper->fbdev && fb_helper->fbdev->dev) 2903 drm_fb_helper_unregister_fbi(fb_helper); 2904 2905 if (fb_helper->fbdev && fb_helper->fbdev->fbdefio) { 2906 fb_deferred_io_cleanup(fb_helper->fbdev); 2907 kfree(fb_helper->fbdev->fbdefio); 2908 fbops = fb_helper->fbdev->fbops; 2909 } 2910 2911 drm_fb_helper_fini(fb_helper); 2912 kfree(fbops); 2913 2914 if (fb_helper->fb) 2915 drm_framebuffer_remove(fb_helper->fb); 2916 } 2917 EXPORT_SYMBOL(drm_fb_helper_fbdev_teardown); 2918 2919 /** 2920 * drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation 2921 * @dev: DRM device 2922 * 2923 * This function can be used as the &drm_driver->lastclose callback for drivers 2924 * that only need to call drm_fb_helper_restore_fbdev_mode_unlocked(). 2925 */ 2926 void drm_fb_helper_lastclose(struct drm_device *dev) 2927 { 2928 drm_fb_helper_restore_fbdev_mode_unlocked(dev->fb_helper); 2929 } 2930 EXPORT_SYMBOL(drm_fb_helper_lastclose); 2931 2932 /** 2933 * drm_fb_helper_output_poll_changed - DRM mode config \.output_poll_changed 2934 * helper for fbdev emulation 2935 * @dev: DRM device 2936 * 2937 * This function can be used as the 2938 * &drm_mode_config_funcs.output_poll_changed callback for drivers that only 2939 * need to call drm_fb_helper_hotplug_event(). 2940 */ 2941 void drm_fb_helper_output_poll_changed(struct drm_device *dev) 2942 { 2943 drm_fb_helper_hotplug_event(dev->fb_helper); 2944 } 2945 EXPORT_SYMBOL(drm_fb_helper_output_poll_changed); 2946 2947 /* @user: 1=userspace, 0=fbcon */ 2948 static int drm_fbdev_fb_open(struct fb_info *info, int user) 2949 { 2950 struct drm_fb_helper *fb_helper = info->par; 2951 2952 if (!try_module_get(fb_helper->dev->driver->fops->owner)) 2953 return -ENODEV; 2954 2955 return 0; 2956 } 2957 2958 static int drm_fbdev_fb_release(struct fb_info *info, int user) 2959 { 2960 struct drm_fb_helper *fb_helper = info->par; 2961 2962 module_put(fb_helper->dev->driver->fops->owner); 2963 2964 return 0; 2965 } 2966 2967 /* 2968 * fb_ops.fb_destroy is called by the last put_fb_info() call at the end of 2969 * unregister_framebuffer() or fb_release(). 2970 */ 2971 static void drm_fbdev_fb_destroy(struct fb_info *info) 2972 { 2973 struct drm_fb_helper *fb_helper = info->par; 2974 struct fb_info *fbi = fb_helper->fbdev; 2975 struct fb_ops *fbops = NULL; 2976 void *shadow = NULL; 2977 2978 if (fbi->fbdefio) { 2979 fb_deferred_io_cleanup(fbi); 2980 shadow = fbi->screen_buffer; 2981 fbops = fbi->fbops; 2982 } 2983 2984 drm_fb_helper_fini(fb_helper); 2985 2986 if (shadow) { 2987 vfree(shadow); 2988 kfree(fbops); 2989 } 2990 2991 drm_client_framebuffer_delete(fb_helper->buffer); 2992 /* 2993 * FIXME: 2994 * Remove conditional when all CMA drivers have been moved over to using 2995 * drm_fbdev_generic_setup(). 2996 */ 2997 if (fb_helper->client.funcs) { 2998 drm_client_release(&fb_helper->client); 2999 kfree(fb_helper); 3000 } 3001 } 3002 3003 static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) 3004 { 3005 struct drm_fb_helper *fb_helper = info->par; 3006 3007 if (fb_helper->dev->driver->gem_prime_mmap) 3008 return fb_helper->dev->driver->gem_prime_mmap(fb_helper->buffer->gem, vma); 3009 else 3010 return -ENODEV; 3011 } 3012 3013 static struct fb_ops drm_fbdev_fb_ops = { 3014 .owner = THIS_MODULE, 3015 DRM_FB_HELPER_DEFAULT_OPS, 3016 .fb_open = drm_fbdev_fb_open, 3017 .fb_release = drm_fbdev_fb_release, 3018 .fb_destroy = drm_fbdev_fb_destroy, 3019 .fb_mmap = drm_fbdev_fb_mmap, 3020 .fb_read = drm_fb_helper_sys_read, 3021 .fb_write = drm_fb_helper_sys_write, 3022 .fb_fillrect = drm_fb_helper_sys_fillrect, 3023 .fb_copyarea = drm_fb_helper_sys_copyarea, 3024 .fb_imageblit = drm_fb_helper_sys_imageblit, 3025 }; 3026 3027 static struct fb_deferred_io drm_fbdev_defio = { 3028 .delay = HZ / 20, 3029 .deferred_io = drm_fb_helper_deferred_io, 3030 }; 3031 3032 /** 3033 * drm_fb_helper_generic_probe - Generic fbdev emulation probe helper 3034 * @fb_helper: fbdev helper structure 3035 * @sizes: describes fbdev size and scanout surface size 3036 * 3037 * This function uses the client API to crate a framebuffer backed by a dumb buffer. 3038 * 3039 * The _sys_ versions are used for &fb_ops.fb_read, fb_write, fb_fillrect, 3040 * fb_copyarea, fb_imageblit. 3041 * 3042 * Returns: 3043 * Zero on success or negative error code on failure. 3044 */ 3045 int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper, 3046 struct drm_fb_helper_surface_size *sizes) 3047 { 3048 struct drm_client_dev *client = &fb_helper->client; 3049 struct drm_client_buffer *buffer; 3050 struct drm_framebuffer *fb; 3051 struct fb_info *fbi; 3052 u32 format; 3053 int ret; 3054 3055 DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n", 3056 sizes->surface_width, sizes->surface_height, 3057 sizes->surface_bpp); 3058 3059 format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); 3060 buffer = drm_client_framebuffer_create(client, sizes->surface_width, 3061 sizes->surface_height, format); 3062 if (IS_ERR(buffer)) 3063 return PTR_ERR(buffer); 3064 3065 fb_helper->buffer = buffer; 3066 fb_helper->fb = buffer->fb; 3067 fb = buffer->fb; 3068 3069 fbi = drm_fb_helper_alloc_fbi(fb_helper); 3070 if (IS_ERR(fbi)) { 3071 ret = PTR_ERR(fbi); 3072 goto err_free_buffer; 3073 } 3074 3075 fbi->par = fb_helper; 3076 fbi->fbops = &drm_fbdev_fb_ops; 3077 fbi->screen_size = fb->height * fb->pitches[0]; 3078 fbi->fix.smem_len = fbi->screen_size; 3079 fbi->screen_buffer = buffer->vaddr; 3080 strcpy(fbi->fix.id, "DRM emulated"); 3081 3082 drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth); 3083 drm_fb_helper_fill_var(fbi, fb_helper, sizes->fb_width, sizes->fb_height); 3084 3085 if (fb->funcs->dirty) { 3086 struct fb_ops *fbops; 3087 void *shadow; 3088 3089 /* 3090 * fb_deferred_io_cleanup() clears &fbops->fb_mmap so a per 3091 * instance version is necessary. 3092 */ 3093 fbops = kzalloc(sizeof(*fbops), GFP_KERNEL); 3094 shadow = vzalloc(fbi->screen_size); 3095 if (!fbops || !shadow) { 3096 kfree(fbops); 3097 vfree(shadow); 3098 ret = -ENOMEM; 3099 goto err_fb_info_destroy; 3100 } 3101 3102 *fbops = *fbi->fbops; 3103 fbi->fbops = fbops; 3104 fbi->screen_buffer = shadow; 3105 fbi->fbdefio = &drm_fbdev_defio; 3106 3107 fb_deferred_io_init(fbi); 3108 } 3109 3110 return 0; 3111 3112 err_fb_info_destroy: 3113 drm_fb_helper_fini(fb_helper); 3114 err_free_buffer: 3115 drm_client_framebuffer_delete(buffer); 3116 3117 return ret; 3118 } 3119 EXPORT_SYMBOL(drm_fb_helper_generic_probe); 3120 3121 static const struct drm_fb_helper_funcs drm_fb_helper_generic_funcs = { 3122 .fb_probe = drm_fb_helper_generic_probe, 3123 }; 3124 3125 static void drm_fbdev_client_unregister(struct drm_client_dev *client) 3126 { 3127 struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); 3128 3129 if (fb_helper->fbdev) { 3130 drm_fb_helper_unregister_fbi(fb_helper); 3131 /* drm_fbdev_fb_destroy() takes care of cleanup */ 3132 return; 3133 } 3134 3135 /* Did drm_fb_helper_fbdev_setup() run? */ 3136 if (fb_helper->dev) 3137 drm_fb_helper_fini(fb_helper); 3138 3139 drm_client_release(client); 3140 kfree(fb_helper); 3141 } 3142 3143 static int drm_fbdev_client_restore(struct drm_client_dev *client) 3144 { 3145 struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); 3146 3147 drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper); 3148 3149 return 0; 3150 } 3151 3152 static int drm_fbdev_client_hotplug(struct drm_client_dev *client) 3153 { 3154 struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); 3155 struct drm_device *dev = client->dev; 3156 int ret; 3157 3158 /* If drm_fb_helper_fbdev_setup() failed, we only try once */ 3159 if (!fb_helper->dev && fb_helper->funcs) 3160 return 0; 3161 3162 if (dev->fb_helper) 3163 return drm_fb_helper_hotplug_event(dev->fb_helper); 3164 3165 if (!dev->mode_config.num_connector) 3166 return 0; 3167 3168 ret = drm_fb_helper_fbdev_setup(dev, fb_helper, &drm_fb_helper_generic_funcs, 3169 fb_helper->preferred_bpp, 0); 3170 if (ret) { 3171 fb_helper->dev = NULL; 3172 fb_helper->fbdev = NULL; 3173 return ret; 3174 } 3175 3176 return 0; 3177 } 3178 3179 static const struct drm_client_funcs drm_fbdev_client_funcs = { 3180 .owner = THIS_MODULE, 3181 .unregister = drm_fbdev_client_unregister, 3182 .restore = drm_fbdev_client_restore, 3183 .hotplug = drm_fbdev_client_hotplug, 3184 }; 3185 3186 /** 3187 * drm_fb_helper_generic_fbdev_setup() - Setup generic fbdev emulation 3188 * @dev: DRM device 3189 * @preferred_bpp: Preferred bits per pixel for the device. 3190 * @dev->mode_config.preferred_depth is used if this is zero. 3191 * 3192 * This function sets up generic fbdev emulation for drivers that supports 3193 * dumb buffers with a virtual address and that can be mmap'ed. 3194 * 3195 * Restore, hotplug events and teardown are all taken care of. Drivers that do 3196 * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves. 3197 * Simple drivers might use drm_mode_config_helper_suspend(). 3198 * 3199 * Drivers that set the dirty callback on their framebuffer will get a shadow 3200 * fbdev buffer that is blitted onto the real buffer. This is done in order to 3201 * make deferred I/O work with all kinds of buffers. 3202 * 3203 * This function is safe to call even when there are no connectors present. 3204 * Setup will be retried on the next hotplug event. 3205 * 3206 * Returns: 3207 * Zero on success or negative error code on failure. 3208 */ 3209 int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp) 3210 { 3211 struct drm_fb_helper *fb_helper; 3212 int ret; 3213 3214 if (!drm_fbdev_emulation) 3215 return 0; 3216 3217 fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL); 3218 if (!fb_helper) 3219 return -ENOMEM; 3220 3221 ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs); 3222 if (ret) { 3223 kfree(fb_helper); 3224 return ret; 3225 } 3226 3227 drm_client_add(&fb_helper->client); 3228 3229 fb_helper->preferred_bpp = preferred_bpp; 3230 3231 drm_fbdev_client_hotplug(&fb_helper->client); 3232 3233 return 0; 3234 } 3235 EXPORT_SYMBOL(drm_fbdev_generic_setup); 3236 3237 /* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT) 3238 * but the module doesn't depend on any fb console symbols. At least 3239 * attempt to load fbcon to avoid leaving the system without a usable console. 3240 */ 3241 int __init drm_fb_helper_modinit(void) 3242 { 3243 #if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) && !defined(CONFIG_EXPERT) 3244 const char name[] = "fbcon"; 3245 struct module *fbcon; 3246 3247 mutex_lock(&module_mutex); 3248 fbcon = find_module(name); 3249 mutex_unlock(&module_mutex); 3250 3251 if (!fbcon) 3252 request_module_nowait(name); 3253 #endif 3254 return 0; 3255 } 3256 EXPORT_SYMBOL(drm_fb_helper_modinit); 3257