Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

backlight: Add pcf50633 backlight driver

This patch adds a backlight driver for controlling the pcf50633 LED module.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>

authored by

Lars-Peter Clausen and committed by
Richard Purdie
2ddfd12f 1f976996

+249
+7
drivers/video/backlight/Kconfig
··· 300 300 help 301 301 Say Y to enable the backlight driver for Marvell 88PM8606. 302 302 303 + config BACKLIGHT_PCF50633 304 + tristate "Backlight driver for NXP PCF50633 MFD" 305 + depends on BACKLIGHT_CLASS_DEVICE && MFD_PCF50633 306 + help 307 + If you have a backlight driven by a NXP PCF50633 MFD, say Y here to 308 + enable its driver. 309 + 303 310 endif # BACKLIGHT_CLASS_DEVICE 304 311 305 312 endif # BACKLIGHT_LCD_SUPPORT
+1
drivers/video/backlight/Makefile
··· 34 34 obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o 35 35 obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o 36 36 obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o 37 + obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o 37 38
+190
drivers/video/backlight/pcf50633-backlight.c
··· 1 + /* 2 + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> 3 + * PCF50633 backlight device driver 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of the GNU General Public License as published by the 7 + * Free Software Foundation; either version 2 of the License, or (at your 8 + * option) any later version. 9 + * 10 + * You should have received a copy of the GNU General Public License along 11 + * with this program; if not, write to the Free Software Foundation, Inc., 12 + * 675 Mass Ave, Cambridge, MA 02139, USA. 13 + * 14 + */ 15 + 16 + #include <linux/kernel.h> 17 + #include <linux/module.h> 18 + #include <linux/slab.h> 19 + #include <linux/platform_device.h> 20 + 21 + #include <linux/backlight.h> 22 + #include <linux/fb.h> 23 + 24 + #include <linux/mfd/pcf50633/core.h> 25 + #include <linux/mfd/pcf50633/backlight.h> 26 + 27 + struct pcf50633_bl { 28 + struct pcf50633 *pcf; 29 + struct backlight_device *bl; 30 + 31 + unsigned int brightness; 32 + unsigned int brightness_limit; 33 + }; 34 + 35 + /* 36 + * pcf50633_bl_set_brightness_limit 37 + * 38 + * Update the brightness limit for the pc50633 backlight. The actual brightness 39 + * will not go above the limit. This is useful to limit power drain for example 40 + * on low battery. 41 + * 42 + * @dev: Pointer to a pcf50633 device 43 + * @limit: The brightness limit. Valid values are 0-63 44 + */ 45 + int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit) 46 + { 47 + struct pcf50633_bl *pcf_bl = platform_get_drvdata(pcf->bl_pdev); 48 + 49 + if (!pcf_bl) 50 + return -ENODEV; 51 + 52 + pcf_bl->brightness_limit = limit & 0x3f; 53 + backlight_update_status(pcf_bl->bl); 54 + 55 + return 0; 56 + } 57 + 58 + static int pcf50633_bl_update_status(struct backlight_device *bl) 59 + { 60 + struct pcf50633_bl *pcf_bl = bl_get_data(bl); 61 + unsigned int new_brightness; 62 + 63 + 64 + if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK) || 65 + bl->props.power != FB_BLANK_UNBLANK) 66 + new_brightness = 0; 67 + else if (bl->props.brightness < pcf_bl->brightness_limit) 68 + new_brightness = bl->props.brightness; 69 + else 70 + new_brightness = pcf_bl->brightness_limit; 71 + 72 + 73 + if (pcf_bl->brightness == new_brightness) 74 + return 0; 75 + 76 + if (new_brightness) { 77 + pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDOUT, 78 + new_brightness); 79 + if (!pcf_bl->brightness) 80 + pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 1); 81 + } else { 82 + pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 0); 83 + } 84 + 85 + pcf_bl->brightness = new_brightness; 86 + 87 + return 0; 88 + } 89 + 90 + static int pcf50633_bl_get_brightness(struct backlight_device *bl) 91 + { 92 + struct pcf50633_bl *pcf_bl = bl_get_data(bl); 93 + return pcf_bl->brightness; 94 + } 95 + 96 + static const struct backlight_ops pcf50633_bl_ops = { 97 + .get_brightness = pcf50633_bl_get_brightness, 98 + .update_status = pcf50633_bl_update_status, 99 + .options = BL_CORE_SUSPENDRESUME, 100 + }; 101 + 102 + static int __devinit pcf50633_bl_probe(struct platform_device *pdev) 103 + { 104 + int ret; 105 + struct pcf50633_bl *pcf_bl; 106 + struct device *parent = pdev->dev.parent; 107 + struct pcf50633_platform_data *pcf50633_data = parent->platform_data; 108 + struct pcf50633_bl_platform_data *pdata = pcf50633_data->backlight_data; 109 + struct backlight_properties bl_props; 110 + 111 + pcf_bl = kzalloc(sizeof(*pcf_bl), GFP_KERNEL); 112 + if (!pcf_bl) 113 + return -ENOMEM; 114 + 115 + bl_props.max_brightness = 0x3f; 116 + bl_props.power = FB_BLANK_UNBLANK; 117 + 118 + if (pdata) { 119 + bl_props.brightness = pdata->default_brightness; 120 + pcf_bl->brightness_limit = pdata->default_brightness_limit; 121 + } else { 122 + bl_props.brightness = 0x3f; 123 + pcf_bl->brightness_limit = 0x3f; 124 + } 125 + 126 + pcf_bl->pcf = dev_to_pcf50633(pdev->dev.parent); 127 + 128 + pcf_bl->bl = backlight_device_register(pdev->name, &pdev->dev, pcf_bl, 129 + &pcf50633_bl_ops, &bl_props); 130 + 131 + if (IS_ERR(pcf_bl->bl)) { 132 + ret = PTR_ERR(pcf_bl->bl); 133 + goto err_free; 134 + } 135 + 136 + platform_set_drvdata(pdev, pcf_bl); 137 + 138 + pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time); 139 + 140 + /* Should be different from bl_props.brightness, so we do not exit 141 + * update_status early the first time it's called */ 142 + pcf_bl->brightness = pcf_bl->bl->props.brightness + 1; 143 + 144 + backlight_update_status(pcf_bl->bl); 145 + 146 + return 0; 147 + 148 + err_free: 149 + kfree(pcf_bl); 150 + 151 + return ret; 152 + } 153 + 154 + static int __devexit pcf50633_bl_remove(struct platform_device *pdev) 155 + { 156 + struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev); 157 + 158 + backlight_device_unregister(pcf_bl->bl); 159 + 160 + platform_set_drvdata(pdev, NULL); 161 + 162 + kfree(pcf_bl); 163 + 164 + return 0; 165 + } 166 + 167 + static struct platform_driver pcf50633_bl_driver = { 168 + .probe = pcf50633_bl_probe, 169 + .remove = __devexit_p(pcf50633_bl_remove), 170 + .driver = { 171 + .name = "pcf50633-backlight", 172 + }, 173 + }; 174 + 175 + static int __init pcf50633_bl_init(void) 176 + { 177 + return platform_driver_register(&pcf50633_bl_driver); 178 + } 179 + module_init(pcf50633_bl_init); 180 + 181 + static void __exit pcf50633_bl_exit(void) 182 + { 183 + platform_driver_unregister(&pcf50633_bl_driver); 184 + } 185 + module_exit(pcf50633_bl_exit); 186 + 187 + MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 188 + MODULE_DESCRIPTION("PCF50633 backlight driver"); 189 + MODULE_LICENSE("GPL"); 190 + MODULE_ALIAS("platform:pcf50633-backlight");
+51
include/linux/mfd/pcf50633/backlight.h
··· 1 + /* 2 + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> 3 + * PCF50633 backlight device driver 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of the GNU General Public License as published by the 7 + * Free Software Foundation; either version 2 of the License, or (at your 8 + * option) any later version. 9 + * 10 + * You should have received a copy of the GNU General Public License along 11 + * with this program; if not, write to the Free Software Foundation, Inc., 12 + * 675 Mass Ave, Cambridge, MA 02139, USA. 13 + * 14 + */ 15 + 16 + #ifndef __LINUX_MFD_PCF50633_BACKLIGHT 17 + #define __LINUX_MFD_PCF50633_BACKLIGHT 18 + 19 + /* 20 + * @default_brightness: Backlight brightness is initialized to this value 21 + * 22 + * Brightness to be used after the driver has been probed. 23 + * Valid range 0-63. 24 + * 25 + * @default_brightness_limit: The actual brightness is limited by this value 26 + * 27 + * Brightness limit to be used after the driver has been probed. This is useful 28 + * when it is not known how much power is available for the backlight during 29 + * probe. 30 + * Valid range 0-63. Can be changed later with pcf50633_bl_set_brightness_limit. 31 + * 32 + * @ramp_time: Display ramp time when changing brightness 33 + * 34 + * When changing the backlights brightness the change is not instant, instead 35 + * it fades smooth from one state to another. This value specifies how long 36 + * the fade should take. The lower the value the higher the fade time. 37 + * Valid range 0-255 38 + */ 39 + struct pcf50633_bl_platform_data { 40 + unsigned int default_brightness; 41 + unsigned int default_brightness_limit; 42 + uint8_t ramp_time; 43 + }; 44 + 45 + 46 + struct pcf50633; 47 + 48 + int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit); 49 + 50 + #endif 51 +