| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | #include <linux/kernel.h> |
|---|
| 2 | 3 | #include <linux/module.h> |
|---|
| 3 | 4 | #include <linux/errno.h> |
|---|
| .. | .. |
|---|
| 296 | 297 | return hw_sm750_pan_display(crtc, var, info); |
|---|
| 297 | 298 | } |
|---|
| 298 | 299 | |
|---|
| 300 | +static inline void lynxfb_set_visual_mode(struct fb_info *info) |
|---|
| 301 | +{ |
|---|
| 302 | + switch (info->var.bits_per_pixel) { |
|---|
| 303 | + case 8: |
|---|
| 304 | + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; |
|---|
| 305 | + break; |
|---|
| 306 | + case 16: |
|---|
| 307 | + case 24: |
|---|
| 308 | + case 32: |
|---|
| 309 | + info->fix.visual = FB_VISUAL_TRUECOLOR; |
|---|
| 310 | + break; |
|---|
| 311 | + default: |
|---|
| 312 | + break; |
|---|
| 313 | + } |
|---|
| 314 | +} |
|---|
| 315 | + |
|---|
| 316 | +static inline int lynxfb_set_color_offsets(struct fb_info *info) |
|---|
| 317 | +{ |
|---|
| 318 | + lynxfb_set_visual_mode(info); |
|---|
| 319 | + |
|---|
| 320 | + switch (info->var.bits_per_pixel) { |
|---|
| 321 | + case 8: |
|---|
| 322 | + info->var.red.offset = 0; |
|---|
| 323 | + info->var.red.length = 8; |
|---|
| 324 | + info->var.green.offset = 0; |
|---|
| 325 | + info->var.green.length = 8; |
|---|
| 326 | + info->var.blue.offset = 0; |
|---|
| 327 | + info->var.blue.length = 8; |
|---|
| 328 | + info->var.transp.length = 0; |
|---|
| 329 | + info->var.transp.offset = 0; |
|---|
| 330 | + break; |
|---|
| 331 | + case 16: |
|---|
| 332 | + info->var.red.offset = 11; |
|---|
| 333 | + info->var.red.length = 5; |
|---|
| 334 | + info->var.green.offset = 5; |
|---|
| 335 | + info->var.green.length = 6; |
|---|
| 336 | + info->var.blue.offset = 0; |
|---|
| 337 | + info->var.blue.length = 5; |
|---|
| 338 | + info->var.transp.length = 0; |
|---|
| 339 | + info->var.transp.offset = 0; |
|---|
| 340 | + break; |
|---|
| 341 | + case 24: |
|---|
| 342 | + case 32: |
|---|
| 343 | + info->var.red.offset = 16; |
|---|
| 344 | + info->var.red.length = 8; |
|---|
| 345 | + info->var.green.offset = 8; |
|---|
| 346 | + info->var.green.length = 8; |
|---|
| 347 | + info->var.blue.offset = 0; |
|---|
| 348 | + info->var.blue.length = 8; |
|---|
| 349 | + break; |
|---|
| 350 | + default: |
|---|
| 351 | + return -EINVAL; |
|---|
| 352 | + } |
|---|
| 353 | + return 0; |
|---|
| 354 | +} |
|---|
| 355 | + |
|---|
| 299 | 356 | static int lynxfb_ops_set_par(struct fb_info *info) |
|---|
| 300 | 357 | { |
|---|
| 301 | 358 | struct lynxfb_par *par; |
|---|
| .. | .. |
|---|
| 327 | 384 | * and these data should be set before setcolreg routine |
|---|
| 328 | 385 | */ |
|---|
| 329 | 386 | |
|---|
| 330 | | - switch (var->bits_per_pixel) { |
|---|
| 331 | | - case 8: |
|---|
| 332 | | - fix->visual = FB_VISUAL_PSEUDOCOLOR; |
|---|
| 333 | | - var->red.offset = 0; |
|---|
| 334 | | - var->red.length = 8; |
|---|
| 335 | | - var->green.offset = 0; |
|---|
| 336 | | - var->green.length = 8; |
|---|
| 337 | | - var->blue.offset = 0; |
|---|
| 338 | | - var->blue.length = 8; |
|---|
| 339 | | - var->transp.length = 0; |
|---|
| 340 | | - var->transp.offset = 0; |
|---|
| 341 | | - break; |
|---|
| 342 | | - case 16: |
|---|
| 343 | | - var->red.offset = 11; |
|---|
| 344 | | - var->red.length = 5; |
|---|
| 345 | | - var->green.offset = 5; |
|---|
| 346 | | - var->green.length = 6; |
|---|
| 347 | | - var->blue.offset = 0; |
|---|
| 348 | | - var->blue.length = 5; |
|---|
| 349 | | - var->transp.length = 0; |
|---|
| 350 | | - var->transp.offset = 0; |
|---|
| 351 | | - fix->visual = FB_VISUAL_TRUECOLOR; |
|---|
| 352 | | - break; |
|---|
| 353 | | - case 24: |
|---|
| 354 | | - case 32: |
|---|
| 355 | | - var->red.offset = 16; |
|---|
| 356 | | - var->red.length = 8; |
|---|
| 357 | | - var->green.offset = 8; |
|---|
| 358 | | - var->green.length = 8; |
|---|
| 359 | | - var->blue.offset = 0; |
|---|
| 360 | | - var->blue.length = 8; |
|---|
| 361 | | - fix->visual = FB_VISUAL_TRUECOLOR; |
|---|
| 362 | | - break; |
|---|
| 363 | | - default: |
|---|
| 364 | | - ret = -EINVAL; |
|---|
| 365 | | - break; |
|---|
| 366 | | - } |
|---|
| 387 | + ret = lynxfb_set_color_offsets(info); |
|---|
| 388 | + |
|---|
| 367 | 389 | var->height = var->width = -1; |
|---|
| 368 | 390 | var->accel_flags = 0;/*FB_ACCELF_TEXT;*/ |
|---|
| 369 | 391 | |
|---|
| 370 | 392 | if (ret) { |
|---|
| 371 | | - pr_err("pixel bpp format not satisfied\n."); |
|---|
| 393 | + pr_err("bpp %d not supported\n", var->bits_per_pixel); |
|---|
| 372 | 394 | return ret; |
|---|
| 373 | 395 | } |
|---|
| 374 | 396 | ret = hw_sm750_crtc_setMode(crtc, var, fix); |
|---|
| .. | .. |
|---|
| 385 | 407 | return chan << bf->offset; |
|---|
| 386 | 408 | } |
|---|
| 387 | 409 | |
|---|
| 388 | | -#ifdef CONFIG_PM |
|---|
| 389 | | -static int lynxfb_suspend(struct pci_dev *pdev, pm_message_t mesg) |
|---|
| 410 | +static int __maybe_unused lynxfb_suspend(struct device *dev) |
|---|
| 390 | 411 | { |
|---|
| 391 | 412 | struct fb_info *info; |
|---|
| 392 | 413 | struct sm750_dev *sm750_dev; |
|---|
| 393 | | - int ret; |
|---|
| 394 | 414 | |
|---|
| 395 | | - if (mesg.event == pdev->dev.power.power_state.event) |
|---|
| 396 | | - return 0; |
|---|
| 397 | | - |
|---|
| 398 | | - ret = 0; |
|---|
| 399 | | - sm750_dev = pci_get_drvdata(pdev); |
|---|
| 400 | | - switch (mesg.event) { |
|---|
| 401 | | - case PM_EVENT_FREEZE: |
|---|
| 402 | | - case PM_EVENT_PRETHAW: |
|---|
| 403 | | - pdev->dev.power.power_state = mesg; |
|---|
| 404 | | - return 0; |
|---|
| 405 | | - } |
|---|
| 415 | + sm750_dev = dev_get_drvdata(dev); |
|---|
| 406 | 416 | |
|---|
| 407 | 417 | console_lock(); |
|---|
| 408 | | - if (mesg.event & PM_EVENT_SLEEP) { |
|---|
| 409 | | - info = sm750_dev->fbinfo[0]; |
|---|
| 410 | | - if (info) |
|---|
| 411 | | - /* 1 means do suspend */ |
|---|
| 412 | | - fb_set_suspend(info, 1); |
|---|
| 413 | | - info = sm750_dev->fbinfo[1]; |
|---|
| 414 | | - if (info) |
|---|
| 415 | | - /* 1 means do suspend */ |
|---|
| 416 | | - fb_set_suspend(info, 1); |
|---|
| 418 | + info = sm750_dev->fbinfo[0]; |
|---|
| 419 | + if (info) |
|---|
| 420 | + /* 1 means do suspend */ |
|---|
| 421 | + fb_set_suspend(info, 1); |
|---|
| 422 | + info = sm750_dev->fbinfo[1]; |
|---|
| 423 | + if (info) |
|---|
| 424 | + /* 1 means do suspend */ |
|---|
| 425 | + fb_set_suspend(info, 1); |
|---|
| 417 | 426 | |
|---|
| 418 | | - ret = pci_save_state(pdev); |
|---|
| 419 | | - if (ret) { |
|---|
| 420 | | - dev_err(&pdev->dev, |
|---|
| 421 | | - "error:%d occurred in pci_save_state\n", ret); |
|---|
| 422 | | - goto lynxfb_suspend_err; |
|---|
| 423 | | - } |
|---|
| 424 | | - |
|---|
| 425 | | - ret = pci_set_power_state(pdev, pci_choose_state(pdev, mesg)); |
|---|
| 426 | | - if (ret) { |
|---|
| 427 | | - dev_err(&pdev->dev, |
|---|
| 428 | | - "error:%d occurred in pci_set_power_state\n", |
|---|
| 429 | | - ret); |
|---|
| 430 | | - goto lynxfb_suspend_err; |
|---|
| 431 | | - } |
|---|
| 432 | | - } |
|---|
| 433 | | - |
|---|
| 434 | | - pdev->dev.power.power_state = mesg; |
|---|
| 435 | | - |
|---|
| 436 | | -lynxfb_suspend_err: |
|---|
| 437 | 427 | console_unlock(); |
|---|
| 438 | | - return ret; |
|---|
| 428 | + return 0; |
|---|
| 439 | 429 | } |
|---|
| 440 | 430 | |
|---|
| 441 | | -static int lynxfb_resume(struct pci_dev *pdev) |
|---|
| 431 | +static int __maybe_unused lynxfb_resume(struct device *dev) |
|---|
| 442 | 432 | { |
|---|
| 433 | + struct pci_dev *pdev = to_pci_dev(dev); |
|---|
| 443 | 434 | struct fb_info *info; |
|---|
| 444 | 435 | struct sm750_dev *sm750_dev; |
|---|
| 445 | 436 | |
|---|
| .. | .. |
|---|
| 447 | 438 | struct lynxfb_crtc *crtc; |
|---|
| 448 | 439 | struct lynx_cursor *cursor; |
|---|
| 449 | 440 | |
|---|
| 450 | | - int ret; |
|---|
| 451 | | - |
|---|
| 452 | | - ret = 0; |
|---|
| 453 | 441 | sm750_dev = pci_get_drvdata(pdev); |
|---|
| 454 | 442 | |
|---|
| 455 | 443 | console_lock(); |
|---|
| 456 | | - |
|---|
| 457 | | - ret = pci_set_power_state(pdev, PCI_D0); |
|---|
| 458 | | - if (ret) { |
|---|
| 459 | | - dev_err(&pdev->dev, |
|---|
| 460 | | - "error:%d occurred in pci_set_power_state\n", ret); |
|---|
| 461 | | - goto lynxfb_resume_err; |
|---|
| 462 | | - } |
|---|
| 463 | | - |
|---|
| 464 | | - if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) { |
|---|
| 465 | | - pci_restore_state(pdev); |
|---|
| 466 | | - ret = pci_enable_device(pdev); |
|---|
| 467 | | - if (ret) { |
|---|
| 468 | | - dev_err(&pdev->dev, |
|---|
| 469 | | - "error:%d occurred in pci_enable_device\n", |
|---|
| 470 | | - ret); |
|---|
| 471 | | - goto lynxfb_resume_err; |
|---|
| 472 | | - } |
|---|
| 473 | | - pci_set_master(pdev); |
|---|
| 474 | | - } |
|---|
| 475 | 444 | |
|---|
| 476 | 445 | hw_sm750_inithw(sm750_dev, pdev); |
|---|
| 477 | 446 | |
|---|
| .. | .. |
|---|
| 501 | 470 | |
|---|
| 502 | 471 | pdev->dev.power.power_state.event = PM_EVENT_RESUME; |
|---|
| 503 | 472 | |
|---|
| 504 | | -lynxfb_resume_err: |
|---|
| 505 | 473 | console_unlock(); |
|---|
| 506 | | - return ret; |
|---|
| 474 | + return 0; |
|---|
| 507 | 475 | } |
|---|
| 508 | | -#endif |
|---|
| 509 | 476 | |
|---|
| 510 | 477 | static int lynxfb_ops_check_var(struct fb_var_screeninfo *var, |
|---|
| 511 | 478 | struct fb_info *info) |
|---|
| 512 | 479 | { |
|---|
| 480 | + int ret; |
|---|
| 513 | 481 | struct lynxfb_par *par; |
|---|
| 514 | 482 | struct lynxfb_crtc *crtc; |
|---|
| 515 | 483 | resource_size_t request; |
|---|
| 516 | 484 | |
|---|
| 485 | + ret = 0; |
|---|
| 517 | 486 | par = info->par; |
|---|
| 518 | 487 | crtc = &par->crtc; |
|---|
| 519 | 488 | |
|---|
| .. | .. |
|---|
| 522 | 491 | var->yres, |
|---|
| 523 | 492 | var->bits_per_pixel); |
|---|
| 524 | 493 | |
|---|
| 525 | | - switch (var->bits_per_pixel) { |
|---|
| 526 | | - case 8: |
|---|
| 527 | | - info->fix.visual = FB_VISUAL_PSEUDOCOLOR; |
|---|
| 528 | | - var->red.offset = 0; |
|---|
| 529 | | - var->red.length = 8; |
|---|
| 530 | | - var->green.offset = 0; |
|---|
| 531 | | - var->green.length = 8; |
|---|
| 532 | | - var->blue.offset = 0; |
|---|
| 533 | | - var->blue.length = 8; |
|---|
| 534 | | - var->transp.length = 0; |
|---|
| 535 | | - var->transp.offset = 0; |
|---|
| 536 | | - break; |
|---|
| 537 | | - case 16: |
|---|
| 538 | | - var->red.offset = 11; |
|---|
| 539 | | - var->red.length = 5; |
|---|
| 540 | | - var->green.offset = 5; |
|---|
| 541 | | - var->green.length = 6; |
|---|
| 542 | | - var->blue.offset = 0; |
|---|
| 543 | | - var->blue.length = 5; |
|---|
| 544 | | - var->transp.length = 0; |
|---|
| 545 | | - var->transp.offset = 0; |
|---|
| 546 | | - info->fix.visual = FB_VISUAL_TRUECOLOR; |
|---|
| 547 | | - break; |
|---|
| 548 | | - case 24: |
|---|
| 549 | | - case 32: |
|---|
| 550 | | - var->red.offset = 16; |
|---|
| 551 | | - var->red.length = 8; |
|---|
| 552 | | - var->green.offset = 8; |
|---|
| 553 | | - var->green.length = 8; |
|---|
| 554 | | - var->blue.offset = 0; |
|---|
| 555 | | - var->blue.length = 8; |
|---|
| 556 | | - info->fix.visual = FB_VISUAL_TRUECOLOR; |
|---|
| 557 | | - break; |
|---|
| 558 | | - default: |
|---|
| 494 | + ret = lynxfb_set_color_offsets(info); |
|---|
| 495 | + |
|---|
| 496 | + if (ret) { |
|---|
| 559 | 497 | pr_err("bpp %d not supported\n", var->bits_per_pixel); |
|---|
| 560 | | - return -EINVAL; |
|---|
| 498 | + return ret; |
|---|
| 561 | 499 | } |
|---|
| 500 | + |
|---|
| 562 | 501 | var->height = var->width = -1; |
|---|
| 563 | 502 | var->accel_flags = 0;/* FB_ACCELF_TEXT; */ |
|---|
| 564 | 503 | |
|---|
| 565 | | - /* check if current fb's video memory big enought to hold the onscreen*/ |
|---|
| 504 | + /* check if current fb's video memory big enough to hold the onscreen*/ |
|---|
| 566 | 505 | request = var->xres_virtual * (var->bits_per_pixel >> 3); |
|---|
| 567 | 506 | /* defaulty crtc->channel go with par->index */ |
|---|
| 568 | 507 | |
|---|
| .. | .. |
|---|
| 695 | 634 | output->paths = sm750_crt; |
|---|
| 696 | 635 | crtc->channel = sm750_secondary; |
|---|
| 697 | 636 | /* not consider of padding stuffs for oScreen,need fix */ |
|---|
| 698 | | - crtc->oScreen = (sm750_dev->vidmem_size >> 1); |
|---|
| 637 | + crtc->oScreen = sm750_dev->vidmem_size >> 1; |
|---|
| 699 | 638 | crtc->vScreen = sm750_dev->pvMem + crtc->oScreen; |
|---|
| 700 | 639 | } |
|---|
| 701 | 640 | break; |
|---|
| .. | .. |
|---|
| 708 | 647 | } else { |
|---|
| 709 | 648 | output->paths = sm750_crt; |
|---|
| 710 | 649 | crtc->channel = sm750_primary; |
|---|
| 711 | | - /* not consider of padding stuffs for oScreen,need fix */ |
|---|
| 712 | | - crtc->oScreen = (sm750_dev->vidmem_size >> 1); |
|---|
| 650 | + /* not consider of padding stuffs for oScreen, |
|---|
| 651 | + * need fix |
|---|
| 652 | + */ |
|---|
| 653 | + crtc->oScreen = sm750_dev->vidmem_size >> 1; |
|---|
| 713 | 654 | crtc->vScreen = sm750_dev->pvMem + crtc->oScreen; |
|---|
| 714 | 655 | } |
|---|
| 715 | 656 | break; |
|---|
| .. | .. |
|---|
| 747 | 688 | lynx750_ext, NULL, vesa_modes, |
|---|
| 748 | 689 | }; |
|---|
| 749 | 690 | int cdb[] = {ARRAY_SIZE(lynx750_ext), 0, VESA_MODEDB_SIZE}; |
|---|
| 750 | | - static const char *mdb_desc[] = { |
|---|
| 691 | + static const char * const mdb_desc[] = { |
|---|
| 751 | 692 | "driver prepared modes", |
|---|
| 752 | 693 | "kernel prepared default modedb", |
|---|
| 753 | 694 | "kernel HELPERS prepared vesa_modes", |
|---|
| .. | .. |
|---|
| 892 | 833 | pr_info("fix->mmio_start = %lx\n", fix->mmio_start); |
|---|
| 893 | 834 | fix->mmio_len = sm750_dev->vidreg_size; |
|---|
| 894 | 835 | pr_info("fix->mmio_len = %x\n", fix->mmio_len); |
|---|
| 895 | | - switch (var->bits_per_pixel) { |
|---|
| 896 | | - case 8: |
|---|
| 897 | | - fix->visual = FB_VISUAL_PSEUDOCOLOR; |
|---|
| 898 | | - break; |
|---|
| 899 | | - case 16: |
|---|
| 900 | | - case 24: |
|---|
| 901 | | - case 32: |
|---|
| 902 | | - fix->visual = FB_VISUAL_TRUECOLOR; |
|---|
| 903 | | - break; |
|---|
| 904 | | - } |
|---|
| 836 | + |
|---|
| 837 | + lynxfb_set_visual_mode(info); |
|---|
| 905 | 838 | |
|---|
| 906 | 839 | /* set var */ |
|---|
| 907 | 840 | var->activate = FB_ACTIVATE_NOW; |
|---|
| .. | .. |
|---|
| 1008 | 941 | } |
|---|
| 1009 | 942 | } |
|---|
| 1010 | 943 | |
|---|
| 1011 | | -static void sm750fb_frambuffer_release(struct sm750_dev *sm750_dev) |
|---|
| 944 | +static void sm750fb_framebuffer_release(struct sm750_dev *sm750_dev) |
|---|
| 1012 | 945 | { |
|---|
| 1013 | 946 | struct fb_info *fb_info; |
|---|
| 1014 | 947 | |
|---|
| .. | .. |
|---|
| 1020 | 953 | } |
|---|
| 1021 | 954 | } |
|---|
| 1022 | 955 | |
|---|
| 1023 | | -static int sm750fb_frambuffer_alloc(struct sm750_dev *sm750_dev, int fbidx) |
|---|
| 956 | +static int sm750fb_framebuffer_alloc(struct sm750_dev *sm750_dev, int fbidx) |
|---|
| 1024 | 957 | { |
|---|
| 1025 | 958 | struct fb_info *fb_info; |
|---|
| 1026 | 959 | struct lynxfb_par *par; |
|---|
| .. | .. |
|---|
| 1138 | 1071 | /* allocate frame buffer info structures according to g_dualview */ |
|---|
| 1139 | 1072 | max_fb = g_dualview ? 2 : 1; |
|---|
| 1140 | 1073 | for (fbidx = 0; fbidx < max_fb; fbidx++) { |
|---|
| 1141 | | - err = sm750fb_frambuffer_alloc(sm750_dev, fbidx); |
|---|
| 1074 | + err = sm750fb_framebuffer_alloc(sm750_dev, fbidx); |
|---|
| 1142 | 1075 | if (err) |
|---|
| 1143 | 1076 | goto release_fb; |
|---|
| 1144 | 1077 | } |
|---|
| .. | .. |
|---|
| 1146 | 1079 | return 0; |
|---|
| 1147 | 1080 | |
|---|
| 1148 | 1081 | release_fb: |
|---|
| 1149 | | - sm750fb_frambuffer_release(sm750_dev); |
|---|
| 1082 | + sm750fb_framebuffer_release(sm750_dev); |
|---|
| 1150 | 1083 | return err; |
|---|
| 1151 | 1084 | } |
|---|
| 1152 | 1085 | |
|---|
| .. | .. |
|---|
| 1156 | 1089 | |
|---|
| 1157 | 1090 | sm750_dev = pci_get_drvdata(pdev); |
|---|
| 1158 | 1091 | |
|---|
| 1159 | | - sm750fb_frambuffer_release(sm750_dev); |
|---|
| 1092 | + sm750fb_framebuffer_release(sm750_dev); |
|---|
| 1160 | 1093 | arch_phys_wc_del(sm750_dev->mtrr.vram); |
|---|
| 1161 | 1094 | |
|---|
| 1162 | 1095 | iounmap(sm750_dev->pvReg); |
|---|
| .. | .. |
|---|
| 1222 | 1155 | |
|---|
| 1223 | 1156 | MODULE_DEVICE_TABLE(pci, smi_pci_table); |
|---|
| 1224 | 1157 | |
|---|
| 1158 | +static SIMPLE_DEV_PM_OPS(lynxfb_pm_ops, lynxfb_suspend, lynxfb_resume); |
|---|
| 1159 | + |
|---|
| 1225 | 1160 | static struct pci_driver lynxfb_driver = { |
|---|
| 1226 | 1161 | .name = "sm750fb", |
|---|
| 1227 | 1162 | .id_table = smi_pci_table, |
|---|
| 1228 | 1163 | .probe = lynxfb_pci_probe, |
|---|
| 1229 | 1164 | .remove = lynxfb_pci_remove, |
|---|
| 1230 | | -#ifdef CONFIG_PM |
|---|
| 1231 | | - .suspend = lynxfb_suspend, |
|---|
| 1232 | | - .resume = lynxfb_resume, |
|---|
| 1233 | | -#endif |
|---|
| 1165 | + .driver.pm = &lynxfb_pm_ops, |
|---|
| 1234 | 1166 | }; |
|---|
| 1235 | 1167 | |
|---|
| 1236 | 1168 | static int __init lynxfb_init(void) |
|---|