aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/pxafb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/pxafb.c')
-rw-r--r--drivers/video/pxafb.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index a280a52f8efe..f9b12ab59642 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -37,6 +37,8 @@
37#include <linux/cpufreq.h> 37#include <linux/cpufreq.h>
38#include <linux/platform_device.h> 38#include <linux/platform_device.h>
39#include <linux/dma-mapping.h> 39#include <linux/dma-mapping.h>
40#include <linux/clk.h>
41#include <linux/err.h>
40 42
41#include <asm/hardware.h> 43#include <asm/hardware.h>
42#include <asm/io.h> 44#include <asm/io.h>
@@ -506,15 +508,15 @@ static struct fb_ops pxafb_ops = {
506 * 508 *
507 * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below. 509 * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
508 */ 510 */
509static inline unsigned int get_pcd(unsigned int pixclock) 511static inline unsigned int get_pcd(struct pxafb_info *fbi, unsigned int pixclock)
510{ 512{
511 unsigned long long pcd; 513 unsigned long long pcd;
512 514
513 /* FIXME: Need to take into account Double Pixel Clock mode 515 /* FIXME: Need to take into account Double Pixel Clock mode
514 * (DPC) bit? or perhaps set it based on the various clock 516 * (DPC) bit? or perhaps set it based on the various clock
515 * speeds */ 517 * speeds */
516 518 pcd = (unsigned long long)(clk_get_rate(fbi->clk) / 10000);
517 pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock; 519 pcd *= pixclock;
518 do_div(pcd, 100000000 * 2); 520 do_div(pcd, 100000000 * 2);
519 /* no need for this, since we should subtract 1 anyway. they cancel */ 521 /* no need for this, since we should subtract 1 anyway. they cancel */
520 /* pcd += 1; */ /* make up for integer math truncations */ 522 /* pcd += 1; */ /* make up for integer math truncations */
@@ -523,19 +525,21 @@ static inline unsigned int get_pcd(unsigned int pixclock)
523 525
524/* 526/*
525 * Some touchscreens need hsync information from the video driver to 527 * Some touchscreens need hsync information from the video driver to
526 * function correctly. We export it here. 528 * function correctly. We export it here. Note that 'hsync_time' and
529 * the value returned from pxafb_get_hsync_time() is the *reciprocal*
530 * of the hsync period in seconds.
527 */ 531 */
528static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd) 532static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
529{ 533{
530 unsigned long long htime; 534 unsigned long htime;
531 535
532 if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) { 536 if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
533 fbi->hsync_time=0; 537 fbi->hsync_time=0;
534 return; 538 return;
535 } 539 }
536 540
537 htime = (unsigned long long)get_lcdclk_frequency_10khz() * 10000; 541 htime = clk_get_rate(fbi->clk) / (pcd * fbi->fb.var.hsync_len);
538 do_div(htime, pcd * fbi->fb.var.hsync_len); 542
539 fbi->hsync_time = htime; 543 fbi->hsync_time = htime;
540} 544}
541 545
@@ -560,7 +564,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
560{ 564{
561 struct pxafb_lcd_reg new_regs; 565 struct pxafb_lcd_reg new_regs;
562 u_long flags; 566 u_long flags;
563 u_int lines_per_panel, pcd = get_pcd(var->pixclock); 567 u_int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
564 568
565 pr_debug("pxafb: Configuring PXA LCD\n"); 569 pr_debug("pxafb: Configuring PXA LCD\n");
566 570
@@ -803,7 +807,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
803 pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); 807 pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
804 808
805 /* enable LCD controller clock */ 809 /* enable LCD controller clock */
806 pxa_set_cken(CKEN_LCD, 1); 810 clk_enable(fbi->clk);
807 811
808 /* Sequence from 11.7.10 */ 812 /* Sequence from 11.7.10 */
809 LCCR3 = fbi->reg_lccr3; 813 LCCR3 = fbi->reg_lccr3;
@@ -840,7 +844,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
840 remove_wait_queue(&fbi->ctrlr_wait, &wait); 844 remove_wait_queue(&fbi->ctrlr_wait, &wait);
841 845
842 /* disable LCD controller clock */ 846 /* disable LCD controller clock */
843 pxa_set_cken(CKEN_LCD, 0); 847 clk_disable(fbi->clk);
844} 848}
845 849
846/* 850/*
@@ -994,7 +998,7 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
994 break; 998 break;
995 999
996 case CPUFREQ_POSTCHANGE: 1000 case CPUFREQ_POSTCHANGE:
997 pcd = get_pcd(fbi->fb.var.pixclock); 1001 pcd = get_pcd(fbi, fbi->fb.var.pixclock);
998 set_hsync_time(fbi, pcd); 1002 set_hsync_time(fbi, pcd);
999 fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); 1003 fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
1000 set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); 1004 set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
@@ -1119,6 +1123,12 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
1119 memset(fbi, 0, sizeof(struct pxafb_info)); 1123 memset(fbi, 0, sizeof(struct pxafb_info));
1120 fbi->dev = dev; 1124 fbi->dev = dev;
1121 1125
1126 fbi->clk = clk_get(dev, "LCDCLK");
1127 if (IS_ERR(fbi->clk)) {
1128 kfree(fbi);
1129 return NULL;
1130 }
1131
1122 strcpy(fbi->fb.fix.id, PXA_NAME); 1132 strcpy(fbi->fb.fix.id, PXA_NAME);
1123 1133
1124 fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; 1134 fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;