LCOV - code coverage report
Current view: top level - drivers/leds/trigger - ledtrig-backlight.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 1 37 2.7 %
Date: 2020-09-30 20:25:40 Functions: 1 7 14.3 %
Branches: 0 16 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * Backlight emulation LED trigger
       4                 :            :  *
       5                 :            :  * Copyright 2008 (C) Rodolfo Giometti <giometti@linux.it>
       6                 :            :  * Copyright 2008 (C) Eurotech S.p.A. <info@eurotech.it>
       7                 :            :  */
       8                 :            : 
       9                 :            : #include <linux/module.h>
      10                 :            : #include <linux/kernel.h>
      11                 :            : #include <linux/slab.h>
      12                 :            : #include <linux/init.h>
      13                 :            : #include <linux/fb.h>
      14                 :            : #include <linux/leds.h>
      15                 :            : #include "../leds.h"
      16                 :            : 
      17                 :            : #define BLANK           1
      18                 :            : #define UNBLANK         0
      19                 :            : 
      20                 :            : struct bl_trig_notifier {
      21                 :            :         struct led_classdev *led;
      22                 :            :         int brightness;
      23                 :            :         int old_status;
      24                 :            :         struct notifier_block notifier;
      25                 :            :         unsigned invert;
      26                 :            : };
      27                 :            : 
      28                 :          0 : static int fb_notifier_callback(struct notifier_block *p,
      29                 :            :                                 unsigned long event, void *data)
      30                 :            : {
      31                 :            :         struct bl_trig_notifier *n = container_of(p,
      32                 :            :                                         struct bl_trig_notifier, notifier);
      33                 :          0 :         struct led_classdev *led = n->led;
      34                 :            :         struct fb_event *fb_event = data;
      35                 :            :         int *blank;
      36                 :            :         int new_status;
      37                 :            : 
      38                 :            :         /* If we aren't interested in this event, skip it immediately ... */
      39         [ #  # ]:          0 :         if (event != FB_EVENT_BLANK)
      40                 :            :                 return 0;
      41                 :            : 
      42                 :          0 :         blank = fb_event->data;
      43                 :          0 :         new_status = *blank ? BLANK : UNBLANK;
      44                 :            : 
      45         [ #  # ]:          0 :         if (new_status == n->old_status)
      46                 :            :                 return 0;
      47                 :            : 
      48         [ #  # ]:          0 :         if ((n->old_status == UNBLANK) ^ n->invert) {
      49                 :          0 :                 n->brightness = led->brightness;
      50                 :          0 :                 led_set_brightness_nosleep(led, LED_OFF);
      51                 :            :         } else {
      52                 :          0 :                 led_set_brightness_nosleep(led, n->brightness);
      53                 :            :         }
      54                 :            : 
      55                 :          0 :         n->old_status = new_status;
      56                 :            : 
      57                 :          0 :         return 0;
      58                 :            : }
      59                 :            : 
      60                 :          0 : static ssize_t bl_trig_invert_show(struct device *dev,
      61                 :            :                 struct device_attribute *attr, char *buf)
      62                 :            : {
      63                 :            :         struct bl_trig_notifier *n = led_trigger_get_drvdata(dev);
      64                 :            : 
      65                 :          0 :         return sprintf(buf, "%u\n", n->invert);
      66                 :            : }
      67                 :            : 
      68                 :          0 : static ssize_t bl_trig_invert_store(struct device *dev,
      69                 :            :                 struct device_attribute *attr, const char *buf, size_t num)
      70                 :            : {
      71                 :            :         struct led_classdev *led = led_trigger_get_led(dev);
      72                 :            :         struct bl_trig_notifier *n = led_trigger_get_drvdata(dev);
      73                 :            :         unsigned long invert;
      74                 :            :         int ret;
      75                 :            : 
      76                 :            :         ret = kstrtoul(buf, 10, &invert);
      77         [ #  # ]:          0 :         if (ret < 0)
      78                 :            :                 return ret;
      79                 :            : 
      80         [ #  # ]:          0 :         if (invert > 1)
      81                 :            :                 return -EINVAL;
      82                 :            : 
      83                 :          0 :         n->invert = invert;
      84                 :            : 
      85                 :            :         /* After inverting, we need to update the LED. */
      86         [ #  # ]:          0 :         if ((n->old_status == BLANK) ^ n->invert)
      87                 :          0 :                 led_set_brightness_nosleep(led, LED_OFF);
      88                 :            :         else
      89                 :          0 :                 led_set_brightness_nosleep(led, n->brightness);
      90                 :            : 
      91                 :          0 :         return num;
      92                 :            : }
      93                 :            : static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store);
      94                 :            : 
      95                 :            : static struct attribute *bl_trig_attrs[] = {
      96                 :            :         &dev_attr_inverted.attr,
      97                 :            :         NULL,
      98                 :            : };
      99                 :            : ATTRIBUTE_GROUPS(bl_trig);
     100                 :            : 
     101                 :          0 : static int bl_trig_activate(struct led_classdev *led)
     102                 :            : {
     103                 :            :         int ret;
     104                 :            : 
     105                 :            :         struct bl_trig_notifier *n;
     106                 :            : 
     107                 :          0 :         n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL);
     108         [ #  # ]:          0 :         if (!n)
     109                 :            :                 return -ENOMEM;
     110                 :            :         led_set_trigger_data(led, n);
     111                 :            : 
     112                 :          0 :         n->led = led;
     113                 :          0 :         n->brightness = led->brightness;
     114                 :          0 :         n->old_status = UNBLANK;
     115                 :          0 :         n->notifier.notifier_call = fb_notifier_callback;
     116                 :            : 
     117                 :          0 :         ret = fb_register_client(&n->notifier);
     118         [ #  # ]:          0 :         if (ret)
     119                 :          0 :                 dev_err(led->dev, "unable to register backlight trigger\n");
     120                 :            : 
     121                 :            :         return 0;
     122                 :            : }
     123                 :            : 
     124                 :          0 : static void bl_trig_deactivate(struct led_classdev *led)
     125                 :            : {
     126                 :            :         struct bl_trig_notifier *n = led_get_trigger_data(led);
     127                 :            : 
     128                 :          0 :         fb_unregister_client(&n->notifier);
     129                 :          0 :         kfree(n);
     130                 :          0 : }
     131                 :            : 
     132                 :            : static struct led_trigger bl_led_trigger = {
     133                 :            :         .name           = "backlight",
     134                 :            :         .activate       = bl_trig_activate,
     135                 :            :         .deactivate     = bl_trig_deactivate,
     136                 :            :         .groups         = bl_trig_groups,
     137                 :            : };
     138                 :        207 : module_led_trigger(bl_led_trigger);
     139                 :            : 
     140                 :            : MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
     141                 :            : MODULE_DESCRIPTION("Backlight emulation LED trigger");
     142                 :            : MODULE_LICENSE("GPL v2");

Generated by: LCOV version 1.14