1/* 2 * Backlight Driver for Sharp Zaurus Handhelds (various models) 3 * 4 * Copyright (c) 2004-2006 Richard Purdie 5 * 6 * Based on Sharp's 2.4 Backlight Driver 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 */ 13 14#include <linux/module.h> 15#include <linux/kernel.h> 16#include <linux/init.h> 17#include <linux/platform_device.h> 18#include <linux/mutex.h> 19#include <linux/fb.h> 20#include <linux/backlight.h> 21#include <asm/arch/sharpsl.h> 22#include <asm/hardware/sharpsl_pm.h> 23 24static int corgibl_intensity; 25static struct backlight_properties corgibl_data; 26static struct backlight_device *corgi_backlight_device; 27static struct corgibl_machinfo *bl_machinfo; 28 29static unsigned long corgibl_flags; 30#define CORGIBL_SUSPENDED 0x01 31#define CORGIBL_BATTLOW 0x02 32 33static int corgibl_send_intensity(struct backlight_device *bd) 34{ 35 void (*corgi_kick_batt)(void); 36 int intensity = bd->props.brightness; 37 38 if (bd->props.power != FB_BLANK_UNBLANK) 39 intensity = 0; 40 if (bd->props.fb_blank != FB_BLANK_UNBLANK) 41 intensity = 0; 42 if (corgibl_flags & CORGIBL_SUSPENDED) 43 intensity = 0; 44 if (corgibl_flags & CORGIBL_BATTLOW) 45 intensity &= bl_machinfo->limit_mask; 46 47 bl_machinfo->set_bl_intensity(intensity); 48 49 corgibl_intensity = intensity; 50 51 corgi_kick_batt = symbol_get(sharpsl_battery_kick); 52 if (corgi_kick_batt) { 53 corgi_kick_batt(); 54 symbol_put(sharpsl_battery_kick); 55 } 56 57 return 0; 58} 59 60#ifdef CONFIG_PM 61static int corgibl_suspend(struct platform_device *pdev, pm_message_t state) 62{ 63 struct backlight_device *bd = platform_get_drvdata(pdev); 64 65 corgibl_flags |= CORGIBL_SUSPENDED; 66 backlight_update_status(bd); 67 return 0; 68} 69 70static int corgibl_resume(struct platform_device *pdev) 71{ 72 struct backlight_device *bd = platform_get_drvdata(pdev); 73 74 corgibl_flags &= ~CORGIBL_SUSPENDED; 75 backlight_update_status(bd); 76 return 0; 77} 78#else 79#define corgibl_suspend NULL 80#define corgibl_resume NULL 81#endif 82 83static int corgibl_get_intensity(struct backlight_device *bd) 84{ 85 return corgibl_intensity; 86} 87 88/* 89 * Called when the battery is low to limit the backlight intensity. 90 * If limit==0 clear any limit, otherwise limit the intensity 91 */ 92void corgibl_limit_intensity(int limit) 93{ 94 if (limit) 95 corgibl_flags |= CORGIBL_BATTLOW; 96 else 97 corgibl_flags &= ~CORGIBL_BATTLOW; 98 backlight_update_status(corgi_backlight_device); 99} 100EXPORT_SYMBOL(corgibl_limit_intensity); 101 102 103static struct backlight_ops corgibl_ops = { 104 .get_brightness = corgibl_get_intensity, 105 .update_status = corgibl_send_intensity, 106}; 107 108static int corgibl_probe(struct platform_device *pdev) 109{ 110 struct corgibl_machinfo *machinfo = pdev->dev.platform_data; 111 112 bl_machinfo = machinfo; 113 if (!machinfo->limit_mask) 114 machinfo->limit_mask = -1; 115 116 corgi_backlight_device = backlight_device_register ("corgi-bl", 117 &pdev->dev, NULL, &corgibl_ops); 118 if (IS_ERR (corgi_backlight_device)) 119 return PTR_ERR (corgi_backlight_device); 120 121 platform_set_drvdata(pdev, corgi_backlight_device); 122 123 corgi_backlight_device->props.max_brightness = machinfo->max_intensity; 124 corgi_backlight_device->props.power = FB_BLANK_UNBLANK; 125 corgi_backlight_device->props.brightness = machinfo->default_intensity; 126 backlight_update_status(corgi_backlight_device); 127 128 printk("Corgi Backlight Driver Initialized.\n"); 129 return 0; 130} 131 132static int corgibl_remove(struct platform_device *pdev) 133{ 134 struct backlight_device *bd = platform_get_drvdata(pdev); 135 136 corgibl_data.power = 0; 137 corgibl_data.brightness = 0; 138 backlight_update_status(bd); 139 140 backlight_device_unregister(bd); 141 142 printk("Corgi Backlight Driver Unloaded\n"); 143 return 0; 144} 145 146static struct platform_driver corgibl_driver = { 147 .probe = corgibl_probe, 148 .remove = corgibl_remove, 149 .suspend = corgibl_suspend, 150 .resume = corgibl_resume, 151 .driver = { 152 .name = "corgi-bl", 153 }, 154}; 155 156static int __init corgibl_init(void) 157{ 158 return platform_driver_register(&corgibl_driver); 159} 160 161static void __exit corgibl_exit(void) 162{ 163 platform_driver_unregister(&corgibl_driver); 164} 165 166module_init(corgibl_init); 167module_exit(corgibl_exit); 168 169MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); 170MODULE_DESCRIPTION("Corgi Backlight Driver"); 171MODULE_LICENSE("GPL"); 172