Commit 72e3524c authored by Russell King's avatar Russell King Committed by Russell King

[ARM] pxa: update pxafb to use clk support

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent a6dba20c
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -506,15 +508,15 @@ static struct fb_ops pxafb_ops = { ...@@ -506,15 +508,15 @@ static struct fb_ops pxafb_ops = {
* *
* Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below. * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
*/ */
static inline unsigned int get_pcd(unsigned int pixclock) static inline unsigned int get_pcd(struct pxafb_info *fbi, unsigned int pixclock)
{ {
unsigned long long pcd; unsigned long long pcd;
/* FIXME: Need to take into account Double Pixel Clock mode /* FIXME: Need to take into account Double Pixel Clock mode
* (DPC) bit? or perhaps set it based on the various clock * (DPC) bit? or perhaps set it based on the various clock
* speeds */ * speeds */
pcd = (unsigned long long)(clk_get_rate(fbi->clk) / 10000);
pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock; pcd *= pixclock;
do_div(pcd, 100000000 * 2); do_div(pcd, 100000000 * 2);
/* no need for this, since we should subtract 1 anyway. they cancel */ /* no need for this, since we should subtract 1 anyway. they cancel */
/* pcd += 1; */ /* make up for integer math truncations */ /* pcd += 1; */ /* make up for integer math truncations */
...@@ -523,19 +525,21 @@ static inline unsigned int get_pcd(unsigned int pixclock) ...@@ -523,19 +525,21 @@ static inline unsigned int get_pcd(unsigned int pixclock)
/* /*
* Some touchscreens need hsync information from the video driver to * Some touchscreens need hsync information from the video driver to
* function correctly. We export it here. * function correctly. We export it here. Note that 'hsync_time' and
* the value returned from pxafb_get_hsync_time() is the *reciprocal*
* of the hsync period in seconds.
*/ */
static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd) static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
{ {
unsigned long long htime; unsigned long htime;
if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) { if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
fbi->hsync_time=0; fbi->hsync_time=0;
return; return;
} }
htime = (unsigned long long)get_lcdclk_frequency_10khz() * 10000; htime = clk_get_rate(fbi->clk) / (pcd * fbi->fb.var.hsync_len);
do_div(htime, pcd * fbi->fb.var.hsync_len);
fbi->hsync_time = htime; fbi->hsync_time = htime;
} }
...@@ -560,7 +564,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info * ...@@ -560,7 +564,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
{ {
struct pxafb_lcd_reg new_regs; struct pxafb_lcd_reg new_regs;
u_long flags; u_long flags;
u_int lines_per_panel, pcd = get_pcd(var->pixclock); u_int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
pr_debug("pxafb: Configuring PXA LCD\n"); pr_debug("pxafb: Configuring PXA LCD\n");
...@@ -803,7 +807,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) ...@@ -803,7 +807,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
/* enable LCD controller clock */ /* enable LCD controller clock */
pxa_set_cken(CKEN_LCD, 1); clk_enable(fbi->clk);
/* Sequence from 11.7.10 */ /* Sequence from 11.7.10 */
LCCR3 = fbi->reg_lccr3; LCCR3 = fbi->reg_lccr3;
...@@ -840,7 +844,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) ...@@ -840,7 +844,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
remove_wait_queue(&fbi->ctrlr_wait, &wait); remove_wait_queue(&fbi->ctrlr_wait, &wait);
/* disable LCD controller clock */ /* disable LCD controller clock */
pxa_set_cken(CKEN_LCD, 0); clk_disable(fbi->clk);
} }
/* /*
...@@ -994,7 +998,7 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data) ...@@ -994,7 +998,7 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
break; break;
case CPUFREQ_POSTCHANGE: case CPUFREQ_POSTCHANGE:
pcd = get_pcd(fbi->fb.var.pixclock); pcd = get_pcd(fbi, fbi->fb.var.pixclock);
set_hsync_time(fbi, pcd); set_hsync_time(fbi, pcd);
fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
...@@ -1119,6 +1123,12 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev) ...@@ -1119,6 +1123,12 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
memset(fbi, 0, sizeof(struct pxafb_info)); memset(fbi, 0, sizeof(struct pxafb_info));
fbi->dev = dev; fbi->dev = dev;
fbi->clk = clk_get(dev, "LCDCLK");
if (IS_ERR(fbi->clk)) {
kfree(fbi);
return NULL;
}
strcpy(fbi->fb.fix.id, PXA_NAME); strcpy(fbi->fb.fix.id, PXA_NAME);
fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
......
...@@ -40,6 +40,7 @@ struct pxafb_dma_descriptor { ...@@ -40,6 +40,7 @@ struct pxafb_dma_descriptor {
struct pxafb_info { struct pxafb_info {
struct fb_info fb; struct fb_info fb;
struct device *dev; struct device *dev;
struct clk *clk;
/* /*
* These are the addresses we mapped * These are the addresses we mapped
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment