diff options
Diffstat (limited to 'drivers/video/fbdev/au1100fb.c')
| -rw-r--r-- | drivers/video/fbdev/au1100fb.c | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c index 372d4aea9d1c..0676746ec68c 100644 --- a/drivers/video/fbdev/au1100fb.c +++ b/drivers/video/fbdev/au1100fb.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | * with this program; if not, write to the Free Software Foundation, Inc., | 41 | * with this program; if not, write to the Free Software Foundation, Inc., |
| 42 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 42 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 43 | */ | 43 | */ |
| 44 | #include <linux/clk.h> | ||
| 44 | #include <linux/module.h> | 45 | #include <linux/module.h> |
| 45 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
| 46 | #include <linux/errno.h> | 47 | #include <linux/errno.h> |
| @@ -113,7 +114,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) | |||
| 113 | case VESA_NO_BLANKING: | 114 | case VESA_NO_BLANKING: |
| 114 | /* Turn on panel */ | 115 | /* Turn on panel */ |
| 115 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; | 116 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; |
| 116 | au_sync(); | 117 | wmb(); /* drain writebuffer */ |
| 117 | break; | 118 | break; |
| 118 | 119 | ||
| 119 | case VESA_VSYNC_SUSPEND: | 120 | case VESA_VSYNC_SUSPEND: |
| @@ -121,7 +122,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) | |||
| 121 | case VESA_POWERDOWN: | 122 | case VESA_POWERDOWN: |
| 122 | /* Turn off panel */ | 123 | /* Turn off panel */ |
| 123 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; | 124 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; |
| 124 | au_sync(); | 125 | wmb(); /* drain writebuffer */ |
| 125 | break; | 126 | break; |
| 126 | default: | 127 | default: |
| 127 | break; | 128 | break; |
| @@ -434,7 +435,7 @@ static int au1100fb_drv_probe(struct platform_device *dev) | |||
| 434 | struct au1100fb_device *fbdev = NULL; | 435 | struct au1100fb_device *fbdev = NULL; |
| 435 | struct resource *regs_res; | 436 | struct resource *regs_res; |
| 436 | unsigned long page; | 437 | unsigned long page; |
| 437 | u32 sys_clksrc; | 438 | struct clk *c; |
| 438 | 439 | ||
| 439 | /* Allocate new device private */ | 440 | /* Allocate new device private */ |
| 440 | fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device), | 441 | fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device), |
| @@ -473,6 +474,13 @@ static int au1100fb_drv_probe(struct platform_device *dev) | |||
| 473 | print_dbg("Register memory map at %p", fbdev->regs); | 474 | print_dbg("Register memory map at %p", fbdev->regs); |
| 474 | print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); | 475 | print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); |
| 475 | 476 | ||
| 477 | c = clk_get(NULL, "lcd_intclk"); | ||
| 478 | if (!IS_ERR(c)) { | ||
| 479 | fbdev->lcdclk = c; | ||
| 480 | clk_set_rate(c, 48000000); | ||
| 481 | clk_prepare_enable(c); | ||
| 482 | } | ||
| 483 | |||
| 476 | /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ | 484 | /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ |
| 477 | fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * | 485 | fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * |
| 478 | (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; | 486 | (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; |
| @@ -506,10 +514,6 @@ static int au1100fb_drv_probe(struct platform_device *dev) | |||
| 506 | print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); | 514 | print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); |
| 507 | print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); | 515 | print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); |
| 508 | 516 | ||
| 509 | /* Setup LCD clock to AUX (48 MHz) */ | ||
| 510 | sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL); | ||
| 511 | au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC); | ||
| 512 | |||
| 513 | /* load the panel info into the var struct */ | 517 | /* load the panel info into the var struct */ |
| 514 | au1100fb_var.bits_per_pixel = fbdev->panel->bpp; | 518 | au1100fb_var.bits_per_pixel = fbdev->panel->bpp; |
| 515 | au1100fb_var.xres = fbdev->panel->xres; | 519 | au1100fb_var.xres = fbdev->panel->xres; |
| @@ -546,6 +550,10 @@ static int au1100fb_drv_probe(struct platform_device *dev) | |||
| 546 | return 0; | 550 | return 0; |
| 547 | 551 | ||
| 548 | failed: | 552 | failed: |
| 553 | if (fbdev->lcdclk) { | ||
| 554 | clk_disable_unprepare(fbdev->lcdclk); | ||
| 555 | clk_put(fbdev->lcdclk); | ||
| 556 | } | ||
| 549 | if (fbdev->fb_mem) { | 557 | if (fbdev->fb_mem) { |
| 550 | dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem, | 558 | dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem, |
| 551 | fbdev->fb_phys); | 559 | fbdev->fb_phys); |
| @@ -576,11 +584,15 @@ int au1100fb_drv_remove(struct platform_device *dev) | |||
| 576 | 584 | ||
| 577 | fb_dealloc_cmap(&fbdev->info.cmap); | 585 | fb_dealloc_cmap(&fbdev->info.cmap); |
| 578 | 586 | ||
| 587 | if (fbdev->lcdclk) { | ||
| 588 | clk_disable_unprepare(fbdev->lcdclk); | ||
| 589 | clk_put(fbdev->lcdclk); | ||
| 590 | } | ||
| 591 | |||
| 579 | return 0; | 592 | return 0; |
| 580 | } | 593 | } |
| 581 | 594 | ||
| 582 | #ifdef CONFIG_PM | 595 | #ifdef CONFIG_PM |
| 583 | static u32 sys_clksrc; | ||
| 584 | static struct au1100fb_regs fbregs; | 596 | static struct au1100fb_regs fbregs; |
| 585 | 597 | ||
| 586 | int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state) | 598 | int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state) |
| @@ -590,14 +602,11 @@ int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state) | |||
| 590 | if (!fbdev) | 602 | if (!fbdev) |
| 591 | return 0; | 603 | return 0; |
| 592 | 604 | ||
| 593 | /* Save the clock source state */ | ||
| 594 | sys_clksrc = au_readl(SYS_CLKSRC); | ||
| 595 | |||
| 596 | /* Blank the LCD */ | 605 | /* Blank the LCD */ |
| 597 | au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info); | 606 | au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info); |
| 598 | 607 | ||
| 599 | /* Stop LCD clocking */ | 608 | if (fbdev->lcdclk) |
| 600 | au_writel(sys_clksrc & ~SYS_CS_ML_MASK, SYS_CLKSRC); | 609 | clk_disable(fbdev->lcdclk); |
| 601 | 610 | ||
| 602 | memcpy(&fbregs, fbdev->regs, sizeof(struct au1100fb_regs)); | 611 | memcpy(&fbregs, fbdev->regs, sizeof(struct au1100fb_regs)); |
| 603 | 612 | ||
| @@ -613,8 +622,8 @@ int au1100fb_drv_resume(struct platform_device *dev) | |||
| 613 | 622 | ||
| 614 | memcpy(fbdev->regs, &fbregs, sizeof(struct au1100fb_regs)); | 623 | memcpy(fbdev->regs, &fbregs, sizeof(struct au1100fb_regs)); |
| 615 | 624 | ||
| 616 | /* Restart LCD clocking */ | 625 | if (fbdev->lcdclk) |
| 617 | au_writel(sys_clksrc, SYS_CLKSRC); | 626 | clk_enable(fbdev->lcdclk); |
| 618 | 627 | ||
| 619 | /* Unblank the LCD */ | 628 | /* Unblank the LCD */ |
| 620 | au1100fb_fb_blank(VESA_NO_BLANKING, &fbdev->info); | 629 | au1100fb_fb_blank(VESA_NO_BLANKING, &fbdev->info); |
