root/drivers/video/backlight/apple_bl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. intel_chipset_set_brightness
  2. intel_chipset_send_intensity
  3. intel_chipset_get_intensity
  4. nvidia_chipset_set_brightness
  5. nvidia_chipset_send_intensity
  6. nvidia_chipset_get_intensity
  7. apple_bl_add
  8. apple_bl_remove
  9. apple_bl_register
  10. apple_bl_unregister
  11. apple_bl_init
  12. apple_bl_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  Backlight Driver for Intel-based Apples
   4  *
   5  *  Copyright (c) Red Hat <mjg@redhat.com>
   6  *  Based on code from Pommed:
   7  *  Copyright (C) 2006 Nicolas Boichat <nicolas @boichat.ch>
   8  *  Copyright (C) 2006 Felipe Alfaro Solana <felipe_alfaro @linuxmail.org>
   9  *  Copyright (C) 2007 Julien BLACHE <jb@jblache.org>
  10  *
  11  *  This driver triggers SMIs which cause the firmware to change the
  12  *  backlight brightness. This is icky in many ways, but it's impractical to
  13  *  get at the firmware code in order to figure out what it's actually doing.
  14  */
  15 
  16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  17 
  18 #include <linux/module.h>
  19 #include <linux/kernel.h>
  20 #include <linux/init.h>
  21 #include <linux/backlight.h>
  22 #include <linux/err.h>
  23 #include <linux/io.h>
  24 #include <linux/pci.h>
  25 #include <linux/acpi.h>
  26 #include <linux/atomic.h>
  27 #include <linux/apple_bl.h>
  28 
  29 static struct backlight_device *apple_backlight_device;
  30 
  31 struct hw_data {
  32         /* I/O resource to allocate. */
  33         unsigned long iostart;
  34         unsigned long iolen;
  35         /* Backlight operations structure. */
  36         const struct backlight_ops backlight_ops;
  37         void (*set_brightness)(int);
  38 };
  39 
  40 static const struct hw_data *hw_data;
  41 
  42 /* Module parameters. */
  43 static int debug;
  44 module_param_named(debug, debug, int, 0644);
  45 MODULE_PARM_DESC(debug, "Set to one to enable debugging messages.");
  46 
  47 /*
  48  * Implementation for machines with Intel chipset.
  49  */
  50 static void intel_chipset_set_brightness(int intensity)
  51 {
  52         outb(0x04 | (intensity << 4), 0xb3);
  53         outb(0xbf, 0xb2);
  54 }
  55 
  56 static int intel_chipset_send_intensity(struct backlight_device *bd)
  57 {
  58         int intensity = bd->props.brightness;
  59 
  60         if (debug)
  61                 pr_debug("setting brightness to %d\n", intensity);
  62 
  63         intel_chipset_set_brightness(intensity);
  64         return 0;
  65 }
  66 
  67 static int intel_chipset_get_intensity(struct backlight_device *bd)
  68 {
  69         int intensity;
  70 
  71         outb(0x03, 0xb3);
  72         outb(0xbf, 0xb2);
  73         intensity = inb(0xb3) >> 4;
  74 
  75         if (debug)
  76                 pr_debug("read brightness of %d\n", intensity);
  77 
  78         return intensity;
  79 }
  80 
  81 static const struct hw_data intel_chipset_data = {
  82         .iostart = 0xb2,
  83         .iolen = 2,
  84         .backlight_ops  = {
  85                 .options        = BL_CORE_SUSPENDRESUME,
  86                 .get_brightness = intel_chipset_get_intensity,
  87                 .update_status  = intel_chipset_send_intensity,
  88         },
  89         .set_brightness = intel_chipset_set_brightness,
  90 };
  91 
  92 /*
  93  * Implementation for machines with Nvidia chipset.
  94  */
  95 static void nvidia_chipset_set_brightness(int intensity)
  96 {
  97         outb(0x04 | (intensity << 4), 0x52f);
  98         outb(0xbf, 0x52e);
  99 }
 100 
 101 static int nvidia_chipset_send_intensity(struct backlight_device *bd)
 102 {
 103         int intensity = bd->props.brightness;
 104 
 105         if (debug)
 106                 pr_debug("setting brightness to %d\n", intensity);
 107 
 108         nvidia_chipset_set_brightness(intensity);
 109         return 0;
 110 }
 111 
 112 static int nvidia_chipset_get_intensity(struct backlight_device *bd)
 113 {
 114         int intensity;
 115 
 116         outb(0x03, 0x52f);
 117         outb(0xbf, 0x52e);
 118         intensity = inb(0x52f) >> 4;
 119 
 120         if (debug)
 121                 pr_debug("read brightness of %d\n", intensity);
 122 
 123         return intensity;
 124 }
 125 
 126 static const struct hw_data nvidia_chipset_data = {
 127         .iostart = 0x52e,
 128         .iolen = 2,
 129         .backlight_ops          = {
 130                 .options        = BL_CORE_SUSPENDRESUME,
 131                 .get_brightness = nvidia_chipset_get_intensity,
 132                 .update_status  = nvidia_chipset_send_intensity
 133         },
 134         .set_brightness = nvidia_chipset_set_brightness,
 135 };
 136 
 137 static int apple_bl_add(struct acpi_device *dev)
 138 {
 139         struct backlight_properties props;
 140         struct pci_dev *host;
 141         int intensity;
 142 
 143         host = pci_get_domain_bus_and_slot(0, 0, 0);
 144 
 145         if (!host) {
 146                 pr_err("unable to find PCI host\n");
 147                 return -ENODEV;
 148         }
 149 
 150         if (host->vendor == PCI_VENDOR_ID_INTEL)
 151                 hw_data = &intel_chipset_data;
 152         else if (host->vendor == PCI_VENDOR_ID_NVIDIA)
 153                 hw_data = &nvidia_chipset_data;
 154 
 155         pci_dev_put(host);
 156 
 157         if (!hw_data) {
 158                 pr_err("unknown hardware\n");
 159                 return -ENODEV;
 160         }
 161 
 162         /* Check that the hardware responds - this may not work under EFI */
 163 
 164         intensity = hw_data->backlight_ops.get_brightness(NULL);
 165 
 166         if (!intensity) {
 167                 hw_data->set_brightness(1);
 168                 if (!hw_data->backlight_ops.get_brightness(NULL))
 169                         return -ENODEV;
 170 
 171                 hw_data->set_brightness(0);
 172         }
 173 
 174         if (!request_region(hw_data->iostart, hw_data->iolen,
 175                             "Apple backlight"))
 176                 return -ENXIO;
 177 
 178         memset(&props, 0, sizeof(struct backlight_properties));
 179         props.type = BACKLIGHT_PLATFORM;
 180         props.max_brightness = 15;
 181         apple_backlight_device = backlight_device_register("apple_backlight",
 182                                   NULL, NULL, &hw_data->backlight_ops, &props);
 183 
 184         if (IS_ERR(apple_backlight_device)) {
 185                 release_region(hw_data->iostart, hw_data->iolen);
 186                 return PTR_ERR(apple_backlight_device);
 187         }
 188 
 189         apple_backlight_device->props.brightness =
 190                 hw_data->backlight_ops.get_brightness(apple_backlight_device);
 191         backlight_update_status(apple_backlight_device);
 192 
 193         return 0;
 194 }
 195 
 196 static int apple_bl_remove(struct acpi_device *dev)
 197 {
 198         backlight_device_unregister(apple_backlight_device);
 199 
 200         release_region(hw_data->iostart, hw_data->iolen);
 201         hw_data = NULL;
 202         return 0;
 203 }
 204 
 205 static const struct acpi_device_id apple_bl_ids[] = {
 206         {"APP0002", 0},
 207         {"", 0},
 208 };
 209 
 210 static struct acpi_driver apple_bl_driver = {
 211         .name = "Apple backlight",
 212         .ids = apple_bl_ids,
 213         .ops = {
 214                 .add = apple_bl_add,
 215                 .remove = apple_bl_remove,
 216         },
 217 };
 218 
 219 static atomic_t apple_bl_registered = ATOMIC_INIT(0);
 220 
 221 int apple_bl_register(void)
 222 {
 223         if (atomic_xchg(&apple_bl_registered, 1) == 0)
 224                 return acpi_bus_register_driver(&apple_bl_driver);
 225 
 226         return 0;
 227 }
 228 EXPORT_SYMBOL_GPL(apple_bl_register);
 229 
 230 void apple_bl_unregister(void)
 231 {
 232         if (atomic_xchg(&apple_bl_registered, 0) == 1)
 233                 acpi_bus_unregister_driver(&apple_bl_driver);
 234 }
 235 EXPORT_SYMBOL_GPL(apple_bl_unregister);
 236 
 237 static int __init apple_bl_init(void)
 238 {
 239         return apple_bl_register();
 240 }
 241 
 242 static void __exit apple_bl_exit(void)
 243 {
 244         apple_bl_unregister();
 245 }
 246 
 247 module_init(apple_bl_init);
 248 module_exit(apple_bl_exit);
 249 
 250 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
 251 MODULE_DESCRIPTION("Apple Backlight Driver");
 252 MODULE_LICENSE("GPL");
 253 MODULE_DEVICE_TABLE(acpi, apple_bl_ids);
 254 MODULE_ALIAS("mbp_nvidia_bl");

/* [<][>][^][v][top][bottom][index][help] */