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