diff options
Diffstat (limited to 'drivers/video/fbdev')
-rw-r--r-- | drivers/video/fbdev/au1100fb.c | 39 | ||||
-rw-r--r-- | drivers/video/fbdev/au1100fb.h | 1 | ||||
-rw-r--r-- | drivers/video/fbdev/au1200fb.c | 81 |
3 files changed, 63 insertions, 58 deletions
diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c index 372d4ae..0676746e 100644 --- a/drivers/video/fbdev/au1100fb.c +++ b/drivers/video/fbdev/au1100fb.c @@ -41,6 +41,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/clk.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -113,7 +114,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) case VESA_NO_BLANKING: /* Turn on panel */ fbdev->regs->lcd_control |= LCD_CONTROL_GO; - au_sync(); + wmb(); /* drain writebuffer */ break; case VESA_VSYNC_SUSPEND: @@ -121,7 +122,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) case VESA_POWERDOWN: /* Turn off panel */ fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; - au_sync(); + wmb(); /* drain writebuffer */ break; default: break; @@ -434,7 +435,7 @@ static int au1100fb_drv_probe(struct platform_device *dev) struct au1100fb_device *fbdev = NULL; struct resource *regs_res; unsigned long page; - u32 sys_clksrc; + struct clk *c; /* Allocate new device private */ fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device), @@ -473,6 +474,13 @@ static int au1100fb_drv_probe(struct platform_device *dev) print_dbg("Register memory map at %p", fbdev->regs); print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); + c = clk_get(NULL, "lcd_intclk"); + if (!IS_ERR(c)) { + fbdev->lcdclk = c; + clk_set_rate(c, 48000000); + clk_prepare_enable(c); + } + /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; @@ -506,10 +514,6 @@ static int au1100fb_drv_probe(struct platform_device *dev) print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); - /* Setup LCD clock to AUX (48 MHz) */ - sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL); - au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC); - /* load the panel info into the var struct */ au1100fb_var.bits_per_pixel = fbdev->panel->bpp; au1100fb_var.xres = fbdev->panel->xres; @@ -546,6 +550,10 @@ static int au1100fb_drv_probe(struct platform_device *dev) return 0; failed: + if (fbdev->lcdclk) { + clk_disable_unprepare(fbdev->lcdclk); + clk_put(fbdev->lcdclk); + } if (fbdev->fb_mem) { dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys); @@ -576,11 +584,15 @@ int au1100fb_drv_remove(struct platform_device *dev) fb_dealloc_cmap(&fbdev->info.cmap); + if (fbdev->lcdclk) { + clk_disable_unprepare(fbdev->lcdclk); + clk_put(fbdev->lcdclk); + } + return 0; } #ifdef CONFIG_PM -static u32 sys_clksrc; static struct au1100fb_regs fbregs; 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) if (!fbdev) return 0; - /* Save the clock source state */ - sys_clksrc = au_readl(SYS_CLKSRC); - /* Blank the LCD */ au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info); - /* Stop LCD clocking */ - au_writel(sys_clksrc & ~SYS_CS_ML_MASK, SYS_CLKSRC); + if (fbdev->lcdclk) + clk_disable(fbdev->lcdclk); memcpy(&fbregs, fbdev->regs, sizeof(struct au1100fb_regs)); @@ -613,8 +622,8 @@ int au1100fb_drv_resume(struct platform_device *dev) memcpy(fbdev->regs, &fbregs, sizeof(struct au1100fb_regs)); - /* Restart LCD clocking */ - au_writel(sys_clksrc, SYS_CLKSRC); + if (fbdev->lcdclk) + clk_enable(fbdev->lcdclk); /* Unblank the LCD */ au1100fb_fb_blank(VESA_NO_BLANKING, &fbdev->info); diff --git a/drivers/video/fbdev/au1100fb.h b/drivers/video/fbdev/au1100fb.h index 12d9642d..9af1993 100644 --- a/drivers/video/fbdev/au1100fb.h +++ b/drivers/video/fbdev/au1100fb.h @@ -109,6 +109,7 @@ struct au1100fb_device { size_t fb_len; dma_addr_t fb_phys; int panel_idx; + struct clk *lcdclk; }; /********************************************************************/ diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index 4cfba78..40494db 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -30,6 +30,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/clk.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/kernel.h> @@ -330,9 +331,8 @@ struct panel_settings uint32 mode_pwmhi; uint32 mode_outmask; uint32 mode_fifoctrl; - uint32 mode_toyclksrc; uint32 mode_backlight; - uint32 mode_auxpll; + uint32 lcdclk; #define Xres min_xres #define Yres min_yres u32 min_xres; /* Minimum horizontal resolution */ @@ -379,9 +379,8 @@ static struct panel_settings known_lcd_panels[] = .mode_pwmhi = 0x00000000, .mode_outmask = 0x00FFFFFF, .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ + .lcdclk = 96, 320, 320, 240, 240, }, @@ -407,9 +406,8 @@ static struct panel_settings known_lcd_panels[] = .mode_pwmhi = 0x00000000, .mode_outmask = 0x00FFFFFF, .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ + .lcdclk = 96, 640, 480, 640, 480, }, @@ -435,9 +433,8 @@ static struct panel_settings known_lcd_panels[] = .mode_pwmhi = 0x00000000, .mode_outmask = 0x00FFFFFF, .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ + .lcdclk = 96, 800, 800, 600, 600, }, @@ -463,9 +460,8 @@ static struct panel_settings known_lcd_panels[] = .mode_pwmhi = 0x00000000, .mode_outmask = 0x00FFFFFF, .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ .mode_backlight = 0x00000000, - .mode_auxpll = 6, /* 72MHz AUXPLL */ + .lcdclk = 72, 1024, 1024, 768, 768, }, @@ -491,9 +487,8 @@ static struct panel_settings known_lcd_panels[] = .mode_pwmhi = 0x00000000, .mode_outmask = 0x00FFFFFF, .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ .mode_backlight = 0x00000000, - .mode_auxpll = 10, /* 120MHz AUXPLL */ + .lcdclk = 120, 1280, 1280, 1024, 1024, }, @@ -519,9 +514,8 @@ static struct panel_settings known_lcd_panels[] = .mode_pwmhi = 0x03400000, /* SCB 0x0 */ .mode_outmask = 0x00FFFFFF, .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ + .lcdclk = 96, 1024, 1024, 768, 768, }, @@ -550,9 +544,8 @@ static struct panel_settings known_lcd_panels[] = .mode_pwmhi = 0x03400000, .mode_outmask = 0x00fcfcfc, .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ + .lcdclk = 96, 640, 480, 640, 480, }, @@ -581,9 +574,8 @@ static struct panel_settings known_lcd_panels[] = .mode_pwmhi = 0x03400000, .mode_outmask = 0x00fcfcfc, .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ + .lcdclk = 96, /* 96MHz AUXPLL */ 320, 320, 240, 240, }, @@ -612,9 +604,8 @@ static struct panel_settings known_lcd_panels[] = .mode_pwmhi = 0x03400000, .mode_outmask = 0x00fcfcfc, .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ + .lcdclk = 96, 856, 856, 480, 480, }, @@ -646,9 +637,8 @@ static struct panel_settings known_lcd_panels[] = .mode_pwmhi = 0x00000000, .mode_outmask = 0x00FFFFFF, .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ .mode_backlight = 0x00000000, - .mode_auxpll = (48/12) * 2, + .lcdclk = 96, 800, 800, 480, 480, }, @@ -764,7 +754,7 @@ static int au1200_setlocation (struct au1200fb_device *fbdev, int plane, /* Disable the window while making changes, then restore WINEN */ winenable = lcd->winenable & (1 << plane); - au_sync(); + wmb(); /* drain writebuffer */ lcd->winenable &= ~(1 << plane); lcd->window[plane].winctrl0 = winctrl0; lcd->window[plane].winctrl1 = winctrl1; @@ -772,7 +762,7 @@ static int au1200_setlocation (struct au1200fb_device *fbdev, int plane, lcd->window[plane].winbuf1 = fbdev->fb_phys; lcd->window[plane].winbufctrl = 0; /* select winbuf0 */ lcd->winenable |= winenable; - au_sync(); + wmb(); /* drain writebuffer */ return 0; } @@ -788,22 +778,21 @@ static void au1200_setpanel(struct panel_settings *newpanel, /* Make sure all windows disabled */ winenable = lcd->winenable; lcd->winenable = 0; - au_sync(); + wmb(); /* drain writebuffer */ /* * Ensure everything is disabled before reconfiguring */ if (lcd->screen & LCD_SCREEN_SEN) { /* Wait for vertical sync period */ lcd->intstatus = LCD_INT_SS; - while ((lcd->intstatus & LCD_INT_SS) == 0) { - au_sync(); - } + while ((lcd->intstatus & LCD_INT_SS) == 0) + ; lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/ do { lcd->intstatus = lcd->intstatus; /*clear interrupts*/ - au_sync(); + wmb(); /* drain writebuffer */ /*wait for controller to shut down*/ } while ((lcd->intstatus & LCD_INT_SD) == 0); @@ -829,11 +818,17 @@ static void au1200_setpanel(struct panel_settings *newpanel, */ if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) { - uint32 sys_clksrc; - au_writel(panel->mode_auxpll, SYS_AUXPLL); - sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f; - sys_clksrc |= panel->mode_toyclksrc; - au_writel(sys_clksrc, SYS_CLKSRC); + struct clk *c = clk_get(NULL, "lcd_intclk"); + long r, pc = panel->lcdclk * 1000000; + + if (!IS_ERR(c)) { + r = clk_round_rate(c, pc); + if ((pc - r) < (pc / 10)) { /* 10% slack */ + clk_set_rate(c, r); + clk_prepare_enable(c); + } + clk_put(c); + } } /* @@ -847,7 +842,7 @@ static void au1200_setpanel(struct panel_settings *newpanel, lcd->pwmhi = panel->mode_pwmhi; lcd->outmask = panel->mode_outmask; lcd->fifoctrl = panel->mode_fifoctrl; - au_sync(); + wmb(); /* drain writebuffer */ /* fixme: Check window settings to make sure still valid * for new geometry */ @@ -863,7 +858,7 @@ static void au1200_setpanel(struct panel_settings *newpanel, * Re-enable screen now that it is configured */ lcd->screen |= LCD_SCREEN_SEN; - au_sync(); + wmb(); /* drain writebuffer */ /* Call init of panel */ if (pd->panel_init) @@ -956,7 +951,7 @@ static void au1200_setmode(struct au1200fb_device *fbdev) | LCD_WINCTRL2_SCY_1 ) ; lcd->winenable |= win->w[plane].mode_winenable; - au_sync(); + wmb(); /* drain writebuffer */ } @@ -1270,7 +1265,7 @@ static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) if (pdata->flags & SCREEN_MASK) lcd->colorkeymsk = pdata->mask; - au_sync(); + wmb(); /* drain writebuffer */ } static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) @@ -1288,7 +1283,7 @@ static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) hi1 = (lcd->pwmhi >> 16) + 1; divider = (lcd->pwmdiv & 0x3FFFF) + 1; pdata->brightness = ((hi1 << 8) / divider) - 1; - au_sync(); + wmb(); /* drain writebuffer */ } static void set_window(unsigned int plane, @@ -1387,7 +1382,7 @@ static void set_window(unsigned int plane, val |= (pdata->enable & 1) << plane; lcd->winenable = val; } - au_sync(); + wmb(); /* drain writebuffer */ } static void get_window(unsigned int plane, @@ -1414,7 +1409,7 @@ static void get_window(unsigned int plane, pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21; pdata->enable = (lcd->winenable >> plane) & 1; - au_sync(); + wmb(); /* drain writebuffer */ } static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, @@ -1511,7 +1506,7 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id) { /* Nothing to do for now, just clear any pending interrupt */ lcd->intstatus = lcd->intstatus; - au_sync(); + wmb(); /* drain writebuffer */ return IRQ_HANDLED; } @@ -1809,7 +1804,7 @@ static int au1200fb_drv_suspend(struct device *dev) au1200_setpanel(NULL, pd); lcd->outmask = 0; - au_sync(); + wmb(); /* drain writebuffer */ return 0; } |