aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2009-01-15 09:21:00 -0500
committerSascha Hauer <s.hauer@pengutronix.de>2009-03-27 09:51:14 -0400
commitf909ef6437a8388e3f1272c67ee29071f930bd6b (patch)
treeef0451e73617ba70e41391b65c249bae25999331 /drivers/video
parent74bef9a4fa978669b234c4454daa596c0494c09a (diff)
imxfb: add clock support
v2: Added change from Martin Fuzzey: pixclock should be in pico seconds instead of MHz. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/imxfb.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index bd1cb75cd14b..8f7a2b2c78e7 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -26,9 +26,11 @@
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/ioport.h> 27#include <linux/ioport.h>
28#include <linux/cpufreq.h> 28#include <linux/cpufreq.h>
29#include <linux/clk.h>
29#include <linux/platform_device.h> 30#include <linux/platform_device.h>
30#include <linux/dma-mapping.h> 31#include <linux/dma-mapping.h>
31#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/math64.h>
32 34
33#include <mach/imxfb.h> 35#include <mach/imxfb.h>
34 36
@@ -141,6 +143,7 @@ struct imxfb_rgb {
141struct imxfb_info { 143struct imxfb_info {
142 struct platform_device *pdev; 144 struct platform_device *pdev;
143 void __iomem *regs; 145 void __iomem *regs;
146 struct clk *clk;
144 147
145 u_int max_bpp; 148 u_int max_bpp;
146 u_int max_xres; 149 u_int max_xres;
@@ -403,6 +406,8 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
403 406
404 writel(RMCR_LCDC_EN, fbi->regs + LCDC_RMCR); 407 writel(RMCR_LCDC_EN, fbi->regs + LCDC_RMCR);
405 408
409 clk_enable(fbi->clk);
410
406 if (fbi->backlight_power) 411 if (fbi->backlight_power)
407 fbi->backlight_power(1); 412 fbi->backlight_power(1);
408 if (fbi->lcd_power) 413 if (fbi->lcd_power)
@@ -418,6 +423,8 @@ static void imxfb_disable_controller(struct imxfb_info *fbi)
418 if (fbi->lcd_power) 423 if (fbi->lcd_power)
419 fbi->lcd_power(0); 424 fbi->lcd_power(0);
420 425
426 clk_disable(fbi->clk);
427
421 writel(0, fbi->regs + LCDC_RMCR); 428 writel(0, fbi->regs + LCDC_RMCR);
422} 429}
423 430
@@ -461,6 +468,9 @@ static struct fb_ops imxfb_ops = {
461static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info) 468static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
462{ 469{
463 struct imxfb_info *fbi = info->par; 470 struct imxfb_info *fbi = info->par;
471 unsigned int pcr, lcd_clk;
472 unsigned long long tmp;
473
464 pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n", 474 pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
465 var->xres, var->hsync_len, 475 var->xres, var->hsync_len,
466 var->left_margin, var->right_margin); 476 var->left_margin, var->right_margin);
@@ -507,7 +517,23 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
507 517
508 writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres), 518 writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres),
509 fbi->regs + LCDC_SIZE); 519 fbi->regs + LCDC_SIZE);
510 writel(fbi->pcr, fbi->regs + LCDC_PCR); 520
521 lcd_clk = clk_get_rate(fbi->clk);
522 tmp = var->pixclock * (unsigned long long)lcd_clk;
523 do_div(tmp, 1000000);
524 if (do_div(tmp, 1000000) > 500000)
525 tmp++;
526 pcr = (unsigned int)tmp;
527 if (--pcr > 0x3F) {
528 pcr = 0x3F;
529 printk(KERN_WARNING "Must limit pixel clock to %uHz\n",
530 lcd_clk / pcr);
531 }
532
533 /* add sync polarities */
534 pcr |= fbi->pcr & ~0x3F;
535
536 writel(pcr, fbi->regs + LCDC_PCR);
511 writel(fbi->pwmr, fbi->regs + LCDC_PWMR); 537 writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
512 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); 538 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
513 writel(fbi->dmacr, fbi->regs + LCDC_DMACR); 539 writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
@@ -649,6 +675,13 @@ static int __init imxfb_probe(struct platform_device *pdev)
649 goto failed_req; 675 goto failed_req;
650 } 676 }
651 677
678 fbi->clk = clk_get(&pdev->dev, NULL);
679 if (IS_ERR(fbi->clk)) {
680 ret = PTR_ERR(fbi->clk);;
681 dev_err(&pdev->dev, "unable to get clock: %d\n", ret);
682 goto failed_getclock;
683 }
684
652 fbi->regs = ioremap(res->start, resource_size(res)); 685 fbi->regs = ioremap(res->start, resource_size(res));
653 if (fbi->regs == NULL) { 686 if (fbi->regs == NULL) {
654 printk(KERN_ERR"Cannot map frame buffer registers\n"); 687 printk(KERN_ERR"Cannot map frame buffer registers\n");
@@ -717,6 +750,8 @@ failed_platform_init:
717 dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu, 750 dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu,
718 fbi->map_dma); 751 fbi->map_dma);
719failed_map: 752failed_map:
753 clk_put(fbi->clk);
754failed_getclock:
720 iounmap(fbi->regs); 755 iounmap(fbi->regs);
721failed_ioremap: 756failed_ioremap:
722 release_mem_region(res->start, res->end - res->start); 757 release_mem_region(res->start, res->end - res->start);
@@ -751,6 +786,9 @@ static int __devexit imxfb_remove(struct platform_device *pdev)
751 786
752 iounmap(fbi->regs); 787 iounmap(fbi->regs);
753 release_mem_region(res->start, res->end - res->start + 1); 788 release_mem_region(res->start, res->end - res->start + 1);
789 clk_disable(fbi->clk);
790 clk_put(fbi->clk);
791
754 platform_set_drvdata(pdev, NULL); 792 platform_set_drvdata(pdev, NULL);
755 793
756 return 0; 794 return 0;