mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 06:43:09 +00:00
s3c-fb: CPUFREQ frequency scaling support
Add support for CPU frequency scaling in the S3C24XX video driver. Signed-off-by: Simtec Linux Team <linux@simtec.co.uk> Signed-off-by: Ben Dooks <ben@simtec.co.uk> Cc: Dave Jones <davej@codemonkey.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
ddc518d9f8
commit
0dac6ecdc0
@ -24,6 +24,7 @@
|
|||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/cpufreq.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
@ -89,7 +90,7 @@ static void s3c2410fb_set_lcdaddr(struct fb_info *info)
|
|||||||
static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,
|
static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,
|
||||||
unsigned long pixclk)
|
unsigned long pixclk)
|
||||||
{
|
{
|
||||||
unsigned long clk = clk_get_rate(fbi->clk);
|
unsigned long clk = fbi->clk_rate;
|
||||||
unsigned long long div;
|
unsigned long long div;
|
||||||
|
|
||||||
/* pixclk is in picoseconds, our clock is in Hz
|
/* pixclk is in picoseconds, our clock is in Hz
|
||||||
@ -758,6 +759,57 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
|
|||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CPU_FREQ
|
||||||
|
|
||||||
|
static int s3c2410fb_cpufreq_transition(struct notifier_block *nb,
|
||||||
|
unsigned long val, void *data)
|
||||||
|
{
|
||||||
|
struct cpufreq_freqs *freqs = data;
|
||||||
|
struct s3c2410fb_info *info;
|
||||||
|
struct fb_info *fbinfo;
|
||||||
|
long delta_f;
|
||||||
|
|
||||||
|
info = container_of(nb, struct s3c2410fb_info, freq_transition);
|
||||||
|
fbinfo = platform_get_drvdata(to_platform_device(info->dev));
|
||||||
|
|
||||||
|
/* work out change, <0 for speed-up */
|
||||||
|
delta_f = info->clk_rate - clk_get_rate(info->clk);
|
||||||
|
|
||||||
|
if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) ||
|
||||||
|
(val == CPUFREQ_PRECHANGE && delta_f < 0)) {
|
||||||
|
info->clk_rate = clk_get_rate(info->clk);
|
||||||
|
s3c2410fb_activate_var(fbinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int s3c2410fb_cpufreq_register(struct s3c2410fb_info *info)
|
||||||
|
{
|
||||||
|
info->freq_transition.notifier_call = s3c2410fb_cpufreq_transition;
|
||||||
|
|
||||||
|
return cpufreq_register_notifier(&info->freq_transition,
|
||||||
|
CPUFREQ_TRANSITION_NOTIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
|
||||||
|
{
|
||||||
|
cpufreq_unregister_notifier(&info->freq_transition,
|
||||||
|
CPUFREQ_TRANSITION_NOTIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static inline int s3c2410fb_cpufreq_register(struct s3c2410fb_info *info)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static char driver_name[] = "s3c2410fb";
|
static char driver_name[] = "s3c2410fb";
|
||||||
|
|
||||||
static int __init s3c24xxfb_probe(struct platform_device *pdev,
|
static int __init s3c24xxfb_probe(struct platform_device *pdev,
|
||||||
@ -875,6 +927,8 @@ static int __init s3c24xxfb_probe(struct platform_device *pdev,
|
|||||||
|
|
||||||
msleep(1);
|
msleep(1);
|
||||||
|
|
||||||
|
info->clk_rate = clk_get_rate(info->clk);
|
||||||
|
|
||||||
/* find maximum required memory size for display */
|
/* find maximum required memory size for display */
|
||||||
for (i = 0; i < mach_info->num_displays; i++) {
|
for (i = 0; i < mach_info->num_displays; i++) {
|
||||||
unsigned long smem_len = mach_info->displays[i].xres;
|
unsigned long smem_len = mach_info->displays[i].xres;
|
||||||
@ -904,11 +958,17 @@ static int __init s3c24xxfb_probe(struct platform_device *pdev,
|
|||||||
|
|
||||||
s3c2410fb_check_var(&fbinfo->var, fbinfo);
|
s3c2410fb_check_var(&fbinfo->var, fbinfo);
|
||||||
|
|
||||||
|
ret = s3c2410fb_cpufreq_register(info);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "Failed to register cpufreq\n");
|
||||||
|
goto free_video_memory;
|
||||||
|
}
|
||||||
|
|
||||||
ret = register_framebuffer(fbinfo);
|
ret = register_framebuffer(fbinfo);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk(KERN_ERR "Failed to register framebuffer device: %d\n",
|
printk(KERN_ERR "Failed to register framebuffer device: %d\n",
|
||||||
ret);
|
ret);
|
||||||
goto free_video_memory;
|
goto free_cpufreq;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create device files */
|
/* create device files */
|
||||||
@ -922,6 +982,8 @@ static int __init s3c24xxfb_probe(struct platform_device *pdev,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
free_cpufreq:
|
||||||
|
s3c2410fb_cpufreq_deregister(info);
|
||||||
free_video_memory:
|
free_video_memory:
|
||||||
s3c2410fb_unmap_video_memory(fbinfo);
|
s3c2410fb_unmap_video_memory(fbinfo);
|
||||||
release_clock:
|
release_clock:
|
||||||
@ -961,6 +1023,7 @@ static int s3c2410fb_remove(struct platform_device *pdev)
|
|||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
unregister_framebuffer(fbinfo);
|
unregister_framebuffer(fbinfo);
|
||||||
|
s3c2410fb_cpufreq_deregister(info);
|
||||||
|
|
||||||
s3c2410fb_lcd_enable(info, 0);
|
s3c2410fb_lcd_enable(info, 0);
|
||||||
msleep(1);
|
msleep(1);
|
||||||
|
@ -29,8 +29,13 @@ struct s3c2410fb_info {
|
|||||||
enum s3c_drv_type drv_type;
|
enum s3c_drv_type drv_type;
|
||||||
struct s3c2410fb_hw regs;
|
struct s3c2410fb_hw regs;
|
||||||
|
|
||||||
|
unsigned long clk_rate;
|
||||||
unsigned int palette_ready;
|
unsigned int palette_ready;
|
||||||
|
|
||||||
|
#ifdef CONFIG_CPU_FREQ
|
||||||
|
struct notifier_block freq_transition;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* keep these registers in case we need to re-write palette */
|
/* keep these registers in case we need to re-write palette */
|
||||||
u32 palette_buffer[256];
|
u32 palette_buffer[256];
|
||||||
u32 pseudo_pal[16];
|
u32 pseudo_pal[16];
|
||||||
|
Loading…
Reference in New Issue
Block a user