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 | |
| parent | a6dba20c5c7b3a18d69bcbd60a1d2ebc0536f0ce (diff) | |
[ARM] pxa: update pxafb to use clk support
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
| -rw-r--r-- | drivers/video/pxafb.c | 36 | ||||
| -rw-r--r-- | drivers/video/pxafb.h | 1 |
2 files changed, 24 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; |
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h index 7499a1c4bf79..f8605b807b0a 100644 --- a/drivers/video/pxafb.h +++ b/drivers/video/pxafb.h | |||
| @@ -40,6 +40,7 @@ struct pxafb_dma_descriptor { | |||
| 40 | struct pxafb_info { | 40 | struct pxafb_info { |
| 41 | struct fb_info fb; | 41 | struct fb_info fb; |
| 42 | struct device *dev; | 42 | struct device *dev; |
| 43 | struct clk *clk; | ||
| 43 | 44 | ||
| 44 | /* | 45 | /* |
| 45 | * These are the addresses we mapped | 46 | * These are the addresses we mapped |
