1 /* 2 * linux/drivers/video/fbmem.c 3 * 4 * Copyright (C) 1994 Martin Schaller 5 * 6 * 2001 - Documented with DocBook 7 * - Brad Douglas <brad@neruo.com> 8 * 9 * This file is subject to the terms and conditions of the GNU General Public 10 * License. See the file COPYING in the main directory of this archive 11 * for more details. 12 */ 13 14 #include <linux/module.h> 15 16 #include <linux/compat.h> 17 #include <linux/types.h> 18 #include <linux/errno.h> 19 #include <linux/kernel.h> 20 #include <linux/major.h> 21 #include <linux/slab.h> 22 #include <linux/mm.h> 23 #include <linux/mman.h> 24 #include <linux/vt.h> 25 #include <linux/init.h> 26 #include <linux/linux_logo.h> 27 #include <linux/proc_fs.h> 28 #include <linux/seq_file.h> 29 #include <linux/console.h> 30 #include <linux/kmod.h> 31 #include <linux/err.h> 32 #include <linux/device.h> 33 #include <linux/efi.h> 34 #include <linux/fb.h> 35 #include <linux/fbcon.h> 36 #include <linux/mem_encrypt.h> 37 #include <linux/pci.h> 38 39 #include <asm/fb.h> 40 41 42 /* 43 * Frame buffer device initialization and setup routines 44 */ 45 46 #define FBPIXMAPSIZE (1024 * 8) 47 48 static DEFINE_MUTEX(registration_lock); 49 50 struct fb_info *registered_fb[FB_MAX] __read_mostly; 51 EXPORT_SYMBOL(registered_fb); 52 53 int num_registered_fb __read_mostly; 54 EXPORT_SYMBOL(num_registered_fb); 55 56 bool fb_center_logo __read_mostly; 57 58 int fb_logo_count __read_mostly = -1; 59 60 static struct fb_info *get_fb_info(unsigned int idx) 61 { 62 struct fb_info *fb_info; 63 64 if (idx >= FB_MAX) 65 return ERR_PTR(-ENODEV); 66 67 mutex_lock(®istration_lock); 68 fb_info = registered_fb[idx]; 69 if (fb_info) 70 refcount_inc(&fb_info->count); 71 mutex_unlock(®istration_lock); 72 73 return fb_info; 74 } 75 76 static void put_fb_info(struct fb_info *fb_info) 77 { 78 if (!refcount_dec_and_test(&fb_info->count)) 79 return; 80 if (fb_info->fbops->fb_destroy) 81 fb_info->fbops->fb_destroy(fb_info); 82 } 83 84 /* 85 * Helpers 86 */ 87 88 int fb_get_color_depth(struct fb_var_screeninfo *var, 89 struct fb_fix_screeninfo *fix) 90 { 91 int depth = 0; 92 93 if (fix->visual == FB_VISUAL_MONO01 || 94 fix->visual == FB_VISUAL_MONO10) 95 depth = 1; 96 else { 97 if (var->green.length == var->blue.length && 98 var->green.length == var->red.length && 99 var->green.offset == var->blue.offset && 100 var->green.offset == var->red.offset) 101 depth = var->green.length; 102 else 103 depth = var->green.length + var->red.length + 104 var->blue.length; 105 } 106 107 return depth; 108 } 109 EXPORT_SYMBOL(fb_get_color_depth); 110 111 /* 112 * Data padding functions. 113 */ 114 void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height) 115 { 116 __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height); 117 } 118 EXPORT_SYMBOL(fb_pad_aligned_buffer); 119 120 void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height, 121 u32 shift_high, u32 shift_low, u32 mod) 122 { 123 u8 mask = (u8) (0xfff << shift_high), tmp; 124 int i, j; 125 126 for (i = height; i--; ) { 127 for (j = 0; j < idx; j++) { 128 tmp = dst[j]; 129 tmp &= mask; 130 tmp |= *src >> shift_low; 131 dst[j] = tmp; 132 tmp = *src << shift_high; 133 dst[j+1] = tmp; 134 src++; 135 } 136 tmp = dst[idx]; 137 tmp &= mask; 138 tmp |= *src >> shift_low; 139 dst[idx] = tmp; 140 if (shift_high < mod) { 141 tmp = *src << shift_high; 142 dst[idx+1] = tmp; 143 } 144 src++; 145 dst += d_pitch; 146 } 147 } 148 EXPORT_SYMBOL(fb_pad_unaligned_buffer); 149 150 /* 151 * we need to lock this section since fb_cursor 152 * may use fb_imageblit() 153 */ 154 char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size) 155 { 156 u32 align = buf->buf_align - 1, offset; 157 char *addr = buf->addr; 158 159 /* If IO mapped, we need to sync before access, no sharing of 160 * the pixmap is done 161 */ 162 if (buf->flags & FB_PIXMAP_IO) { 163 if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC)) 164 info->fbops->fb_sync(info); 165 return addr; 166 } 167 168 /* See if we fit in the remaining pixmap space */ 169 offset = buf->offset + align; 170 offset &= ~align; 171 if (offset + size > buf->size) { 172 /* We do not fit. In order to be able to re-use the buffer, 173 * we must ensure no asynchronous DMA'ing or whatever operation 174 * is in progress, we sync for that. 175 */ 176 if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC)) 177 info->fbops->fb_sync(info); 178 offset = 0; 179 } 180 buf->offset = offset + size; 181 addr += offset; 182 183 return addr; 184 } 185 EXPORT_SYMBOL(fb_get_buffer_offset); 186 187 #ifdef CONFIG_LOGO 188 189 static inline unsigned safe_shift(unsigned d, int n) 190 { 191 return n < 0 ? d >> -n : d << n; 192 } 193 194 static void fb_set_logocmap(struct fb_info *info, 195 const struct linux_logo *logo) 196 { 197 struct fb_cmap palette_cmap; 198 u16 palette_green[16]; 199 u16 palette_blue[16]; 200 u16 palette_red[16]; 201 int i, j, n; 202 const unsigned char *clut = logo->clut; 203 204 palette_cmap.start = 0; 205 palette_cmap.len = 16; 206 palette_cmap.red = palette_red; 207 palette_cmap.green = palette_green; 208 palette_cmap.blue = palette_blue; 209 palette_cmap.transp = NULL; 210 211 for (i = 0; i < logo->clutsize; i += n) { 212 n = logo->clutsize - i; 213 /* palette_cmap provides space for only 16 colors at once */ 214 if (n > 16) 215 n = 16; 216 palette_cmap.start = 32 + i; 217 palette_cmap.len = n; 218 for (j = 0; j < n; ++j) { 219 palette_cmap.red[j] = clut[0] << 8 | clut[0]; 220 palette_cmap.green[j] = clut[1] << 8 | clut[1]; 221 palette_cmap.blue[j] = clut[2] << 8 | clut[2]; 222 clut += 3; 223 } 224 fb_set_cmap(&palette_cmap, info); 225 } 226 } 227 228 static void fb_set_logo_truepalette(struct fb_info *info, 229 const struct linux_logo *logo, 230 u32 *palette) 231 { 232 static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; 233 unsigned char redmask, greenmask, bluemask; 234 int redshift, greenshift, blueshift; 235 int i; 236 const unsigned char *clut = logo->clut; 237 238 /* 239 * We have to create a temporary palette since console palette is only 240 * 16 colors long. 241 */ 242 /* Bug: Doesn't obey msb_right ... (who needs that?) */ 243 redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8]; 244 greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8]; 245 bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8]; 246 redshift = info->var.red.offset - (8 - info->var.red.length); 247 greenshift = info->var.green.offset - (8 - info->var.green.length); 248 blueshift = info->var.blue.offset - (8 - info->var.blue.length); 249 250 for ( i = 0; i < logo->clutsize; i++) { 251 palette[i+32] = (safe_shift((clut[0] & redmask), redshift) | 252 safe_shift((clut[1] & greenmask), greenshift) | 253 safe_shift((clut[2] & bluemask), blueshift)); 254 clut += 3; 255 } 256 } 257 258 static void fb_set_logo_directpalette(struct fb_info *info, 259 const struct linux_logo *logo, 260 u32 *palette) 261 { 262 int redshift, greenshift, blueshift; 263 int i; 264 265 redshift = info->var.red.offset; 266 greenshift = info->var.green.offset; 267 blueshift = info->var.blue.offset; 268 269 for (i = 32; i < 32 + logo->clutsize; i++) 270 palette[i] = i << redshift | i << greenshift | i << blueshift; 271 } 272 273 static void fb_set_logo(struct fb_info *info, 274 const struct linux_logo *logo, u8 *dst, 275 int depth) 276 { 277 int i, j, k; 278 const u8 *src = logo->data; 279 u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0; 280 u8 fg = 1, d; 281 282 switch (fb_get_color_depth(&info->var, &info->fix)) { 283 case 1: 284 fg = 1; 285 break; 286 case 2: 287 fg = 3; 288 break; 289 default: 290 fg = 7; 291 break; 292 } 293 294 if (info->fix.visual == FB_VISUAL_MONO01 || 295 info->fix.visual == FB_VISUAL_MONO10) 296 fg = ~((u8) (0xfff << info->var.green.length)); 297 298 switch (depth) { 299 case 4: 300 for (i = 0; i < logo->height; i++) 301 for (j = 0; j < logo->width; src++) { 302 *dst++ = *src >> 4; 303 j++; 304 if (j < logo->width) { 305 *dst++ = *src & 0x0f; 306 j++; 307 } 308 } 309 break; 310 case 1: 311 for (i = 0; i < logo->height; i++) { 312 for (j = 0; j < logo->width; src++) { 313 d = *src ^ xor; 314 for (k = 7; k >= 0 && j < logo->width; k--) { 315 *dst++ = ((d >> k) & 1) ? fg : 0; 316 j++; 317 } 318 } 319 } 320 break; 321 } 322 } 323 324 /* 325 * Three (3) kinds of logo maps exist. linux_logo_clut224 (>16 colors), 326 * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors). Depending on 327 * the visual format and color depth of the framebuffer, the DAC, the 328 * pseudo_palette, and the logo data will be adjusted accordingly. 329 * 330 * Case 1 - linux_logo_clut224: 331 * Color exceeds the number of console colors (16), thus we set the hardware DAC 332 * using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set. 333 * 334 * For visuals that require color info from the pseudo_palette, we also construct 335 * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags 336 * will be set. 337 * 338 * Case 2 - linux_logo_vga16: 339 * The number of colors just matches the console colors, thus there is no need 340 * to set the DAC or the pseudo_palette. However, the bitmap is packed, ie, 341 * each byte contains color information for two pixels (upper and lower nibble). 342 * To be consistent with fb_imageblit() usage, we therefore separate the two 343 * nibbles into separate bytes. The "depth" flag will be set to 4. 344 * 345 * Case 3 - linux_logo_mono: 346 * This is similar with Case 2. Each byte contains information for 8 pixels. 347 * We isolate each bit and expand each into a byte. The "depth" flag will 348 * be set to 1. 349 */ 350 static struct logo_data { 351 int depth; 352 int needs_directpalette; 353 int needs_truepalette; 354 int needs_cmapreset; 355 const struct linux_logo *logo; 356 } fb_logo __read_mostly; 357 358 static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) 359 { 360 u32 size = width * height, i; 361 362 out += size - 1; 363 364 for (i = size; i--; ) 365 *out-- = *in++; 366 } 367 368 static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height) 369 { 370 int i, j, h = height - 1; 371 372 for (i = 0; i < height; i++) 373 for (j = 0; j < width; j++) 374 out[height * j + h - i] = *in++; 375 } 376 377 static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height) 378 { 379 int i, j, w = width - 1; 380 381 for (i = 0; i < height; i++) 382 for (j = 0; j < width; j++) 383 out[height * (w - j) + i] = *in++; 384 } 385 386 static void fb_rotate_logo(struct fb_info *info, u8 *dst, 387 struct fb_image *image, int rotate) 388 { 389 u32 tmp; 390 391 if (rotate == FB_ROTATE_UD) { 392 fb_rotate_logo_ud(image->data, dst, image->width, 393 image->height); 394 image->dx = info->var.xres - image->width - image->dx; 395 image->dy = info->var.yres - image->height - image->dy; 396 } else if (rotate == FB_ROTATE_CW) { 397 fb_rotate_logo_cw(image->data, dst, image->width, 398 image->height); 399 swap(image->width, image->height); 400 tmp = image->dy; 401 image->dy = image->dx; 402 image->dx = info->var.xres - image->width - tmp; 403 } else if (rotate == FB_ROTATE_CCW) { 404 fb_rotate_logo_ccw(image->data, dst, image->width, 405 image->height); 406 swap(image->width, image->height); 407 tmp = image->dx; 408 image->dx = image->dy; 409 image->dy = info->var.yres - image->height - tmp; 410 } 411 412 image->data = dst; 413 } 414 415 static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, 416 int rotate, unsigned int num) 417 { 418 unsigned int x; 419 420 if (image->width > info->var.xres || image->height > info->var.yres) 421 return; 422 423 if (rotate == FB_ROTATE_UR) { 424 for (x = 0; 425 x < num && image->dx + image->width <= info->var.xres; 426 x++) { 427 info->fbops->fb_imageblit(info, image); 428 image->dx += image->width + 8; 429 } 430 } else if (rotate == FB_ROTATE_UD) { 431 u32 dx = image->dx; 432 433 for (x = 0; x < num && image->dx <= dx; x++) { 434 info->fbops->fb_imageblit(info, image); 435 image->dx -= image->width + 8; 436 } 437 } else if (rotate == FB_ROTATE_CW) { 438 for (x = 0; 439 x < num && image->dy + image->height <= info->var.yres; 440 x++) { 441 info->fbops->fb_imageblit(info, image); 442 image->dy += image->height + 8; 443 } 444 } else if (rotate == FB_ROTATE_CCW) { 445 u32 dy = image->dy; 446 447 for (x = 0; x < num && image->dy <= dy; x++) { 448 info->fbops->fb_imageblit(info, image); 449 image->dy -= image->height + 8; 450 } 451 } 452 } 453 454 static int fb_show_logo_line(struct fb_info *info, int rotate, 455 const struct linux_logo *logo, int y, 456 unsigned int n) 457 { 458 u32 *palette = NULL, *saved_pseudo_palette = NULL; 459 unsigned char *logo_new = NULL, *logo_rotate = NULL; 460 struct fb_image image; 461 462 /* Return if the frame buffer is not mapped or suspended */ 463 if (logo == NULL || info->state != FBINFO_STATE_RUNNING || 464 info->fbops->owner) 465 return 0; 466 467 image.depth = 8; 468 image.data = logo->data; 469 470 if (fb_logo.needs_cmapreset) 471 fb_set_logocmap(info, logo); 472 473 if (fb_logo.needs_truepalette || 474 fb_logo.needs_directpalette) { 475 palette = kmalloc(256 * 4, GFP_KERNEL); 476 if (palette == NULL) 477 return 0; 478 479 if (fb_logo.needs_truepalette) 480 fb_set_logo_truepalette(info, logo, palette); 481 else 482 fb_set_logo_directpalette(info, logo, palette); 483 484 saved_pseudo_palette = info->pseudo_palette; 485 info->pseudo_palette = palette; 486 } 487 488 if (fb_logo.depth <= 4) { 489 logo_new = kmalloc_array(logo->width, logo->height, 490 GFP_KERNEL); 491 if (logo_new == NULL) { 492 kfree(palette); 493 if (saved_pseudo_palette) 494 info->pseudo_palette = saved_pseudo_palette; 495 return 0; 496 } 497 image.data = logo_new; 498 fb_set_logo(info, logo, logo_new, fb_logo.depth); 499 } 500 501 if (fb_center_logo) { 502 int xres = info->var.xres; 503 int yres = info->var.yres; 504 505 if (rotate == FB_ROTATE_CW || rotate == FB_ROTATE_CCW) { 506 xres = info->var.yres; 507 yres = info->var.xres; 508 } 509 510 while (n && (n * (logo->width + 8) - 8 > xres)) 511 --n; 512 image.dx = (xres - n * (logo->width + 8) - 8) / 2; 513 image.dy = y ?: (yres - logo->height) / 2; 514 } else { 515 image.dx = 0; 516 image.dy = y; 517 } 518 519 image.width = logo->width; 520 image.height = logo->height; 521 522 if (rotate) { 523 logo_rotate = kmalloc_array(logo->width, logo->height, 524 GFP_KERNEL); 525 if (logo_rotate) 526 fb_rotate_logo(info, logo_rotate, &image, rotate); 527 } 528 529 fb_do_show_logo(info, &image, rotate, n); 530 531 kfree(palette); 532 if (saved_pseudo_palette != NULL) 533 info->pseudo_palette = saved_pseudo_palette; 534 kfree(logo_new); 535 kfree(logo_rotate); 536 return image.dy + logo->height; 537 } 538 539 540 #ifdef CONFIG_FB_LOGO_EXTRA 541 542 #define FB_LOGO_EX_NUM_MAX 10 543 static struct logo_data_extra { 544 const struct linux_logo *logo; 545 unsigned int n; 546 } fb_logo_ex[FB_LOGO_EX_NUM_MAX]; 547 static unsigned int fb_logo_ex_num; 548 549 void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n) 550 { 551 if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX) 552 return; 553 554 fb_logo_ex[fb_logo_ex_num].logo = logo; 555 fb_logo_ex[fb_logo_ex_num].n = n; 556 fb_logo_ex_num++; 557 } 558 559 static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height, 560 unsigned int yres) 561 { 562 unsigned int i; 563 564 /* FIXME: logo_ex supports only truecolor fb. */ 565 if (info->fix.visual != FB_VISUAL_TRUECOLOR) 566 fb_logo_ex_num = 0; 567 568 for (i = 0; i < fb_logo_ex_num; i++) { 569 if (fb_logo_ex[i].logo->type != fb_logo.logo->type) { 570 fb_logo_ex[i].logo = NULL; 571 continue; 572 } 573 height += fb_logo_ex[i].logo->height; 574 if (height > yres) { 575 height -= fb_logo_ex[i].logo->height; 576 fb_logo_ex_num = i; 577 break; 578 } 579 } 580 return height; 581 } 582 583 static int fb_show_extra_logos(struct fb_info *info, int y, int rotate) 584 { 585 unsigned int i; 586 587 for (i = 0; i < fb_logo_ex_num; i++) 588 y = fb_show_logo_line(info, rotate, 589 fb_logo_ex[i].logo, y, fb_logo_ex[i].n); 590 591 return y; 592 } 593 594 #else /* !CONFIG_FB_LOGO_EXTRA */ 595 596 static inline int fb_prepare_extra_logos(struct fb_info *info, 597 unsigned int height, 598 unsigned int yres) 599 { 600 return height; 601 } 602 603 static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate) 604 { 605 return y; 606 } 607 608 #endif /* CONFIG_FB_LOGO_EXTRA */ 609 610 611 int fb_prepare_logo(struct fb_info *info, int rotate) 612 { 613 int depth = fb_get_color_depth(&info->var, &info->fix); 614 unsigned int yres; 615 int height; 616 617 memset(&fb_logo, 0, sizeof(struct logo_data)); 618 619 if (info->flags & FBINFO_MISC_TILEBLITTING || 620 info->fbops->owner || !fb_logo_count) 621 return 0; 622 623 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { 624 depth = info->var.blue.length; 625 if (info->var.red.length < depth) 626 depth = info->var.red.length; 627 if (info->var.green.length < depth) 628 depth = info->var.green.length; 629 } 630 631 if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) { 632 /* assume console colormap */ 633 depth = 4; 634 } 635 636 /* Return if no suitable logo was found */ 637 fb_logo.logo = fb_find_logo(depth); 638 639 if (!fb_logo.logo) { 640 return 0; 641 } 642 643 if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) 644 yres = info->var.yres; 645 else 646 yres = info->var.xres; 647 648 if (fb_logo.logo->height > yres) { 649 fb_logo.logo = NULL; 650 return 0; 651 } 652 653 /* What depth we asked for might be different from what we get */ 654 if (fb_logo.logo->type == LINUX_LOGO_CLUT224) 655 fb_logo.depth = 8; 656 else if (fb_logo.logo->type == LINUX_LOGO_VGA16) 657 fb_logo.depth = 4; 658 else 659 fb_logo.depth = 1; 660 661 662 if (fb_logo.depth > 4 && depth > 4) { 663 switch (info->fix.visual) { 664 case FB_VISUAL_TRUECOLOR: 665 fb_logo.needs_truepalette = 1; 666 break; 667 case FB_VISUAL_DIRECTCOLOR: 668 fb_logo.needs_directpalette = 1; 669 fb_logo.needs_cmapreset = 1; 670 break; 671 case FB_VISUAL_PSEUDOCOLOR: 672 fb_logo.needs_cmapreset = 1; 673 break; 674 } 675 } 676 677 height = fb_logo.logo->height; 678 if (fb_center_logo) 679 height += (yres - fb_logo.logo->height) / 2; 680 681 return fb_prepare_extra_logos(info, height, yres); 682 } 683 684 int fb_show_logo(struct fb_info *info, int rotate) 685 { 686 unsigned int count; 687 int y; 688 689 if (!fb_logo_count) 690 return 0; 691 692 count = fb_logo_count < 0 ? num_online_cpus() : fb_logo_count; 693 y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, count); 694 y = fb_show_extra_logos(info, y, rotate); 695 696 return y; 697 } 698 #else 699 int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; } 700 int fb_show_logo(struct fb_info *info, int rotate) { return 0; } 701 #endif /* CONFIG_LOGO */ 702 EXPORT_SYMBOL(fb_prepare_logo); 703 EXPORT_SYMBOL(fb_show_logo); 704 705 static void *fb_seq_start(struct seq_file *m, loff_t *pos) 706 { 707 mutex_lock(®istration_lock); 708 return (*pos < FB_MAX) ? pos : NULL; 709 } 710 711 static void *fb_seq_next(struct seq_file *m, void *v, loff_t *pos) 712 { 713 (*pos)++; 714 return (*pos < FB_MAX) ? pos : NULL; 715 } 716 717 static void fb_seq_stop(struct seq_file *m, void *v) 718 { 719 mutex_unlock(®istration_lock); 720 } 721 722 static int fb_seq_show(struct seq_file *m, void *v) 723 { 724 int i = *(loff_t *)v; 725 struct fb_info *fi = registered_fb[i]; 726 727 if (fi) 728 seq_printf(m, "%d %s\n", fi->node, fi->fix.id); 729 return 0; 730 } 731 732 static const struct seq_operations __maybe_unused proc_fb_seq_ops = { 733 .start = fb_seq_start, 734 .next = fb_seq_next, 735 .stop = fb_seq_stop, 736 .show = fb_seq_show, 737 }; 738 739 /* 740 * We hold a reference to the fb_info in file->private_data, 741 * but if the current registered fb has changed, we don't 742 * actually want to use it. 743 * 744 * So look up the fb_info using the inode minor number, 745 * and just verify it against the reference we have. 746 */ 747 static struct fb_info *file_fb_info(struct file *file) 748 { 749 struct inode *inode = file_inode(file); 750 int fbidx = iminor(inode); 751 struct fb_info *info = registered_fb[fbidx]; 752 753 if (info != file->private_data) 754 info = NULL; 755 return info; 756 } 757 758 static ssize_t 759 fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 760 { 761 unsigned long p = *ppos; 762 struct fb_info *info = file_fb_info(file); 763 u8 *buffer, *dst; 764 u8 __iomem *src; 765 int c, cnt = 0, err = 0; 766 unsigned long total_size; 767 768 if (!info || ! info->screen_base) 769 return -ENODEV; 770 771 if (info->state != FBINFO_STATE_RUNNING) 772 return -EPERM; 773 774 if (info->fbops->fb_read) 775 return info->fbops->fb_read(info, buf, count, ppos); 776 777 total_size = info->screen_size; 778 779 if (total_size == 0) 780 total_size = info->fix.smem_len; 781 782 if (p >= total_size) 783 return 0; 784 785 if (count >= total_size) 786 count = total_size; 787 788 if (count + p > total_size) 789 count = total_size - p; 790 791 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, 792 GFP_KERNEL); 793 if (!buffer) 794 return -ENOMEM; 795 796 src = (u8 __iomem *) (info->screen_base + p); 797 798 if (info->fbops->fb_sync) 799 info->fbops->fb_sync(info); 800 801 while (count) { 802 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 803 dst = buffer; 804 fb_memcpy_fromfb(dst, src, c); 805 dst += c; 806 src += c; 807 808 if (copy_to_user(buf, buffer, c)) { 809 err = -EFAULT; 810 break; 811 } 812 *ppos += c; 813 buf += c; 814 cnt += c; 815 count -= c; 816 } 817 818 kfree(buffer); 819 820 return (err) ? err : cnt; 821 } 822 823 static ssize_t 824 fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 825 { 826 unsigned long p = *ppos; 827 struct fb_info *info = file_fb_info(file); 828 u8 *buffer, *src; 829 u8 __iomem *dst; 830 int c, cnt = 0, err = 0; 831 unsigned long total_size; 832 833 if (!info || !info->screen_base) 834 return -ENODEV; 835 836 if (info->state != FBINFO_STATE_RUNNING) 837 return -EPERM; 838 839 if (info->fbops->fb_write) 840 return info->fbops->fb_write(info, buf, count, ppos); 841 842 total_size = info->screen_size; 843 844 if (total_size == 0) 845 total_size = info->fix.smem_len; 846 847 if (p > total_size) 848 return -EFBIG; 849 850 if (count > total_size) { 851 err = -EFBIG; 852 count = total_size; 853 } 854 855 if (count + p > total_size) { 856 if (!err) 857 err = -ENOSPC; 858 859 count = total_size - p; 860 } 861 862 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, 863 GFP_KERNEL); 864 if (!buffer) 865 return -ENOMEM; 866 867 dst = (u8 __iomem *) (info->screen_base + p); 868 869 if (info->fbops->fb_sync) 870 info->fbops->fb_sync(info); 871 872 while (count) { 873 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 874 src = buffer; 875 876 if (copy_from_user(src, buf, c)) { 877 err = -EFAULT; 878 break; 879 } 880 881 fb_memcpy_tofb(dst, src, c); 882 dst += c; 883 src += c; 884 *ppos += c; 885 buf += c; 886 cnt += c; 887 count -= c; 888 } 889 890 kfree(buffer); 891 892 return (cnt) ? cnt : err; 893 } 894 895 int 896 fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) 897 { 898 struct fb_fix_screeninfo *fix = &info->fix; 899 unsigned int yres = info->var.yres; 900 int err = 0; 901 902 if (var->yoffset > 0) { 903 if (var->vmode & FB_VMODE_YWRAP) { 904 if (!fix->ywrapstep || (var->yoffset % fix->ywrapstep)) 905 err = -EINVAL; 906 else 907 yres = 0; 908 } else if (!fix->ypanstep || (var->yoffset % fix->ypanstep)) 909 err = -EINVAL; 910 } 911 912 if (var->xoffset > 0 && (!fix->xpanstep || 913 (var->xoffset % fix->xpanstep))) 914 err = -EINVAL; 915 916 if (err || !info->fbops->fb_pan_display || 917 var->yoffset > info->var.yres_virtual - yres || 918 var->xoffset > info->var.xres_virtual - info->var.xres) 919 return -EINVAL; 920 921 if ((err = info->fbops->fb_pan_display(var, info))) 922 return err; 923 info->var.xoffset = var->xoffset; 924 info->var.yoffset = var->yoffset; 925 if (var->vmode & FB_VMODE_YWRAP) 926 info->var.vmode |= FB_VMODE_YWRAP; 927 else 928 info->var.vmode &= ~FB_VMODE_YWRAP; 929 return 0; 930 } 931 EXPORT_SYMBOL(fb_pan_display); 932 933 static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, 934 u32 activate) 935 { 936 struct fb_blit_caps caps, fbcaps; 937 int err = 0; 938 939 memset(&caps, 0, sizeof(caps)); 940 memset(&fbcaps, 0, sizeof(fbcaps)); 941 caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0; 942 fbcon_get_requirement(info, &caps); 943 info->fbops->fb_get_caps(info, &fbcaps, var); 944 945 if (((fbcaps.x ^ caps.x) & caps.x) || 946 ((fbcaps.y ^ caps.y) & caps.y) || 947 (fbcaps.len < caps.len)) 948 err = -EINVAL; 949 950 return err; 951 } 952 953 int 954 fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) 955 { 956 int ret = 0; 957 u32 activate; 958 struct fb_var_screeninfo old_var; 959 struct fb_videomode mode; 960 struct fb_event event; 961 u32 unused; 962 963 if (var->activate & FB_ACTIVATE_INV_MODE) { 964 struct fb_videomode mode1, mode2; 965 966 fb_var_to_videomode(&mode1, var); 967 fb_var_to_videomode(&mode2, &info->var); 968 /* make sure we don't delete the videomode of current var */ 969 ret = fb_mode_is_equal(&mode1, &mode2); 970 if (!ret) { 971 ret = fbcon_mode_deleted(info, &mode1); 972 if (!ret) 973 fb_delete_videomode(&mode1, &info->modelist); 974 } 975 976 return ret ? -EINVAL : 0; 977 } 978 979 if (!(var->activate & FB_ACTIVATE_FORCE) && 980 !memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) 981 return 0; 982 983 activate = var->activate; 984 985 /* When using FOURCC mode, make sure the red, green, blue and 986 * transp fields are set to 0. 987 */ 988 if ((info->fix.capabilities & FB_CAP_FOURCC) && 989 var->grayscale > 1) { 990 if (var->red.offset || var->green.offset || 991 var->blue.offset || var->transp.offset || 992 var->red.length || var->green.length || 993 var->blue.length || var->transp.length || 994 var->red.msb_right || var->green.msb_right || 995 var->blue.msb_right || var->transp.msb_right) 996 return -EINVAL; 997 } 998 999 if (!info->fbops->fb_check_var) { 1000 *var = info->var; 1001 return 0; 1002 } 1003 1004 /* bitfill_aligned() assumes that it's at least 8x8 */ 1005 if (var->xres < 8 || var->yres < 8) 1006 return -EINVAL; 1007 1008 /* Too huge resolution causes multiplication overflow. */ 1009 if (check_mul_overflow(var->xres, var->yres, &unused) || 1010 check_mul_overflow(var->xres_virtual, var->yres_virtual, &unused)) 1011 return -EINVAL; 1012 1013 ret = info->fbops->fb_check_var(var, info); 1014 1015 if (ret) 1016 return ret; 1017 1018 if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) 1019 return 0; 1020 1021 if (info->fbops->fb_get_caps) { 1022 ret = fb_check_caps(info, var, activate); 1023 1024 if (ret) 1025 return ret; 1026 } 1027 1028 old_var = info->var; 1029 info->var = *var; 1030 1031 if (info->fbops->fb_set_par) { 1032 ret = info->fbops->fb_set_par(info); 1033 1034 if (ret) { 1035 info->var = old_var; 1036 printk(KERN_WARNING "detected " 1037 "fb_set_par error, " 1038 "error code: %d\n", ret); 1039 return ret; 1040 } 1041 } 1042 1043 fb_pan_display(info, &info->var); 1044 fb_set_cmap(&info->cmap, info); 1045 fb_var_to_videomode(&mode, &info->var); 1046 1047 if (info->modelist.prev && info->modelist.next && 1048 !list_empty(&info->modelist)) 1049 ret = fb_add_videomode(&mode, &info->modelist); 1050 1051 if (ret) 1052 return ret; 1053 1054 event.info = info; 1055 event.data = &mode; 1056 fb_notifier_call_chain(FB_EVENT_MODE_CHANGE, &event); 1057 1058 return 0; 1059 } 1060 EXPORT_SYMBOL(fb_set_var); 1061 1062 int 1063 fb_blank(struct fb_info *info, int blank) 1064 { 1065 struct fb_event event; 1066 int ret = -EINVAL; 1067 1068 if (blank > FB_BLANK_POWERDOWN) 1069 blank = FB_BLANK_POWERDOWN; 1070 1071 event.info = info; 1072 event.data = ␣ 1073 1074 if (info->fbops->fb_blank) 1075 ret = info->fbops->fb_blank(blank, info); 1076 1077 if (!ret) 1078 fb_notifier_call_chain(FB_EVENT_BLANK, &event); 1079 1080 return ret; 1081 } 1082 EXPORT_SYMBOL(fb_blank); 1083 1084 static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, 1085 unsigned long arg) 1086 { 1087 const struct fb_ops *fb; 1088 struct fb_var_screeninfo var; 1089 struct fb_fix_screeninfo fix; 1090 struct fb_cmap cmap_from; 1091 struct fb_cmap_user cmap; 1092 void __user *argp = (void __user *)arg; 1093 long ret = 0; 1094 1095 switch (cmd) { 1096 case FBIOGET_VSCREENINFO: 1097 lock_fb_info(info); 1098 var = info->var; 1099 unlock_fb_info(info); 1100 1101 ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0; 1102 break; 1103 case FBIOPUT_VSCREENINFO: 1104 if (copy_from_user(&var, argp, sizeof(var))) 1105 return -EFAULT; 1106 console_lock(); 1107 lock_fb_info(info); 1108 ret = fb_set_var(info, &var); 1109 if (!ret) 1110 fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL); 1111 unlock_fb_info(info); 1112 console_unlock(); 1113 if (!ret && copy_to_user(argp, &var, sizeof(var))) 1114 ret = -EFAULT; 1115 break; 1116 case FBIOGET_FSCREENINFO: 1117 lock_fb_info(info); 1118 memcpy(&fix, &info->fix, sizeof(fix)); 1119 if (info->flags & FBINFO_HIDE_SMEM_START) 1120 fix.smem_start = 0; 1121 unlock_fb_info(info); 1122 1123 ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0; 1124 break; 1125 case FBIOPUTCMAP: 1126 if (copy_from_user(&cmap, argp, sizeof(cmap))) 1127 return -EFAULT; 1128 ret = fb_set_user_cmap(&cmap, info); 1129 break; 1130 case FBIOGETCMAP: 1131 if (copy_from_user(&cmap, argp, sizeof(cmap))) 1132 return -EFAULT; 1133 lock_fb_info(info); 1134 cmap_from = info->cmap; 1135 unlock_fb_info(info); 1136 ret = fb_cmap_to_user(&cmap_from, &cmap); 1137 break; 1138 case FBIOPAN_DISPLAY: 1139 if (copy_from_user(&var, argp, sizeof(var))) 1140 return -EFAULT; 1141 console_lock(); 1142 lock_fb_info(info); 1143 ret = fb_pan_display(info, &var); 1144 unlock_fb_info(info); 1145 console_unlock(); 1146 if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) 1147 return -EFAULT; 1148 break; 1149 case FBIO_CURSOR: 1150 ret = -EINVAL; 1151 break; 1152 case FBIOGET_CON2FBMAP: 1153 ret = fbcon_get_con2fb_map_ioctl(argp); 1154 break; 1155 case FBIOPUT_CON2FBMAP: 1156 ret = fbcon_set_con2fb_map_ioctl(argp); 1157 break; 1158 case FBIOBLANK: 1159 if (arg > FB_BLANK_POWERDOWN) 1160 return -EINVAL; 1161 console_lock(); 1162 lock_fb_info(info); 1163 ret = fb_blank(info, arg); 1164 /* might again call into fb_blank */ 1165 fbcon_fb_blanked(info, arg); 1166 unlock_fb_info(info); 1167 console_unlock(); 1168 break; 1169 default: 1170 lock_fb_info(info); 1171 fb = info->fbops; 1172 if (fb->fb_ioctl) 1173 ret = fb->fb_ioctl(info, cmd, arg); 1174 else 1175 ret = -ENOTTY; 1176 unlock_fb_info(info); 1177 } 1178 return ret; 1179 } 1180 1181 static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 1182 { 1183 struct fb_info *info = file_fb_info(file); 1184 1185 if (!info) 1186 return -ENODEV; 1187 return do_fb_ioctl(info, cmd, arg); 1188 } 1189 1190 #ifdef CONFIG_COMPAT 1191 struct fb_fix_screeninfo32 { 1192 char id[16]; 1193 compat_caddr_t smem_start; 1194 u32 smem_len; 1195 u32 type; 1196 u32 type_aux; 1197 u32 visual; 1198 u16 xpanstep; 1199 u16 ypanstep; 1200 u16 ywrapstep; 1201 u32 line_length; 1202 compat_caddr_t mmio_start; 1203 u32 mmio_len; 1204 u32 accel; 1205 u16 reserved[3]; 1206 }; 1207 1208 struct fb_cmap32 { 1209 u32 start; 1210 u32 len; 1211 compat_caddr_t red; 1212 compat_caddr_t green; 1213 compat_caddr_t blue; 1214 compat_caddr_t transp; 1215 }; 1216 1217 static int fb_getput_cmap(struct fb_info *info, unsigned int cmd, 1218 unsigned long arg) 1219 { 1220 struct fb_cmap32 cmap32; 1221 struct fb_cmap cmap_from; 1222 struct fb_cmap_user cmap; 1223 1224 if (copy_from_user(&cmap32, compat_ptr(arg), sizeof(cmap32))) 1225 return -EFAULT; 1226 1227 cmap = (struct fb_cmap_user) { 1228 .start = cmap32.start, 1229 .len = cmap32.len, 1230 .red = compat_ptr(cmap32.red), 1231 .green = compat_ptr(cmap32.green), 1232 .blue = compat_ptr(cmap32.blue), 1233 .transp = compat_ptr(cmap32.transp), 1234 }; 1235 1236 if (cmd == FBIOPUTCMAP) 1237 return fb_set_user_cmap(&cmap, info); 1238 1239 lock_fb_info(info); 1240 cmap_from = info->cmap; 1241 unlock_fb_info(info); 1242 1243 return fb_cmap_to_user(&cmap_from, &cmap); 1244 } 1245 1246 static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, 1247 struct fb_fix_screeninfo32 __user *fix32) 1248 { 1249 __u32 data; 1250 int err; 1251 1252 err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id)); 1253 1254 data = (__u32) (unsigned long) fix->smem_start; 1255 err |= put_user(data, &fix32->smem_start); 1256 1257 err |= put_user(fix->smem_len, &fix32->smem_len); 1258 err |= put_user(fix->type, &fix32->type); 1259 err |= put_user(fix->type_aux, &fix32->type_aux); 1260 err |= put_user(fix->visual, &fix32->visual); 1261 err |= put_user(fix->xpanstep, &fix32->xpanstep); 1262 err |= put_user(fix->ypanstep, &fix32->ypanstep); 1263 err |= put_user(fix->ywrapstep, &fix32->ywrapstep); 1264 err |= put_user(fix->line_length, &fix32->line_length); 1265 1266 data = (__u32) (unsigned long) fix->mmio_start; 1267 err |= put_user(data, &fix32->mmio_start); 1268 1269 err |= put_user(fix->mmio_len, &fix32->mmio_len); 1270 err |= put_user(fix->accel, &fix32->accel); 1271 err |= copy_to_user(fix32->reserved, fix->reserved, 1272 sizeof(fix->reserved)); 1273 1274 if (err) 1275 return -EFAULT; 1276 return 0; 1277 } 1278 1279 static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd, 1280 unsigned long arg) 1281 { 1282 struct fb_fix_screeninfo fix; 1283 1284 lock_fb_info(info); 1285 fix = info->fix; 1286 if (info->flags & FBINFO_HIDE_SMEM_START) 1287 fix.smem_start = 0; 1288 unlock_fb_info(info); 1289 return do_fscreeninfo_to_user(&fix, compat_ptr(arg)); 1290 } 1291 1292 static long fb_compat_ioctl(struct file *file, unsigned int cmd, 1293 unsigned long arg) 1294 { 1295 struct fb_info *info = file_fb_info(file); 1296 const struct fb_ops *fb; 1297 long ret = -ENOIOCTLCMD; 1298 1299 if (!info) 1300 return -ENODEV; 1301 fb = info->fbops; 1302 switch(cmd) { 1303 case FBIOGET_VSCREENINFO: 1304 case FBIOPUT_VSCREENINFO: 1305 case FBIOPAN_DISPLAY: 1306 case FBIOGET_CON2FBMAP: 1307 case FBIOPUT_CON2FBMAP: 1308 arg = (unsigned long) compat_ptr(arg); 1309 fallthrough; 1310 case FBIOBLANK: 1311 ret = do_fb_ioctl(info, cmd, arg); 1312 break; 1313 1314 case FBIOGET_FSCREENINFO: 1315 ret = fb_get_fscreeninfo(info, cmd, arg); 1316 break; 1317 1318 case FBIOGETCMAP: 1319 case FBIOPUTCMAP: 1320 ret = fb_getput_cmap(info, cmd, arg); 1321 break; 1322 1323 default: 1324 if (fb->fb_compat_ioctl) 1325 ret = fb->fb_compat_ioctl(info, cmd, arg); 1326 break; 1327 } 1328 return ret; 1329 } 1330 #endif 1331 1332 static int 1333 fb_mmap(struct file *file, struct vm_area_struct * vma) 1334 { 1335 struct fb_info *info = file_fb_info(file); 1336 int (*fb_mmap_fn)(struct fb_info *info, struct vm_area_struct *vma); 1337 unsigned long mmio_pgoff; 1338 unsigned long start; 1339 u32 len; 1340 1341 if (!info) 1342 return -ENODEV; 1343 mutex_lock(&info->mm_lock); 1344 1345 fb_mmap_fn = info->fbops->fb_mmap; 1346 1347 #if IS_ENABLED(CONFIG_FB_DEFERRED_IO) 1348 if (info->fbdefio) 1349 fb_mmap_fn = fb_deferred_io_mmap; 1350 #endif 1351 1352 if (fb_mmap_fn) { 1353 int res; 1354 1355 /* 1356 * The framebuffer needs to be accessed decrypted, be sure 1357 * SME protection is removed ahead of the call 1358 */ 1359 vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1360 res = fb_mmap_fn(info, vma); 1361 mutex_unlock(&info->mm_lock); 1362 return res; 1363 } 1364 1365 /* 1366 * Ugh. This can be either the frame buffer mapping, or 1367 * if pgoff points past it, the mmio mapping. 1368 */ 1369 start = info->fix.smem_start; 1370 len = info->fix.smem_len; 1371 mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT; 1372 if (vma->vm_pgoff >= mmio_pgoff) { 1373 if (info->var.accel_flags) { 1374 mutex_unlock(&info->mm_lock); 1375 return -EINVAL; 1376 } 1377 1378 vma->vm_pgoff -= mmio_pgoff; 1379 start = info->fix.mmio_start; 1380 len = info->fix.mmio_len; 1381 } 1382 mutex_unlock(&info->mm_lock); 1383 1384 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 1385 fb_pgprotect(file, vma, start); 1386 1387 return vm_iomap_memory(vma, start, len); 1388 } 1389 1390 static int 1391 fb_open(struct inode *inode, struct file *file) 1392 __acquires(&info->lock) 1393 __releases(&info->lock) 1394 { 1395 int fbidx = iminor(inode); 1396 struct fb_info *info; 1397 int res = 0; 1398 1399 info = get_fb_info(fbidx); 1400 if (!info) { 1401 request_module("fb%d", fbidx); 1402 info = get_fb_info(fbidx); 1403 if (!info) 1404 return -ENODEV; 1405 } 1406 if (IS_ERR(info)) 1407 return PTR_ERR(info); 1408 1409 lock_fb_info(info); 1410 if (!try_module_get(info->fbops->owner)) { 1411 res = -ENODEV; 1412 goto out; 1413 } 1414 file->private_data = info; 1415 if (info->fbops->fb_open) { 1416 res = info->fbops->fb_open(info,1); 1417 if (res) 1418 module_put(info->fbops->owner); 1419 } 1420 #ifdef CONFIG_FB_DEFERRED_IO 1421 if (info->fbdefio) 1422 fb_deferred_io_open(info, inode, file); 1423 #endif 1424 out: 1425 unlock_fb_info(info); 1426 if (res) 1427 put_fb_info(info); 1428 return res; 1429 } 1430 1431 static int 1432 fb_release(struct inode *inode, struct file *file) 1433 __acquires(&info->lock) 1434 __releases(&info->lock) 1435 { 1436 struct fb_info * const info = file->private_data; 1437 1438 lock_fb_info(info); 1439 if (info->fbops->fb_release) 1440 info->fbops->fb_release(info,1); 1441 module_put(info->fbops->owner); 1442 unlock_fb_info(info); 1443 put_fb_info(info); 1444 return 0; 1445 } 1446 1447 #if defined(CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA) && !defined(CONFIG_MMU) 1448 unsigned long get_fb_unmapped_area(struct file *filp, 1449 unsigned long addr, unsigned long len, 1450 unsigned long pgoff, unsigned long flags) 1451 { 1452 struct fb_info * const info = filp->private_data; 1453 unsigned long fb_size = PAGE_ALIGN(info->fix.smem_len); 1454 1455 if (pgoff > fb_size || len > fb_size - pgoff) 1456 return -EINVAL; 1457 1458 return (unsigned long)info->screen_base + pgoff; 1459 } 1460 #endif 1461 1462 static const struct file_operations fb_fops = { 1463 .owner = THIS_MODULE, 1464 .read = fb_read, 1465 .write = fb_write, 1466 .unlocked_ioctl = fb_ioctl, 1467 #ifdef CONFIG_COMPAT 1468 .compat_ioctl = fb_compat_ioctl, 1469 #endif 1470 .mmap = fb_mmap, 1471 .open = fb_open, 1472 .release = fb_release, 1473 #if defined(HAVE_ARCH_FB_UNMAPPED_AREA) || \ 1474 (defined(CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA) && \ 1475 !defined(CONFIG_MMU)) 1476 .get_unmapped_area = get_fb_unmapped_area, 1477 #endif 1478 #ifdef CONFIG_FB_DEFERRED_IO 1479 .fsync = fb_deferred_io_fsync, 1480 #endif 1481 .llseek = default_llseek, 1482 }; 1483 1484 struct class *fb_class; 1485 EXPORT_SYMBOL(fb_class); 1486 1487 static int fb_check_foreignness(struct fb_info *fi) 1488 { 1489 const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN; 1490 1491 fi->flags &= ~FBINFO_FOREIGN_ENDIAN; 1492 1493 #ifdef __BIG_ENDIAN 1494 fi->flags |= foreign_endian ? 0 : FBINFO_BE_MATH; 1495 #else 1496 fi->flags |= foreign_endian ? FBINFO_BE_MATH : 0; 1497 #endif /* __BIG_ENDIAN */ 1498 1499 if (fi->flags & FBINFO_BE_MATH && !fb_be_math(fi)) { 1500 pr_err("%s: enable CONFIG_FB_BIG_ENDIAN to " 1501 "support this framebuffer\n", fi->fix.id); 1502 return -ENOSYS; 1503 } else if (!(fi->flags & FBINFO_BE_MATH) && fb_be_math(fi)) { 1504 pr_err("%s: enable CONFIG_FB_LITTLE_ENDIAN to " 1505 "support this framebuffer\n", fi->fix.id); 1506 return -ENOSYS; 1507 } 1508 1509 return 0; 1510 } 1511 1512 static bool apertures_overlap(struct aperture *gen, struct aperture *hw) 1513 { 1514 /* is the generic aperture base the same as the HW one */ 1515 if (gen->base == hw->base) 1516 return true; 1517 /* is the generic aperture base inside the hw base->hw base+size */ 1518 if (gen->base > hw->base && gen->base < hw->base + hw->size) 1519 return true; 1520 return false; 1521 } 1522 1523 static bool fb_do_apertures_overlap(struct apertures_struct *gena, 1524 struct apertures_struct *hwa) 1525 { 1526 int i, j; 1527 if (!hwa || !gena) 1528 return false; 1529 1530 for (i = 0; i < hwa->count; ++i) { 1531 struct aperture *h = &hwa->ranges[i]; 1532 for (j = 0; j < gena->count; ++j) { 1533 struct aperture *g = &gena->ranges[j]; 1534 printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n", 1535 (unsigned long long)g->base, 1536 (unsigned long long)g->size, 1537 (unsigned long long)h->base, 1538 (unsigned long long)h->size); 1539 if (apertures_overlap(g, h)) 1540 return true; 1541 } 1542 } 1543 1544 return false; 1545 } 1546 1547 static void do_unregister_framebuffer(struct fb_info *fb_info); 1548 1549 #define VGA_FB_PHYS 0xA0000 1550 static void do_remove_conflicting_framebuffers(struct apertures_struct *a, 1551 const char *name, bool primary) 1552 { 1553 int i; 1554 1555 /* check all firmware fbs and kick off if the base addr overlaps */ 1556 for_each_registered_fb(i) { 1557 struct apertures_struct *gen_aper; 1558 1559 if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE)) 1560 continue; 1561 1562 gen_aper = registered_fb[i]->apertures; 1563 if (fb_do_apertures_overlap(gen_aper, a) || 1564 (primary && gen_aper && gen_aper->count && 1565 gen_aper->ranges[0].base == VGA_FB_PHYS)) { 1566 1567 printk(KERN_INFO "fb%d: switching to %s from %s\n", 1568 i, name, registered_fb[i]->fix.id); 1569 do_unregister_framebuffer(registered_fb[i]); 1570 } 1571 } 1572 } 1573 1574 static bool lockless_register_fb; 1575 module_param_named_unsafe(lockless_register_fb, lockless_register_fb, bool, 0400); 1576 MODULE_PARM_DESC(lockless_register_fb, 1577 "Lockless framebuffer registration for debugging [default=off]"); 1578 1579 static int do_register_framebuffer(struct fb_info *fb_info) 1580 { 1581 int i, ret; 1582 struct fb_videomode mode; 1583 1584 if (fb_check_foreignness(fb_info)) 1585 return -ENOSYS; 1586 1587 do_remove_conflicting_framebuffers(fb_info->apertures, 1588 fb_info->fix.id, 1589 fb_is_primary_device(fb_info)); 1590 1591 if (num_registered_fb == FB_MAX) 1592 return -ENXIO; 1593 1594 num_registered_fb++; 1595 for (i = 0 ; i < FB_MAX; i++) 1596 if (!registered_fb[i]) 1597 break; 1598 fb_info->node = i; 1599 refcount_set(&fb_info->count, 1); 1600 mutex_init(&fb_info->lock); 1601 mutex_init(&fb_info->mm_lock); 1602 1603 fb_info->dev = device_create(fb_class, fb_info->device, 1604 MKDEV(FB_MAJOR, i), NULL, "fb%d", i); 1605 if (IS_ERR(fb_info->dev)) { 1606 /* Not fatal */ 1607 printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev)); 1608 fb_info->dev = NULL; 1609 } else 1610 fb_init_device(fb_info); 1611 1612 if (fb_info->pixmap.addr == NULL) { 1613 fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL); 1614 if (fb_info->pixmap.addr) { 1615 fb_info->pixmap.size = FBPIXMAPSIZE; 1616 fb_info->pixmap.buf_align = 1; 1617 fb_info->pixmap.scan_align = 1; 1618 fb_info->pixmap.access_align = 32; 1619 fb_info->pixmap.flags = FB_PIXMAP_DEFAULT; 1620 } 1621 } 1622 fb_info->pixmap.offset = 0; 1623 1624 if (!fb_info->pixmap.blit_x) 1625 fb_info->pixmap.blit_x = ~(u32)0; 1626 1627 if (!fb_info->pixmap.blit_y) 1628 fb_info->pixmap.blit_y = ~(u32)0; 1629 1630 if (!fb_info->modelist.prev || !fb_info->modelist.next) 1631 INIT_LIST_HEAD(&fb_info->modelist); 1632 1633 if (fb_info->skip_vt_switch) 1634 pm_vt_switch_required(fb_info->dev, false); 1635 else 1636 pm_vt_switch_required(fb_info->dev, true); 1637 1638 fb_var_to_videomode(&mode, &fb_info->var); 1639 fb_add_videomode(&mode, &fb_info->modelist); 1640 registered_fb[i] = fb_info; 1641 1642 #ifdef CONFIG_GUMSTIX_AM200EPD 1643 { 1644 struct fb_event event; 1645 event.info = fb_info; 1646 fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); 1647 } 1648 #endif 1649 1650 if (!lockless_register_fb) 1651 console_lock(); 1652 else 1653 atomic_inc(&ignore_console_lock_warning); 1654 lock_fb_info(fb_info); 1655 ret = fbcon_fb_registered(fb_info); 1656 unlock_fb_info(fb_info); 1657 1658 if (!lockless_register_fb) 1659 console_unlock(); 1660 else 1661 atomic_dec(&ignore_console_lock_warning); 1662 return ret; 1663 } 1664 1665 static void unbind_console(struct fb_info *fb_info) 1666 { 1667 int i = fb_info->node; 1668 1669 if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)) 1670 return; 1671 1672 console_lock(); 1673 lock_fb_info(fb_info); 1674 fbcon_fb_unbind(fb_info); 1675 unlock_fb_info(fb_info); 1676 console_unlock(); 1677 } 1678 1679 static void unlink_framebuffer(struct fb_info *fb_info) 1680 { 1681 int i; 1682 1683 i = fb_info->node; 1684 if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)) 1685 return; 1686 1687 if (!fb_info->dev) 1688 return; 1689 1690 device_destroy(fb_class, MKDEV(FB_MAJOR, i)); 1691 1692 pm_vt_switch_unregister(fb_info->dev); 1693 1694 unbind_console(fb_info); 1695 1696 fb_info->dev = NULL; 1697 } 1698 1699 static void do_unregister_framebuffer(struct fb_info *fb_info) 1700 { 1701 unlink_framebuffer(fb_info); 1702 if (fb_info->pixmap.addr && 1703 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) { 1704 kfree(fb_info->pixmap.addr); 1705 fb_info->pixmap.addr = NULL; 1706 } 1707 1708 fb_destroy_modelist(&fb_info->modelist); 1709 registered_fb[fb_info->node] = NULL; 1710 num_registered_fb--; 1711 fb_cleanup_device(fb_info); 1712 #ifdef CONFIG_GUMSTIX_AM200EPD 1713 { 1714 struct fb_event event; 1715 event.info = fb_info; 1716 fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); 1717 } 1718 #endif 1719 console_lock(); 1720 fbcon_fb_unregistered(fb_info); 1721 console_unlock(); 1722 1723 /* this may free fb info */ 1724 put_fb_info(fb_info); 1725 } 1726 1727 /** 1728 * remove_conflicting_framebuffers - remove firmware-configured framebuffers 1729 * @a: memory range, users of which are to be removed 1730 * @name: requesting driver name 1731 * @primary: also kick vga16fb if present 1732 * 1733 * This function removes framebuffer devices (initialized by firmware/bootloader) 1734 * which use memory range described by @a. If @a is NULL all such devices are 1735 * removed. 1736 */ 1737 int remove_conflicting_framebuffers(struct apertures_struct *a, 1738 const char *name, bool primary) 1739 { 1740 bool do_free = false; 1741 1742 if (!a) { 1743 a = alloc_apertures(1); 1744 if (!a) 1745 return -ENOMEM; 1746 1747 a->ranges[0].base = 0; 1748 a->ranges[0].size = ~0; 1749 do_free = true; 1750 } 1751 1752 mutex_lock(®istration_lock); 1753 do_remove_conflicting_framebuffers(a, name, primary); 1754 mutex_unlock(®istration_lock); 1755 1756 if (do_free) 1757 kfree(a); 1758 1759 return 0; 1760 } 1761 EXPORT_SYMBOL(remove_conflicting_framebuffers); 1762 1763 /** 1764 * is_firmware_framebuffer - detect if firmware-configured framebuffer matches 1765 * @a: memory range, users of which are to be checked 1766 * 1767 * This function checks framebuffer devices (initialized by firmware/bootloader) 1768 * which use memory range described by @a. If @a matchesm the function returns 1769 * true, otherwise false. 1770 */ 1771 bool is_firmware_framebuffer(struct apertures_struct *a) 1772 { 1773 bool do_free = false; 1774 bool found = false; 1775 int i; 1776 1777 if (!a) { 1778 a = alloc_apertures(1); 1779 if (!a) 1780 return false; 1781 1782 a->ranges[0].base = 0; 1783 a->ranges[0].size = ~0; 1784 do_free = true; 1785 } 1786 1787 mutex_lock(®istration_lock); 1788 /* check all firmware fbs and kick off if the base addr overlaps */ 1789 for_each_registered_fb(i) { 1790 struct apertures_struct *gen_aper; 1791 1792 if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE)) 1793 continue; 1794 1795 gen_aper = registered_fb[i]->apertures; 1796 if (fb_do_apertures_overlap(gen_aper, a)) { 1797 found = true; 1798 break; 1799 } 1800 } 1801 mutex_unlock(®istration_lock); 1802 1803 if (do_free) 1804 kfree(a); 1805 1806 return found; 1807 } 1808 EXPORT_SYMBOL(is_firmware_framebuffer); 1809 1810 /** 1811 * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices 1812 * @pdev: PCI device 1813 * @name: requesting driver name 1814 * 1815 * This function removes framebuffer devices (eg. initialized by firmware) 1816 * using memory range configured for any of @pdev's memory bars. 1817 * 1818 * The function assumes that PCI device with shadowed ROM drives a primary 1819 * display and so kicks out vga16fb. 1820 */ 1821 int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name) 1822 { 1823 struct apertures_struct *ap; 1824 bool primary = false; 1825 int err, idx, bar; 1826 1827 for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) { 1828 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) 1829 continue; 1830 idx++; 1831 } 1832 1833 ap = alloc_apertures(idx); 1834 if (!ap) 1835 return -ENOMEM; 1836 1837 for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) { 1838 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) 1839 continue; 1840 ap->ranges[idx].base = pci_resource_start(pdev, bar); 1841 ap->ranges[idx].size = pci_resource_len(pdev, bar); 1842 pci_dbg(pdev, "%s: bar %d: 0x%lx -> 0x%lx\n", __func__, bar, 1843 (unsigned long)pci_resource_start(pdev, bar), 1844 (unsigned long)pci_resource_end(pdev, bar)); 1845 idx++; 1846 } 1847 1848 #ifdef CONFIG_X86 1849 primary = pdev->resource[PCI_ROM_RESOURCE].flags & 1850 IORESOURCE_ROM_SHADOW; 1851 #endif 1852 err = remove_conflicting_framebuffers(ap, name, primary); 1853 kfree(ap); 1854 return err; 1855 } 1856 EXPORT_SYMBOL(remove_conflicting_pci_framebuffers); 1857 1858 /** 1859 * register_framebuffer - registers a frame buffer device 1860 * @fb_info: frame buffer info structure 1861 * 1862 * Registers a frame buffer device @fb_info. 1863 * 1864 * Returns negative errno on error, or zero for success. 1865 * 1866 */ 1867 int 1868 register_framebuffer(struct fb_info *fb_info) 1869 { 1870 int ret; 1871 1872 mutex_lock(®istration_lock); 1873 ret = do_register_framebuffer(fb_info); 1874 mutex_unlock(®istration_lock); 1875 1876 return ret; 1877 } 1878 EXPORT_SYMBOL(register_framebuffer); 1879 1880 /** 1881 * unregister_framebuffer - releases a frame buffer device 1882 * @fb_info: frame buffer info structure 1883 * 1884 * Unregisters a frame buffer device @fb_info. 1885 * 1886 * Returns negative errno on error, or zero for success. 1887 * 1888 * This function will also notify the framebuffer console 1889 * to release the driver. 1890 * 1891 * This is meant to be called within a driver's module_exit() 1892 * function. If this is called outside module_exit(), ensure 1893 * that the driver implements fb_open() and fb_release() to 1894 * check that no processes are using the device. 1895 */ 1896 void 1897 unregister_framebuffer(struct fb_info *fb_info) 1898 { 1899 mutex_lock(®istration_lock); 1900 do_unregister_framebuffer(fb_info); 1901 mutex_unlock(®istration_lock); 1902 } 1903 EXPORT_SYMBOL(unregister_framebuffer); 1904 1905 /** 1906 * fb_set_suspend - low level driver signals suspend 1907 * @info: framebuffer affected 1908 * @state: 0 = resuming, !=0 = suspending 1909 * 1910 * This is meant to be used by low level drivers to 1911 * signal suspend/resume to the core & clients. 1912 * It must be called with the console semaphore held 1913 */ 1914 void fb_set_suspend(struct fb_info *info, int state) 1915 { 1916 WARN_CONSOLE_UNLOCKED(); 1917 1918 if (state) { 1919 fbcon_suspended(info); 1920 info->state = FBINFO_STATE_SUSPENDED; 1921 } else { 1922 info->state = FBINFO_STATE_RUNNING; 1923 fbcon_resumed(info); 1924 } 1925 } 1926 EXPORT_SYMBOL(fb_set_suspend); 1927 1928 /** 1929 * fbmem_init - init frame buffer subsystem 1930 * 1931 * Initialize the frame buffer subsystem. 1932 * 1933 * NOTE: This function is _only_ to be called by drivers/char/mem.c. 1934 * 1935 */ 1936 1937 static int __init 1938 fbmem_init(void) 1939 { 1940 int ret; 1941 1942 if (!proc_create_seq("fb", 0, NULL, &proc_fb_seq_ops)) 1943 return -ENOMEM; 1944 1945 ret = register_chrdev(FB_MAJOR, "fb", &fb_fops); 1946 if (ret) { 1947 printk("unable to get major %d for fb devs\n", FB_MAJOR); 1948 goto err_chrdev; 1949 } 1950 1951 fb_class = class_create(THIS_MODULE, "graphics"); 1952 if (IS_ERR(fb_class)) { 1953 ret = PTR_ERR(fb_class); 1954 pr_warn("Unable to create fb class; errno = %d\n", ret); 1955 fb_class = NULL; 1956 goto err_class; 1957 } 1958 1959 fb_console_init(); 1960 1961 return 0; 1962 1963 err_class: 1964 unregister_chrdev(FB_MAJOR, "fb"); 1965 err_chrdev: 1966 remove_proc_entry("fb", NULL); 1967 return ret; 1968 } 1969 1970 #ifdef MODULE 1971 module_init(fbmem_init); 1972 static void __exit 1973 fbmem_exit(void) 1974 { 1975 fb_console_exit(); 1976 1977 remove_proc_entry("fb", NULL); 1978 class_destroy(fb_class); 1979 unregister_chrdev(FB_MAJOR, "fb"); 1980 } 1981 1982 module_exit(fbmem_exit); 1983 MODULE_LICENSE("GPL"); 1984 MODULE_DESCRIPTION("Framebuffer base"); 1985 #else 1986 subsys_initcall(fbmem_init); 1987 #endif 1988 1989 int fb_new_modelist(struct fb_info *info) 1990 { 1991 struct fb_var_screeninfo var = info->var; 1992 struct list_head *pos, *n; 1993 struct fb_modelist *modelist; 1994 struct fb_videomode *m, mode; 1995 int err; 1996 1997 list_for_each_safe(pos, n, &info->modelist) { 1998 modelist = list_entry(pos, struct fb_modelist, list); 1999 m = &modelist->mode; 2000 fb_videomode_to_var(&var, m); 2001 var.activate = FB_ACTIVATE_TEST; 2002 err = fb_set_var(info, &var); 2003 fb_var_to_videomode(&mode, &var); 2004 if (err || !fb_mode_is_equal(m, &mode)) { 2005 list_del(pos); 2006 kfree(pos); 2007 } 2008 } 2009 2010 if (list_empty(&info->modelist)) 2011 return 1; 2012 2013 fbcon_new_modelist(info); 2014 2015 return 0; 2016 } 2017 2018 MODULE_LICENSE("GPL"); 2019