1d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie/* 2d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie * Generic Backlight Driver 3d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie * 4d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie * Copyright (c) 2004-2008 Richard Purdie 5d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie * 6d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie * This program is free software; you can redistribute it and/or modify 7d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie * it under the terms of the GNU General Public License version 2 as 8d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie * published by the Free Software Foundation. 9d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie * 10d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie */ 11d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 12d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie#include <linux/module.h> 13d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie#include <linux/kernel.h> 14d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie#include <linux/init.h> 15d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie#include <linux/platform_device.h> 16d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie#include <linux/mutex.h> 17d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie#include <linux/fb.h> 18d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie#include <linux/backlight.h> 19d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 20d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdiestatic int genericbl_intensity; 21d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdiestatic struct backlight_device *generic_backlight_device; 22d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdiestatic struct generic_bl_info *bl_machinfo; 23d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 24d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie/* Flag to signal when the battery is low */ 25d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie#define GENERICBL_BATTLOW BL_CORE_DRIVER1 26d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 27d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdiestatic int genericbl_send_intensity(struct backlight_device *bd) 28d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie{ 29d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie int intensity = bd->props.brightness; 30d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 31d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie if (bd->props.power != FB_BLANK_UNBLANK) 32d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie intensity = 0; 33d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie if (bd->props.state & BL_CORE_FBBLANK) 34d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie intensity = 0; 35d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie if (bd->props.state & BL_CORE_SUSPENDED) 36d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie intensity = 0; 37d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie if (bd->props.state & GENERICBL_BATTLOW) 38d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie intensity &= bl_machinfo->limit_mask; 39d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 40d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie bl_machinfo->set_bl_intensity(intensity); 41d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 42d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie genericbl_intensity = intensity; 43d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 44d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie if (bl_machinfo->kick_battery) 45d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie bl_machinfo->kick_battery(); 46d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 47d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie return 0; 48d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie} 49d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 50d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdiestatic int genericbl_get_intensity(struct backlight_device *bd) 51d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie{ 52d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie return genericbl_intensity; 53d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie} 54d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 55d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie/* 56d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie * Called when the battery is low to limit the backlight intensity. 57d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie * If limit==0 clear any limit, otherwise limit the intensity 58d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie */ 591bff3a2093161d1b982a0958e4eb194bf3c8ce47Axel Linvoid genericbl_limit_intensity(int limit) 60d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie{ 61d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie struct backlight_device *bd = generic_backlight_device; 62d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 63d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie mutex_lock(&bd->ops_lock); 64d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie if (limit) 65d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie bd->props.state |= GENERICBL_BATTLOW; 66d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie else 67d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie bd->props.state &= ~GENERICBL_BATTLOW; 68d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie backlight_update_status(generic_backlight_device); 69d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie mutex_unlock(&bd->ops_lock); 70d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie} 711bff3a2093161d1b982a0958e4eb194bf3c8ce47Axel LinEXPORT_SYMBOL(genericbl_limit_intensity); 72d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 739905a43b2d563e6f89e4c63c4278ada03f2ebb14Emese Revfystatic const struct backlight_ops genericbl_ops = { 74d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie .options = BL_CORE_SUSPENDRESUME, 75d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie .get_brightness = genericbl_get_intensity, 76d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie .update_status = genericbl_send_intensity, 77d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie}; 78d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 79d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdiestatic int genericbl_probe(struct platform_device *pdev) 80d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie{ 81a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett struct backlight_properties props; 82d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie struct generic_bl_info *machinfo = pdev->dev.platform_data; 83d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie const char *name = "generic-bl"; 84d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie struct backlight_device *bd; 85d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 86d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie bl_machinfo = machinfo; 87d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie if (!machinfo->limit_mask) 88d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie machinfo->limit_mask = -1; 89d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 90d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie if (machinfo->name) 91d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie name = machinfo->name; 92d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 93a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett memset(&props, 0, sizeof(struct backlight_properties)); 94bb7ca747f8d6243b3943c5b133048652020f4a50Matthew Garrett props.type = BACKLIGHT_RAW; 95a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett props.max_brightness = machinfo->max_intensity; 96a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops, 97a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett &props); 98d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie if (IS_ERR (bd)) 99d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie return PTR_ERR (bd); 100d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 101d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie platform_set_drvdata(pdev, bd); 102d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 103d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie bd->props.power = FB_BLANK_UNBLANK; 104d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie bd->props.brightness = machinfo->default_intensity; 105d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie backlight_update_status(bd); 106d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 107d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie generic_backlight_device = bd; 108d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 109d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie printk("Generic Backlight Driver Initialized.\n"); 110d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie return 0; 111d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie} 112d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 113d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdiestatic int genericbl_remove(struct platform_device *pdev) 114d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie{ 115d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie struct backlight_device *bd = platform_get_drvdata(pdev); 116d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 117d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie bd->props.power = 0; 118d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie bd->props.brightness = 0; 119d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie backlight_update_status(bd); 120d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 121d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie backlight_device_unregister(bd); 122d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 123d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie printk("Generic Backlight Driver Unloaded\n"); 124d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie return 0; 125d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie} 126d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 127d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdiestatic struct platform_driver genericbl_driver = { 128d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie .probe = genericbl_probe, 129d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie .remove = genericbl_remove, 130d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie .driver = { 131d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie .name = "generic-bl", 132d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie }, 133d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie}; 134d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 13581178e021689bf86c328f144aa0f0e1b50f5e94cAxel Linmodule_platform_driver(genericbl_driver); 136d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard Purdie 137d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard PurdieMODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); 138d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard PurdieMODULE_DESCRIPTION("Generic Backlight Driver"); 139d00ba726725c6f41e43df00f83e484ba8f9fac5cRichard PurdieMODULE_LICENSE("GPL"); 140