diff options
Diffstat (limited to 'drivers/video/backlight/kb3886_bl.c')
-rw-r--r-- | drivers/video/backlight/kb3886_bl.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c new file mode 100644 index 000000000..96312c3af --- /dev/null +++ b/drivers/video/backlight/kb3886_bl.c @@ -0,0 +1,197 @@ +/* + * Backlight Driver for the KB3886 Backlight + * + * Copyright (c) 2007-2008 Claudio Nieder + * + * Based on corgi_bl.c by Richard Purdie and kb3886 driver by Robert Woerle + * + * 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/delay.h> +#include <linux/dmi.h> + +#define KB3886_PARENT 0x64 +#define KB3886_IO 0x60 +#define KB3886_ADC_DAC_PWM 0xC4 +#define KB3886_PWM0_WRITE 0x81 +#define KB3886_PWM0_READ 0x41 + +static DEFINE_MUTEX(bl_mutex); + +static void kb3886_bl_set_intensity(int intensity) +{ + mutex_lock(&bl_mutex); + intensity = intensity&0xff; + outb(KB3886_ADC_DAC_PWM, KB3886_PARENT); + usleep_range(10000, 11000); + outb(KB3886_PWM0_WRITE, KB3886_IO); + usleep_range(10000, 11000); + outb(intensity, KB3886_IO); + mutex_unlock(&bl_mutex); +} + +struct kb3886bl_machinfo { + int max_intensity; + int default_intensity; + int limit_mask; + void (*set_bl_intensity)(int intensity); +}; + +static struct kb3886bl_machinfo kb3886_bl_machinfo = { + .max_intensity = 0xff, + .default_intensity = 0xa0, + .limit_mask = 0x7f, + .set_bl_intensity = kb3886_bl_set_intensity, +}; + +static struct platform_device kb3886bl_device = { + .name = "kb3886-bl", + .dev = { + .platform_data = &kb3886_bl_machinfo, + }, + .id = -1, +}; + +static struct platform_device *devices[] __initdata = { + &kb3886bl_device, +}; + +/* + * Back to driver + */ + +static int kb3886bl_intensity; +static struct backlight_device *kb3886_backlight_device; +static struct kb3886bl_machinfo *bl_machinfo; + +static unsigned long kb3886bl_flags; +#define KB3886BL_SUSPENDED 0x01 + +static const struct dmi_system_id kb3886bl_device_table[] __initconst = { + { + .ident = "Sahara Touch-iT", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SDV"), + DMI_MATCH(DMI_PRODUCT_NAME, "iTouch T201"), + }, + }, + { } +}; + +static int kb3886bl_send_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 (kb3886bl_flags & KB3886BL_SUSPENDED) + intensity = 0; + + bl_machinfo->set_bl_intensity(intensity); + + kb3886bl_intensity = intensity; + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int kb3886bl_suspend(struct device *dev) +{ + struct backlight_device *bd = dev_get_drvdata(dev); + + kb3886bl_flags |= KB3886BL_SUSPENDED; + backlight_update_status(bd); + return 0; +} + +static int kb3886bl_resume(struct device *dev) +{ + struct backlight_device *bd = dev_get_drvdata(dev); + + kb3886bl_flags &= ~KB3886BL_SUSPENDED; + backlight_update_status(bd); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(kb3886bl_pm_ops, kb3886bl_suspend, kb3886bl_resume); + +static int kb3886bl_get_intensity(struct backlight_device *bd) +{ + return kb3886bl_intensity; +} + +static const struct backlight_ops kb3886bl_ops = { + .get_brightness = kb3886bl_get_intensity, + .update_status = kb3886bl_send_intensity, +}; + +static int kb3886bl_probe(struct platform_device *pdev) +{ + struct backlight_properties props; + struct kb3886bl_machinfo *machinfo = dev_get_platdata(&pdev->dev); + + bl_machinfo = machinfo; + if (!machinfo->limit_mask) + machinfo->limit_mask = -1; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = machinfo->max_intensity; + kb3886_backlight_device = devm_backlight_device_register(&pdev->dev, + "kb3886-bl", &pdev->dev, + NULL, &kb3886bl_ops, + &props); + if (IS_ERR(kb3886_backlight_device)) + return PTR_ERR(kb3886_backlight_device); + + platform_set_drvdata(pdev, kb3886_backlight_device); + + kb3886_backlight_device->props.power = FB_BLANK_UNBLANK; + kb3886_backlight_device->props.brightness = machinfo->default_intensity; + backlight_update_status(kb3886_backlight_device); + + return 0; +} + +static struct platform_driver kb3886bl_driver = { + .probe = kb3886bl_probe, + .driver = { + .name = "kb3886-bl", + .pm = &kb3886bl_pm_ops, + }, +}; + +static int __init kb3886_init(void) +{ + if (!dmi_check_system(kb3886bl_device_table)) + return -ENODEV; + + platform_add_devices(devices, ARRAY_SIZE(devices)); + return platform_driver_register(&kb3886bl_driver); +} + +static void __exit kb3886_exit(void) +{ + platform_driver_unregister(&kb3886bl_driver); +} + +module_init(kb3886_init); +module_exit(kb3886_exit); + +MODULE_AUTHOR("Claudio Nieder <private@claudio.ch>"); +MODULE_DESCRIPTION("Tabletkiosk Sahara Touch-iT Backlight Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("dmi:*:svnSDV:pniTouchT201:*"); |