aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/chipsfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/chipsfb.c')
-rw-r--r--drivers/video/chipsfb.c176
1 files changed, 92 insertions, 84 deletions
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 95e72550d43f..e75a965ec760 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -28,22 +28,17 @@
28#include <linux/fb.h> 28#include <linux/fb.h>
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/pci.h> 30#include <linux/pci.h>
31#include <linux/console.h>
31#include <asm/io.h> 32#include <asm/io.h>
32 33
33#ifdef CONFIG_PMAC_BACKLIGHT 34#ifdef CONFIG_PMAC_BACKLIGHT
34#include <asm/backlight.h> 35#include <asm/backlight.h>
35#endif 36#endif
36#ifdef CONFIG_PMAC_PBOOK
37#include <linux/adb.h>
38#include <linux/pmu.h>
39#endif
40 37
41/* 38/*
42 * Since we access the display with inb/outb to fixed port numbers, 39 * Since we access the display with inb/outb to fixed port numbers,
43 * we can only handle one 6555x chip. -- paulus 40 * we can only handle one 6555x chip. -- paulus
44 */ 41 */
45static struct fb_info chipsfb_info;
46
47#define write_ind(num, val, ap, dp) do { \ 42#define write_ind(num, val, ap, dp) do { \
48 outb((num), (ap)); outb((val), (dp)); \ 43 outb((num), (ap)); outb((val), (dp)); \
49} while (0) 44} while (0)
@@ -74,14 +69,6 @@ static struct fb_info chipsfb_info;
74 inb(0x3da); read_ind(num, var, 0x3c0, 0x3c1); \ 69 inb(0x3da); read_ind(num, var, 0x3c0, 0x3c1); \
75} while (0) 70} while (0)
76 71
77#ifdef CONFIG_PMAC_PBOOK
78static unsigned char *save_framebuffer;
79int chips_sleep_notify(struct pmu_sleep_notifier *self, int when);
80static struct pmu_sleep_notifier chips_sleep_notifier = {
81 chips_sleep_notify, SLEEP_LEVEL_VIDEO,
82};
83#endif
84
85/* 72/*
86 * Exported functions 73 * Exported functions
87 */ 74 */
@@ -356,6 +343,8 @@ static struct fb_var_screeninfo chipsfb_var __initdata = {
356 343
357static void __init init_chips(struct fb_info *p, unsigned long addr) 344static void __init init_chips(struct fb_info *p, unsigned long addr)
358{ 345{
346 memset(p->screen_base, 0, 0x100000);
347
359 p->fix = chipsfb_fix; 348 p->fix = chipsfb_fix;
360 p->fix.smem_start = addr; 349 p->fix.smem_start = addr;
361 350
@@ -366,34 +355,41 @@ static void __init init_chips(struct fb_info *p, unsigned long addr)
366 355
367 fb_alloc_cmap(&p->cmap, 256, 0); 356 fb_alloc_cmap(&p->cmap, 256, 0);
368 357
369 if (register_framebuffer(p) < 0) {
370 printk(KERN_ERR "C&T 65550 framebuffer failed to register\n");
371 return;
372 }
373
374 printk(KERN_INFO "fb%d: Chips 65550 frame buffer (%dK RAM detected)\n",
375 p->node, p->fix.smem_len / 1024);
376
377 chips_hw_init(); 358 chips_hw_init();
378} 359}
379 360
380static int __devinit 361static int __devinit
381chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) 362chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
382{ 363{
383 struct fb_info *p = &chipsfb_info; 364 struct fb_info *p;
384 unsigned long addr, size; 365 unsigned long addr, size;
385 unsigned short cmd; 366 unsigned short cmd;
367 int rc = -ENODEV;
368
369 if (pci_enable_device(dp) < 0) {
370 dev_err(&dp->dev, "Cannot enable PCI device\n");
371 goto err_out;
372 }
386 373
387 if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) 374 if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
388 return -ENODEV; 375 goto err_disable;
389 addr = pci_resource_start(dp, 0); 376 addr = pci_resource_start(dp, 0);
390 size = pci_resource_len(dp, 0); 377 size = pci_resource_len(dp, 0);
391 if (addr == 0) 378 if (addr == 0)
392 return -ENODEV; 379 goto err_disable;
393 if (p->screen_base != 0) 380
394 return -EBUSY; 381 p = framebuffer_alloc(0, &dp->dev);
395 if (!request_mem_region(addr, size, "chipsfb")) 382 if (p == NULL) {
396 return -EBUSY; 383 dev_err(&dp->dev, "Cannot allocate framebuffer structure\n");
384 rc = -ENOMEM;
385 goto err_disable;
386 }
387
388 if (pci_request_region(dp, 0, "chipsfb") != 0) {
389 dev_err(&dp->dev, "Cannot request framebuffer\n");
390 rc = -EBUSY;
391 goto err_release_fb;
392 }
397 393
398#ifdef __BIG_ENDIAN 394#ifdef __BIG_ENDIAN
399 addr += 0x800000; // Use big-endian aperture 395 addr += 0x800000; // Use big-endian aperture
@@ -411,37 +407,89 @@ chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
411 set_backlight_enable(1); 407 set_backlight_enable(1);
412#endif /* CONFIG_PMAC_BACKLIGHT */ 408#endif /* CONFIG_PMAC_BACKLIGHT */
413 409
410#ifdef CONFIG_PPC
414 p->screen_base = __ioremap(addr, 0x200000, _PAGE_NO_CACHE); 411 p->screen_base = __ioremap(addr, 0x200000, _PAGE_NO_CACHE);
412#else
413 p->screen_base = ioremap(addr, 0x200000);
414#endif
415 if (p->screen_base == NULL) { 415 if (p->screen_base == NULL) {
416 release_mem_region(addr, size); 416 dev_err(&dp->dev, "Cannot map framebuffer\n");
417 return -ENOMEM; 417 rc = -ENOMEM;
418 goto err_release_pci;
418 } 419 }
420
421 pci_set_drvdata(dp, p);
419 p->device = &dp->dev; 422 p->device = &dp->dev;
423
420 init_chips(p, addr); 424 init_chips(p, addr);
421 425
422#ifdef CONFIG_PMAC_PBOOK 426 if (register_framebuffer(p) < 0) {
423 pmu_register_sleep_notifier(&chips_sleep_notifier); 427 dev_err(&dp->dev,"C&T 65550 framebuffer failed to register\n");
424#endif /* CONFIG_PMAC_PBOOK */ 428 goto err_unmap;
429 }
430
431 dev_info(&dp->dev,"fb%d: Chips 65550 frame buffer"
432 " (%dK RAM detected)\n",
433 p->node, p->fix.smem_len / 1024);
425 434
426 pci_set_drvdata(dp, p);
427 return 0; 435 return 0;
436
437 err_unmap:
438 iounmap(p->screen_base);
439 err_release_pci:
440 pci_release_region(dp, 0);
441 err_release_fb:
442 framebuffer_release(p);
443 err_disable:
444 err_out:
445 return rc;
428} 446}
429 447
430static void __devexit chipsfb_remove(struct pci_dev *dp) 448static void __devexit chipsfb_remove(struct pci_dev *dp)
431{ 449{
432 struct fb_info *p = pci_get_drvdata(dp); 450 struct fb_info *p = pci_get_drvdata(dp);
433 451
434 if (p != &chipsfb_info || p->screen_base == NULL) 452 if (p->screen_base == NULL)
435 return; 453 return;
436 unregister_framebuffer(p); 454 unregister_framebuffer(p);
437 iounmap(p->screen_base); 455 iounmap(p->screen_base);
438 p->screen_base = NULL; 456 p->screen_base = NULL;
439 release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0)); 457 pci_release_region(dp, 0);
458}
459
460#ifdef CONFIG_PM
461static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
462{
463 struct fb_info *p = pci_get_drvdata(pdev);
464
465 if (state == pdev->dev.power.power_state)
466 return 0;
467 if (state != PM_SUSPEND_MEM)
468 goto done;
469
470 acquire_console_sem();
471 chipsfb_blank(1, p);
472 fb_set_suspend(p, 1);
473 release_console_sem();
474 done:
475 pdev->dev.power.power_state = state;
476 return 0;
477}
478
479static int chipsfb_pci_resume(struct pci_dev *pdev)
480{
481 struct fb_info *p = pci_get_drvdata(pdev);
440 482
441#ifdef CONFIG_PMAC_PBOOK 483 acquire_console_sem();
442 pmu_unregister_sleep_notifier(&chips_sleep_notifier); 484 fb_set_suspend(p, 0);
443#endif /* CONFIG_PMAC_PBOOK */ 485 chipsfb_blank(0, p);
486 release_console_sem();
487
488 pdev->dev.power.power_state = PMSG_ON;
489 return 0;
444} 490}
491#endif /* CONFIG_PM */
492
445 493
446static struct pci_device_id chipsfb_pci_tbl[] = { 494static struct pci_device_id chipsfb_pci_tbl[] = {
447 { PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_65550, PCI_ANY_ID, PCI_ANY_ID }, 495 { PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_65550, PCI_ANY_ID, PCI_ANY_ID },
@@ -455,6 +503,10 @@ static struct pci_driver chipsfb_driver = {
455 .id_table = chipsfb_pci_tbl, 503 .id_table = chipsfb_pci_tbl,
456 .probe = chipsfb_pci_init, 504 .probe = chipsfb_pci_init,
457 .remove = __devexit_p(chipsfb_remove), 505 .remove = __devexit_p(chipsfb_remove),
506#ifdef CONFIG_PM
507 .suspend = chipsfb_pci_suspend,
508 .resume = chipsfb_pci_resume,
509#endif
458}; 510};
459 511
460int __init chips_init(void) 512int __init chips_init(void)
@@ -472,48 +524,4 @@ static void __exit chipsfb_exit(void)
472 pci_unregister_driver(&chipsfb_driver); 524 pci_unregister_driver(&chipsfb_driver);
473} 525}
474 526
475#ifdef CONFIG_PMAC_PBOOK
476/*
477 * Save the contents of the frame buffer when we go to sleep,
478 * and restore it when we wake up again.
479 */
480int
481chips_sleep_notify(struct pmu_sleep_notifier *self, int when)
482{
483 struct fb_info *p = &chipsfb_info;
484 int nb = p->var.yres * p->fix.line_length;
485
486 if (p->screen_base == NULL)
487 return PBOOK_SLEEP_OK;
488
489 switch (when) {
490 case PBOOK_SLEEP_REQUEST:
491 save_framebuffer = vmalloc(nb);
492 if (save_framebuffer == NULL)
493 return PBOOK_SLEEP_REFUSE;
494 break;
495 case PBOOK_SLEEP_REJECT:
496 if (save_framebuffer) {
497 vfree(save_framebuffer);
498 save_framebuffer = NULL;
499 }
500 break;
501 case PBOOK_SLEEP_NOW:
502 chipsfb_blank(1, p);
503 if (save_framebuffer)
504 memcpy(save_framebuffer, p->screen_base, nb);
505 break;
506 case PBOOK_WAKE:
507 if (save_framebuffer) {
508 memcpy(p->screen_base, save_framebuffer, nb);
509 vfree(save_framebuffer);
510 save_framebuffer = NULL;
511 }
512 chipsfb_blank(0, p);
513 break;
514 }
515 return PBOOK_SLEEP_OK;
516}
517#endif /* CONFIG_PMAC_PBOOK */
518
519MODULE_LICENSE("GPL"); 527MODULE_LICENSE("GPL");