diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/video/imxfb.c | 40 |
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 { | |||
| 141 | struct imxfb_info { | 143 | struct 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 = { | |||
| 461 | static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info) | 468 | static 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); |
| 719 | failed_map: | 752 | failed_map: |
| 753 | clk_put(fbi->clk); | ||
| 754 | failed_getclock: | ||
| 720 | iounmap(fbi->regs); | 755 | iounmap(fbi->regs); |
| 721 | failed_ioremap: | 756 | failed_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; |
