2 * gpio_backlight.c - Simple GPIO-controlled backlight
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <linux/backlight.h>
10 #include <linux/err.h>
12 #include <linux/gpio.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
17 #include <linux/of_gpio.h>
18 #include <linux/platform_data/gpio_backlight.h>
19 #include <linux/platform_device.h>
20 #include <linux/slab.h>
22 struct gpio_backlight
{
31 static int gpio_backlight_update_status(struct backlight_device
*bl
)
33 struct gpio_backlight
*gbl
= bl_get_data(bl
);
34 int brightness
= bl
->props
.brightness
;
36 if (bl
->props
.power
!= FB_BLANK_UNBLANK
||
37 bl
->props
.fb_blank
!= FB_BLANK_UNBLANK
||
38 bl
->props
.state
& (BL_CORE_SUSPENDED
| BL_CORE_FBBLANK
))
41 gpio_set_value_cansleep(gbl
->gpio
,
42 brightness
? gbl
->active
: !gbl
->active
);
47 static int gpio_backlight_check_fb(struct backlight_device
*bl
,
50 struct gpio_backlight
*gbl
= bl_get_data(bl
);
52 return gbl
->fbdev
== NULL
|| gbl
->fbdev
== info
->dev
;
55 static const struct backlight_ops gpio_backlight_ops
= {
56 .options
= BL_CORE_SUSPENDRESUME
,
57 .update_status
= gpio_backlight_update_status
,
58 .check_fb
= gpio_backlight_check_fb
,
61 static int gpio_backlight_probe_dt(struct platform_device
*pdev
,
62 struct gpio_backlight
*gbl
)
64 struct device_node
*np
= pdev
->dev
.of_node
;
65 enum of_gpio_flags gpio_flags
;
67 gbl
->gpio
= of_get_gpio_flags(np
, 0, &gpio_flags
);
69 if (!gpio_is_valid(gbl
->gpio
)) {
70 if (gbl
->gpio
!= -EPROBE_DEFER
) {
72 "Error: The gpios parameter is missing or invalid.\n");
77 gbl
->active
= (gpio_flags
& OF_GPIO_ACTIVE_LOW
) ? 0 : 1;
79 gbl
->def_value
= of_property_read_bool(np
, "default-on");
84 static int gpio_backlight_probe(struct platform_device
*pdev
)
86 struct gpio_backlight_platform_data
*pdata
=
87 dev_get_platdata(&pdev
->dev
);
88 struct backlight_properties props
;
89 struct backlight_device
*bl
;
90 struct gpio_backlight
*gbl
;
91 struct device_node
*np
= pdev
->dev
.of_node
;
92 unsigned long flags
= GPIOF_DIR_OUT
;
97 "failed to find platform data or device tree node.\n");
101 gbl
= devm_kzalloc(&pdev
->dev
, sizeof(*gbl
), GFP_KERNEL
);
105 gbl
->dev
= &pdev
->dev
;
108 ret
= gpio_backlight_probe_dt(pdev
, gbl
);
112 gbl
->fbdev
= pdata
->fbdev
;
113 gbl
->gpio
= pdata
->gpio
;
114 gbl
->active
= pdata
->active_low
? 0 : 1;
115 gbl
->def_value
= pdata
->def_value
;
119 flags
|= gbl
->def_value
? GPIOF_INIT_HIGH
: GPIOF_INIT_LOW
;
121 flags
|= gbl
->def_value
? GPIOF_INIT_LOW
: GPIOF_INIT_HIGH
;
123 ret
= devm_gpio_request_one(gbl
->dev
, gbl
->gpio
, flags
,
124 pdata
? pdata
->name
: "backlight");
126 dev_err(&pdev
->dev
, "unable to request GPIO\n");
130 memset(&props
, 0, sizeof(props
));
131 props
.type
= BACKLIGHT_RAW
;
132 props
.max_brightness
= 1;
133 bl
= devm_backlight_device_register(&pdev
->dev
, dev_name(&pdev
->dev
),
134 &pdev
->dev
, gbl
, &gpio_backlight_ops
,
137 dev_err(&pdev
->dev
, "failed to register backlight\n");
141 bl
->props
.brightness
= gbl
->def_value
;
142 backlight_update_status(bl
);
144 platform_set_drvdata(pdev
, bl
);
149 static struct of_device_id gpio_backlight_of_match
[] = {
150 { .compatible
= "gpio-backlight" },
154 MODULE_DEVICE_TABLE(of
, gpio_backlight_of_match
);
157 static struct platform_driver gpio_backlight_driver
= {
159 .name
= "gpio-backlight",
160 .of_match_table
= of_match_ptr(gpio_backlight_of_match
),
162 .probe
= gpio_backlight_probe
,
165 module_platform_driver(gpio_backlight_driver
);
167 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
168 MODULE_DESCRIPTION("GPIO-based Backlight Driver");
169 MODULE_LICENSE("GPL");
170 MODULE_ALIAS("platform:gpio-backlight");