全部博文(75)
分类: LINUX
2009-08-24 23:00:25
Backlight framework in linux-2.6.29
The framework adds support for low-level control of the LCD backlight, which include support for brightness and power.
To make your backlight driver registered into the kernel, the framework provides the only backlight_device_register() API function, which will create “bl_power”, “brightness”, “actual_brightnes” and “max_brightness” files under /sys/class/backlight/your_backlight_driver/. These files represent the properties of your backlight driver, for example, “bl_power” denotes which power state, your backlight driver is in now; writing values to “brightness” will reduce or increase the “brightness”, and read to “actual_brightness”, “max_brightness” returns the current value of brightness and maximum brightness, respectively.
/**
*
backlight_device_register - create and register a new object of
* backlight_device class.
* @name: the
name of the new object(must be the same as the name of the
* respective framebuffer device).
* @parent: a
pointer to the parent device
* @devdata: an
optional pointer to be stored for private driver use. The
* methods may retrieve it by using
bl_get_data(bd).
* @ops: the
backlight operations structure.
*
* Creates and
registers new backlight device. Returns either an
* ERR_PTR() or
a pointer to the newly allocated device.
*/
struct backlight_device
*backlight_device_register(const char *name,
struct
device *parent, void *devdata, struct backlight_ops *ops)
{
struct
backlight_device *new_bd;
int rc;
pr_debug("backlight_device_register:
name=%s\n", name);
new_bd
= kzalloc(sizeof(struct backlight_device), GFP_KERNEL);
<-- allocate space for new backlight device.
if (!new_bd)
return
ERR_PTR(-ENOMEM);
mutex_init(&new_bd->update_lock);
mutex_init(&new_bd->ops_lock);
new_bd->dev.class
= backlight_class; <――the class of your backlight driver will resides in.
new_bd->dev.parent
= parent; < —— designates the
parent of your backlight device.
new_bd->dev.release
= bl_device_release;
dev_set_name(&new_bd->dev,
name); <—— assign the
device name.
dev_set_drvdata(&new_bd->dev,
devdata); < —— stored for private driver use
rc =
device_register(&new_bd->dev); < ——
register the new created backlight device.
if (rc)
{
kfree(new_bd);
return
ERR_PTR(rc);
}
rc =
backlight_register_fb(new_bd);
if (rc)
{
device_unregister(&new_bd->dev);
return
ERR_PTR(rc);
}
new_bd->ops
= ops; <—— assign the
operating functions, the hardware-related part needs to be implemented by you.
#ifdef CONFIG_PMAC_BACKLIGHT
mutex_lock(&pmac_backlight_mutex);
if
(!pmac_backlight)
pmac_backlight
= new_bd;
mutex_unlock(&pmac_backlight_mutex);
#endif
return
new_bd;
}
The initialization of backlight_class should be prior to the registration of backlight device for any Lcd device, so, make use of postcore_initcall(backlight_class_init);
static int __init backlight_class_init(void)
{
backlight_class
= class_create(THIS_MODULE, "backlight"); <——
create backlight class
if
(IS_ERR(backlight_class)) {
printk(KERN_WARNING
"Unable to create backlight class; errno = %ld\n",
PTR_ERR(backlight_class));
return
PTR_ERR(backlight_class);
}
backlight_class->dev_attrs
= bl_device_attributes;<—— assign the properties of the classs
backlight_class->suspend
= backlight_suspend;
backlight_class->resume
= backlight_resume;
return
0;
}
Let’s see the properties then.
static struct device_attribute bl_device_attributes[]
= {
__ATTR(bl_power,
0644, backlight_show_power, backlight_store_power),
__ATTR(brightness,
0644, backlight_show_brightness,
backlight_store_brightness),
__ATTR(actual_brightness,
0444, backlight_show_actual_brightness,
NULL),
__ATTR(max_brightness,
0444, backlight_show_max_brightness, NULL),
__ATTR_NULL,
};
static ssize_t backlight_show_power(struct device *dev,
struct device_attribute *attr,char *buf)
{
struct backlight_device *bd = to_backlight_device(dev);
return sprintf(buf, "%d\n", bd->props.power); < —— return the current power state
}
static ssize_t backlight_store_power(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int rc;
struct backlight_device *bd = to_backlight_device(dev);
unsigned long power;
rc = strict_strtoul(buf, 0, &power);
if (rc)
return rc;
rc = -ENXIO;
mutex_lock(&bd->ops_lock);
if (bd->ops) {
pr_debug("backlight: set power to %lu\n", power);
if (bd->props.power != power) {
bd->props.power = power; <—— change the power state to the assigned state
backlight_update_status(bd); < —— update to the assigned power state
}
rc = count;
}
mutex_unlock(&bd->ops_lock);
return rc;
}
static ssize_t backlight_show_brightness(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct backlight_device *bd = to_backlight_device(dev);
return sprintf(buf, "%d\n", bd->props.brightness); <—— return the current brightness
}
static ssize_t backlight_store_brightness(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int rc;
struct backlight_device *bd = to_backlight_device(dev);
unsigned long brightness;
rc = strict_strtoul(buf, 0, &brightness);
if (rc)
return rc;
rc = -ENXIO;
mutex_lock(&bd->ops_lock);
if (bd->ops) {
if (brightness > bd->props.max_brightness)
rc = -EINVAL;
else {
pr_debug("backlight: set brightness to %lu\n",
brightness);
bd->props.brightness = brightness;
<—— change the brightness to the assigned state
backlight_update_status(bd); <—— update to the assigned brightness value
rc = count;
}
}
mutex_unlock(&bd->ops_lock);
return rc;
}
static ssize_t backlight_show_max_brightness(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct backlight_device *bd = to_backlight_device(dev);
return sprintf(buf, "%d\n", bd->props.max_brightness);
<—— return the maximum brightness
}
static ssize_t backlight_show_actual_brightness(struct device *dev,
struct device_attribute *attr, char *buf)
{
int rc = -ENXIO;
struct backlight_device *bd = to_backlight_device(dev);
mutex_lock(&bd->ops_lock);
if (bd->ops && bd->ops->get_brightness)
rc = sprintf(buf, "%d\n", bd->ops->get_brightness(bd));
<—— return the current brightness
mutex_unlock(&bd->ops_lock);
return rc;
}
Drivers/vedio/backlight/omap_bl.c is a good example for your reference to implement your own backlight driver.
|