davinci: fb: add cpufreq support
authorChaithrika U S <chaithrika@ti.com>
Wed, 16 Dec 2009 00:46:29 +0000 (16:46 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 16 Dec 2009 15:20:02 +0000 (07:20 -0800)
Add cpufreq support for DA8xx/OMAP-L1xx frame buffer driver

Signed-off-by: Chaithrika U S <chaithrika@ti.com>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
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>
drivers/video/da8xx-fb.c

index fe0025213a82f925f04d4dc9e99ce046e5d40a2b..8966274bbbbca3ea9e3d66d3d1b8f731019b3a8c 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
+#include <linux/cpufreq.h>
 #include <video/da8xx-fb.h>
 
 #define DRIVER_NAME "da8xx_lcdc"
@@ -114,6 +115,9 @@ struct da8xx_fb_par {
        unsigned int databuf_sz;
        unsigned int palette_sz;
        unsigned int pxl_clk;
+#ifdef CONFIG_CPU_FREQ
+       struct notifier_block   freq_transition;
+#endif
 };
 
 /* Variable Screen Information */
@@ -586,6 +590,41 @@ static int fb_check_var(struct fb_var_screeninfo *var,
        return err;
 }
 
+#ifdef CONFIG_CPU_FREQ
+static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
+                                    unsigned long val, void *data)
+{
+       struct da8xx_fb_par *par;
+       unsigned int reg;
+
+       par = container_of(nb, struct da8xx_fb_par, freq_transition);
+       if (val == CPUFREQ_PRECHANGE) {
+               reg = lcdc_read(LCD_RASTER_CTRL_REG);
+               lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+       } else if (val == CPUFREQ_POSTCHANGE) {
+               lcd_calc_clk_divider(par);
+               reg = lcdc_read(LCD_RASTER_CTRL_REG);
+               lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+       }
+
+       return 0;
+}
+
+static inline int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par)
+{
+       par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition;
+
+       return cpufreq_register_notifier(&par->freq_transition,
+                                        CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par)
+{
+       cpufreq_unregister_notifier(&par->freq_transition,
+                                   CPUFREQ_TRANSITION_NOTIFIER);
+}
+#endif
+
 static int __devexit fb_remove(struct platform_device *dev)
 {
        struct fb_info *info = dev_get_drvdata(&dev->dev);
@@ -593,6 +632,9 @@ static int __devexit fb_remove(struct platform_device *dev)
        if (info) {
                struct da8xx_fb_par *par = info->par;
 
+#ifdef CONFIG_CPU_FREQ
+               lcd_da8xx_cpufreq_deregister(par);
+#endif
                if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE)
                        lcd_disable_raster(par);
                lcdc_write(0, LCD_RASTER_CTRL_REG);
@@ -826,12 +868,25 @@ static int __init fb_probe(struct platform_device *device)
                goto err_dealloc_cmap;
        }
 
+#ifdef CONFIG_CPU_FREQ
+       ret = lcd_da8xx_cpufreq_register(par);
+       if (ret) {
+               dev_err(&device->dev, "failed to register cpufreq\n");
+               goto err_cpu_freq;
+       }
+#endif
+
        /* enable raster engine */
        lcdc_write(lcdc_read(LCD_RASTER_CTRL_REG) |
                        LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
 
        return 0;
 
+#ifdef CONFIG_CPU_FREQ
+err_cpu_freq:
+       unregister_framebuffer(da8xx_fb_info);
+#endif
+
 err_dealloc_cmap:
        fb_dealloc_cmap(&da8xx_fb_info->cmap);