diff options
Diffstat (limited to 'drivers/video/backlight/gpio_backlight.c')
| -rw-r--r-- | drivers/video/backlight/gpio_backlight.c | 137 |
1 files changed, 45 insertions, 92 deletions
diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c index 18134416b154..728a546904b0 100644 --- a/drivers/video/backlight/gpio_backlight.c +++ b/drivers/video/backlight/gpio_backlight.c @@ -1,163 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * gpio_backlight.c - Simple GPIO-controlled backlight - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/backlight.h> #include <linux/err.h> -#include <linux/fb.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_gpio.h> #include <linux/platform_data/gpio_backlight.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/slab.h> struct gpio_backlight { struct device *dev; - struct device *fbdev; - - int gpio; - int active; - int def_value; + struct gpio_desc *gpiod; }; static int gpio_backlight_update_status(struct backlight_device *bl) { struct gpio_backlight *gbl = bl_get_data(bl); - int brightness = bl->props.brightness; - - if (bl->props.power != FB_BLANK_UNBLANK || - bl->props.fb_blank != FB_BLANK_UNBLANK || - bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) - brightness = 0; - gpio_set_value_cansleep(gbl->gpio, - brightness ? gbl->active : !gbl->active); + gpiod_set_value_cansleep(gbl->gpiod, backlight_get_brightness(bl)); return 0; } -static int gpio_backlight_check_fb(struct backlight_device *bl, - struct fb_info *info) +static bool gpio_backlight_controls_device(struct backlight_device *bl, + struct device *display_dev) { struct gpio_backlight *gbl = bl_get_data(bl); - return gbl->fbdev == NULL || gbl->fbdev == info->dev; + return !gbl->dev || gbl->dev == display_dev; } static const struct backlight_ops gpio_backlight_ops = { - .options = BL_CORE_SUSPENDRESUME, - .update_status = gpio_backlight_update_status, - .check_fb = gpio_backlight_check_fb, + .options = BL_CORE_SUSPENDRESUME, + .update_status = gpio_backlight_update_status, + .controls_device = gpio_backlight_controls_device, }; -static int gpio_backlight_probe_dt(struct platform_device *pdev, - struct gpio_backlight *gbl) -{ - struct device_node *np = pdev->dev.of_node; - enum of_gpio_flags gpio_flags; - - gbl->gpio = of_get_gpio_flags(np, 0, &gpio_flags); - - if (!gpio_is_valid(gbl->gpio)) { - if (gbl->gpio != -EPROBE_DEFER) { - dev_err(&pdev->dev, - "Error: The gpios parameter is missing or invalid.\n"); - } - return gbl->gpio; - } - - gbl->active = (gpio_flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; - - gbl->def_value = of_property_read_bool(np, "default-on"); - - return 0; -} - static int gpio_backlight_probe(struct platform_device *pdev) { - struct gpio_backlight_platform_data *pdata = - dev_get_platdata(&pdev->dev); + struct device *dev = &pdev->dev; + struct gpio_backlight_platform_data *pdata = dev_get_platdata(dev); + struct device_node *of_node = dev->of_node; struct backlight_properties props; struct backlight_device *bl; struct gpio_backlight *gbl; - struct device_node *np = pdev->dev.of_node; - unsigned long flags = GPIOF_DIR_OUT; - int ret; - - if (!pdata && !np) { - dev_err(&pdev->dev, - "failed to find platform data or device tree node.\n"); - return -ENODEV; - } + int ret, init_brightness, def_value; - gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); + gbl = devm_kzalloc(dev, sizeof(*gbl), GFP_KERNEL); if (gbl == NULL) return -ENOMEM; - gbl->dev = &pdev->dev; - - if (np) { - ret = gpio_backlight_probe_dt(pdev, gbl); - if (ret) - return ret; - } else { - gbl->fbdev = pdata->fbdev; - gbl->gpio = pdata->gpio; - gbl->active = pdata->active_low ? 0 : 1; - gbl->def_value = pdata->def_value; - } + if (pdata) + gbl->dev = pdata->dev; - if (gbl->active) - flags |= gbl->def_value ? GPIOF_INIT_HIGH : GPIOF_INIT_LOW; - else - flags |= gbl->def_value ? GPIOF_INIT_LOW : GPIOF_INIT_HIGH; + def_value = device_property_read_bool(dev, "default-on"); - ret = devm_gpio_request_one(gbl->dev, gbl->gpio, flags, - pdata ? pdata->name : "backlight"); - if (ret < 0) { - dev_err(&pdev->dev, "unable to request GPIO\n"); - return ret; - } + gbl->gpiod = devm_gpiod_get(dev, NULL, GPIOD_ASIS); + if (IS_ERR(gbl->gpiod)) + return dev_err_probe(dev, PTR_ERR(gbl->gpiod), + "The gpios parameter is missing or invalid\n"); memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; props.max_brightness = 1; - bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), - &pdev->dev, gbl, &gpio_backlight_ops, - &props); + bl = devm_backlight_device_register(dev, dev_name(dev), dev, gbl, + &gpio_backlight_ops, &props); if (IS_ERR(bl)) { - dev_err(&pdev->dev, "failed to register backlight\n"); + dev_err(dev, "failed to register backlight\n"); return PTR_ERR(bl); } - bl->props.brightness = gbl->def_value; - backlight_update_status(bl); + /* Set the initial power state */ + if (!of_node || !of_node->phandle) + /* Not booted with device tree or no phandle link to the node */ + bl->props.power = def_value ? BACKLIGHT_POWER_ON + : BACKLIGHT_POWER_OFF; + else if (gpiod_get_value_cansleep(gbl->gpiod) == 0) + bl->props.power = BACKLIGHT_POWER_OFF; + else + bl->props.power = BACKLIGHT_POWER_ON; + + bl->props.brightness = 1; + + init_brightness = backlight_get_brightness(bl); + ret = gpiod_direction_output(gbl->gpiod, init_brightness); + if (ret) { + dev_err(dev, "failed to set initial brightness\n"); + return ret; + } platform_set_drvdata(pdev, bl); return 0; } -#ifdef CONFIG_OF static struct of_device_id gpio_backlight_of_match[] = { { .compatible = "gpio-backlight" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, gpio_backlight_of_match); -#endif static struct platform_driver gpio_backlight_driver = { .driver = { .name = "gpio-backlight", - .of_match_table = of_match_ptr(gpio_backlight_of_match), + .of_match_table = gpio_backlight_of_match, }, .probe = gpio_backlight_probe, }; |
