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/kernel.h> 33 #include <linux/sysrq.h> 34 #include <linux/slab.h> 35 #include <linux/fb.h> 36 #include <linux/module.h> 37 #include <drm/drmP.h> 38 #include <drm/drm_crtc.h> 39 #include <drm/drm_fb_helper.h> 40 #include <drm/drm_crtc_helper.h> 41 42 static LIST_HEAD(kernel_fb_helper_list); 43 44 /** 45 * DOC: fbdev helpers 46 * 47 * The fb helper functions are useful to provide an fbdev on top of a drm kernel 48 * mode setting driver. They can be used mostly independantely from the crtc 49 * helper functions used by many drivers to implement the kernel mode setting 50 * interfaces. 51 * 52 * Initialization is done as a three-step process with drm_fb_helper_init(), 53 * drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config(). 54 * Drivers with fancier requirements than the default beheviour can override the 55 * second step with their own code. Teardown is done with drm_fb_helper_fini(). 56 * 57 * At runtime drivers should restore the fbdev console by calling 58 * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They 59 * should also notify the fb helper code from updates to the output 60 * configuration by calling drm_fb_helper_hotplug_event(). For easier 61 * integration with the output polling code in drm_crtc_helper.c the modeset 62 * code proves a ->output_poll_changed callback. 63 * 64 * All other functions exported by the fb helper library can be used to 65 * implement the fbdev driver interface by the driver. 66 */ 67 68 /** 69 * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev 70 * emulation helper 71 * @fb_helper: fbdev initialized with drm_fb_helper_init 72 * 73 * This functions adds all the available connectors for use with the given 74 * fb_helper. This is a separate step to allow drivers to freely assign 75 * connectors to the fbdev, e.g. if some are reserved for special purposes or 76 * not adequate to be used for the fbcon. 77 * 78 * Since this is part of the initial setup before the fbdev is published, no 79 * locking is required. 80 */ 81 int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) 82 { 83 struct drm_device *dev = fb_helper->dev; 84 struct drm_connector *connector; 85 int i; 86 87 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 88 struct drm_fb_helper_connector *fb_helper_connector; 89 90 fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL); 91 if (!fb_helper_connector) 92 goto fail; 93 94 fb_helper_connector->connector = connector; 95 fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector; 96 } 97 return 0; 98 fail: 99 for (i = 0; i < fb_helper->connector_count; i++) { 100 kfree(fb_helper->connector_info[i]); 101 fb_helper->connector_info[i] = NULL; 102 } 103 fb_helper->connector_count = 0; 104 return -ENOMEM; 105 } 106 EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); 107 108 static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper) 109 { 110 struct drm_fb_helper_connector *fb_helper_conn; 111 int i; 112 113 for (i = 0; i < fb_helper->connector_count; i++) { 114 struct drm_cmdline_mode *mode; 115 struct drm_connector *connector; 116 char *option = NULL; 117 118 fb_helper_conn = fb_helper->connector_info[i]; 119 connector = fb_helper_conn->connector; 120 mode = &fb_helper_conn->cmdline_mode; 121 122 /* do something on return - turn off connector maybe */ 123 if (fb_get_options(drm_get_connector_name(connector), &option)) 124 continue; 125 126 if (drm_mode_parse_command_line_for_connector(option, 127 connector, 128 mode)) { 129 if (mode->force) { 130 const char *s; 131 switch (mode->force) { 132 case DRM_FORCE_OFF: 133 s = "OFF"; 134 break; 135 case DRM_FORCE_ON_DIGITAL: 136 s = "ON - dig"; 137 break; 138 default: 139 case DRM_FORCE_ON: 140 s = "ON"; 141 break; 142 } 143 144 DRM_INFO("forcing %s connector %s\n", 145 drm_get_connector_name(connector), s); 146 connector->force = mode->force; 147 } 148 149 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", 150 drm_get_connector_name(connector), 151 mode->xres, mode->yres, 152 mode->refresh_specified ? mode->refresh : 60, 153 mode->rb ? " reduced blanking" : "", 154 mode->margins ? " with margins" : "", 155 mode->interlace ? " interlaced" : ""); 156 } 157 158 } 159 return 0; 160 } 161 162 static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper) 163 { 164 uint16_t *r_base, *g_base, *b_base; 165 int i; 166 167 if (helper->funcs->gamma_get == NULL) 168 return; 169 170 r_base = crtc->gamma_store; 171 g_base = r_base + crtc->gamma_size; 172 b_base = g_base + crtc->gamma_size; 173 174 for (i = 0; i < crtc->gamma_size; i++) 175 helper->funcs->gamma_get(crtc, &r_base[i], &g_base[i], &b_base[i], i); 176 } 177 178 static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) 179 { 180 uint16_t *r_base, *g_base, *b_base; 181 182 if (crtc->funcs->gamma_set == NULL) 183 return; 184 185 r_base = crtc->gamma_store; 186 g_base = r_base + crtc->gamma_size; 187 b_base = g_base + crtc->gamma_size; 188 189 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); 190 } 191 192 /** 193 * drm_fb_helper_debug_enter - implementation for ->fb_debug_enter 194 * @info: fbdev registered by the helper 195 */ 196 int drm_fb_helper_debug_enter(struct fb_info *info) 197 { 198 struct drm_fb_helper *helper = info->par; 199 struct drm_crtc_helper_funcs *funcs; 200 int i; 201 202 if (list_empty(&kernel_fb_helper_list)) 203 return false; 204 205 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { 206 for (i = 0; i < helper->crtc_count; i++) { 207 struct drm_mode_set *mode_set = 208 &helper->crtc_info[i].mode_set; 209 210 if (!mode_set->crtc->enabled) 211 continue; 212 213 funcs = mode_set->crtc->helper_private; 214 drm_fb_helper_save_lut_atomic(mode_set->crtc, helper); 215 funcs->mode_set_base_atomic(mode_set->crtc, 216 mode_set->fb, 217 mode_set->x, 218 mode_set->y, 219 ENTER_ATOMIC_MODE_SET); 220 } 221 } 222 223 return 0; 224 } 225 EXPORT_SYMBOL(drm_fb_helper_debug_enter); 226 227 /* Find the real fb for a given fb helper CRTC */ 228 static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc) 229 { 230 struct drm_device *dev = crtc->dev; 231 struct drm_crtc *c; 232 233 list_for_each_entry(c, &dev->mode_config.crtc_list, head) { 234 if (crtc->base.id == c->base.id) 235 return c->fb; 236 } 237 238 return NULL; 239 } 240 241 /** 242 * drm_fb_helper_debug_leave - implementation for ->fb_debug_leave 243 * @info: fbdev registered by the helper 244 */ 245 int drm_fb_helper_debug_leave(struct fb_info *info) 246 { 247 struct drm_fb_helper *helper = info->par; 248 struct drm_crtc *crtc; 249 struct drm_crtc_helper_funcs *funcs; 250 struct drm_framebuffer *fb; 251 int i; 252 253 for (i = 0; i < helper->crtc_count; i++) { 254 struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; 255 crtc = mode_set->crtc; 256 funcs = crtc->helper_private; 257 fb = drm_mode_config_fb(crtc); 258 259 if (!crtc->enabled) 260 continue; 261 262 if (!fb) { 263 DRM_ERROR("no fb to restore??\n"); 264 continue; 265 } 266 267 drm_fb_helper_restore_lut_atomic(mode_set->crtc); 268 funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x, 269 crtc->y, LEAVE_ATOMIC_MODE_SET); 270 } 271 272 return 0; 273 } 274 EXPORT_SYMBOL(drm_fb_helper_debug_leave); 275 276 /** 277 * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration 278 * @fb_helper: fbcon to restore 279 * 280 * This should be called from driver's drm ->lastclose callback 281 * when implementing an fbcon on top of kms using this helper. This ensures that 282 * the user isn't greeted with a black screen when e.g. X dies. 283 */ 284 bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) 285 { 286 struct drm_device *dev = fb_helper->dev; 287 struct drm_plane *plane; 288 bool error = false; 289 int i; 290 291 drm_warn_on_modeset_not_all_locked(dev); 292 293 list_for_each_entry(plane, &dev->mode_config.plane_list, head) 294 drm_plane_force_disable(plane); 295 296 for (i = 0; i < fb_helper->crtc_count; i++) { 297 struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; 298 struct drm_crtc *crtc = mode_set->crtc; 299 int ret; 300 301 if (crtc->funcs->cursor_set) { 302 ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0); 303 if (ret) 304 error = true; 305 } 306 307 ret = drm_mode_set_config_internal(mode_set); 308 if (ret) 309 error = true; 310 } 311 return error; 312 } 313 EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode); 314 315 /* 316 * restore fbcon display for all kms driver's using this helper, used for sysrq 317 * and panic handling. 318 */ 319 static bool drm_fb_helper_force_kernel_mode(void) 320 { 321 bool ret, error = false; 322 struct drm_fb_helper *helper; 323 324 if (list_empty(&kernel_fb_helper_list)) 325 return false; 326 327 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { 328 if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF) 329 continue; 330 331 ret = drm_fb_helper_restore_fbdev_mode(helper); 332 if (ret) 333 error = true; 334 } 335 return error; 336 } 337 338 static int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed, 339 void *panic_str) 340 { 341 /* 342 * It's a waste of time and effort to switch back to text console 343 * if the kernel should reboot before panic messages can be seen. 344 */ 345 if (panic_timeout < 0) 346 return 0; 347 348 pr_err("panic occurred, switching back to text console\n"); 349 return drm_fb_helper_force_kernel_mode(); 350 } 351 352 static struct notifier_block paniced = { 353 .notifier_call = drm_fb_helper_panic, 354 }; 355 356 static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) 357 { 358 struct drm_device *dev = fb_helper->dev; 359 struct drm_crtc *crtc; 360 int bound = 0, crtcs_bound = 0; 361 362 /* Sometimes user space wants everything disabled, so don't steal the 363 * display if there's a master. */ 364 if (dev->primary->master) 365 return false; 366 367 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 368 if (crtc->fb) 369 crtcs_bound++; 370 if (crtc->fb == fb_helper->fb) 371 bound++; 372 } 373 374 if (bound < crtcs_bound) 375 return false; 376 377 return true; 378 } 379 380 #ifdef CONFIG_MAGIC_SYSRQ 381 static void drm_fb_helper_restore_work_fn(struct work_struct *ignored) 382 { 383 bool ret; 384 ret = drm_fb_helper_force_kernel_mode(); 385 if (ret == true) 386 DRM_ERROR("Failed to restore crtc configuration\n"); 387 } 388 static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn); 389 390 static void drm_fb_helper_sysrq(int dummy1) 391 { 392 schedule_work(&drm_fb_helper_restore_work); 393 } 394 395 static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { 396 .handler = drm_fb_helper_sysrq, 397 .help_msg = "force-fb(V)", 398 .action_msg = "Restore framebuffer console", 399 }; 400 #else 401 static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { }; 402 #endif 403 404 static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) 405 { 406 struct drm_fb_helper *fb_helper = info->par; 407 struct drm_device *dev = fb_helper->dev; 408 struct drm_crtc *crtc; 409 struct drm_connector *connector; 410 int i, j; 411 412 /* 413 * fbdev->blank can be called from irq context in case of a panic. 414 * Since we already have our own special panic handler which will 415 * restore the fbdev console mode completely, just bail out early. 416 */ 417 if (oops_in_progress) 418 return; 419 420 /* 421 * For each CRTC in this fb, turn the connectors on/off. 422 */ 423 drm_modeset_lock_all(dev); 424 if (!drm_fb_helper_is_bound(fb_helper)) { 425 drm_modeset_unlock_all(dev); 426 return; 427 } 428 429 for (i = 0; i < fb_helper->crtc_count; i++) { 430 crtc = fb_helper->crtc_info[i].mode_set.crtc; 431 432 if (!crtc->enabled) 433 continue; 434 435 /* Walk the connectors & encoders on this fb turning them on/off */ 436 for (j = 0; j < fb_helper->connector_count; j++) { 437 connector = fb_helper->connector_info[j]->connector; 438 connector->funcs->dpms(connector, dpms_mode); 439 drm_object_property_set_value(&connector->base, 440 dev->mode_config.dpms_property, dpms_mode); 441 } 442 } 443 drm_modeset_unlock_all(dev); 444 } 445 446 /** 447 * drm_fb_helper_blank - implementation for ->fb_blank 448 * @blank: desired blanking state 449 * @info: fbdev registered by the helper 450 */ 451 int drm_fb_helper_blank(int blank, struct fb_info *info) 452 { 453 switch (blank) { 454 /* Display: On; HSync: On, VSync: On */ 455 case FB_BLANK_UNBLANK: 456 drm_fb_helper_dpms(info, DRM_MODE_DPMS_ON); 457 break; 458 /* Display: Off; HSync: On, VSync: On */ 459 case FB_BLANK_NORMAL: 460 drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY); 461 break; 462 /* Display: Off; HSync: Off, VSync: On */ 463 case FB_BLANK_HSYNC_SUSPEND: 464 drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY); 465 break; 466 /* Display: Off; HSync: On, VSync: Off */ 467 case FB_BLANK_VSYNC_SUSPEND: 468 drm_fb_helper_dpms(info, DRM_MODE_DPMS_SUSPEND); 469 break; 470 /* Display: Off; HSync: Off, VSync: Off */ 471 case FB_BLANK_POWERDOWN: 472 drm_fb_helper_dpms(info, DRM_MODE_DPMS_OFF); 473 break; 474 } 475 return 0; 476 } 477 EXPORT_SYMBOL(drm_fb_helper_blank); 478 479 static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) 480 { 481 int i; 482 483 for (i = 0; i < helper->connector_count; i++) 484 kfree(helper->connector_info[i]); 485 kfree(helper->connector_info); 486 for (i = 0; i < helper->crtc_count; i++) { 487 kfree(helper->crtc_info[i].mode_set.connectors); 488 if (helper->crtc_info[i].mode_set.mode) 489 drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode); 490 } 491 kfree(helper->crtc_info); 492 } 493 494 /** 495 * drm_fb_helper_init - initialize a drm_fb_helper structure 496 * @dev: drm device 497 * @fb_helper: driver-allocated fbdev helper structure to initialize 498 * @crtc_count: maximum number of crtcs to support in this fbdev emulation 499 * @max_conn_count: max connector count 500 * 501 * This allocates the structures for the fbdev helper with the given limits. 502 * Note that this won't yet touch the hardware (through the driver interfaces) 503 * nor register the fbdev. This is only done in drm_fb_helper_initial_config() 504 * to allow driver writes more control over the exact init sequence. 505 * 506 * Drivers must set fb_helper->funcs before calling 507 * drm_fb_helper_initial_config(). 508 * 509 * RETURNS: 510 * Zero if everything went ok, nonzero otherwise. 511 */ 512 int drm_fb_helper_init(struct drm_device *dev, 513 struct drm_fb_helper *fb_helper, 514 int crtc_count, int max_conn_count) 515 { 516 struct drm_crtc *crtc; 517 int i; 518 519 fb_helper->dev = dev; 520 521 INIT_LIST_HEAD(&fb_helper->kernel_fb_list); 522 523 fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); 524 if (!fb_helper->crtc_info) 525 return -ENOMEM; 526 527 fb_helper->crtc_count = crtc_count; 528 fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL); 529 if (!fb_helper->connector_info) { 530 kfree(fb_helper->crtc_info); 531 return -ENOMEM; 532 } 533 fb_helper->connector_count = 0; 534 535 for (i = 0; i < crtc_count; i++) { 536 fb_helper->crtc_info[i].mode_set.connectors = 537 kcalloc(max_conn_count, 538 sizeof(struct drm_connector *), 539 GFP_KERNEL); 540 541 if (!fb_helper->crtc_info[i].mode_set.connectors) 542 goto out_free; 543 fb_helper->crtc_info[i].mode_set.num_connectors = 0; 544 } 545 546 i = 0; 547 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 548 fb_helper->crtc_info[i].mode_set.crtc = crtc; 549 i++; 550 } 551 552 return 0; 553 out_free: 554 drm_fb_helper_crtc_free(fb_helper); 555 return -ENOMEM; 556 } 557 EXPORT_SYMBOL(drm_fb_helper_init); 558 559 void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) 560 { 561 if (!list_empty(&fb_helper->kernel_fb_list)) { 562 list_del(&fb_helper->kernel_fb_list); 563 if (list_empty(&kernel_fb_helper_list)) { 564 pr_info("drm: unregistered panic notifier\n"); 565 atomic_notifier_chain_unregister(&panic_notifier_list, 566 &paniced); 567 unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); 568 } 569 } 570 571 drm_fb_helper_crtc_free(fb_helper); 572 573 } 574 EXPORT_SYMBOL(drm_fb_helper_fini); 575 576 static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, 577 u16 blue, u16 regno, struct fb_info *info) 578 { 579 struct drm_fb_helper *fb_helper = info->par; 580 struct drm_framebuffer *fb = fb_helper->fb; 581 int pindex; 582 583 if (info->fix.visual == FB_VISUAL_TRUECOLOR) { 584 u32 *palette; 585 u32 value; 586 /* place color in psuedopalette */ 587 if (regno > 16) 588 return -EINVAL; 589 palette = (u32 *)info->pseudo_palette; 590 red >>= (16 - info->var.red.length); 591 green >>= (16 - info->var.green.length); 592 blue >>= (16 - info->var.blue.length); 593 value = (red << info->var.red.offset) | 594 (green << info->var.green.offset) | 595 (blue << info->var.blue.offset); 596 if (info->var.transp.length > 0) { 597 u32 mask = (1 << info->var.transp.length) - 1; 598 mask <<= info->var.transp.offset; 599 value |= mask; 600 } 601 palette[regno] = value; 602 return 0; 603 } 604 605 /* 606 * The driver really shouldn't advertise pseudo/directcolor 607 * visuals if it can't deal with the palette. 608 */ 609 if (WARN_ON(!fb_helper->funcs->gamma_set || 610 !fb_helper->funcs->gamma_get)) 611 return -EINVAL; 612 613 pindex = regno; 614 615 if (fb->bits_per_pixel == 16) { 616 pindex = regno << 3; 617 618 if (fb->depth == 16 && regno > 63) 619 return -EINVAL; 620 if (fb->depth == 15 && regno > 31) 621 return -EINVAL; 622 623 if (fb->depth == 16) { 624 u16 r, g, b; 625 int i; 626 if (regno < 32) { 627 for (i = 0; i < 8; i++) 628 fb_helper->funcs->gamma_set(crtc, red, 629 green, blue, pindex + i); 630 } 631 632 fb_helper->funcs->gamma_get(crtc, &r, 633 &g, &b, 634 pindex >> 1); 635 636 for (i = 0; i < 4; i++) 637 fb_helper->funcs->gamma_set(crtc, r, 638 green, b, 639 (pindex >> 1) + i); 640 } 641 } 642 643 if (fb->depth != 16) 644 fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex); 645 return 0; 646 } 647 648 /** 649 * drm_fb_helper_setcmap - implementation for ->fb_setcmap 650 * @cmap: cmap to set 651 * @info: fbdev registered by the helper 652 */ 653 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) 654 { 655 struct drm_fb_helper *fb_helper = info->par; 656 struct drm_device *dev = fb_helper->dev; 657 struct drm_crtc_helper_funcs *crtc_funcs; 658 u16 *red, *green, *blue, *transp; 659 struct drm_crtc *crtc; 660 int i, j, rc = 0; 661 int start; 662 663 drm_modeset_lock_all(dev); 664 if (!drm_fb_helper_is_bound(fb_helper)) { 665 drm_modeset_unlock_all(dev); 666 return -EBUSY; 667 } 668 669 for (i = 0; i < fb_helper->crtc_count; i++) { 670 crtc = fb_helper->crtc_info[i].mode_set.crtc; 671 crtc_funcs = crtc->helper_private; 672 673 red = cmap->red; 674 green = cmap->green; 675 blue = cmap->blue; 676 transp = cmap->transp; 677 start = cmap->start; 678 679 for (j = 0; j < cmap->len; j++) { 680 u16 hred, hgreen, hblue, htransp = 0xffff; 681 682 hred = *red++; 683 hgreen = *green++; 684 hblue = *blue++; 685 686 if (transp) 687 htransp = *transp++; 688 689 rc = setcolreg(crtc, hred, hgreen, hblue, start++, info); 690 if (rc) 691 goto out; 692 } 693 if (crtc_funcs->load_lut) 694 crtc_funcs->load_lut(crtc); 695 } 696 out: 697 drm_modeset_unlock_all(dev); 698 return rc; 699 } 700 EXPORT_SYMBOL(drm_fb_helper_setcmap); 701 702 /** 703 * drm_fb_helper_check_var - implementation for ->fb_check_var 704 * @var: screeninfo to check 705 * @info: fbdev registered by the helper 706 */ 707 int drm_fb_helper_check_var(struct fb_var_screeninfo *var, 708 struct fb_info *info) 709 { 710 struct drm_fb_helper *fb_helper = info->par; 711 struct drm_framebuffer *fb = fb_helper->fb; 712 int depth; 713 714 if (var->pixclock != 0 || in_dbg_master()) 715 return -EINVAL; 716 717 /* Need to resize the fb object !!! */ 718 if (var->bits_per_pixel > fb->bits_per_pixel || 719 var->xres > fb->width || var->yres > fb->height || 720 var->xres_virtual > fb->width || var->yres_virtual > fb->height) { 721 DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb " 722 "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n", 723 var->xres, var->yres, var->bits_per_pixel, 724 var->xres_virtual, var->yres_virtual, 725 fb->width, fb->height, fb->bits_per_pixel); 726 return -EINVAL; 727 } 728 729 switch (var->bits_per_pixel) { 730 case 16: 731 depth = (var->green.length == 6) ? 16 : 15; 732 break; 733 case 32: 734 depth = (var->transp.length > 0) ? 32 : 24; 735 break; 736 default: 737 depth = var->bits_per_pixel; 738 break; 739 } 740 741 switch (depth) { 742 case 8: 743 var->red.offset = 0; 744 var->green.offset = 0; 745 var->blue.offset = 0; 746 var->red.length = 8; 747 var->green.length = 8; 748 var->blue.length = 8; 749 var->transp.length = 0; 750 var->transp.offset = 0; 751 break; 752 case 15: 753 var->red.offset = 10; 754 var->green.offset = 5; 755 var->blue.offset = 0; 756 var->red.length = 5; 757 var->green.length = 5; 758 var->blue.length = 5; 759 var->transp.length = 1; 760 var->transp.offset = 15; 761 break; 762 case 16: 763 var->red.offset = 11; 764 var->green.offset = 5; 765 var->blue.offset = 0; 766 var->red.length = 5; 767 var->green.length = 6; 768 var->blue.length = 5; 769 var->transp.length = 0; 770 var->transp.offset = 0; 771 break; 772 case 24: 773 var->red.offset = 16; 774 var->green.offset = 8; 775 var->blue.offset = 0; 776 var->red.length = 8; 777 var->green.length = 8; 778 var->blue.length = 8; 779 var->transp.length = 0; 780 var->transp.offset = 0; 781 break; 782 case 32: 783 var->red.offset = 16; 784 var->green.offset = 8; 785 var->blue.offset = 0; 786 var->red.length = 8; 787 var->green.length = 8; 788 var->blue.length = 8; 789 var->transp.length = 8; 790 var->transp.offset = 24; 791 break; 792 default: 793 return -EINVAL; 794 } 795 return 0; 796 } 797 EXPORT_SYMBOL(drm_fb_helper_check_var); 798 799 /** 800 * drm_fb_helper_set_par - implementation for ->fb_set_par 801 * @info: fbdev registered by the helper 802 * 803 * This will let fbcon do the mode init and is called at initialization time by 804 * the fbdev core when registering the driver, and later on through the hotplug 805 * callback. 806 */ 807 int drm_fb_helper_set_par(struct fb_info *info) 808 { 809 struct drm_fb_helper *fb_helper = info->par; 810 struct drm_device *dev = fb_helper->dev; 811 struct fb_var_screeninfo *var = &info->var; 812 int ret; 813 int i; 814 815 if (var->pixclock != 0) { 816 DRM_ERROR("PIXEL CLOCK SET\n"); 817 return -EINVAL; 818 } 819 820 drm_modeset_lock_all(dev); 821 for (i = 0; i < fb_helper->crtc_count; i++) { 822 ret = drm_mode_set_config_internal(&fb_helper->crtc_info[i].mode_set); 823 if (ret) { 824 drm_modeset_unlock_all(dev); 825 return ret; 826 } 827 } 828 drm_modeset_unlock_all(dev); 829 830 if (fb_helper->delayed_hotplug) { 831 fb_helper->delayed_hotplug = false; 832 drm_fb_helper_hotplug_event(fb_helper); 833 } 834 return 0; 835 } 836 EXPORT_SYMBOL(drm_fb_helper_set_par); 837 838 /** 839 * drm_fb_helper_pan_display - implementation for ->fb_pan_display 840 * @var: updated screen information 841 * @info: fbdev registered by the helper 842 */ 843 int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, 844 struct fb_info *info) 845 { 846 struct drm_fb_helper *fb_helper = info->par; 847 struct drm_device *dev = fb_helper->dev; 848 struct drm_mode_set *modeset; 849 int ret = 0; 850 int i; 851 852 drm_modeset_lock_all(dev); 853 if (!drm_fb_helper_is_bound(fb_helper)) { 854 drm_modeset_unlock_all(dev); 855 return -EBUSY; 856 } 857 858 for (i = 0; i < fb_helper->crtc_count; i++) { 859 modeset = &fb_helper->crtc_info[i].mode_set; 860 861 modeset->x = var->xoffset; 862 modeset->y = var->yoffset; 863 864 if (modeset->num_connectors) { 865 ret = drm_mode_set_config_internal(modeset); 866 if (!ret) { 867 info->var.xoffset = var->xoffset; 868 info->var.yoffset = var->yoffset; 869 } 870 } 871 } 872 drm_modeset_unlock_all(dev); 873 return ret; 874 } 875 EXPORT_SYMBOL(drm_fb_helper_pan_display); 876 877 /* 878 * Allocates the backing storage and sets up the fbdev info structure through 879 * the ->fb_probe callback and then registers the fbdev and sets up the panic 880 * notifier. 881 */ 882 static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, 883 int preferred_bpp) 884 { 885 int ret = 0; 886 int crtc_count = 0; 887 int i; 888 struct fb_info *info; 889 struct drm_fb_helper_surface_size sizes; 890 int gamma_size = 0; 891 892 memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size)); 893 sizes.surface_depth = 24; 894 sizes.surface_bpp = 32; 895 sizes.fb_width = (unsigned)-1; 896 sizes.fb_height = (unsigned)-1; 897 898 /* if driver picks 8 or 16 by default use that 899 for both depth/bpp */ 900 if (preferred_bpp != sizes.surface_bpp) 901 sizes.surface_depth = sizes.surface_bpp = preferred_bpp; 902 903 /* first up get a count of crtcs now in use and new min/maxes width/heights */ 904 for (i = 0; i < fb_helper->connector_count; i++) { 905 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; 906 struct drm_cmdline_mode *cmdline_mode; 907 908 cmdline_mode = &fb_helper_conn->cmdline_mode; 909 910 if (cmdline_mode->bpp_specified) { 911 switch (cmdline_mode->bpp) { 912 case 8: 913 sizes.surface_depth = sizes.surface_bpp = 8; 914 break; 915 case 15: 916 sizes.surface_depth = 15; 917 sizes.surface_bpp = 16; 918 break; 919 case 16: 920 sizes.surface_depth = sizes.surface_bpp = 16; 921 break; 922 case 24: 923 sizes.surface_depth = sizes.surface_bpp = 24; 924 break; 925 case 32: 926 sizes.surface_depth = 24; 927 sizes.surface_bpp = 32; 928 break; 929 } 930 break; 931 } 932 } 933 934 crtc_count = 0; 935 for (i = 0; i < fb_helper->crtc_count; i++) { 936 struct drm_display_mode *desired_mode; 937 desired_mode = fb_helper->crtc_info[i].desired_mode; 938 939 if (desired_mode) { 940 if (gamma_size == 0) 941 gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size; 942 if (desired_mode->hdisplay < sizes.fb_width) 943 sizes.fb_width = desired_mode->hdisplay; 944 if (desired_mode->vdisplay < sizes.fb_height) 945 sizes.fb_height = desired_mode->vdisplay; 946 if (desired_mode->hdisplay > sizes.surface_width) 947 sizes.surface_width = desired_mode->hdisplay; 948 if (desired_mode->vdisplay > sizes.surface_height) 949 sizes.surface_height = desired_mode->vdisplay; 950 crtc_count++; 951 } 952 } 953 954 if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { 955 /* hmm everyone went away - assume VGA cable just fell out 956 and will come back later. */ 957 DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n"); 958 sizes.fb_width = sizes.surface_width = 1024; 959 sizes.fb_height = sizes.surface_height = 768; 960 } 961 962 /* push down into drivers */ 963 ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes); 964 if (ret < 0) 965 return ret; 966 967 info = fb_helper->fbdev; 968 969 /* 970 * Set the fb pointer - usually drm_setup_crtcs does this for hotplug 971 * events, but at init time drm_setup_crtcs needs to be called before 972 * the fb is allocated (since we need to figure out the desired size of 973 * the fb before we can allocate it ...). Hence we need to fix things up 974 * here again. 975 */ 976 for (i = 0; i < fb_helper->crtc_count; i++) 977 if (fb_helper->crtc_info[i].mode_set.num_connectors) 978 fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; 979 980 981 info->var.pixclock = 0; 982 if (register_framebuffer(info) < 0) 983 return -EINVAL; 984 985 dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n", 986 info->node, info->fix.id); 987 988 /* Switch back to kernel console on panic */ 989 /* multi card linked list maybe */ 990 if (list_empty(&kernel_fb_helper_list)) { 991 dev_info(fb_helper->dev->dev, "registered panic notifier\n"); 992 atomic_notifier_chain_register(&panic_notifier_list, 993 &paniced); 994 register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); 995 } 996 997 list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); 998 999 return 0; 1000 } 1001 1002 /** 1003 * drm_fb_helper_fill_fix - initializes fixed fbdev information 1004 * @info: fbdev registered by the helper 1005 * @pitch: desired pitch 1006 * @depth: desired depth 1007 * 1008 * Helper to fill in the fixed fbdev information useful for a non-accelerated 1009 * fbdev emulations. Drivers which support acceleration methods which impose 1010 * additional constraints need to set up their own limits. 1011 * 1012 * Drivers should call this (or their equivalent setup code) from their 1013 * ->fb_probe callback. 1014 */ 1015 void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, 1016 uint32_t depth) 1017 { 1018 info->fix.type = FB_TYPE_PACKED_PIXELS; 1019 info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR : 1020 FB_VISUAL_TRUECOLOR; 1021 info->fix.mmio_start = 0; 1022 info->fix.mmio_len = 0; 1023 info->fix.type_aux = 0; 1024 info->fix.xpanstep = 1; /* doing it in hw */ 1025 info->fix.ypanstep = 1; /* doing it in hw */ 1026 info->fix.ywrapstep = 0; 1027 info->fix.accel = FB_ACCEL_NONE; 1028 info->fix.type_aux = 0; 1029 1030 info->fix.line_length = pitch; 1031 return; 1032 } 1033 EXPORT_SYMBOL(drm_fb_helper_fill_fix); 1034 1035 /** 1036 * drm_fb_helper_fill_var - initalizes variable fbdev information 1037 * @info: fbdev instance to set up 1038 * @fb_helper: fb helper instance to use as template 1039 * @fb_width: desired fb width 1040 * @fb_height: desired fb height 1041 * 1042 * Sets up the variable fbdev metainformation from the given fb helper instance 1043 * and the drm framebuffer allocated in fb_helper->fb. 1044 * 1045 * Drivers should call this (or their equivalent setup code) from their 1046 * ->fb_probe callback after having allocated the fbdev backing 1047 * storage framebuffer. 1048 */ 1049 void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, 1050 uint32_t fb_width, uint32_t fb_height) 1051 { 1052 struct drm_framebuffer *fb = fb_helper->fb; 1053 info->pseudo_palette = fb_helper->pseudo_palette; 1054 info->var.xres_virtual = fb->width; 1055 info->var.yres_virtual = fb->height; 1056 info->var.bits_per_pixel = fb->bits_per_pixel; 1057 info->var.accel_flags = FB_ACCELF_TEXT; 1058 info->var.xoffset = 0; 1059 info->var.yoffset = 0; 1060 info->var.activate = FB_ACTIVATE_NOW; 1061 info->var.height = -1; 1062 info->var.width = -1; 1063 1064 switch (fb->depth) { 1065 case 8: 1066 info->var.red.offset = 0; 1067 info->var.green.offset = 0; 1068 info->var.blue.offset = 0; 1069 info->var.red.length = 8; /* 8bit DAC */ 1070 info->var.green.length = 8; 1071 info->var.blue.length = 8; 1072 info->var.transp.offset = 0; 1073 info->var.transp.length = 0; 1074 break; 1075 case 15: 1076 info->var.red.offset = 10; 1077 info->var.green.offset = 5; 1078 info->var.blue.offset = 0; 1079 info->var.red.length = 5; 1080 info->var.green.length = 5; 1081 info->var.blue.length = 5; 1082 info->var.transp.offset = 15; 1083 info->var.transp.length = 1; 1084 break; 1085 case 16: 1086 info->var.red.offset = 11; 1087 info->var.green.offset = 5; 1088 info->var.blue.offset = 0; 1089 info->var.red.length = 5; 1090 info->var.green.length = 6; 1091 info->var.blue.length = 5; 1092 info->var.transp.offset = 0; 1093 break; 1094 case 24: 1095 info->var.red.offset = 16; 1096 info->var.green.offset = 8; 1097 info->var.blue.offset = 0; 1098 info->var.red.length = 8; 1099 info->var.green.length = 8; 1100 info->var.blue.length = 8; 1101 info->var.transp.offset = 0; 1102 info->var.transp.length = 0; 1103 break; 1104 case 32: 1105 info->var.red.offset = 16; 1106 info->var.green.offset = 8; 1107 info->var.blue.offset = 0; 1108 info->var.red.length = 8; 1109 info->var.green.length = 8; 1110 info->var.blue.length = 8; 1111 info->var.transp.offset = 24; 1112 info->var.transp.length = 8; 1113 break; 1114 default: 1115 break; 1116 } 1117 1118 info->var.xres = fb_width; 1119 info->var.yres = fb_height; 1120 } 1121 EXPORT_SYMBOL(drm_fb_helper_fill_var); 1122 1123 static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper, 1124 uint32_t maxX, 1125 uint32_t maxY) 1126 { 1127 struct drm_connector *connector; 1128 int count = 0; 1129 int i; 1130 1131 for (i = 0; i < fb_helper->connector_count; i++) { 1132 connector = fb_helper->connector_info[i]->connector; 1133 count += connector->funcs->fill_modes(connector, maxX, maxY); 1134 } 1135 1136 return count; 1137 } 1138 1139 static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height) 1140 { 1141 struct drm_display_mode *mode; 1142 1143 list_for_each_entry(mode, &fb_connector->connector->modes, head) { 1144 if (drm_mode_width(mode) > width || 1145 drm_mode_height(mode) > height) 1146 continue; 1147 if (mode->type & DRM_MODE_TYPE_PREFERRED) 1148 return mode; 1149 } 1150 return NULL; 1151 } 1152 1153 static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) 1154 { 1155 struct drm_cmdline_mode *cmdline_mode; 1156 cmdline_mode = &fb_connector->cmdline_mode; 1157 return cmdline_mode->specified; 1158 } 1159 1160 static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, 1161 int width, int height) 1162 { 1163 struct drm_cmdline_mode *cmdline_mode; 1164 struct drm_display_mode *mode = NULL; 1165 1166 cmdline_mode = &fb_helper_conn->cmdline_mode; 1167 if (cmdline_mode->specified == false) 1168 return mode; 1169 1170 /* attempt to find a matching mode in the list of modes 1171 * we have gotten so far, if not add a CVT mode that conforms 1172 */ 1173 if (cmdline_mode->rb || cmdline_mode->margins) 1174 goto create_mode; 1175 1176 list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { 1177 /* check width/height */ 1178 if (mode->hdisplay != cmdline_mode->xres || 1179 mode->vdisplay != cmdline_mode->yres) 1180 continue; 1181 1182 if (cmdline_mode->refresh_specified) { 1183 if (mode->vrefresh != cmdline_mode->refresh) 1184 continue; 1185 } 1186 1187 if (cmdline_mode->interlace) { 1188 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) 1189 continue; 1190 } 1191 return mode; 1192 } 1193 1194 create_mode: 1195 mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev, 1196 cmdline_mode); 1197 list_add(&mode->head, &fb_helper_conn->connector->modes); 1198 return mode; 1199 } 1200 1201 static bool drm_connector_enabled(struct drm_connector *connector, bool strict) 1202 { 1203 bool enable; 1204 1205 if (strict) 1206 enable = connector->status == connector_status_connected; 1207 else 1208 enable = connector->status != connector_status_disconnected; 1209 1210 return enable; 1211 } 1212 1213 static void drm_enable_connectors(struct drm_fb_helper *fb_helper, 1214 bool *enabled) 1215 { 1216 bool any_enabled = false; 1217 struct drm_connector *connector; 1218 int i = 0; 1219 1220 for (i = 0; i < fb_helper->connector_count; i++) { 1221 connector = fb_helper->connector_info[i]->connector; 1222 enabled[i] = drm_connector_enabled(connector, true); 1223 DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, 1224 enabled[i] ? "yes" : "no"); 1225 any_enabled |= enabled[i]; 1226 } 1227 1228 if (any_enabled) 1229 return; 1230 1231 for (i = 0; i < fb_helper->connector_count; i++) { 1232 connector = fb_helper->connector_info[i]->connector; 1233 enabled[i] = drm_connector_enabled(connector, false); 1234 } 1235 } 1236 1237 static bool drm_target_cloned(struct drm_fb_helper *fb_helper, 1238 struct drm_display_mode **modes, 1239 bool *enabled, int width, int height) 1240 { 1241 int count, i, j; 1242 bool can_clone = false; 1243 struct drm_fb_helper_connector *fb_helper_conn; 1244 struct drm_display_mode *dmt_mode, *mode; 1245 1246 /* only contemplate cloning in the single crtc case */ 1247 if (fb_helper->crtc_count > 1) 1248 return false; 1249 1250 count = 0; 1251 for (i = 0; i < fb_helper->connector_count; i++) { 1252 if (enabled[i]) 1253 count++; 1254 } 1255 1256 /* only contemplate cloning if more than one connector is enabled */ 1257 if (count <= 1) 1258 return false; 1259 1260 /* check the command line or if nothing common pick 1024x768 */ 1261 can_clone = true; 1262 for (i = 0; i < fb_helper->connector_count; i++) { 1263 if (!enabled[i]) 1264 continue; 1265 fb_helper_conn = fb_helper->connector_info[i]; 1266 modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height); 1267 if (!modes[i]) { 1268 can_clone = false; 1269 break; 1270 } 1271 for (j = 0; j < i; j++) { 1272 if (!enabled[j]) 1273 continue; 1274 if (!drm_mode_equal(modes[j], modes[i])) 1275 can_clone = false; 1276 } 1277 } 1278 1279 if (can_clone) { 1280 DRM_DEBUG_KMS("can clone using command line\n"); 1281 return true; 1282 } 1283 1284 /* try and find a 1024x768 mode on each connector */ 1285 can_clone = true; 1286 dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false); 1287 1288 for (i = 0; i < fb_helper->connector_count; i++) { 1289 1290 if (!enabled[i]) 1291 continue; 1292 1293 fb_helper_conn = fb_helper->connector_info[i]; 1294 list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { 1295 if (drm_mode_equal(mode, dmt_mode)) 1296 modes[i] = mode; 1297 } 1298 if (!modes[i]) 1299 can_clone = false; 1300 } 1301 1302 if (can_clone) { 1303 DRM_DEBUG_KMS("can clone using 1024x768\n"); 1304 return true; 1305 } 1306 DRM_INFO("kms: can't enable cloning when we probably wanted to.\n"); 1307 return false; 1308 } 1309 1310 static bool drm_target_preferred(struct drm_fb_helper *fb_helper, 1311 struct drm_display_mode **modes, 1312 bool *enabled, int width, int height) 1313 { 1314 struct drm_fb_helper_connector *fb_helper_conn; 1315 int i; 1316 1317 for (i = 0; i < fb_helper->connector_count; i++) { 1318 fb_helper_conn = fb_helper->connector_info[i]; 1319 1320 if (enabled[i] == false) 1321 continue; 1322 1323 DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", 1324 fb_helper_conn->connector->base.id); 1325 1326 /* got for command line mode first */ 1327 modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height); 1328 if (!modes[i]) { 1329 DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", 1330 fb_helper_conn->connector->base.id); 1331 modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height); 1332 } 1333 /* No preferred modes, pick one off the list */ 1334 if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) { 1335 list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head) 1336 break; 1337 } 1338 DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : 1339 "none"); 1340 } 1341 return true; 1342 } 1343 1344 static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, 1345 struct drm_fb_helper_crtc **best_crtcs, 1346 struct drm_display_mode **modes, 1347 int n, int width, int height) 1348 { 1349 int c, o; 1350 struct drm_device *dev = fb_helper->dev; 1351 struct drm_connector *connector; 1352 struct drm_connector_helper_funcs *connector_funcs; 1353 struct drm_encoder *encoder; 1354 int my_score, best_score, score; 1355 struct drm_fb_helper_crtc **crtcs, *crtc; 1356 struct drm_fb_helper_connector *fb_helper_conn; 1357 1358 if (n == fb_helper->connector_count) 1359 return 0; 1360 1361 fb_helper_conn = fb_helper->connector_info[n]; 1362 connector = fb_helper_conn->connector; 1363 1364 best_crtcs[n] = NULL; 1365 best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height); 1366 if (modes[n] == NULL) 1367 return best_score; 1368 1369 crtcs = kzalloc(dev->mode_config.num_connector * 1370 sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); 1371 if (!crtcs) 1372 return best_score; 1373 1374 my_score = 1; 1375 if (connector->status == connector_status_connected) 1376 my_score++; 1377 if (drm_has_cmdline_mode(fb_helper_conn)) 1378 my_score++; 1379 if (drm_has_preferred_mode(fb_helper_conn, width, height)) 1380 my_score++; 1381 1382 connector_funcs = connector->helper_private; 1383 encoder = connector_funcs->best_encoder(connector); 1384 if (!encoder) 1385 goto out; 1386 1387 /* select a crtc for this connector and then attempt to configure 1388 remaining connectors */ 1389 for (c = 0; c < fb_helper->crtc_count; c++) { 1390 crtc = &fb_helper->crtc_info[c]; 1391 1392 if ((encoder->possible_crtcs & (1 << c)) == 0) 1393 continue; 1394 1395 for (o = 0; o < n; o++) 1396 if (best_crtcs[o] == crtc) 1397 break; 1398 1399 if (o < n) { 1400 /* ignore cloning unless only a single crtc */ 1401 if (fb_helper->crtc_count > 1) 1402 continue; 1403 1404 if (!drm_mode_equal(modes[o], modes[n])) 1405 continue; 1406 } 1407 1408 crtcs[n] = crtc; 1409 memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *)); 1410 score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1, 1411 width, height); 1412 if (score > best_score) { 1413 best_score = score; 1414 memcpy(best_crtcs, crtcs, 1415 dev->mode_config.num_connector * 1416 sizeof(struct drm_fb_helper_crtc *)); 1417 } 1418 } 1419 out: 1420 kfree(crtcs); 1421 return best_score; 1422 } 1423 1424 static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) 1425 { 1426 struct drm_device *dev = fb_helper->dev; 1427 struct drm_fb_helper_crtc **crtcs; 1428 struct drm_display_mode **modes; 1429 struct drm_mode_set *modeset; 1430 bool *enabled; 1431 int width, height; 1432 int i; 1433 1434 DRM_DEBUG_KMS("\n"); 1435 1436 width = dev->mode_config.max_width; 1437 height = dev->mode_config.max_height; 1438 1439 crtcs = kcalloc(dev->mode_config.num_connector, 1440 sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); 1441 modes = kcalloc(dev->mode_config.num_connector, 1442 sizeof(struct drm_display_mode *), GFP_KERNEL); 1443 enabled = kcalloc(dev->mode_config.num_connector, 1444 sizeof(bool), GFP_KERNEL); 1445 if (!crtcs || !modes || !enabled) { 1446 DRM_ERROR("Memory allocation failed\n"); 1447 goto out; 1448 } 1449 1450 1451 drm_enable_connectors(fb_helper, enabled); 1452 1453 if (!(fb_helper->funcs->initial_config && 1454 fb_helper->funcs->initial_config(fb_helper, crtcs, modes, 1455 enabled, width, height))) { 1456 memset(modes, 0, dev->mode_config.num_connector*sizeof(modes[0])); 1457 memset(crtcs, 0, dev->mode_config.num_connector*sizeof(crtcs[0])); 1458 1459 if (!drm_target_cloned(fb_helper, 1460 modes, enabled, width, height) && 1461 !drm_target_preferred(fb_helper, 1462 modes, enabled, width, height)) 1463 DRM_ERROR("Unable to find initial modes\n"); 1464 1465 DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", 1466 width, height); 1467 1468 drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height); 1469 } 1470 1471 /* need to set the modesets up here for use later */ 1472 /* fill out the connector<->crtc mappings into the modesets */ 1473 for (i = 0; i < fb_helper->crtc_count; i++) { 1474 modeset = &fb_helper->crtc_info[i].mode_set; 1475 modeset->num_connectors = 0; 1476 modeset->fb = NULL; 1477 } 1478 1479 for (i = 0; i < fb_helper->connector_count; i++) { 1480 struct drm_display_mode *mode = modes[i]; 1481 struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; 1482 modeset = &fb_crtc->mode_set; 1483 1484 if (mode && fb_crtc) { 1485 DRM_DEBUG_KMS("desired mode %s set on crtc %d\n", 1486 mode->name, fb_crtc->mode_set.crtc->base.id); 1487 fb_crtc->desired_mode = mode; 1488 if (modeset->mode) 1489 drm_mode_destroy(dev, modeset->mode); 1490 modeset->mode = drm_mode_duplicate(dev, 1491 fb_crtc->desired_mode); 1492 modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector; 1493 modeset->fb = fb_helper->fb; 1494 } 1495 } 1496 1497 /* Clear out any old modes if there are no more connected outputs. */ 1498 for (i = 0; i < fb_helper->crtc_count; i++) { 1499 modeset = &fb_helper->crtc_info[i].mode_set; 1500 if (modeset->num_connectors == 0) { 1501 BUG_ON(modeset->fb); 1502 BUG_ON(modeset->num_connectors); 1503 if (modeset->mode) 1504 drm_mode_destroy(dev, modeset->mode); 1505 modeset->mode = NULL; 1506 } 1507 } 1508 out: 1509 kfree(crtcs); 1510 kfree(modes); 1511 kfree(enabled); 1512 } 1513 1514 /** 1515 * drm_fb_helper_initial_config - setup a sane initial connector configuration 1516 * @fb_helper: fb_helper device struct 1517 * @bpp_sel: bpp value to use for the framebuffer configuration 1518 * 1519 * Scans the CRTCs and connectors and tries to put together an initial setup. 1520 * At the moment, this is a cloned configuration across all heads with 1521 * a new framebuffer object as the backing store. 1522 * 1523 * Note that this also registers the fbdev and so allows userspace to call into 1524 * the driver through the fbdev interfaces. 1525 * 1526 * This function will call down into the ->fb_probe callback to let 1527 * the driver allocate and initialize the fbdev info structure and the drm 1528 * framebuffer used to back the fbdev. drm_fb_helper_fill_var() and 1529 * drm_fb_helper_fill_fix() are provided as helpers to setup simple default 1530 * values for the fbdev info structure. 1531 * 1532 * RETURNS: 1533 * Zero if everything went ok, nonzero otherwise. 1534 */ 1535 bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) 1536 { 1537 struct drm_device *dev = fb_helper->dev; 1538 int count = 0; 1539 1540 drm_fb_helper_parse_command_line(fb_helper); 1541 1542 count = drm_fb_helper_probe_connector_modes(fb_helper, 1543 dev->mode_config.max_width, 1544 dev->mode_config.max_height); 1545 /* 1546 * we shouldn't end up with no modes here. 1547 */ 1548 if (count == 0) 1549 dev_info(fb_helper->dev->dev, "No connectors reported connected with modes\n"); 1550 1551 drm_setup_crtcs(fb_helper); 1552 1553 return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); 1554 } 1555 EXPORT_SYMBOL(drm_fb_helper_initial_config); 1556 1557 /** 1558 * drm_fb_helper_hotplug_event - respond to a hotplug notification by 1559 * probing all the outputs attached to the fb 1560 * @fb_helper: the drm_fb_helper 1561 * 1562 * Scan the connectors attached to the fb_helper and try to put together a 1563 * setup after *notification of a change in output configuration. 1564 * 1565 * Called at runtime, takes the mode config locks to be able to check/change the 1566 * modeset configuration. Must be run from process context (which usually means 1567 * either the output polling work or a work item launched from the driver's 1568 * hotplug interrupt). 1569 * 1570 * Note that the driver must ensure that this is only called _after_ the fb has 1571 * been fully set up, i.e. after the call to drm_fb_helper_initial_config. 1572 * 1573 * RETURNS: 1574 * 0 on success and a non-zero error code otherwise. 1575 */ 1576 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) 1577 { 1578 struct drm_device *dev = fb_helper->dev; 1579 u32 max_width, max_height; 1580 1581 if (!fb_helper->fb) 1582 return 0; 1583 1584 mutex_lock(&fb_helper->dev->mode_config.mutex); 1585 if (!drm_fb_helper_is_bound(fb_helper)) { 1586 fb_helper->delayed_hotplug = true; 1587 mutex_unlock(&fb_helper->dev->mode_config.mutex); 1588 return 0; 1589 } 1590 DRM_DEBUG_KMS("\n"); 1591 1592 max_width = fb_helper->fb->width; 1593 max_height = fb_helper->fb->height; 1594 1595 drm_fb_helper_probe_connector_modes(fb_helper, max_width, max_height); 1596 mutex_unlock(&fb_helper->dev->mode_config.mutex); 1597 1598 drm_modeset_lock_all(dev); 1599 drm_setup_crtcs(fb_helper); 1600 drm_modeset_unlock_all(dev); 1601 drm_fb_helper_set_par(fb_helper->fbdev); 1602 1603 return 0; 1604 } 1605 EXPORT_SYMBOL(drm_fb_helper_hotplug_event); 1606 1607 /* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT) 1608 * but the module doesn't depend on any fb console symbols. At least 1609 * attempt to load fbcon to avoid leaving the system without a usable console. 1610 */ 1611 #if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) && !defined(CONFIG_EXPERT) 1612 static int __init drm_fb_helper_modinit(void) 1613 { 1614 const char *name = "fbcon"; 1615 struct module *fbcon; 1616 1617 mutex_lock(&module_mutex); 1618 fbcon = find_module(name); 1619 mutex_unlock(&module_mutex); 1620 1621 if (!fbcon) 1622 request_module_nowait(name); 1623 return 0; 1624 } 1625 1626 module_init(drm_fb_helper_modinit); 1627 #endif 1628