0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010
0011 #include <linux/module.h>
0012 #include <linux/init.h>
0013 #include <linux/device.h>
0014 #include <linux/backlight.h>
0015 #include <linux/notifier.h>
0016 #include <linux/ctype.h>
0017 #include <linux/err.h>
0018 #include <linux/fb.h>
0019 #include <linux/slab.h>
0020
0021 #ifdef CONFIG_PMAC_BACKLIGHT
0022 #include <asm/backlight.h>
0023 #endif
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 static struct list_head backlight_dev_list;
0067 static struct mutex backlight_dev_list_mutex;
0068 static struct blocking_notifier_head backlight_notifier;
0069
0070 static const char *const backlight_types[] = {
0071 [BACKLIGHT_RAW] = "raw",
0072 [BACKLIGHT_PLATFORM] = "platform",
0073 [BACKLIGHT_FIRMWARE] = "firmware",
0074 };
0075
0076 static const char *const backlight_scale_types[] = {
0077 [BACKLIGHT_SCALE_UNKNOWN] = "unknown",
0078 [BACKLIGHT_SCALE_LINEAR] = "linear",
0079 [BACKLIGHT_SCALE_NON_LINEAR] = "non-linear",
0080 };
0081
0082 #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
0083 defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 static int fb_notifier_callback(struct notifier_block *self,
0097 unsigned long event, void *data)
0098 {
0099 struct backlight_device *bd;
0100 struct fb_event *evdata = data;
0101 int node = evdata->info->node;
0102 int fb_blank = 0;
0103
0104
0105 if (event != FB_EVENT_BLANK)
0106 return 0;
0107
0108 bd = container_of(self, struct backlight_device, fb_notif);
0109 mutex_lock(&bd->ops_lock);
0110
0111 if (!bd->ops)
0112 goto out;
0113 if (bd->ops->check_fb && !bd->ops->check_fb(bd, evdata->info))
0114 goto out;
0115
0116 fb_blank = *(int *)evdata->data;
0117 if (fb_blank == FB_BLANK_UNBLANK && !bd->fb_bl_on[node]) {
0118 bd->fb_bl_on[node] = true;
0119 if (!bd->use_count++) {
0120 bd->props.state &= ~BL_CORE_FBBLANK;
0121 bd->props.fb_blank = FB_BLANK_UNBLANK;
0122 backlight_update_status(bd);
0123 }
0124 } else if (fb_blank != FB_BLANK_UNBLANK && bd->fb_bl_on[node]) {
0125 bd->fb_bl_on[node] = false;
0126 if (!(--bd->use_count)) {
0127 bd->props.state |= BL_CORE_FBBLANK;
0128 bd->props.fb_blank = fb_blank;
0129 backlight_update_status(bd);
0130 }
0131 }
0132 out:
0133 mutex_unlock(&bd->ops_lock);
0134 return 0;
0135 }
0136
0137 static int backlight_register_fb(struct backlight_device *bd)
0138 {
0139 memset(&bd->fb_notif, 0, sizeof(bd->fb_notif));
0140 bd->fb_notif.notifier_call = fb_notifier_callback;
0141
0142 return fb_register_client(&bd->fb_notif);
0143 }
0144
0145 static void backlight_unregister_fb(struct backlight_device *bd)
0146 {
0147 fb_unregister_client(&bd->fb_notif);
0148 }
0149 #else
0150 static inline int backlight_register_fb(struct backlight_device *bd)
0151 {
0152 return 0;
0153 }
0154
0155 static inline void backlight_unregister_fb(struct backlight_device *bd)
0156 {
0157 }
0158 #endif
0159
0160 static void backlight_generate_event(struct backlight_device *bd,
0161 enum backlight_update_reason reason)
0162 {
0163 char *envp[2];
0164
0165 switch (reason) {
0166 case BACKLIGHT_UPDATE_SYSFS:
0167 envp[0] = "SOURCE=sysfs";
0168 break;
0169 case BACKLIGHT_UPDATE_HOTKEY:
0170 envp[0] = "SOURCE=hotkey";
0171 break;
0172 default:
0173 envp[0] = "SOURCE=unknown";
0174 break;
0175 }
0176 envp[1] = NULL;
0177 kobject_uevent_env(&bd->dev.kobj, KOBJ_CHANGE, envp);
0178 sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness");
0179 }
0180
0181 static ssize_t bl_power_show(struct device *dev, struct device_attribute *attr,
0182 char *buf)
0183 {
0184 struct backlight_device *bd = to_backlight_device(dev);
0185
0186 return sprintf(buf, "%d\n", bd->props.power);
0187 }
0188
0189 static ssize_t bl_power_store(struct device *dev, struct device_attribute *attr,
0190 const char *buf, size_t count)
0191 {
0192 int rc;
0193 struct backlight_device *bd = to_backlight_device(dev);
0194 unsigned long power, old_power;
0195
0196 rc = kstrtoul(buf, 0, &power);
0197 if (rc)
0198 return rc;
0199
0200 rc = -ENXIO;
0201 mutex_lock(&bd->ops_lock);
0202 if (bd->ops) {
0203 pr_debug("set power to %lu\n", power);
0204 if (bd->props.power != power) {
0205 old_power = bd->props.power;
0206 bd->props.power = power;
0207 rc = backlight_update_status(bd);
0208 if (rc)
0209 bd->props.power = old_power;
0210 else
0211 rc = count;
0212 } else {
0213 rc = count;
0214 }
0215 }
0216 mutex_unlock(&bd->ops_lock);
0217
0218 return rc;
0219 }
0220 static DEVICE_ATTR_RW(bl_power);
0221
0222 static ssize_t brightness_show(struct device *dev,
0223 struct device_attribute *attr, char *buf)
0224 {
0225 struct backlight_device *bd = to_backlight_device(dev);
0226
0227 return sprintf(buf, "%d\n", bd->props.brightness);
0228 }
0229
0230 int backlight_device_set_brightness(struct backlight_device *bd,
0231 unsigned long brightness)
0232 {
0233 int rc = -ENXIO;
0234
0235 mutex_lock(&bd->ops_lock);
0236 if (bd->ops) {
0237 if (brightness > bd->props.max_brightness)
0238 rc = -EINVAL;
0239 else {
0240 pr_debug("set brightness to %lu\n", brightness);
0241 bd->props.brightness = brightness;
0242 rc = backlight_update_status(bd);
0243 }
0244 }
0245 mutex_unlock(&bd->ops_lock);
0246
0247 backlight_generate_event(bd, BACKLIGHT_UPDATE_SYSFS);
0248
0249 return rc;
0250 }
0251 EXPORT_SYMBOL(backlight_device_set_brightness);
0252
0253 static ssize_t brightness_store(struct device *dev,
0254 struct device_attribute *attr, const char *buf, size_t count)
0255 {
0256 int rc;
0257 struct backlight_device *bd = to_backlight_device(dev);
0258 unsigned long brightness;
0259
0260 rc = kstrtoul(buf, 0, &brightness);
0261 if (rc)
0262 return rc;
0263
0264 rc = backlight_device_set_brightness(bd, brightness);
0265
0266 return rc ? rc : count;
0267 }
0268 static DEVICE_ATTR_RW(brightness);
0269
0270 static ssize_t type_show(struct device *dev, struct device_attribute *attr,
0271 char *buf)
0272 {
0273 struct backlight_device *bd = to_backlight_device(dev);
0274
0275 return sprintf(buf, "%s\n", backlight_types[bd->props.type]);
0276 }
0277 static DEVICE_ATTR_RO(type);
0278
0279 static ssize_t max_brightness_show(struct device *dev,
0280 struct device_attribute *attr, char *buf)
0281 {
0282 struct backlight_device *bd = to_backlight_device(dev);
0283
0284 return sprintf(buf, "%d\n", bd->props.max_brightness);
0285 }
0286 static DEVICE_ATTR_RO(max_brightness);
0287
0288 static ssize_t actual_brightness_show(struct device *dev,
0289 struct device_attribute *attr, char *buf)
0290 {
0291 int rc = -ENXIO;
0292 struct backlight_device *bd = to_backlight_device(dev);
0293
0294 mutex_lock(&bd->ops_lock);
0295 if (bd->ops && bd->ops->get_brightness) {
0296 rc = bd->ops->get_brightness(bd);
0297 if (rc >= 0)
0298 rc = sprintf(buf, "%d\n", rc);
0299 } else {
0300 rc = sprintf(buf, "%d\n", bd->props.brightness);
0301 }
0302 mutex_unlock(&bd->ops_lock);
0303
0304 return rc;
0305 }
0306 static DEVICE_ATTR_RO(actual_brightness);
0307
0308 static ssize_t scale_show(struct device *dev,
0309 struct device_attribute *attr, char *buf)
0310 {
0311 struct backlight_device *bd = to_backlight_device(dev);
0312
0313 if (WARN_ON(bd->props.scale > BACKLIGHT_SCALE_NON_LINEAR))
0314 return sprintf(buf, "unknown\n");
0315
0316 return sprintf(buf, "%s\n", backlight_scale_types[bd->props.scale]);
0317 }
0318 static DEVICE_ATTR_RO(scale);
0319
0320 static struct class *backlight_class;
0321
0322 #ifdef CONFIG_PM_SLEEP
0323 static int backlight_suspend(struct device *dev)
0324 {
0325 struct backlight_device *bd = to_backlight_device(dev);
0326
0327 mutex_lock(&bd->ops_lock);
0328 if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) {
0329 bd->props.state |= BL_CORE_SUSPENDED;
0330 backlight_update_status(bd);
0331 }
0332 mutex_unlock(&bd->ops_lock);
0333
0334 return 0;
0335 }
0336
0337 static int backlight_resume(struct device *dev)
0338 {
0339 struct backlight_device *bd = to_backlight_device(dev);
0340
0341 mutex_lock(&bd->ops_lock);
0342 if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) {
0343 bd->props.state &= ~BL_CORE_SUSPENDED;
0344 backlight_update_status(bd);
0345 }
0346 mutex_unlock(&bd->ops_lock);
0347
0348 return 0;
0349 }
0350 #endif
0351
0352 static SIMPLE_DEV_PM_OPS(backlight_class_dev_pm_ops, backlight_suspend,
0353 backlight_resume);
0354
0355 static void bl_device_release(struct device *dev)
0356 {
0357 struct backlight_device *bd = to_backlight_device(dev);
0358 kfree(bd);
0359 }
0360
0361 static struct attribute *bl_device_attrs[] = {
0362 &dev_attr_bl_power.attr,
0363 &dev_attr_brightness.attr,
0364 &dev_attr_actual_brightness.attr,
0365 &dev_attr_max_brightness.attr,
0366 &dev_attr_scale.attr,
0367 &dev_attr_type.attr,
0368 NULL,
0369 };
0370 ATTRIBUTE_GROUPS(bl_device);
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 void backlight_force_update(struct backlight_device *bd,
0385 enum backlight_update_reason reason)
0386 {
0387 int brightness;
0388
0389 mutex_lock(&bd->ops_lock);
0390 if (bd->ops && bd->ops->get_brightness) {
0391 brightness = bd->ops->get_brightness(bd);
0392 if (brightness >= 0)
0393 bd->props.brightness = brightness;
0394 else
0395 dev_err(&bd->dev,
0396 "Could not update brightness from device: %pe\n",
0397 ERR_PTR(brightness));
0398 }
0399 mutex_unlock(&bd->ops_lock);
0400 backlight_generate_event(bd, reason);
0401 }
0402 EXPORT_SYMBOL(backlight_force_update);
0403
0404
0405 struct backlight_device *backlight_device_register(const char *name,
0406 struct device *parent, void *devdata, const struct backlight_ops *ops,
0407 const struct backlight_properties *props)
0408 {
0409 struct backlight_device *new_bd;
0410 int rc;
0411
0412 pr_debug("backlight_device_register: name=%s\n", name);
0413
0414 new_bd = kzalloc(sizeof(struct backlight_device), GFP_KERNEL);
0415 if (!new_bd)
0416 return ERR_PTR(-ENOMEM);
0417
0418 mutex_init(&new_bd->update_lock);
0419 mutex_init(&new_bd->ops_lock);
0420
0421 new_bd->dev.class = backlight_class;
0422 new_bd->dev.parent = parent;
0423 new_bd->dev.release = bl_device_release;
0424 dev_set_name(&new_bd->dev, "%s", name);
0425 dev_set_drvdata(&new_bd->dev, devdata);
0426
0427
0428 if (props) {
0429 memcpy(&new_bd->props, props,
0430 sizeof(struct backlight_properties));
0431 if (props->type <= 0 || props->type >= BACKLIGHT_TYPE_MAX) {
0432 WARN(1, "%s: invalid backlight type", name);
0433 new_bd->props.type = BACKLIGHT_RAW;
0434 }
0435 } else {
0436 new_bd->props.type = BACKLIGHT_RAW;
0437 }
0438
0439 rc = device_register(&new_bd->dev);
0440 if (rc) {
0441 put_device(&new_bd->dev);
0442 return ERR_PTR(rc);
0443 }
0444
0445 rc = backlight_register_fb(new_bd);
0446 if (rc) {
0447 device_unregister(&new_bd->dev);
0448 return ERR_PTR(rc);
0449 }
0450
0451 new_bd->ops = ops;
0452
0453 #ifdef CONFIG_PMAC_BACKLIGHT
0454 mutex_lock(&pmac_backlight_mutex);
0455 if (!pmac_backlight)
0456 pmac_backlight = new_bd;
0457 mutex_unlock(&pmac_backlight_mutex);
0458 #endif
0459
0460 mutex_lock(&backlight_dev_list_mutex);
0461 list_add(&new_bd->entry, &backlight_dev_list);
0462 mutex_unlock(&backlight_dev_list_mutex);
0463
0464 blocking_notifier_call_chain(&backlight_notifier,
0465 BACKLIGHT_REGISTERED, new_bd);
0466
0467 return new_bd;
0468 }
0469 EXPORT_SYMBOL(backlight_device_register);
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480 struct backlight_device *backlight_device_get_by_type(enum backlight_type type)
0481 {
0482 bool found = false;
0483 struct backlight_device *bd;
0484
0485 mutex_lock(&backlight_dev_list_mutex);
0486 list_for_each_entry(bd, &backlight_dev_list, entry) {
0487 if (bd->props.type == type) {
0488 found = true;
0489 break;
0490 }
0491 }
0492 mutex_unlock(&backlight_dev_list_mutex);
0493
0494 return found ? bd : NULL;
0495 }
0496 EXPORT_SYMBOL(backlight_device_get_by_type);
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509 struct backlight_device *backlight_device_get_by_name(const char *name)
0510 {
0511 struct device *dev;
0512
0513 dev = class_find_device_by_name(backlight_class, name);
0514
0515 return dev ? to_backlight_device(dev) : NULL;
0516 }
0517 EXPORT_SYMBOL(backlight_device_get_by_name);
0518
0519
0520 void backlight_device_unregister(struct backlight_device *bd)
0521 {
0522 if (!bd)
0523 return;
0524
0525 mutex_lock(&backlight_dev_list_mutex);
0526 list_del(&bd->entry);
0527 mutex_unlock(&backlight_dev_list_mutex);
0528
0529 #ifdef CONFIG_PMAC_BACKLIGHT
0530 mutex_lock(&pmac_backlight_mutex);
0531 if (pmac_backlight == bd)
0532 pmac_backlight = NULL;
0533 mutex_unlock(&pmac_backlight_mutex);
0534 #endif
0535
0536 blocking_notifier_call_chain(&backlight_notifier,
0537 BACKLIGHT_UNREGISTERED, bd);
0538
0539 mutex_lock(&bd->ops_lock);
0540 bd->ops = NULL;
0541 mutex_unlock(&bd->ops_lock);
0542
0543 backlight_unregister_fb(bd);
0544 device_unregister(&bd->dev);
0545 }
0546 EXPORT_SYMBOL(backlight_device_unregister);
0547
0548 static void devm_backlight_device_release(struct device *dev, void *res)
0549 {
0550 struct backlight_device *backlight = *(struct backlight_device **)res;
0551
0552 backlight_device_unregister(backlight);
0553 }
0554
0555 static int devm_backlight_device_match(struct device *dev, void *res,
0556 void *data)
0557 {
0558 struct backlight_device **r = res;
0559
0560 return *r == data;
0561 }
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574 int backlight_register_notifier(struct notifier_block *nb)
0575 {
0576 return blocking_notifier_chain_register(&backlight_notifier, nb);
0577 }
0578 EXPORT_SYMBOL(backlight_register_notifier);
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591 int backlight_unregister_notifier(struct notifier_block *nb)
0592 {
0593 return blocking_notifier_chain_unregister(&backlight_notifier, nb);
0594 }
0595 EXPORT_SYMBOL(backlight_unregister_notifier);
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614 struct backlight_device *devm_backlight_device_register(struct device *dev,
0615 const char *name, struct device *parent, void *devdata,
0616 const struct backlight_ops *ops,
0617 const struct backlight_properties *props)
0618 {
0619 struct backlight_device **ptr, *backlight;
0620
0621 ptr = devres_alloc(devm_backlight_device_release, sizeof(*ptr),
0622 GFP_KERNEL);
0623 if (!ptr)
0624 return ERR_PTR(-ENOMEM);
0625
0626 backlight = backlight_device_register(name, parent, devdata, ops,
0627 props);
0628 if (!IS_ERR(backlight)) {
0629 *ptr = backlight;
0630 devres_add(dev, ptr);
0631 } else {
0632 devres_free(ptr);
0633 }
0634
0635 return backlight;
0636 }
0637 EXPORT_SYMBOL(devm_backlight_device_register);
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648 void devm_backlight_device_unregister(struct device *dev,
0649 struct backlight_device *bd)
0650 {
0651 int rc;
0652
0653 rc = devres_release(dev, devm_backlight_device_release,
0654 devm_backlight_device_match, bd);
0655 WARN_ON(rc);
0656 }
0657 EXPORT_SYMBOL(devm_backlight_device_unregister);
0658
0659 #ifdef CONFIG_OF
0660 static int of_parent_match(struct device *dev, const void *data)
0661 {
0662 return dev->parent && dev->parent->of_node == data;
0663 }
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677 struct backlight_device *of_find_backlight_by_node(struct device_node *node)
0678 {
0679 struct device *dev;
0680
0681 dev = class_find_device(backlight_class, NULL, node, of_parent_match);
0682
0683 return dev ? to_backlight_device(dev) : NULL;
0684 }
0685 EXPORT_SYMBOL(of_find_backlight_by_node);
0686 #endif
0687
0688 static struct backlight_device *of_find_backlight(struct device *dev)
0689 {
0690 struct backlight_device *bd = NULL;
0691 struct device_node *np;
0692
0693 if (!dev)
0694 return NULL;
0695
0696 if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
0697 np = of_parse_phandle(dev->of_node, "backlight", 0);
0698 if (np) {
0699 bd = of_find_backlight_by_node(np);
0700 of_node_put(np);
0701 if (!bd)
0702 return ERR_PTR(-EPROBE_DEFER);
0703 }
0704 }
0705
0706 return bd;
0707 }
0708
0709 static void devm_backlight_release(void *data)
0710 {
0711 struct backlight_device *bd = data;
0712
0713 put_device(&bd->dev);
0714 }
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731 struct backlight_device *devm_of_find_backlight(struct device *dev)
0732 {
0733 struct backlight_device *bd;
0734 int ret;
0735
0736 bd = of_find_backlight(dev);
0737 if (IS_ERR_OR_NULL(bd))
0738 return bd;
0739 ret = devm_add_action_or_reset(dev, devm_backlight_release, bd);
0740 if (ret)
0741 return ERR_PTR(ret);
0742
0743 return bd;
0744 }
0745 EXPORT_SYMBOL(devm_of_find_backlight);
0746
0747 static void __exit backlight_class_exit(void)
0748 {
0749 class_destroy(backlight_class);
0750 }
0751
0752 static int __init backlight_class_init(void)
0753 {
0754 backlight_class = class_create(THIS_MODULE, "backlight");
0755 if (IS_ERR(backlight_class)) {
0756 pr_warn("Unable to create backlight class; errno = %ld\n",
0757 PTR_ERR(backlight_class));
0758 return PTR_ERR(backlight_class);
0759 }
0760
0761 backlight_class->dev_groups = bl_device_groups;
0762 backlight_class->pm = &backlight_class_dev_pm_ops;
0763 INIT_LIST_HEAD(&backlight_dev_list);
0764 mutex_init(&backlight_dev_list_mutex);
0765 BLOCKING_INIT_NOTIFIER_HEAD(&backlight_notifier);
0766
0767 return 0;
0768 }
0769
0770
0771
0772
0773
0774 postcore_initcall(backlight_class_init);
0775 module_exit(backlight_class_exit);
0776
0777 MODULE_LICENSE("GPL");
0778 MODULE_AUTHOR("Jamey Hicks <jamey.hicks@hp.com>, Andrew Zabolotny <zap@homelink.ru>");
0779 MODULE_DESCRIPTION("Backlight Lowlevel Control Abstraction");