diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2007-08-20 05:18:42 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-10-12 16:14:56 -0400 |
commit | 72e3524c0b591c30c3a2e2058dd78327ec99efed (patch) | |
tree | d6b37eb55eaa95a083906fce03ebb5c09e34efd7 /drivers/video/pxafb.c | |
parent | a6dba20c5c7b3a18d69bcbd60a1d2ebc0536f0ce (diff) |
[ARM] pxa: update pxafb to use clk support
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/video/pxafb.c')
-rw-r--r-- | drivers/video/pxafb.c | 36 |
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 | */ |
509 | static inline unsigned int get_pcd(unsigned int pixclock) | 511 | static 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 | */ |
528 | static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd) | 532 | static 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; |