linux/drivers/platform/x86/samsung-q10.c
<<
>>
Prefs
   1/*
   2 *  Driver for Samsung Q10 and related laptops: controls the backlight
   3 *
   4 *  Copyright (c) 2011 Frederick van der Wyck <fvanderwyck@gmail.com>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License version 2 as
   8 *  published by the Free Software Foundation.
   9 *
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/kernel.h>
  14#include <linux/init.h>
  15#include <linux/platform_device.h>
  16#include <linux/backlight.h>
  17#include <linux/i8042.h>
  18#include <linux/dmi.h>
  19
  20#define SAMSUNGQ10_BL_MAX_INTENSITY      255
  21#define SAMSUNGQ10_BL_DEFAULT_INTENSITY  185
  22
  23#define SAMSUNGQ10_BL_8042_CMD           0xbe
  24#define SAMSUNGQ10_BL_8042_DATA          { 0x89, 0x91 }
  25
  26static int samsungq10_bl_brightness;
  27
  28static bool force;
  29module_param(force, bool, 0);
  30MODULE_PARM_DESC(force,
  31                "Disable the DMI check and force the driver to be loaded");
  32
  33static int samsungq10_bl_set_intensity(struct backlight_device *bd)
  34{
  35
  36        int brightness = bd->props.brightness;
  37        unsigned char c[3] = SAMSUNGQ10_BL_8042_DATA;
  38
  39        c[2] = (unsigned char)brightness;
  40        i8042_lock_chip();
  41        i8042_command(c, (0x30 << 8) | SAMSUNGQ10_BL_8042_CMD);
  42        i8042_unlock_chip();
  43        samsungq10_bl_brightness = brightness;
  44
  45        return 0;
  46}
  47
  48static int samsungq10_bl_get_intensity(struct backlight_device *bd)
  49{
  50        return samsungq10_bl_brightness;
  51}
  52
  53static const struct backlight_ops samsungq10_bl_ops = {
  54        .get_brightness = samsungq10_bl_get_intensity,
  55        .update_status  = samsungq10_bl_set_intensity,
  56};
  57
  58#ifdef CONFIG_PM_SLEEP
  59static int samsungq10_suspend(struct device *dev)
  60{
  61        return 0;
  62}
  63
  64static int samsungq10_resume(struct device *dev)
  65{
  66
  67        struct backlight_device *bd = dev_get_drvdata(dev);
  68
  69        samsungq10_bl_set_intensity(bd);
  70        return 0;
  71}
  72#else
  73#define samsungq10_suspend NULL
  74#define samsungq10_resume  NULL
  75#endif
  76
  77static SIMPLE_DEV_PM_OPS(samsungq10_pm_ops,
  78                          samsungq10_suspend, samsungq10_resume);
  79
  80static int __devinit samsungq10_probe(struct platform_device *pdev)
  81{
  82
  83        struct backlight_properties props;
  84        struct backlight_device *bd;
  85
  86        memset(&props, 0, sizeof(struct backlight_properties));
  87        props.type = BACKLIGHT_PLATFORM;
  88        props.max_brightness = SAMSUNGQ10_BL_MAX_INTENSITY;
  89        bd = backlight_device_register("samsung", &pdev->dev, NULL,
  90                                       &samsungq10_bl_ops, &props);
  91        if (IS_ERR(bd))
  92                return PTR_ERR(bd);
  93
  94        platform_set_drvdata(pdev, bd);
  95
  96        bd->props.brightness = SAMSUNGQ10_BL_DEFAULT_INTENSITY;
  97        samsungq10_bl_set_intensity(bd);
  98
  99        return 0;
 100}
 101
 102static int __devexit samsungq10_remove(struct platform_device *pdev)
 103{
 104
 105        struct backlight_device *bd = platform_get_drvdata(pdev);
 106
 107        bd->props.brightness = SAMSUNGQ10_BL_DEFAULT_INTENSITY;
 108        samsungq10_bl_set_intensity(bd);
 109
 110        backlight_device_unregister(bd);
 111
 112        return 0;
 113}
 114
 115static struct platform_driver samsungq10_driver = {
 116        .driver         = {
 117                .name   = KBUILD_MODNAME,
 118                .owner  = THIS_MODULE,
 119                .pm     = &samsungq10_pm_ops,
 120        },
 121        .probe          = samsungq10_probe,
 122        .remove         = __devexit_p(samsungq10_remove),
 123};
 124
 125static struct platform_device *samsungq10_device;
 126
 127static int __init dmi_check_callback(const struct dmi_system_id *id)
 128{
 129        printk(KERN_INFO KBUILD_MODNAME ": found model '%s'\n", id->ident);
 130        return 1;
 131}
 132
 133static struct dmi_system_id __initdata samsungq10_dmi_table[] = {
 134        {
 135                .ident = "Samsung Q10",
 136                .matches = {
 137                        DMI_MATCH(DMI_SYS_VENDOR, "Samsung"),
 138                        DMI_MATCH(DMI_PRODUCT_NAME, "SQ10"),
 139                },
 140                .callback = dmi_check_callback,
 141        },
 142        {
 143                .ident = "Samsung Q20",
 144                .matches = {
 145                        DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
 146                        DMI_MATCH(DMI_PRODUCT_NAME, "SENS Q20"),
 147                },
 148                .callback = dmi_check_callback,
 149        },
 150        {
 151                .ident = "Samsung Q25",
 152                .matches = {
 153                        DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
 154                        DMI_MATCH(DMI_PRODUCT_NAME, "NQ25"),
 155                },
 156                .callback = dmi_check_callback,
 157        },
 158        {
 159                .ident = "Dell Latitude X200",
 160                .matches = {
 161                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
 162                        DMI_MATCH(DMI_PRODUCT_NAME, "X200"),
 163                },
 164                .callback = dmi_check_callback,
 165        },
 166        { },
 167};
 168MODULE_DEVICE_TABLE(dmi, samsungq10_dmi_table);
 169
 170static int __init samsungq10_init(void)
 171{
 172        if (!force && !dmi_check_system(samsungq10_dmi_table))
 173                return -ENODEV;
 174
 175        samsungq10_device = platform_create_bundle(&samsungq10_driver,
 176                                                   samsungq10_probe,
 177                                                   NULL, 0, NULL, 0);
 178
 179        if (IS_ERR(samsungq10_device))
 180                return PTR_ERR(samsungq10_device);
 181
 182        return 0;
 183}
 184
 185static void __exit samsungq10_exit(void)
 186{
 187        platform_device_unregister(samsungq10_device);
 188        platform_driver_unregister(&samsungq10_driver);
 189}
 190
 191module_init(samsungq10_init);
 192module_exit(samsungq10_exit);
 193
 194MODULE_AUTHOR("Frederick van der Wyck <fvanderwyck@gmail.com>");
 195MODULE_DESCRIPTION("Samsung Q10 Driver");
 196MODULE_LICENSE("GPL");
 197