Backlight control support for the PXA fram buffer.

Signed-off-by: Rodolfo Giometti <[EMAIL PROTECTED]>

---

Each platform should define the backlight properties in its own setup
file in "linux/arch/arm/mach-pxa/" as follow:

   static int pxafb_bl_get_brightness(struct backlight_device *bl_dev)
   {
        return read_the_backlight_brightness();
   }

   static int pxafb_bl_update_status(struct backlight_device *bl_dev)
   {
           int perc, ret;

           if (bl_dev->props->power != FB_BLANK_UNBLANK ||
               bl_dev->props->fb_blank != FB_BLANK_UNBLANK)
                   perc = 0;
           else
                   perc = bl_dev->props->brightness;

        write_the_backlight_brightness(perc);

           return 0;
   }

   static struct backlight_properties wwpc1100_backlight_props = {
           .get_brightness         = pxafb_bl_get_brightness,
           .update_status          = pxafb_bl_update_status,
           .max_brightness         = 100,
   };
      
and then seting up the fb info as follow:

   wwpc1100_pxafb_info.modes = &special_modes;
   wwpc1100_pxafb_info.bl_props = &wwpc1100_backlight_props;
   set_pxa_fb_info(&wwpc1100_pxafb_info);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index c1536d7..1ee589e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1514,6 +1514,14 @@ config FB_PXA_PARAMETERS
 
          <file:Documentation/fb/pxafb.txt> describes the available parameters.
 
+config FB_PXA_BACKLIGHT
+       bool "Support for backlight control"
+       default y
+       depends on FB_PXA
+       select FB_BACKLIGHT
+       help
+         Say Y here if you want to control the backlight of your display.
+
 config FB_MBX
        tristate "2700G LCD framebuffer support"
        depends on FB && ARCH_PXA
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index b4947c8..489174a 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -9,6 +9,8 @@
  *  which in turn is
  *   Based on acornfb.c Copyright (C) Russell King.
  *
+ * Backlight support by Rodolfo Giometti <[EMAIL PROTECTED]>
+ *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive for
  * more details.
@@ -37,6 +39,7 @@
 #include <linux/cpufreq.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/backlight.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -58,7 +61,6 @@
 #define LCCR0_INVALID_CONFIG_MASK 
(LCCR0_OUM|LCCR0_BM|LCCR0_QDM|LCCR0_DIS|LCCR0_EFM|LCCR0_IUM|LCCR0_SFM|LCCR0_LDM|LCCR0_ENB)
 #define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP|LCCR3_VSP|LCCR3_PCD|LCCR3_BPP)
 
-static void (*pxafb_backlight_power)(int);
 static void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
 
 static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info 
*);
@@ -69,6 +71,71 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int 
state);
 static char g_options[PXAFB_OPTIONS_SIZE] __initdata = "";
 #endif
 
+
+/*
+ * Backlight control
+ */
+#ifdef CONFIG_FB_BACKLIGHT
+static void pxafb_bl_suspend(struct pxafb_info *fbi)
+{
+       struct backlight_device *bl_dev = fbi->fb.bl_dev;
+
+       if (bl_dev) {
+               down(&bl_dev->sem);
+               bl_dev->props->fb_blank = FB_BLANK_POWERDOWN;
+               bl_dev->props->update_status(bl_dev);
+               up(&bl_dev->sem);
+       }
+}
+
+static void pxafb_bl_resume(struct pxafb_info *fbi)
+{
+       struct backlight_device *bl_dev = fbi->fb.bl_dev;
+
+       if (bl_dev) {
+               down(&bl_dev->sem);
+               bl_dev->props->fb_blank = FB_BLANK_UNBLANK;
+               bl_dev->props->update_status(bl_dev);
+               up(&bl_dev->sem);
+       }
+}
+
+static void pxafb_bl_init(struct fb_info *info, struct backlight_properties 
*bl_props)
+{
+       struct backlight_device *bl_dev;
+       char name[16];
+
+       snprintf(name, sizeof(name), "pxabl%d", info->node);
+
+       bl_dev = backlight_device_register(name, info->dev, info, bl_props);
+       if (IS_ERR(bl_dev)) {
+               info->bl_dev = NULL;
+               printk(KERN_WARNING "pxafb: backlight registration failed\n");
+               return;
+       }
+
+       mutex_lock(&info->bl_mutex);
+       info->bl_dev = bl_dev;
+       fb_bl_default_curve(info, 0, 0, 100);   /* level: 0 - 100 */
+       mutex_unlock(&info->bl_mutex);
+
+       down(&bl_dev->sem);
+       bl_dev->props->brightness = bl_props->max_brightness;
+       bl_dev->props->power = FB_BLANK_UNBLANK;
+       bl_dev->props->update_status(bl_dev);
+       up(&bl_dev->sem);
+
+       printk("pxafb: backlight initialized (%s)\n", name);
+}
+#else
+static inline void pxafb_bl_init(struct fb_info *info, struct 
backlight_properties *bl_props) {}
+static inline void pxafb_bl_suspend(struct pxafb_info *fbi) {}
+static inline void pxafb_bl_resume(struct pxafb_info *fbi) {}
+#endif /* CONFIG_FB_BACKLIGHT */
+
+/*
+ *
+ */
 static inline void pxafb_schedule_work(struct pxafb_info *fbi, u_int state)
 {
        unsigned long flags;
@@ -736,14 +803,6 @@ static int pxafb_activate_var(struct fb_var_screeninfo 
*var, struct pxafb_info *
  * to ensure that things happen in the right way 100% of time time.
  *     -- rmk
  */
-static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on)
-{
-       pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff");
-
-       if (pxafb_backlight_power)
-               pxafb_backlight_power(on);
-}
-
 static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
 {
        pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff");
@@ -899,7 +958,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int 
state)
                 */
                if (old_state != C_DISABLE) {
                        fbi->state = state;
-                       __pxafb_backlight_power(fbi, 0);
+                       pxafb_bl_suspend(fbi);
                        __pxafb_lcd_power(fbi, 0);
                        if (old_state != C_DISABLE_CLKCHANGE)
                                pxafb_disable_controller(fbi);
@@ -953,7 +1012,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int 
state)
                        pxafb_setup_gpio(fbi);
                        pxafb_enable_controller(fbi);
                        __pxafb_lcd_power(fbi, 1);
-                       __pxafb_backlight_power(fbi, 1);
+                       pxafb_bl_resume(fbi);
                }
                break;
        }
@@ -1112,11 +1171,10 @@ static struct pxafb_info * __init 
pxafb_init_fbinfo(struct device *dev)
        int i, smemlen;
 
        /* Alloc the pxafb_info and pseudo_palette in one step */
-       fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
+       fbi = (struct pxafb_info *) framebuffer_alloc(sizeof(u32) * 16, dev);
        if (!fbi)
                return NULL;
 
-       memset(fbi, 0, sizeof(struct pxafb_info));
        fbi->dev = dev;
 
        strcpy(fbi->fb.fix.id, PXA_NAME);
@@ -1368,7 +1426,6 @@ int __init pxafb_probe(struct platform_device *dev)
                ret = -EINVAL;
                goto failed;
        }
-       pxafb_backlight_power = inf->pxafb_backlight_power;
        pxafb_lcd_power = inf->pxafb_lcd_power;
        fbi = pxafb_init_fbinfo(&dev->dev);
        if (!fbi) {
@@ -1407,6 +1464,9 @@ int __init pxafb_probe(struct platform_device *dev)
                goto failed;
        }
 
+       /* Register the backlight support */
+       pxafb_bl_init(&fbi->fb, inf->bl_props);
+
 #ifdef CONFIG_PM
        // TODO
 #endif
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index 81c3928..5c89664 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -71,7 +71,7 @@ struct pxafb_mach_info {
         */
        u_int           lccr3;
 
-       void (*pxafb_backlight_power)(int);
+       struct backlight_properties     *bl_props;
        void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
 
 };

Reply via email to