diff options
Diffstat (limited to 'drivers/video/backlight')
| -rw-r--r-- | drivers/video/backlight/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/video/backlight/backlight.c | 42 | ||||
| -rw-r--r-- | drivers/video/backlight/gpio_backlight.c | 61 | ||||
| -rw-r--r-- | drivers/video/backlight/lm3639_bl.c | 17 | ||||
| -rw-r--r-- | drivers/video/backlight/pwm_bl.c | 87 | ||||
| -rw-r--r-- | drivers/video/backlight/s6e63m0.c | 2 |
6 files changed, 150 insertions, 67 deletions
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 5a3eb2ecb52..5d449059a55 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -29,7 +29,7 @@ if LCD_CLASS_DEVICE config LCD_CORGI tristate "LCD Panel support for SHARP corgi/spitz model" - depends on SPI_MASTER && PXA_SHARPSL + depends on SPI_MASTER && PXA_SHARPSL && BACKLIGHT_CLASS_DEVICE help Say y here to support the LCD panels usually found on SHARP corgi (C7x0) and spitz (Cxx00) models. @@ -370,7 +370,7 @@ config BACKLIGHT_AAT2870 config BACKLIGHT_LM3630A tristate "Backlight Driver for LM3630A" - depends on BACKLIGHT_CLASS_DEVICE && I2C + depends on BACKLIGHT_CLASS_DEVICE && I2C && PWM select REGMAP_I2C help This supports TI LM3630A Backlight Driver @@ -386,14 +386,14 @@ config BACKLIGHT_LM3639 config BACKLIGHT_LP855X tristate "Backlight driver for TI LP855X" - depends on BACKLIGHT_CLASS_DEVICE && I2C + depends on BACKLIGHT_CLASS_DEVICE && I2C && PWM help This supports TI LP8550, LP8551, LP8552, LP8553, LP8555, LP8556 and LP8557 backlight driver. config BACKLIGHT_LP8788 tristate "Backlight driver for TI LP8788 MFD" - depends on BACKLIGHT_CLASS_DEVICE && MFD_LP8788 + depends on BACKLIGHT_CLASS_DEVICE && MFD_LP8788 && PWM help This supports TI LP8788 backlight driver. diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 27d3cf255e7..428089009cd 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -23,6 +23,7 @@ static struct list_head backlight_dev_list; static struct mutex backlight_dev_list_mutex; +static struct blocking_notifier_head backlight_notifier; static const char *const backlight_types[] = { [BACKLIGHT_RAW] = "raw", @@ -347,7 +348,7 @@ struct backlight_device *backlight_device_register(const char *name, rc = device_register(&new_bd->dev); if (rc) { - kfree(new_bd); + put_device(&new_bd->dev); return ERR_PTR(rc); } @@ -370,6 +371,9 @@ struct backlight_device *backlight_device_register(const char *name, list_add(&new_bd->entry, &backlight_dev_list); mutex_unlock(&backlight_dev_list_mutex); + blocking_notifier_call_chain(&backlight_notifier, + BACKLIGHT_REGISTERED, new_bd); + return new_bd; } EXPORT_SYMBOL(backlight_device_register); @@ -413,6 +417,10 @@ void backlight_device_unregister(struct backlight_device *bd) pmac_backlight = NULL; mutex_unlock(&pmac_backlight_mutex); #endif + + blocking_notifier_call_chain(&backlight_notifier, + BACKLIGHT_UNREGISTERED, bd); + mutex_lock(&bd->ops_lock); bd->ops = NULL; mutex_unlock(&bd->ops_lock); @@ -438,6 +446,36 @@ static int devm_backlight_device_match(struct device *dev, void *res, } /** + * backlight_register_notifier - get notified of backlight (un)registration + * @nb: notifier block with the notifier to call on backlight (un)registration + * + * @return 0 on success, otherwise a negative error code + * + * Register a notifier to get notified when backlight devices get registered + * or unregistered. + */ +int backlight_register_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&backlight_notifier, nb); +} +EXPORT_SYMBOL(backlight_register_notifier); + +/** + * backlight_unregister_notifier - unregister a backlight notifier + * @nb: notifier block to unregister + * + * @return 0 on success, otherwise a negative error code + * + * Register a notifier to get notified when backlight devices get registered + * or unregistered. + */ +int backlight_unregister_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&backlight_notifier, nb); +} +EXPORT_SYMBOL(backlight_unregister_notifier); + +/** * devm_backlight_device_register - resource managed backlight_device_register() * @dev: the device to register * @name: the name of the device @@ -544,6 +582,8 @@ static int __init backlight_class_init(void) backlight_class->pm = &backlight_class_dev_pm_ops; INIT_LIST_HEAD(&backlight_dev_list); mutex_init(&backlight_dev_list_mutex); + BLOCKING_INIT_NOTIFIER_HEAD(&backlight_notifier); + return 0; } diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c index 81fb12770c2..1cea68848f1 100644 --- a/drivers/video/backlight/gpio_backlight.c +++ b/drivers/video/backlight/gpio_backlight.c @@ -13,6 +13,8 @@ #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/slab.h> @@ -23,6 +25,7 @@ struct gpio_backlight { int gpio; int active; + int def_value; }; static int gpio_backlight_update_status(struct backlight_device *bl) @@ -35,7 +38,8 @@ static int gpio_backlight_update_status(struct backlight_device *bl) bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) brightness = 0; - gpio_set_value(gbl->gpio, brightness ? gbl->active : !gbl->active); + gpio_set_value_cansleep(gbl->gpio, + brightness ? gbl->active : !gbl->active); return 0; } @@ -60,6 +64,29 @@ static const struct backlight_ops gpio_backlight_ops = { .check_fb = gpio_backlight_check_fb, }; +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 = @@ -67,10 +94,12 @@ static int gpio_backlight_probe(struct platform_device *pdev) struct backlight_properties props; struct backlight_device *bl; struct gpio_backlight *gbl; + struct device_node *np = pdev->dev.of_node; int ret; - if (!pdata) { - dev_err(&pdev->dev, "failed to find platform data\n"); + if (!pdata && !np) { + dev_err(&pdev->dev, + "failed to find platform data or device tree node.\n"); return -ENODEV; } @@ -79,14 +108,22 @@ static int gpio_backlight_probe(struct platform_device *pdev) return -ENOMEM; gbl->dev = &pdev->dev; - gbl->fbdev = pdata->fbdev; - gbl->gpio = pdata->gpio; - gbl->active = pdata->active_low ? 0 : 1; + + 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; + } ret = devm_gpio_request_one(gbl->dev, gbl->gpio, GPIOF_DIR_OUT | (gbl->active ? GPIOF_INIT_LOW : GPIOF_INIT_HIGH), - pdata->name); + pdata ? pdata->name : "backlight"); if (ret < 0) { dev_err(&pdev->dev, "unable to request GPIO\n"); return ret; @@ -103,17 +140,25 @@ static int gpio_backlight_probe(struct platform_device *pdev) return PTR_ERR(bl); } - bl->props.brightness = pdata->def_value; + bl->props.brightness = gbl->def_value; backlight_update_status(bl); platform_set_drvdata(pdev, bl); return 0; } +#ifdef CONFIG_OF +static struct of_device_id gpio_backlight_of_match[] = { + { .compatible = "gpio-backlight" }, + { /* sentinel */ } +}; +#endif + static struct platform_driver gpio_backlight_driver = { .driver = { .name = "gpio-backlight", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(gpio_backlight_of_match), }, .probe = gpio_backlight_probe, }; diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c index 6fd60adf922..5f36808d214 100644 --- a/drivers/video/backlight/lm3639_bl.c +++ b/drivers/video/backlight/lm3639_bl.c @@ -349,8 +349,9 @@ static int lm3639_probe(struct i2c_client *client, props.brightness = pdata->init_brt_led; props.max_brightness = pdata->max_brt_led; pchip->bled = - backlight_device_register("lm3639_bled", pchip->dev, pchip, - &lm3639_bled_ops, &props); + devm_backlight_device_register(pchip->dev, "lm3639_bled", + pchip->dev, pchip, &lm3639_bled_ops, + &props); if (IS_ERR(pchip->bled)) { dev_err(&client->dev, "fail : backlight register\n"); ret = PTR_ERR(pchip->bled); @@ -360,7 +361,7 @@ static int lm3639_probe(struct i2c_client *client, ret = device_create_file(&(pchip->bled->dev), &dev_attr_bled_mode); if (ret < 0) { dev_err(&client->dev, "failed : add sysfs entries\n"); - goto err_bled_mode; + goto err_out; } /* flash */ @@ -391,8 +392,6 @@ err_torch: led_classdev_unregister(&pchip->cdev_flash); err_flash: device_remove_file(&(pchip->bled->dev), &dev_attr_bled_mode); -err_bled_mode: - backlight_device_unregister(pchip->bled); err_out: return ret; } @@ -407,10 +406,8 @@ static int lm3639_remove(struct i2c_client *client) led_classdev_unregister(&pchip->cdev_torch); if (&pchip->cdev_flash) led_classdev_unregister(&pchip->cdev_flash); - if (pchip->bled) { + if (pchip->bled) device_remove_file(&(pchip->bled->dev), &dev_attr_bled_mode); - backlight_device_unregister(pchip->bled); - } return 0; } @@ -432,6 +429,6 @@ static struct i2c_driver lm3639_i2c_driver = { module_i2c_driver(lm3639_i2c_driver); MODULE_DESCRIPTION("Texas Instruments Backlight+Flash LED driver for LM3639"); -MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); -MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); +MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>"); +MODULE_AUTHOR("Ldd Mlp <ldd-mlp@list.ti.com>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index b75201ff46f..38ca88bc5c3 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -10,8 +10,8 @@ * published by the Free Software Foundation. */ +#include <linux/gpio/consumer.h> #include <linux/gpio.h> -#include <linux/of_gpio.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> @@ -32,8 +32,7 @@ struct pwm_bl_data { unsigned int *levels; bool enabled; struct regulator *power_supply; - int enable_gpio; - unsigned long enable_gpio_flags; + struct gpio_desc *enable_gpio; unsigned int scale; int (*notify)(struct device *, int brightness); @@ -54,12 +53,8 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb, int brightness) if (err < 0) dev_err(pb->dev, "failed to enable power supply\n"); - if (gpio_is_valid(pb->enable_gpio)) { - if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW) - gpio_set_value(pb->enable_gpio, 0); - else - gpio_set_value(pb->enable_gpio, 1); - } + if (pb->enable_gpio) + gpiod_set_value(pb->enable_gpio, 1); pwm_enable(pb->pwm); pb->enabled = true; @@ -73,12 +68,8 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb) pwm_config(pb->pwm, 0, pb->period); pwm_disable(pb->pwm); - if (gpio_is_valid(pb->enable_gpio)) { - if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW) - gpio_set_value(pb->enable_gpio, 1); - else - gpio_set_value(pb->enable_gpio, 0); - } + if (pb->enable_gpio) + gpiod_set_value(pb->enable_gpio, 0); regulator_disable(pb->power_supply); pb->enabled = false; @@ -148,7 +139,6 @@ static int pwm_backlight_parse_dt(struct device *dev, struct platform_pwm_backlight_data *data) { struct device_node *node = dev->of_node; - enum of_gpio_flags flags; struct property *prop; int length; u32 value; @@ -189,14 +179,6 @@ static int pwm_backlight_parse_dt(struct device *dev, data->max_brightness--; } - data->enable_gpio = of_get_named_gpio_flags(node, "enable-gpios", 0, - &flags); - if (data->enable_gpio == -EPROBE_DEFER) - return -EPROBE_DEFER; - - if (gpio_is_valid(data->enable_gpio) && (flags & OF_GPIO_ACTIVE_LOW)) - data->enable_gpio_flags |= PWM_BACKLIGHT_GPIO_ACTIVE_LOW; - return 0; } @@ -256,8 +238,6 @@ static int pwm_backlight_probe(struct platform_device *pdev) } else pb->scale = data->max_brightness; - pb->enable_gpio = data->enable_gpio; - pb->enable_gpio_flags = data->enable_gpio_flags; pb->notify = data->notify; pb->notify_after = data->notify_after; pb->check_fb = data->check_fb; @@ -265,26 +245,38 @@ static int pwm_backlight_probe(struct platform_device *pdev) pb->dev = &pdev->dev; pb->enabled = false; - if (gpio_is_valid(pb->enable_gpio)) { - unsigned long flags; - - if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW) - flags = GPIOF_OUT_INIT_HIGH; + pb->enable_gpio = devm_gpiod_get(&pdev->dev, "enable"); + if (IS_ERR(pb->enable_gpio)) { + ret = PTR_ERR(pb->enable_gpio); + if (ret == -ENOENT) + pb->enable_gpio = NULL; else - flags = GPIOF_OUT_INIT_LOW; + goto err_alloc; + } - ret = gpio_request_one(pb->enable_gpio, flags, "enable"); + /* + * Compatibility fallback for drivers still using the integer GPIO + * platform data. Must go away soon. + */ + if (!pb->enable_gpio && gpio_is_valid(data->enable_gpio)) { + ret = devm_gpio_request_one(&pdev->dev, data->enable_gpio, + GPIOF_OUT_INIT_HIGH, "enable"); if (ret < 0) { dev_err(&pdev->dev, "failed to request GPIO#%d: %d\n", - pb->enable_gpio, ret); + data->enable_gpio, ret); goto err_alloc; } + + pb->enable_gpio = gpio_to_desc(data->enable_gpio); } + if (pb->enable_gpio) + gpiod_direction_output(pb->enable_gpio, 1); + pb->power_supply = devm_regulator_get(&pdev->dev, "power"); if (IS_ERR(pb->power_supply)) { ret = PTR_ERR(pb->power_supply); - goto err_gpio; + goto err_alloc; } pb->pwm = devm_pwm_get(&pdev->dev, NULL); @@ -295,7 +287,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) if (IS_ERR(pb->pwm)) { dev_err(&pdev->dev, "unable to request legacy PWM\n"); ret = PTR_ERR(pb->pwm); - goto err_gpio; + goto err_alloc; } } @@ -304,12 +296,15 @@ static int pwm_backlight_probe(struct platform_device *pdev) /* * The DT case will set the pwm_period_ns field to 0 and store the * period, parsed from the DT, in the PWM device. For the non-DT case, - * set the period from platform data. + * set the period from platform data if it has not already been set + * via the PWM lookup table. */ - if (data->pwm_period_ns > 0) + pb->period = pwm_get_period(pb->pwm); + if (!pb->period && (data->pwm_period_ns > 0)) { + pb->period = data->pwm_period_ns; pwm_set_period(pb->pwm, data->pwm_period_ns); + } - pb->period = pwm_get_period(pb->pwm); pb->lth_brightness = data->lth_brightness * (pb->period / pb->scale); memset(&props, 0, sizeof(struct backlight_properties)); @@ -320,7 +315,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); ret = PTR_ERR(bl); - goto err_gpio; + goto err_alloc; } if (data->dft_brightness > data->max_brightness) { @@ -336,9 +331,6 @@ static int pwm_backlight_probe(struct platform_device *pdev) platform_set_drvdata(pdev, bl); return 0; -err_gpio: - if (gpio_is_valid(pb->enable_gpio)) - gpio_free(pb->enable_gpio); err_alloc: if (data->exit) data->exit(&pdev->dev); @@ -359,6 +351,14 @@ static int pwm_backlight_remove(struct platform_device *pdev) return 0; } +static void pwm_backlight_shutdown(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct pwm_bl_data *pb = bl_get_data(bl); + + pwm_backlight_power_off(pb); +} + #ifdef CONFIG_PM_SLEEP static int pwm_backlight_suspend(struct device *dev) { @@ -404,6 +404,7 @@ static struct platform_driver pwm_backlight_driver = { }, .probe = pwm_backlight_probe, .remove = pwm_backlight_remove, + .shutdown = pwm_backlight_shutdown, }; module_platform_driver(pwm_backlight_driver); diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c index 510a1bcf76f..2d6d48196c6 100644 --- a/drivers/video/backlight/s6e63m0.c +++ b/drivers/video/backlight/s6e63m0.c @@ -703,7 +703,7 @@ static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev, struct s6e63m0 *lcd = dev_get_drvdata(dev); char temp[3]; - sprintf(temp, "%d\n", lcd->gamma_table_count); + sprintf(temp, "%u\n", lcd->gamma_table_count); strcpy(buf, temp); return strlen(buf); |
