Creation of Cybook 2416 (actually Gen4) repository
This commit is contained in:
65
drivers/video/backlight/Kconfig
Normal file
65
drivers/video/backlight/Kconfig
Normal file
@@ -0,0 +1,65 @@
|
||||
#
|
||||
# Backlight & LCD drivers configuration
|
||||
#
|
||||
|
||||
menuconfig BACKLIGHT_LCD_SUPPORT
|
||||
bool "Backlight & LCD device support"
|
||||
help
|
||||
Enable this to be able to choose the drivers for controlling the
|
||||
backlight and the LCD panel on some platforms, for example on PDAs.
|
||||
|
||||
config BACKLIGHT_CLASS_DEVICE
|
||||
tristate "Lowlevel Backlight controls"
|
||||
depends on BACKLIGHT_LCD_SUPPORT
|
||||
default m
|
||||
help
|
||||
This framework adds support for low-level control of the LCD
|
||||
backlight. This includes support for brightness and power.
|
||||
|
||||
To have support for your specific LCD panel you will have to
|
||||
select the proper drivers which depend on this option.
|
||||
|
||||
config LCD_CLASS_DEVICE
|
||||
tristate "Lowlevel LCD controls"
|
||||
depends on BACKLIGHT_LCD_SUPPORT
|
||||
default m
|
||||
help
|
||||
This framework adds support for low-level control of LCD.
|
||||
Some framebuffer devices connect to platform-specific LCD modules
|
||||
in order to have a platform-specific way to control the flat panel
|
||||
(contrast and applying power to the LCD (not to the backlight!)).
|
||||
|
||||
To have support for your specific LCD panel you will have to
|
||||
select the proper drivers which depend on this option.
|
||||
|
||||
config BACKLIGHT_CORGI
|
||||
tristate "Sharp Corgi Backlight Driver (SL Series)"
|
||||
depends on BACKLIGHT_CLASS_DEVICE && PXA_SHARPSL
|
||||
default y
|
||||
help
|
||||
If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
|
||||
backlight driver.
|
||||
|
||||
config BACKLIGHT_LOCOMO
|
||||
tristate "Sharp LOCOMO LCD/Backlight Driver"
|
||||
depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO
|
||||
default y
|
||||
help
|
||||
If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to
|
||||
enable the LCD/backlight driver.
|
||||
|
||||
config BACKLIGHT_HP680
|
||||
tristate "HP Jornada 680 Backlight Driver"
|
||||
depends on BACKLIGHT_CLASS_DEVICE && SH_HP6XX
|
||||
default y
|
||||
help
|
||||
If you have a HP Jornada 680, say y to enable the
|
||||
backlight driver.
|
||||
|
||||
config BACKLIGHT_PROGEAR
|
||||
tristate "Frontpath ProGear Backlight Driver"
|
||||
depends on BACKLIGHT_CLASS_DEVICE && PCI && X86
|
||||
default n
|
||||
help
|
||||
If you have a Frontpath ProGear say Y to enable the
|
||||
backlight driver.
|
||||
8
drivers/video/backlight/Makefile
Normal file
8
drivers/video/backlight/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
# Backlight & LCD drivers
|
||||
|
||||
obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
|
||||
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
|
||||
obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
|
||||
obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
|
||||
315
drivers/video/backlight/backlight.c
Normal file
315
drivers/video/backlight/backlight.c
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Backlight Lowlevel Control Abstraction
|
||||
*
|
||||
* Copyright (C) 2003,2004 Hewlett-Packard Company
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
#include <asm/backlight.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
|
||||
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
|
||||
/* This callback gets called when something important happens inside a
|
||||
* framebuffer driver. We're looking if that important event is blanking,
|
||||
* and if it is, we're switching backlight power as well ...
|
||||
*/
|
||||
static int fb_notifier_callback(struct notifier_block *self,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
struct backlight_device *bd;
|
||||
struct fb_event *evdata = data;
|
||||
|
||||
/* If we aren't interested in this event, skip it immediately ... */
|
||||
if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK)
|
||||
return 0;
|
||||
|
||||
bd = container_of(self, struct backlight_device, fb_notif);
|
||||
mutex_lock(&bd->ops_lock);
|
||||
if (bd->ops)
|
||||
if (!bd->ops->check_fb ||
|
||||
bd->ops->check_fb(evdata->info)) {
|
||||
bd->props.fb_blank = *(int *)evdata->data;
|
||||
backlight_update_status(bd);
|
||||
}
|
||||
mutex_unlock(&bd->ops_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int backlight_register_fb(struct backlight_device *bd)
|
||||
{
|
||||
memset(&bd->fb_notif, 0, sizeof(bd->fb_notif));
|
||||
bd->fb_notif.notifier_call = fb_notifier_callback;
|
||||
|
||||
return fb_register_client(&bd->fb_notif);
|
||||
}
|
||||
|
||||
static void backlight_unregister_fb(struct backlight_device *bd)
|
||||
{
|
||||
fb_unregister_client(&bd->fb_notif);
|
||||
}
|
||||
#else
|
||||
static inline int backlight_register_fb(struct backlight_device *bd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void backlight_unregister_fb(struct backlight_device *bd)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_FB */
|
||||
|
||||
static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(cdev);
|
||||
|
||||
return sprintf(buf, "%d\n", bd->props.power);
|
||||
}
|
||||
|
||||
static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count)
|
||||
{
|
||||
int rc = -ENXIO;
|
||||
char *endp;
|
||||
struct backlight_device *bd = to_backlight_device(cdev);
|
||||
int power = simple_strtoul(buf, &endp, 0);
|
||||
size_t size = endp - buf;
|
||||
|
||||
if (*endp && isspace(*endp))
|
||||
size++;
|
||||
if (size != count)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&bd->ops_lock);
|
||||
if (bd->ops) {
|
||||
pr_debug("backlight: set power to %d\n", power);
|
||||
bd->props.power = power;
|
||||
backlight_update_status(bd);
|
||||
rc = count;
|
||||
}
|
||||
mutex_unlock(&bd->ops_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(cdev);
|
||||
|
||||
return sprintf(buf, "%d\n", bd->props.brightness);
|
||||
}
|
||||
|
||||
static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count)
|
||||
{
|
||||
int rc = -ENXIO;
|
||||
char *endp;
|
||||
struct backlight_device *bd = to_backlight_device(cdev);
|
||||
int brightness = simple_strtoul(buf, &endp, 0);
|
||||
size_t size = endp - buf;
|
||||
|
||||
if (*endp && isspace(*endp))
|
||||
size++;
|
||||
if (size != count)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&bd->ops_lock);
|
||||
if (bd->ops) {
|
||||
if (brightness > bd->props.max_brightness)
|
||||
rc = -EINVAL;
|
||||
else {
|
||||
pr_debug("backlight: set brightness to %d\n",
|
||||
brightness);
|
||||
bd->props.brightness = brightness;
|
||||
backlight_update_status(bd);
|
||||
rc = count;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&bd->ops_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(cdev);
|
||||
|
||||
return sprintf(buf, "%d\n", bd->props.max_brightness);
|
||||
}
|
||||
|
||||
static ssize_t backlight_show_actual_brightness(struct class_device *cdev,
|
||||
char *buf)
|
||||
{
|
||||
int rc = -ENXIO;
|
||||
struct backlight_device *bd = to_backlight_device(cdev);
|
||||
|
||||
mutex_lock(&bd->ops_lock);
|
||||
if (bd->ops && bd->ops->get_brightness)
|
||||
rc = sprintf(buf, "%d\n", bd->ops->get_brightness(bd));
|
||||
mutex_unlock(&bd->ops_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void backlight_class_release(struct class_device *dev)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
kfree(bd);
|
||||
}
|
||||
|
||||
static struct class backlight_class = {
|
||||
.name = "backlight",
|
||||
.release = backlight_class_release,
|
||||
};
|
||||
|
||||
#define DECLARE_ATTR(_name,_mode,_show,_store) \
|
||||
{ \
|
||||
.attr = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
|
||||
.show = _show, \
|
||||
.store = _store, \
|
||||
}
|
||||
|
||||
static const struct class_device_attribute bl_class_device_attributes[] = {
|
||||
DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power),
|
||||
DECLARE_ATTR(brightness, 0644, backlight_show_brightness,
|
||||
backlight_store_brightness),
|
||||
DECLARE_ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
|
||||
NULL),
|
||||
DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
|
||||
};
|
||||
|
||||
/**
|
||||
* 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).
|
||||
* @devdata: an optional pointer to be stored in the class_device. The
|
||||
* methods may retrieve it by using class_get_devdata(&bd->class_dev).
|
||||
* @ops: the backlight operations structure.
|
||||
*
|
||||
* Creates and registers new backlight class_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 *dev,
|
||||
void *devdata,
|
||||
struct backlight_ops *ops)
|
||||
{
|
||||
int i, rc;
|
||||
struct backlight_device *new_bd;
|
||||
|
||||
pr_debug("backlight_device_alloc: name=%s\n", name);
|
||||
|
||||
new_bd = kzalloc(sizeof(struct backlight_device), GFP_KERNEL);
|
||||
if (!new_bd)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mutex_init(&new_bd->update_lock);
|
||||
mutex_init(&new_bd->ops_lock);
|
||||
new_bd->ops = ops;
|
||||
new_bd->class_dev.class = &backlight_class;
|
||||
new_bd->class_dev.dev = dev;
|
||||
strlcpy(new_bd->class_dev.class_id, name, KOBJ_NAME_LEN);
|
||||
class_set_devdata(&new_bd->class_dev, devdata);
|
||||
|
||||
rc = class_device_register(&new_bd->class_dev);
|
||||
if (rc) {
|
||||
kfree(new_bd);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
rc = backlight_register_fb(new_bd);
|
||||
if (rc) {
|
||||
class_device_unregister(&new_bd->class_dev);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++) {
|
||||
rc = class_device_create_file(&new_bd->class_dev,
|
||||
&bl_class_device_attributes[i]);
|
||||
if (rc) {
|
||||
while (--i >= 0)
|
||||
class_device_remove_file(&new_bd->class_dev,
|
||||
&bl_class_device_attributes[i]);
|
||||
class_device_unregister(&new_bd->class_dev);
|
||||
/* No need to kfree(new_bd) since release() method was called */
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
EXPORT_SYMBOL(backlight_device_register);
|
||||
|
||||
/**
|
||||
* backlight_device_unregister - unregisters a backlight device object.
|
||||
* @bd: the backlight device object to be unregistered and freed.
|
||||
*
|
||||
* Unregisters a previously registered via backlight_device_register object.
|
||||
*/
|
||||
void backlight_device_unregister(struct backlight_device *bd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!bd)
|
||||
return;
|
||||
|
||||
pr_debug("backlight_device_unregister: name=%s\n", bd->class_dev.class_id);
|
||||
|
||||
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||
mutex_lock(&pmac_backlight_mutex);
|
||||
if (pmac_backlight == bd)
|
||||
pmac_backlight = NULL;
|
||||
mutex_unlock(&pmac_backlight_mutex);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++)
|
||||
class_device_remove_file(&bd->class_dev,
|
||||
&bl_class_device_attributes[i]);
|
||||
|
||||
mutex_lock(&bd->ops_lock);
|
||||
bd->ops = NULL;
|
||||
mutex_unlock(&bd->ops_lock);
|
||||
|
||||
backlight_unregister_fb(bd);
|
||||
|
||||
class_device_unregister(&bd->class_dev);
|
||||
}
|
||||
EXPORT_SYMBOL(backlight_device_unregister);
|
||||
|
||||
static void __exit backlight_class_exit(void)
|
||||
{
|
||||
class_unregister(&backlight_class);
|
||||
}
|
||||
|
||||
static int __init backlight_class_init(void)
|
||||
{
|
||||
return class_register(&backlight_class);
|
||||
}
|
||||
|
||||
/*
|
||||
* if this is compiled into the kernel, we need to ensure that the
|
||||
* class is registered before users of the class try to register lcd's
|
||||
*/
|
||||
postcore_initcall(backlight_class_init);
|
||||
module_exit(backlight_class_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jamey Hicks <jamey.hicks@hp.com>, Andrew Zabolotny <zap@homelink.ru>");
|
||||
MODULE_DESCRIPTION("Backlight Lowlevel Control Abstraction");
|
||||
171
drivers/video/backlight/corgi_bl.c
Normal file
171
drivers/video/backlight/corgi_bl.c
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Backlight Driver for Sharp Zaurus Handhelds (various models)
|
||||
*
|
||||
* Copyright (c) 2004-2006 Richard Purdie
|
||||
*
|
||||
* Based on Sharp's 2.4 Backlight Driver
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <asm/arch/sharpsl.h>
|
||||
#include <asm/hardware/sharpsl_pm.h>
|
||||
|
||||
static int corgibl_intensity;
|
||||
static struct backlight_properties corgibl_data;
|
||||
static struct backlight_device *corgi_backlight_device;
|
||||
static struct corgibl_machinfo *bl_machinfo;
|
||||
|
||||
static unsigned long corgibl_flags;
|
||||
#define CORGIBL_SUSPENDED 0x01
|
||||
#define CORGIBL_BATTLOW 0x02
|
||||
|
||||
static int corgibl_send_intensity(struct backlight_device *bd)
|
||||
{
|
||||
void (*corgi_kick_batt)(void);
|
||||
int intensity = bd->props.brightness;
|
||||
|
||||
if (bd->props.power != FB_BLANK_UNBLANK)
|
||||
intensity = 0;
|
||||
if (bd->props.fb_blank != FB_BLANK_UNBLANK)
|
||||
intensity = 0;
|
||||
if (corgibl_flags & CORGIBL_SUSPENDED)
|
||||
intensity = 0;
|
||||
if (corgibl_flags & CORGIBL_BATTLOW)
|
||||
intensity &= bl_machinfo->limit_mask;
|
||||
|
||||
bl_machinfo->set_bl_intensity(intensity);
|
||||
|
||||
corgibl_intensity = intensity;
|
||||
|
||||
corgi_kick_batt = symbol_get(sharpsl_battery_kick);
|
||||
if (corgi_kick_batt) {
|
||||
corgi_kick_batt();
|
||||
symbol_put(sharpsl_battery_kick);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int corgibl_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct backlight_device *bd = platform_get_drvdata(pdev);
|
||||
|
||||
corgibl_flags |= CORGIBL_SUSPENDED;
|
||||
backlight_update_status(bd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int corgibl_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct backlight_device *bd = platform_get_drvdata(pdev);
|
||||
|
||||
corgibl_flags &= ~CORGIBL_SUSPENDED;
|
||||
backlight_update_status(bd);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define corgibl_suspend NULL
|
||||
#define corgibl_resume NULL
|
||||
#endif
|
||||
|
||||
static int corgibl_get_intensity(struct backlight_device *bd)
|
||||
{
|
||||
return corgibl_intensity;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when the battery is low to limit the backlight intensity.
|
||||
* If limit==0 clear any limit, otherwise limit the intensity
|
||||
*/
|
||||
void corgibl_limit_intensity(int limit)
|
||||
{
|
||||
if (limit)
|
||||
corgibl_flags |= CORGIBL_BATTLOW;
|
||||
else
|
||||
corgibl_flags &= ~CORGIBL_BATTLOW;
|
||||
backlight_update_status(corgi_backlight_device);
|
||||
}
|
||||
EXPORT_SYMBOL(corgibl_limit_intensity);
|
||||
|
||||
|
||||
static struct backlight_ops corgibl_ops = {
|
||||
.get_brightness = corgibl_get_intensity,
|
||||
.update_status = corgibl_send_intensity,
|
||||
};
|
||||
|
||||
static int corgibl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct corgibl_machinfo *machinfo = pdev->dev.platform_data;
|
||||
|
||||
bl_machinfo = machinfo;
|
||||
if (!machinfo->limit_mask)
|
||||
machinfo->limit_mask = -1;
|
||||
|
||||
corgi_backlight_device = backlight_device_register ("corgi-bl",
|
||||
&pdev->dev, NULL, &corgibl_ops);
|
||||
if (IS_ERR (corgi_backlight_device))
|
||||
return PTR_ERR (corgi_backlight_device);
|
||||
|
||||
platform_set_drvdata(pdev, corgi_backlight_device);
|
||||
|
||||
corgi_backlight_device->props.max_brightness = machinfo->max_intensity;
|
||||
corgi_backlight_device->props.power = FB_BLANK_UNBLANK;
|
||||
corgi_backlight_device->props.brightness = machinfo->default_intensity;
|
||||
backlight_update_status(corgi_backlight_device);
|
||||
|
||||
printk("Corgi Backlight Driver Initialized.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int corgibl_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct backlight_device *bd = platform_get_drvdata(pdev);
|
||||
|
||||
corgibl_data.power = 0;
|
||||
corgibl_data.brightness = 0;
|
||||
backlight_update_status(bd);
|
||||
|
||||
backlight_device_unregister(bd);
|
||||
|
||||
printk("Corgi Backlight Driver Unloaded\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver corgibl_driver = {
|
||||
.probe = corgibl_probe,
|
||||
.remove = corgibl_remove,
|
||||
.suspend = corgibl_suspend,
|
||||
.resume = corgibl_resume,
|
||||
.driver = {
|
||||
.name = "corgi-bl",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init corgibl_init(void)
|
||||
{
|
||||
return platform_driver_register(&corgibl_driver);
|
||||
}
|
||||
|
||||
static void __exit corgibl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&corgibl_driver);
|
||||
}
|
||||
|
||||
module_init(corgibl_init);
|
||||
module_exit(corgibl_exit);
|
||||
|
||||
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
|
||||
MODULE_DESCRIPTION("Corgi Backlight Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
180
drivers/video/backlight/hp680_bl.c
Normal file
180
drivers/video/backlight/hp680_bl.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Backlight Driver for HP Jornada 680
|
||||
*
|
||||
* Copyright (c) 2005 Andriy Skulysh
|
||||
*
|
||||
* Based on Sharp's Corgi Backlight Driver
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/backlight.h>
|
||||
|
||||
#include <asm/cpu/dac.h>
|
||||
#include <asm/hp6xx.h>
|
||||
#include <asm/hd64461.h>
|
||||
|
||||
#define HP680_MAX_INTENSITY 255
|
||||
#define HP680_DEFAULT_INTENSITY 10
|
||||
|
||||
static int hp680bl_suspended;
|
||||
static int current_intensity = 0;
|
||||
static DEFINE_SPINLOCK(bl_lock);
|
||||
|
||||
static void hp680bl_send_intensity(struct backlight_device *bd)
|
||||
{
|
||||
unsigned long flags;
|
||||
u16 v;
|
||||
int intensity = bd->props.brightness;
|
||||
|
||||
if (bd->props.power != FB_BLANK_UNBLANK)
|
||||
intensity = 0;
|
||||
if (bd->props.fb_blank != FB_BLANK_UNBLANK)
|
||||
intensity = 0;
|
||||
if (hp680bl_suspended)
|
||||
intensity = 0;
|
||||
|
||||
spin_lock_irqsave(&bl_lock, flags);
|
||||
if (intensity && current_intensity == 0) {
|
||||
sh_dac_enable(DAC_LCD_BRIGHTNESS);
|
||||
v = inw(HD64461_GPBDR);
|
||||
v &= ~HD64461_GPBDR_LCDOFF;
|
||||
outw(v, HD64461_GPBDR);
|
||||
sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
|
||||
} else if (intensity == 0 && current_intensity != 0) {
|
||||
sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
|
||||
sh_dac_disable(DAC_LCD_BRIGHTNESS);
|
||||
v = inw(HD64461_GPBDR);
|
||||
v |= HD64461_GPBDR_LCDOFF;
|
||||
outw(v, HD64461_GPBDR);
|
||||
} else if (intensity) {
|
||||
sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
|
||||
}
|
||||
spin_unlock_irqrestore(&bl_lock, flags);
|
||||
|
||||
current_intensity = intensity;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int hp680bl_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct backlight_device *bd = platform_get_drvdata(pdev);
|
||||
|
||||
hp680bl_suspended = 1;
|
||||
hp680bl_send_intensity(bd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hp680bl_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct backlight_device *bd = platform_get_drvdata(pdev);
|
||||
|
||||
hp680bl_suspended = 0;
|
||||
hp680bl_send_intensity(bd);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define hp680bl_suspend NULL
|
||||
#define hp680bl_resume NULL
|
||||
#endif
|
||||
|
||||
static int hp680bl_set_intensity(struct backlight_device *bd)
|
||||
{
|
||||
hp680bl_send_intensity(bd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hp680bl_get_intensity(struct backlight_device *bd)
|
||||
{
|
||||
return current_intensity;
|
||||
}
|
||||
|
||||
static struct backlight_ops hp680bl_ops = {
|
||||
.get_brightness = hp680bl_get_intensity,
|
||||
.update_status = hp680bl_set_intensity,
|
||||
};
|
||||
|
||||
static int __init hp680bl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct backlight_device *bd;
|
||||
|
||||
bd = backlight_device_register ("hp680-bl", &pdev->dev, NULL,
|
||||
&hp680bl_ops);
|
||||
if (IS_ERR(bd))
|
||||
return PTR_ERR(bd);
|
||||
|
||||
platform_set_drvdata(pdev, bd);
|
||||
|
||||
bd->props.max_brightness = HP680_MAX_INTENSITY;
|
||||
bd->props.brightness = HP680_DEFAULT_INTENSITY;
|
||||
hp680bl_send_intensity(bd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hp680bl_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct backlight_device *bd = platform_get_drvdata(pdev);
|
||||
|
||||
hp680bl_data.brightness = 0;
|
||||
hp680bl_data.power = 0;
|
||||
hp680bl_send_intensity(bd);
|
||||
|
||||
backlight_device_unregister(bd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver hp680bl_driver = {
|
||||
.probe = hp680bl_probe,
|
||||
.remove = hp680bl_remove,
|
||||
.suspend = hp680bl_suspend,
|
||||
.resume = hp680bl_resume,
|
||||
.driver = {
|
||||
.name = "hp680-bl",
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *hp680bl_device;
|
||||
|
||||
static int __init hp680bl_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&hp680bl_driver);
|
||||
if (!ret) {
|
||||
hp680bl_device = platform_device_alloc("hp680-bl", -1);
|
||||
if (!hp680bl_device)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = platform_device_add(hp680bl_device);
|
||||
|
||||
if (ret) {
|
||||
platform_device_put(hp680bl_device);
|
||||
platform_driver_unregister(&hp680bl_driver);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit hp680bl_exit(void)
|
||||
{
|
||||
platform_device_unregister(hp680bl_device);
|
||||
platform_driver_unregister(&hp680bl_driver);
|
||||
}
|
||||
|
||||
module_init(hp680bl_init);
|
||||
module_exit(hp680bl_exit);
|
||||
|
||||
MODULE_AUTHOR("Andriy Skulysh <askulysh@gmail.com>");
|
||||
MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
276
drivers/video/backlight/lcd.c
Normal file
276
drivers/video/backlight/lcd.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* LCD Lowlevel Control Abstraction
|
||||
*
|
||||
* Copyright (C) 2003,2004 Hewlett-Packard Company
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/lcd.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
|
||||
defined(CONFIG_LCD_CLASS_DEVICE_MODULE))
|
||||
/* This callback gets called when something important happens inside a
|
||||
* framebuffer driver. We're looking if that important event is blanking,
|
||||
* and if it is, we're switching lcd power as well ...
|
||||
*/
|
||||
static int fb_notifier_callback(struct notifier_block *self,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
struct lcd_device *ld;
|
||||
struct fb_event *evdata = data;
|
||||
|
||||
/* If we aren't interested in this event, skip it immediately ... */
|
||||
if (event != FB_EVENT_BLANK)
|
||||
return 0;
|
||||
|
||||
ld = container_of(self, struct lcd_device, fb_notif);
|
||||
mutex_lock(&ld->ops_lock);
|
||||
if (ld->ops)
|
||||
if (!ld->ops->check_fb || ld->ops->check_fb(evdata->info))
|
||||
ld->ops->set_power(ld, *(int *)evdata->data);
|
||||
mutex_unlock(&ld->ops_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_register_fb(struct lcd_device *ld)
|
||||
{
|
||||
memset(&ld->fb_notif, 0, sizeof(&ld->fb_notif));
|
||||
ld->fb_notif.notifier_call = fb_notifier_callback;
|
||||
return fb_register_client(&ld->fb_notif);
|
||||
}
|
||||
|
||||
static void lcd_unregister_fb(struct lcd_device *ld)
|
||||
{
|
||||
fb_unregister_client(&ld->fb_notif);
|
||||
}
|
||||
#else
|
||||
static int lcd_register_fb(struct lcd_device *ld)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void lcd_unregister_fb(struct lcd_device *ld)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_FB */
|
||||
|
||||
static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
|
||||
{
|
||||
int rc;
|
||||
struct lcd_device *ld = to_lcd_device(cdev);
|
||||
|
||||
mutex_lock(&ld->ops_lock);
|
||||
if (ld->ops && ld->ops->get_power)
|
||||
rc = sprintf(buf, "%d\n", ld->ops->get_power(ld));
|
||||
else
|
||||
rc = -ENXIO;
|
||||
mutex_unlock(&ld->ops_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_t count)
|
||||
{
|
||||
int rc = -ENXIO;
|
||||
char *endp;
|
||||
struct lcd_device *ld = to_lcd_device(cdev);
|
||||
int power = simple_strtoul(buf, &endp, 0);
|
||||
size_t size = endp - buf;
|
||||
|
||||
if (*endp && isspace(*endp))
|
||||
size++;
|
||||
if (size != count)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ld->ops_lock);
|
||||
if (ld->ops && ld->ops->set_power) {
|
||||
pr_debug("lcd: set power to %d\n", power);
|
||||
ld->ops->set_power(ld, power);
|
||||
rc = count;
|
||||
}
|
||||
mutex_unlock(&ld->ops_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t lcd_show_contrast(struct class_device *cdev, char *buf)
|
||||
{
|
||||
int rc = -ENXIO;
|
||||
struct lcd_device *ld = to_lcd_device(cdev);
|
||||
|
||||
mutex_lock(&ld->ops_lock);
|
||||
if (ld->ops && ld->ops->get_contrast)
|
||||
rc = sprintf(buf, "%d\n", ld->ops->get_contrast(ld));
|
||||
mutex_unlock(&ld->ops_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, size_t count)
|
||||
{
|
||||
int rc = -ENXIO;
|
||||
char *endp;
|
||||
struct lcd_device *ld = to_lcd_device(cdev);
|
||||
int contrast = simple_strtoul(buf, &endp, 0);
|
||||
size_t size = endp - buf;
|
||||
|
||||
if (*endp && isspace(*endp))
|
||||
size++;
|
||||
if (size != count)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ld->ops_lock);
|
||||
if (ld->ops && ld->ops->set_contrast) {
|
||||
pr_debug("lcd: set contrast to %d\n", contrast);
|
||||
ld->ops->set_contrast(ld, contrast);
|
||||
rc = count;
|
||||
}
|
||||
mutex_unlock(&ld->ops_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t lcd_show_max_contrast(struct class_device *cdev, char *buf)
|
||||
{
|
||||
struct lcd_device *ld = to_lcd_device(cdev);
|
||||
|
||||
return sprintf(buf, "%d\n", ld->props.max_contrast);
|
||||
}
|
||||
|
||||
static void lcd_class_release(struct class_device *dev)
|
||||
{
|
||||
struct lcd_device *ld = to_lcd_device(dev);
|
||||
kfree(ld);
|
||||
}
|
||||
|
||||
static struct class lcd_class = {
|
||||
.name = "lcd",
|
||||
.release = lcd_class_release,
|
||||
};
|
||||
|
||||
#define DECLARE_ATTR(_name,_mode,_show,_store) \
|
||||
{ \
|
||||
.attr = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
|
||||
.show = _show, \
|
||||
.store = _store, \
|
||||
}
|
||||
|
||||
static const struct class_device_attribute lcd_class_device_attributes[] = {
|
||||
DECLARE_ATTR(power, 0644, lcd_show_power, lcd_store_power),
|
||||
DECLARE_ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast),
|
||||
DECLARE_ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL),
|
||||
};
|
||||
|
||||
/**
|
||||
* lcd_device_register - register a new object of lcd_device class.
|
||||
* @name: the name of the new object(must be the same as the name of the
|
||||
* respective framebuffer device).
|
||||
* @devdata: an optional pointer to be stored in the class_device. The
|
||||
* methods may retrieve it by using class_get_devdata(ld->class_dev).
|
||||
* @ops: the lcd operations structure.
|
||||
*
|
||||
* Creates and registers a new lcd class_device. Returns either an ERR_PTR()
|
||||
* or a pointer to the newly allocated device.
|
||||
*/
|
||||
struct lcd_device *lcd_device_register(const char *name, void *devdata,
|
||||
struct lcd_ops *ops)
|
||||
{
|
||||
int i, rc;
|
||||
struct lcd_device *new_ld;
|
||||
|
||||
pr_debug("lcd_device_register: name=%s\n", name);
|
||||
|
||||
new_ld = kzalloc(sizeof(struct lcd_device), GFP_KERNEL);
|
||||
if (!new_ld)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mutex_init(&new_ld->ops_lock);
|
||||
mutex_init(&new_ld->update_lock);
|
||||
new_ld->ops = ops;
|
||||
new_ld->class_dev.class = &lcd_class;
|
||||
strlcpy(new_ld->class_dev.class_id, name, KOBJ_NAME_LEN);
|
||||
class_set_devdata(&new_ld->class_dev, devdata);
|
||||
|
||||
rc = class_device_register(&new_ld->class_dev);
|
||||
if (rc) {
|
||||
kfree(new_ld);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
rc = lcd_register_fb(new_ld);
|
||||
if (rc) {
|
||||
class_device_unregister(&new_ld->class_dev);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lcd_class_device_attributes); i++) {
|
||||
rc = class_device_create_file(&new_ld->class_dev,
|
||||
&lcd_class_device_attributes[i]);
|
||||
if (rc) {
|
||||
while (--i >= 0)
|
||||
class_device_remove_file(&new_ld->class_dev,
|
||||
&lcd_class_device_attributes[i]);
|
||||
class_device_unregister(&new_ld->class_dev);
|
||||
/* No need to kfree(new_ld) since release() method was called */
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
}
|
||||
|
||||
return new_ld;
|
||||
}
|
||||
EXPORT_SYMBOL(lcd_device_register);
|
||||
|
||||
/**
|
||||
* lcd_device_unregister - unregisters a object of lcd_device class.
|
||||
* @ld: the lcd device object to be unregistered and freed.
|
||||
*
|
||||
* Unregisters a previously registered via lcd_device_register object.
|
||||
*/
|
||||
void lcd_device_unregister(struct lcd_device *ld)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ld)
|
||||
return;
|
||||
|
||||
pr_debug("lcd_device_unregister: name=%s\n", ld->class_dev.class_id);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lcd_class_device_attributes); i++)
|
||||
class_device_remove_file(&ld->class_dev,
|
||||
&lcd_class_device_attributes[i]);
|
||||
|
||||
mutex_lock(&ld->ops_lock);
|
||||
ld->ops = NULL;
|
||||
mutex_unlock(&ld->ops_lock);
|
||||
lcd_unregister_fb(ld);
|
||||
class_device_unregister(&ld->class_dev);
|
||||
}
|
||||
EXPORT_SYMBOL(lcd_device_unregister);
|
||||
|
||||
static void __exit lcd_class_exit(void)
|
||||
{
|
||||
class_unregister(&lcd_class);
|
||||
}
|
||||
|
||||
static int __init lcd_class_init(void)
|
||||
{
|
||||
return class_register(&lcd_class);
|
||||
}
|
||||
|
||||
/*
|
||||
* if this is compiled into the kernel, we need to ensure that the
|
||||
* class is registered before users of the class try to register lcd's
|
||||
*/
|
||||
postcore_initcall(lcd_class_init);
|
||||
module_exit(lcd_class_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jamey Hicks <jamey.hicks@hp.com>, Andrew Zabolotny <zap@homelink.ru>");
|
||||
MODULE_DESCRIPTION("LCD Lowlevel Control Abstraction");
|
||||
247
drivers/video/backlight/locomolcd.c
Normal file
247
drivers/video/backlight/locomolcd.c
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Backlight control code for Sharp Zaurus SL-5500
|
||||
*
|
||||
* Copyright 2005 John Lenz <lenz@cs.wisc.edu>
|
||||
* Maintainer: Pavel Machek <pavel@suse.cz> (unless John wants to :-)
|
||||
* GPL v2
|
||||
*
|
||||
* This driver assumes single CPU. That's okay, because collie is
|
||||
* slightly old hardware, and noone is going to retrofit second CPU to
|
||||
* old PDA.
|
||||
*/
|
||||
|
||||
/* LCD power functions */
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/backlight.h>
|
||||
|
||||
#include <asm/hardware/locomo.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach/sharpsl_param.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include "../../../arch/arm/mach-sa1100/generic.h"
|
||||
|
||||
static struct backlight_device *locomolcd_bl_device;
|
||||
static struct locomo_dev *locomolcd_dev;
|
||||
static unsigned long locomolcd_flags;
|
||||
#define LOCOMOLCD_SUSPENDED 0x01
|
||||
|
||||
static void locomolcd_on(int comadj)
|
||||
{
|
||||
locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0);
|
||||
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 1);
|
||||
mdelay(2);
|
||||
|
||||
locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0);
|
||||
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 1);
|
||||
mdelay(2);
|
||||
|
||||
locomo_m62332_senddata(locomolcd_dev, comadj, 0);
|
||||
mdelay(5);
|
||||
|
||||
locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 0);
|
||||
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 1);
|
||||
mdelay(10);
|
||||
|
||||
/* TFTCRST | CPSOUT=0 | CPSEN */
|
||||
locomo_writel(0x01, locomolcd_dev->mapbase + LOCOMO_TC);
|
||||
|
||||
/* Set CPSD */
|
||||
locomo_writel(6, locomolcd_dev->mapbase + LOCOMO_CPSD);
|
||||
|
||||
/* TFTCRST | CPSOUT=0 | CPSEN */
|
||||
locomo_writel((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC);
|
||||
mdelay(10);
|
||||
|
||||
locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0);
|
||||
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 1);
|
||||
}
|
||||
|
||||
static void locomolcd_off(int comadj)
|
||||
{
|
||||
/* TFTCRST=1 | CPSOUT=1 | CPSEN = 0 */
|
||||
locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC);
|
||||
mdelay(1);
|
||||
|
||||
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0);
|
||||
mdelay(110);
|
||||
|
||||
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 0);
|
||||
mdelay(700);
|
||||
|
||||
/* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */
|
||||
locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC);
|
||||
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0);
|
||||
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0);
|
||||
}
|
||||
|
||||
void locomolcd_power(int on)
|
||||
{
|
||||
int comadj = sharpsl_param.comadj;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (!locomolcd_dev) {
|
||||
local_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* read comadj */
|
||||
if (comadj == -1 && machine_is_collie())
|
||||
comadj = 128;
|
||||
if (comadj == -1 && machine_is_poodle())
|
||||
comadj = 118;
|
||||
|
||||
if (on)
|
||||
locomolcd_on(comadj);
|
||||
else
|
||||
locomolcd_off(comadj);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(locomolcd_power);
|
||||
|
||||
|
||||
static int current_intensity;
|
||||
|
||||
static int locomolcd_set_intensity(struct backlight_device *bd)
|
||||
{
|
||||
int intensity = bd->props.brightness;
|
||||
|
||||
if (bd->props.power != FB_BLANK_UNBLANK)
|
||||
intensity = 0;
|
||||
if (bd->props.fb_blank != FB_BLANK_UNBLANK)
|
||||
intensity = 0;
|
||||
if (locomolcd_flags & LOCOMOLCD_SUSPENDED)
|
||||
intensity = 0;
|
||||
|
||||
switch (intensity) {
|
||||
/* AC and non-AC are handled differently, but produce same results in sharp code? */
|
||||
case 0: locomo_frontlight_set(locomolcd_dev, 0, 0, 161); break;
|
||||
case 1: locomo_frontlight_set(locomolcd_dev, 117, 0, 161); break;
|
||||
case 2: locomo_frontlight_set(locomolcd_dev, 163, 0, 148); break;
|
||||
case 3: locomo_frontlight_set(locomolcd_dev, 194, 0, 161); break;
|
||||
case 4: locomo_frontlight_set(locomolcd_dev, 194, 1, 161); break;
|
||||
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
current_intensity = intensity;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int locomolcd_get_intensity(struct backlight_device *bd)
|
||||
{
|
||||
return current_intensity;
|
||||
}
|
||||
|
||||
static struct backlight_ops locomobl_data = {
|
||||
.get_brightness = locomolcd_get_intensity,
|
||||
.update_status = locomolcd_set_intensity,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int locomolcd_suspend(struct locomo_dev *dev, pm_message_t state)
|
||||
{
|
||||
locomolcd_flags |= LOCOMOLCD_SUSPENDED;
|
||||
locomolcd_set_intensity(locomolcd_bl_device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int locomolcd_resume(struct locomo_dev *dev)
|
||||
{
|
||||
locomolcd_flags &= ~LOCOMOLCD_SUSPENDED;
|
||||
locomolcd_set_intensity(locomolcd_bl_device);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define locomolcd_suspend NULL
|
||||
#define locomolcd_resume NULL
|
||||
#endif
|
||||
|
||||
static int locomolcd_probe(struct locomo_dev *ldev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
locomolcd_dev = ldev;
|
||||
|
||||
locomo_gpio_set_dir(ldev->dev.parent, LOCOMO_GPIO_FL_VR, 0);
|
||||
|
||||
/* the poodle_lcd_power function is called for the first time
|
||||
* from fs_initcall, which is before locomo is activated.
|
||||
* We need to recall poodle_lcd_power here*/
|
||||
if (machine_is_poodle())
|
||||
locomolcd_power(1);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
locomolcd_bl_device = backlight_device_register("locomo-bl", &ldev->dev, NULL, &locomobl_data);
|
||||
|
||||
if (IS_ERR (locomolcd_bl_device))
|
||||
return PTR_ERR (locomolcd_bl_device);
|
||||
|
||||
/* Set up frontlight so that screen is readable */
|
||||
locomolcd_bl_device->props.max_brightness = 4,
|
||||
locomolcd_bl_device->props.brightness = 2;
|
||||
locomolcd_set_intensity(locomolcd_bl_device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int locomolcd_remove(struct locomo_dev *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
locomolcd_bl_device->props.brightness = 0;
|
||||
locomolcd_bl_device->props.power = 0;
|
||||
locomolcd_set_intensity(locomolcd_bl_device);
|
||||
|
||||
backlight_device_unregister(locomolcd_bl_device);
|
||||
local_irq_save(flags);
|
||||
locomolcd_dev = NULL;
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct locomo_driver poodle_lcd_driver = {
|
||||
.drv = {
|
||||
.name = "locomo-backlight",
|
||||
},
|
||||
.devid = LOCOMO_DEVID_BACKLIGHT,
|
||||
.probe = locomolcd_probe,
|
||||
.remove = locomolcd_remove,
|
||||
.suspend = locomolcd_suspend,
|
||||
.resume = locomolcd_resume,
|
||||
};
|
||||
|
||||
|
||||
static int __init locomolcd_init(void)
|
||||
{
|
||||
int ret = locomo_driver_register(&poodle_lcd_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_SA1100_COLLIE
|
||||
sa1100fb_lcd_power = locomolcd_power;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit locomolcd_exit(void)
|
||||
{
|
||||
locomo_driver_unregister(&poodle_lcd_driver);
|
||||
}
|
||||
|
||||
module_init(locomolcd_init);
|
||||
module_exit(locomolcd_exit);
|
||||
|
||||
MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>, Pavel Machek <pavel@suse.cz>");
|
||||
MODULE_DESCRIPTION("Collie LCD driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
153
drivers/video/backlight/progear_bl.c
Normal file
153
drivers/video/backlight/progear_bl.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Backlight Driver for Frontpath ProGear HX1050+
|
||||
*
|
||||
* Copyright (c) 2006 Marcin Juszkiewicz
|
||||
*
|
||||
* Based on Progear LCD driver by M Schacht
|
||||
* <mschacht at alumni dot washington dot edu>
|
||||
*
|
||||
* Based on Sharp's Corgi Backlight Driver
|
||||
* Based on Backlight Driver for HP Jornada 680
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#define PMU_LPCR 0xB0
|
||||
#define SB_MPS1 0x61
|
||||
#define HW_LEVEL_MAX 0x77
|
||||
#define HW_LEVEL_MIN 0x4f
|
||||
|
||||
static struct pci_dev *pmu_dev = NULL;
|
||||
static struct pci_dev *sb_dev = NULL;
|
||||
|
||||
static int progearbl_set_intensity(struct backlight_device *bd)
|
||||
{
|
||||
int intensity = bd->props.brightness;
|
||||
|
||||
if (bd->props.power != FB_BLANK_UNBLANK)
|
||||
intensity = 0;
|
||||
if (bd->props.fb_blank != FB_BLANK_UNBLANK)
|
||||
intensity = 0;
|
||||
|
||||
pci_write_config_byte(pmu_dev, PMU_LPCR, intensity + HW_LEVEL_MIN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int progearbl_get_intensity(struct backlight_device *bd)
|
||||
{
|
||||
u8 intensity;
|
||||
pci_read_config_byte(pmu_dev, PMU_LPCR, &intensity);
|
||||
|
||||
return intensity - HW_LEVEL_MIN;
|
||||
}
|
||||
|
||||
static struct backlight_ops progearbl_ops = {
|
||||
.get_brightness = progearbl_get_intensity,
|
||||
.update_status = progearbl_set_intensity,
|
||||
};
|
||||
|
||||
static int progearbl_probe(struct platform_device *pdev)
|
||||
{
|
||||
u8 temp;
|
||||
struct backlight_device *progear_backlight_device;
|
||||
|
||||
pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL);
|
||||
if (!pmu_dev) {
|
||||
printk("ALI M7101 PMU not found.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
|
||||
if (!sb_dev) {
|
||||
printk("ALI 1533 SB not found.\n");
|
||||
pci_dev_put(pmu_dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Set SB_MPS1 to enable brightness control. */
|
||||
pci_read_config_byte(sb_dev, SB_MPS1, &temp);
|
||||
pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
|
||||
|
||||
progear_backlight_device = backlight_device_register("progear-bl",
|
||||
&pdev->dev, NULL,
|
||||
&progearbl_ops);
|
||||
if (IS_ERR(progear_backlight_device))
|
||||
return PTR_ERR(progear_backlight_device);
|
||||
|
||||
platform_set_drvdata(pdev, progear_backlight_device);
|
||||
|
||||
progear_backlight_device->props.power = FB_BLANK_UNBLANK;
|
||||
progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
|
||||
progear_backlight_device->props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
|
||||
progearbl_set_intensity(progear_backlight_device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int progearbl_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct backlight_device *bd = platform_get_drvdata(pdev);
|
||||
backlight_device_unregister(bd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver progearbl_driver = {
|
||||
.probe = progearbl_probe,
|
||||
.remove = progearbl_remove,
|
||||
.driver = {
|
||||
.name = "progear-bl",
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *progearbl_device;
|
||||
|
||||
static int __init progearbl_init(void)
|
||||
{
|
||||
int ret = platform_driver_register(&progearbl_driver);
|
||||
|
||||
if (!ret) {
|
||||
progearbl_device = platform_device_alloc("progear-bl", -1);
|
||||
if (!progearbl_device)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = platform_device_add(progearbl_device);
|
||||
|
||||
if (ret) {
|
||||
platform_device_put(progearbl_device);
|
||||
platform_driver_unregister(&progearbl_driver);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit progearbl_exit(void)
|
||||
{
|
||||
pci_dev_put(pmu_dev);
|
||||
pci_dev_put(sb_dev);
|
||||
|
||||
platform_device_unregister(progearbl_device);
|
||||
platform_driver_unregister(&progearbl_driver);
|
||||
}
|
||||
|
||||
module_init(progearbl_init);
|
||||
module_exit(progearbl_exit);
|
||||
|
||||
MODULE_AUTHOR("Marcin Juszkiewicz <linux@hrw.one.pl>");
|
||||
MODULE_DESCRIPTION("ProGear Backlight Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
Reference in New Issue
Block a user