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

Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-backlight

* 'for-linus' of git://git.o-hand.com/linux-rpurdie-backlight:
gta02: Use pcf50633 backlight driver instead of platform backlight driver.
backlight: pcf50633: Register a pcf50633-backlight device in pcf50633 core driver.
backlight: Add pcf50633 backlight driver
backlight: 88pm860x_bl: fix error handling in pm860x_backlight_probe
backlight: max8925_bl: Fix error handling path
backlight: l4f00242t03: fix error handling in l4f00242t03_probe
backlight: add S6E63M0 AMOLED LCD Panel driver
backlight: adp8860: add support for ADP8861 & ADP8863
backlight: mbp_nvidia_bl - Fix DMI_SYS_VENDOR for MacBook1,1
backlight: Add Cirrus EP93xx backlight driver
backlight: l4f00242t03: Fix regulators handling code in remove function
backlight: fix adp8860_bl build errors
backlight: new driver for the ADP8860 backlight parts
backlight: 88pm860x_bl - potential memory leak
backlight: mbp_nvidia_bl - add support for older MacBookPro and MacBook 6,1.
backlight: Kconfig cleanup
backlight: backlight_device_register() return ERR_PTR()

+2750 -120
+9 -67
arch/arm/mach-s3c2440/mach-gta02.c
··· 49 49 #include <linux/io.h> 50 50 51 51 #include <linux/i2c.h> 52 - #include <linux/backlight.h> 53 52 #include <linux/regulator/machine.h> 54 53 55 54 #include <linux/mfd/pcf50633/core.h> ··· 56 57 #include <linux/mfd/pcf50633/adc.h> 57 58 #include <linux/mfd/pcf50633/gpio.h> 58 59 #include <linux/mfd/pcf50633/pmic.h> 60 + #include <linux/mfd/pcf50633/backlight.h> 59 61 60 62 #include <asm/mach/arch.h> 61 63 #include <asm/mach/map.h> ··· 254 254 "battery", 255 255 }; 256 256 257 + static struct pcf50633_bl_platform_data gta02_backlight_data = { 258 + .default_brightness = 0x3f, 259 + .default_brightness_limit = 0, 260 + .ramp_time = 5, 261 + }; 262 + 257 263 struct pcf50633_platform_data gta02_pcf_pdata = { 258 264 .resumers = { 259 265 [0] = PCF50633_INT1_USBINS | ··· 276 270 .num_batteries = ARRAY_SIZE(gta02_batteries), 277 271 278 272 .charger_reference_current_ma = 1000, 273 + 274 + .backlight_data = &gta02_backlight_data, 279 275 280 276 .reg_init_data = { 281 277 [PCF50633_REGULATOR_AUTO] = { ··· 486 478 487 479 }; 488 480 489 - 490 - 491 - static void gta02_bl_set_intensity(int intensity) 492 - { 493 - struct pcf50633 *pcf = gta02_pcf; 494 - int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT); 495 - 496 - /* We map 8-bit intensity to 6-bit intensity in hardware. */ 497 - intensity >>= 2; 498 - 499 - /* 500 - * This can happen during, eg, print of panic on blanked console, 501 - * but we can't service i2c without interrupts active, so abort. 502 - */ 503 - if (in_atomic()) { 504 - printk(KERN_ERR "gta02_bl_set_intensity called while atomic\n"); 505 - return; 506 - } 507 - 508 - old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT); 509 - if (intensity == old_intensity) 510 - return; 511 - 512 - /* We can't do this anywhere else. */ 513 - pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 5); 514 - 515 - if (!(pcf50633_reg_read(pcf, PCF50633_REG_LEDENA) & 3)) 516 - old_intensity = 0; 517 - 518 - /* 519 - * The PCF50633 cannot handle LEDOUT = 0 (datasheet p60) 520 - * if seen, you have to re-enable the LED unit. 521 - */ 522 - if (!intensity || !old_intensity) 523 - pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0); 524 - 525 - /* Illegal to set LEDOUT to 0. */ 526 - if (!intensity) 527 - pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, 2); 528 - else 529 - pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, 530 - intensity); 531 - 532 - if (intensity) 533 - pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 2); 534 - 535 - } 536 - 537 - static struct generic_bl_info gta02_bl_info = { 538 - .name = "gta02-bl", 539 - .max_intensity = 0xff, 540 - .default_intensity = 0xff, 541 - .set_bl_intensity = gta02_bl_set_intensity, 542 - }; 543 - 544 - static struct platform_device gta02_bl_dev = { 545 - .name = "generic-bl", 546 - .id = 1, 547 - .dev = { 548 - .platform_data = &gta02_bl_info, 549 - }, 550 - }; 551 - 552 - 553 - 554 481 /* USB */ 555 482 static struct s3c2410_hcd_info gta02_usb_info __initdata = { 556 483 .port[0] = { ··· 522 579 /* These guys DO need to be children of PMU. */ 523 580 524 581 static struct platform_device *gta02_devices_pmu_children[] = { 525 - &gta02_bl_dev, 526 582 }; 527 583 528 584
+3
drivers/mfd/pcf50633-core.c
··· 620 620 &pcf->mbc_pdev); 621 621 pcf50633_client_dev_register(pcf, "pcf50633-adc", 622 622 &pcf->adc_pdev); 623 + pcf50633_client_dev_register(pcf, "pcf50633-backlight", 624 + &pcf->bl_pdev); 625 + 623 626 624 627 for (i = 0; i < PCF50633_NUM_REGULATORS; i++) { 625 628 struct platform_device *pdev;
+2
drivers/video/backlight/88pm860x_bl.c
··· 222 222 data->port = __check_device(pdata, name); 223 223 if (data->port < 0) { 224 224 dev_err(&pdev->dev, "wrong platform data is assigned"); 225 + kfree(data); 225 226 return -EINVAL; 226 227 } 227 228 ··· 267 266 backlight_update_status(bl); 268 267 return 0; 269 268 out: 269 + backlight_device_unregister(bl); 270 270 kfree(data); 271 271 return ret; 272 272 }
+72 -44
drivers/video/backlight/Kconfig
··· 8 8 Enable this to be able to choose the drivers for controlling the 9 9 backlight and the LCD panel on some platforms, for example on PDAs. 10 10 11 + if BACKLIGHT_LCD_SUPPORT 12 + 11 13 # 12 14 # LCD 13 15 # 14 16 config LCD_CLASS_DEVICE 15 17 tristate "Lowlevel LCD controls" 16 - depends on BACKLIGHT_LCD_SUPPORT 17 18 default m 18 19 help 19 20 This framework adds support for low-level control of LCD. ··· 25 24 To have support for your specific LCD panel you will have to 26 25 select the proper drivers which depend on this option. 27 26 27 + if LCD_CLASS_DEVICE 28 + 28 29 config LCD_CORGI 29 30 tristate "LCD Panel support for SHARP corgi/spitz model" 30 - depends on LCD_CLASS_DEVICE && SPI_MASTER && PXA_SHARPSL 31 + depends on SPI_MASTER && PXA_SHARPSL 31 32 help 32 33 Say y here to support the LCD panels usually found on SHARP 33 34 corgi (C7x0) and spitz (Cxx00) models. 34 35 35 36 config LCD_L4F00242T03 36 37 tristate "Epson L4F00242T03 LCD" 37 - depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO 38 + depends on SPI_MASTER && GENERIC_GPIO 38 39 help 39 40 SPI driver for Epson L4F00242T03. This provides basic support 40 41 for init and powering the LCD up/down through a sysfs interface. 41 42 42 43 config LCD_LMS283GF05 43 44 tristate "Samsung LMS283GF05 LCD" 44 - depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO 45 + depends on SPI_MASTER && GENERIC_GPIO 45 46 help 46 47 SPI driver for Samsung LMS283GF05. This provides basic support 47 48 for powering the LCD up/down through a sysfs interface. 48 49 49 50 config LCD_LTV350QV 50 51 tristate "Samsung LTV350QV LCD Panel" 51 - depends on LCD_CLASS_DEVICE && SPI_MASTER 52 - default n 52 + depends on SPI_MASTER 53 53 help 54 54 If you have a Samsung LTV350QV LCD panel, say y to include a 55 55 power control driver for it. The panel starts up in power ··· 61 59 62 60 config LCD_ILI9320 63 61 tristate 64 - depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT 65 - default n 66 62 help 67 63 If you have a panel based on the ILI9320 controller chip 68 64 then say y to include a power driver for it. 69 65 70 66 config LCD_TDO24M 71 67 tristate "Toppoly TDO24M and TDO35S LCD Panels support" 72 - depends on LCD_CLASS_DEVICE && SPI_MASTER 73 - default n 68 + depends on SPI_MASTER 74 69 help 75 70 If you have a Toppoly TDO24M/TDO35S series LCD panel, say y here to 76 71 include the support for it. 77 72 78 73 config LCD_VGG2432A4 79 74 tristate "VGG2432A4 LCM device support" 80 - depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER 75 + depends on SPI_MASTER 81 76 select LCD_ILI9320 82 - default n 83 77 help 84 78 If you have a VGG2432A4 panel based on the ILI9320 controller chip 85 79 then say y to include a power driver for it. 86 80 87 81 config LCD_PLATFORM 88 82 tristate "Platform LCD controls" 89 - depends on LCD_CLASS_DEVICE 90 83 help 91 84 This driver provides a platform-device registered LCD power 92 85 control interface. 93 86 94 87 config LCD_TOSA 95 88 tristate "Sharp SL-6000 LCD Driver" 96 - depends on LCD_CLASS_DEVICE && SPI 97 - depends on MACH_TOSA 98 - default n 89 + depends on SPI && MACH_TOSA 99 90 help 100 91 If you have an Sharp SL-6000 Zaurus say Y to enable a driver 101 92 for its LCD. 102 93 103 94 config LCD_HP700 104 95 tristate "HP Jornada 700 series LCD Driver" 105 - depends on LCD_CLASS_DEVICE 106 96 depends on SA1100_JORNADA720_SSP && !PREEMPT 107 97 default y 108 98 help 109 99 If you have an HP Jornada 700 series handheld (710/720/728) 110 100 say Y to enable LCD control driver. 111 101 102 + config LCD_S6E63M0 103 + tristate "S6E63M0 AMOLED LCD Driver" 104 + depends on SPI && BACKLIGHT_CLASS_DEVICE 105 + default n 106 + help 107 + If you have an S6E63M0 LCD Panel, say Y to enable its 108 + LCD control driver. 109 + 110 + endif # LCD_CLASS_DEVICE 111 + 112 112 # 113 113 # Backlight 114 114 # 115 115 config BACKLIGHT_CLASS_DEVICE 116 116 tristate "Lowlevel Backlight controls" 117 - depends on BACKLIGHT_LCD_SUPPORT 118 117 default m 119 118 help 120 119 This framework adds support for low-level control of the LCD ··· 124 121 To have support for your specific LCD panel you will have to 125 122 select the proper drivers which depend on this option. 126 123 124 + if BACKLIGHT_CLASS_DEVICE 125 + 127 126 config BACKLIGHT_ATMEL_LCDC 128 127 bool "Atmel LCDC Contrast-as-Backlight control" 129 - depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL 128 + depends on FB_ATMEL 130 129 default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK 131 130 help 132 131 This provides a backlight control internal to the Atmel LCDC ··· 141 136 142 137 config BACKLIGHT_ATMEL_PWM 143 138 tristate "Atmel PWM backlight control" 144 - depends on BACKLIGHT_CLASS_DEVICE && ATMEL_PWM 145 - default n 139 + depends on ATMEL_PWM 146 140 help 147 141 Say Y here if you want to use the PWM peripheral in Atmel AT91 and 148 142 AVR32 devices. This driver will need additional platform data to know ··· 150 146 To compile this driver as a module, choose M here: the module will be 151 147 called atmel-pwm-bl. 152 148 149 + config BACKLIGHT_EP93XX 150 + tristate "Cirrus EP93xx Backlight Driver" 151 + depends on FB_EP93XX 152 + help 153 + If you have a LCD backlight connected to the BRIGHT output of 154 + the EP93xx, say Y here to enable this driver. 155 + 156 + To compile this driver as a module, choose M here: the module will 157 + be called ep93xx_bl. 158 + 153 159 config BACKLIGHT_GENERIC 154 160 tristate "Generic (aka Sharp Corgi) Backlight Driver" 155 - depends on BACKLIGHT_CLASS_DEVICE 156 161 default y 157 162 help 158 163 Say y to enable the generic platform backlight driver previously ··· 170 157 171 158 config BACKLIGHT_LOCOMO 172 159 tristate "Sharp LOCOMO LCD/Backlight Driver" 173 - depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO 160 + depends on SHARP_LOCOMO 174 161 default y 175 162 help 176 163 If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to ··· 178 165 179 166 config BACKLIGHT_OMAP1 180 167 tristate "OMAP1 PWL-based LCD Backlight" 181 - depends on BACKLIGHT_CLASS_DEVICE && ARCH_OMAP1 168 + depends on ARCH_OMAP1 182 169 default y 183 170 help 184 171 This driver controls the LCD backlight level and power for ··· 187 174 188 175 config BACKLIGHT_HP680 189 176 tristate "HP Jornada 680 Backlight Driver" 190 - depends on BACKLIGHT_CLASS_DEVICE && SH_HP6XX 177 + depends on SH_HP6XX 191 178 default y 192 179 help 193 180 If you have a HP Jornada 680, say y to enable the ··· 195 182 196 183 config BACKLIGHT_HP700 197 184 tristate "HP Jornada 700 series Backlight Driver" 198 - depends on BACKLIGHT_CLASS_DEVICE 199 185 depends on SA1100_JORNADA720_SSP && !PREEMPT 200 186 default y 201 187 help ··· 203 191 204 192 config BACKLIGHT_PROGEAR 205 193 tristate "Frontpath ProGear Backlight Driver" 206 - depends on BACKLIGHT_CLASS_DEVICE && PCI && X86 207 - default n 194 + depends on PCI && X86 208 195 help 209 196 If you have a Frontpath ProGear say Y to enable the 210 197 backlight driver. 211 198 212 199 config BACKLIGHT_CARILLO_RANCH 213 200 tristate "Intel Carillo Ranch Backlight Driver" 214 - depends on BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 215 - default n 201 + depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 216 202 help 217 203 If you have a Intel LE80578 (Carillo Ranch) say Y to enable the 218 204 backlight driver. 219 205 220 206 config BACKLIGHT_PWM 221 207 tristate "Generic PWM based Backlight Driver" 222 - depends on BACKLIGHT_CLASS_DEVICE && HAVE_PWM 208 + depends on HAVE_PWM 223 209 help 224 210 If you have a LCD backlight adjustable by PWM, say Y to enable 225 211 this driver. 226 212 227 213 config BACKLIGHT_DA903X 228 214 tristate "Backlight Driver for DA9030/DA9034 using WLED" 229 - depends on BACKLIGHT_CLASS_DEVICE && PMIC_DA903X 215 + depends on PMIC_DA903X 230 216 help 231 217 If you have a LCD backlight connected to the WLED output of DA9030 232 218 or DA9034 WLED output, say Y here to enable this driver. 233 219 234 220 config BACKLIGHT_MAX8925 235 221 tristate "Backlight driver for MAX8925" 236 - depends on BACKLIGHT_CLASS_DEVICE && MFD_MAX8925 222 + depends on MFD_MAX8925 237 223 help 238 224 If you have a LCD backlight connected to the WLED output of MAX8925 239 225 WLED output, say Y here to enable this driver. 240 226 241 227 config BACKLIGHT_MBP_NVIDIA 242 228 tristate "MacBook Pro Nvidia Backlight Driver" 243 - depends on BACKLIGHT_CLASS_DEVICE && X86 244 - default n 229 + depends on X86 245 230 help 246 231 If you have an Apple Macbook Pro with Nvidia graphics hardware say Y 247 232 to enable a driver for its backlight 248 233 249 234 config BACKLIGHT_TOSA 250 235 tristate "Sharp SL-6000 Backlight Driver" 251 - depends on BACKLIGHT_CLASS_DEVICE && I2C 252 - depends on MACH_TOSA && LCD_TOSA 253 - default n 236 + depends on I2C && MACH_TOSA && LCD_TOSA 254 237 help 255 238 If you have an Sharp SL-6000 Zaurus say Y to enable a driver 256 239 for its backlight 257 240 258 241 config BACKLIGHT_SAHARA 259 242 tristate "Tabletkiosk Sahara Touch-iT Backlight Driver" 260 - depends on BACKLIGHT_CLASS_DEVICE && X86 261 - default n 243 + depends on X86 262 244 help 263 245 If you have a Tabletkiosk Sahara Touch-iT, say y to enable the 264 246 backlight driver. 265 247 266 248 config BACKLIGHT_WM831X 267 249 tristate "WM831x PMIC Backlight Driver" 268 - depends on BACKLIGHT_CLASS_DEVICE && MFD_WM831X 250 + depends on MFD_WM831X 269 251 help 270 252 If you have a backlight driven by the ISINK and DCDC of a 271 253 WM831x PMIC say y to enable the backlight driver for it. 272 254 273 255 config BACKLIGHT_ADX 274 256 tristate "Avionic Design Xanthos Backlight Driver" 275 - depends on BACKLIGHT_CLASS_DEVICE && ARCH_PXA_ADX 257 + depends on ARCH_PXA_ADX 276 258 default y 277 259 help 278 260 Say Y to enable the backlight driver on Avionic Design Xanthos-based ··· 274 268 275 269 config BACKLIGHT_ADP5520 276 270 tristate "Backlight Driver for ADP5520/ADP5501 using WLED" 277 - depends on BACKLIGHT_CLASS_DEVICE && PMIC_ADP5520 271 + depends on PMIC_ADP5520 278 272 help 279 273 If you have a LCD backlight connected to the BST/BL_SNK output of 280 274 ADP5520 or ADP5501, say Y here to enable this driver. ··· 282 276 To compile this driver as a module, choose M here: the module will 283 277 be called adp5520_bl. 284 278 279 + config BACKLIGHT_ADP8860 280 + tristate "Backlight Driver for ADP8860/ADP8861/ADP8863 using WLED" 281 + depends on BACKLIGHT_CLASS_DEVICE && I2C 282 + select NEW_LEDS 283 + select LEDS_CLASS 284 + help 285 + If you have a LCD backlight connected to the ADP8860, ADP8861 or 286 + ADP8863 say Y here to enable this driver. 287 + 288 + To compile this driver as a module, choose M here: the module will 289 + be called adp8860_bl. 290 + 285 291 config BACKLIGHT_88PM860X 286 292 tristate "Backlight Driver for 88PM8606 using WLED" 287 - depends on BACKLIGHT_CLASS_DEVICE && MFD_88PM860X 293 + depends on MFD_88PM860X 288 294 help 289 295 Say Y to enable the backlight driver for Marvell 88PM8606. 290 296 297 + config BACKLIGHT_PCF50633 298 + tristate "Backlight driver for NXP PCF50633 MFD" 299 + depends on BACKLIGHT_CLASS_DEVICE && MFD_PCF50633 300 + help 301 + If you have a backlight driven by a NXP PCF50633 MFD, say Y here to 302 + enable its driver. 303 + 304 + endif # BACKLIGHT_CLASS_DEVICE 305 + 306 + endif # BACKLIGHT_LCD_SUPPORT
+4
drivers/video/backlight/Makefile
··· 11 11 obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o 12 12 obj-$(CONFIG_LCD_TDO24M) += tdo24m.o 13 13 obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o 14 + obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o 14 15 15 16 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o 16 17 obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o 18 + obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o 17 19 obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o 18 20 obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o 19 21 obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o ··· 32 30 obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o 33 31 obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o 34 32 obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o 33 + obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o 35 34 obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o 35 + obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o 36 36
+838
drivers/video/backlight/adp8860_bl.c
··· 1 + /* 2 + * Backlight driver for Analog Devices ADP8860 Backlight Devices 3 + * 4 + * Copyright 2009-2010 Analog Devices Inc. 5 + * 6 + * Licensed under the GPL-2 or later. 7 + */ 8 + 9 + #include <linux/module.h> 10 + #include <linux/version.h> 11 + #include <linux/init.h> 12 + #include <linux/errno.h> 13 + #include <linux/pm.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/i2c.h> 16 + #include <linux/fb.h> 17 + #include <linux/backlight.h> 18 + #include <linux/leds.h> 19 + #include <linux/slab.h> 20 + #include <linux/workqueue.h> 21 + 22 + #include <linux/i2c/adp8860.h> 23 + #define ADP8860_EXT_FEATURES 24 + #define ADP8860_USE_LEDS 25 + 26 + #define ADP8860_MFDVID 0x00 /* Manufacturer and device ID */ 27 + #define ADP8860_MDCR 0x01 /* Device mode and status */ 28 + #define ADP8860_MDCR2 0x02 /* Device mode and Status Register 2 */ 29 + #define ADP8860_INTR_EN 0x03 /* Interrupts enable */ 30 + #define ADP8860_CFGR 0x04 /* Configuration register */ 31 + #define ADP8860_BLSEN 0x05 /* Sink enable backlight or independent */ 32 + #define ADP8860_BLOFF 0x06 /* Backlight off timeout */ 33 + #define ADP8860_BLDIM 0x07 /* Backlight dim timeout */ 34 + #define ADP8860_BLFR 0x08 /* Backlight fade in and out rates */ 35 + #define ADP8860_BLMX1 0x09 /* Backlight (Brightness Level 1-daylight) maximum current */ 36 + #define ADP8860_BLDM1 0x0A /* Backlight (Brightness Level 1-daylight) dim current */ 37 + #define ADP8860_BLMX2 0x0B /* Backlight (Brightness Level 2-office) maximum current */ 38 + #define ADP8860_BLDM2 0x0C /* Backlight (Brightness Level 2-office) dim current */ 39 + #define ADP8860_BLMX3 0x0D /* Backlight (Brightness Level 3-dark) maximum current */ 40 + #define ADP8860_BLDM3 0x0E /* Backlight (Brightness Level 3-dark) dim current */ 41 + #define ADP8860_ISCFR 0x0F /* Independent sink current fade control register */ 42 + #define ADP8860_ISCC 0x10 /* Independent sink current control register */ 43 + #define ADP8860_ISCT1 0x11 /* Independent Sink Current Timer Register LED[7:5] */ 44 + #define ADP8860_ISCT2 0x12 /* Independent Sink Current Timer Register LED[4:1] */ 45 + #define ADP8860_ISCF 0x13 /* Independent sink current fade register */ 46 + #define ADP8860_ISC7 0x14 /* Independent Sink Current LED7 */ 47 + #define ADP8860_ISC6 0x15 /* Independent Sink Current LED6 */ 48 + #define ADP8860_ISC5 0x16 /* Independent Sink Current LED5 */ 49 + #define ADP8860_ISC4 0x17 /* Independent Sink Current LED4 */ 50 + #define ADP8860_ISC3 0x18 /* Independent Sink Current LED3 */ 51 + #define ADP8860_ISC2 0x19 /* Independent Sink Current LED2 */ 52 + #define ADP8860_ISC1 0x1A /* Independent Sink Current LED1 */ 53 + #define ADP8860_CCFG 0x1B /* Comparator configuration */ 54 + #define ADP8860_CCFG2 0x1C /* Second comparator configuration */ 55 + #define ADP8860_L2_TRP 0x1D /* L2 comparator reference */ 56 + #define ADP8860_L2_HYS 0x1E /* L2 hysteresis */ 57 + #define ADP8860_L3_TRP 0x1F /* L3 comparator reference */ 58 + #define ADP8860_L3_HYS 0x20 /* L3 hysteresis */ 59 + #define ADP8860_PH1LEVL 0x21 /* First phototransistor ambient light level-low byte register */ 60 + #define ADP8860_PH1LEVH 0x22 /* First phototransistor ambient light level-high byte register */ 61 + #define ADP8860_PH2LEVL 0x23 /* Second phototransistor ambient light level-low byte register */ 62 + #define ADP8860_PH2LEVH 0x24 /* Second phototransistor ambient light level-high byte register */ 63 + 64 + #define ADP8860_MANUFID 0x0 /* Analog Devices ADP8860 Manufacturer ID */ 65 + #define ADP8861_MANUFID 0x4 /* Analog Devices ADP8861 Manufacturer ID */ 66 + #define ADP8863_MANUFID 0x2 /* Analog Devices ADP8863 Manufacturer ID */ 67 + 68 + #define ADP8860_DEVID(x) ((x) & 0xF) 69 + #define ADP8860_MANID(x) ((x) >> 4) 70 + 71 + /* MDCR Device mode and status */ 72 + #define INT_CFG (1 << 6) 73 + #define NSTBY (1 << 5) 74 + #define DIM_EN (1 << 4) 75 + #define GDWN_DIS (1 << 3) 76 + #define SIS_EN (1 << 2) 77 + #define CMP_AUTOEN (1 << 1) 78 + #define BLEN (1 << 0) 79 + 80 + /* ADP8860_CCFG Main ALS comparator level enable */ 81 + #define L3_EN (1 << 1) 82 + #define L2_EN (1 << 0) 83 + 84 + #define CFGR_BLV_SHIFT 3 85 + #define CFGR_BLV_MASK 0x3 86 + #define ADP8860_FLAG_LED_MASK 0xFF 87 + 88 + #define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4)) 89 + #define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1)) 90 + #define ALS_CCFG_VAL(filt) ((0x7 & filt) << 5) 91 + 92 + enum { 93 + adp8860, 94 + adp8861, 95 + adp8863 96 + }; 97 + 98 + struct adp8860_led { 99 + struct led_classdev cdev; 100 + struct work_struct work; 101 + struct i2c_client *client; 102 + enum led_brightness new_brightness; 103 + int id; 104 + int flags; 105 + }; 106 + 107 + struct adp8860_bl { 108 + struct i2c_client *client; 109 + struct backlight_device *bl; 110 + struct adp8860_led *led; 111 + struct adp8860_backlight_platform_data *pdata; 112 + struct mutex lock; 113 + unsigned long cached_daylight_max; 114 + int id; 115 + int revid; 116 + int current_brightness; 117 + unsigned en_ambl_sens:1; 118 + unsigned gdwn_dis:1; 119 + }; 120 + 121 + static int adp8860_read(struct i2c_client *client, int reg, uint8_t *val) 122 + { 123 + int ret; 124 + 125 + ret = i2c_smbus_read_byte_data(client, reg); 126 + if (ret < 0) { 127 + dev_err(&client->dev, "failed reading at 0x%02x\n", reg); 128 + return ret; 129 + } 130 + 131 + *val = (uint8_t)ret; 132 + return 0; 133 + } 134 + 135 + static int adp8860_write(struct i2c_client *client, u8 reg, u8 val) 136 + { 137 + return i2c_smbus_write_byte_data(client, reg, val); 138 + } 139 + 140 + static int adp8860_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask) 141 + { 142 + struct adp8860_bl *data = i2c_get_clientdata(client); 143 + uint8_t reg_val; 144 + int ret; 145 + 146 + mutex_lock(&data->lock); 147 + 148 + ret = adp8860_read(client, reg, &reg_val); 149 + 150 + if (!ret && ((reg_val & bit_mask) == 0)) { 151 + reg_val |= bit_mask; 152 + ret = adp8860_write(client, reg, reg_val); 153 + } 154 + 155 + mutex_unlock(&data->lock); 156 + return ret; 157 + } 158 + 159 + static int adp8860_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask) 160 + { 161 + struct adp8860_bl *data = i2c_get_clientdata(client); 162 + uint8_t reg_val; 163 + int ret; 164 + 165 + mutex_lock(&data->lock); 166 + 167 + ret = adp8860_read(client, reg, &reg_val); 168 + 169 + if (!ret && (reg_val & bit_mask)) { 170 + reg_val &= ~bit_mask; 171 + ret = adp8860_write(client, reg, reg_val); 172 + } 173 + 174 + mutex_unlock(&data->lock); 175 + return ret; 176 + } 177 + 178 + /* 179 + * Independent sink / LED 180 + */ 181 + #if defined(ADP8860_USE_LEDS) 182 + static void adp8860_led_work(struct work_struct *work) 183 + { 184 + struct adp8860_led *led = container_of(work, struct adp8860_led, work); 185 + adp8860_write(led->client, ADP8860_ISC1 - led->id + 1, 186 + led->new_brightness >> 1); 187 + } 188 + 189 + static void adp8860_led_set(struct led_classdev *led_cdev, 190 + enum led_brightness value) 191 + { 192 + struct adp8860_led *led; 193 + 194 + led = container_of(led_cdev, struct adp8860_led, cdev); 195 + led->new_brightness = value; 196 + schedule_work(&led->work); 197 + } 198 + 199 + static int adp8860_led_setup(struct adp8860_led *led) 200 + { 201 + struct i2c_client *client = led->client; 202 + int ret = 0; 203 + 204 + ret = adp8860_write(client, ADP8860_ISC1 - led->id + 1, 0); 205 + ret |= adp8860_set_bits(client, ADP8860_ISCC, 1 << (led->id - 1)); 206 + 207 + if (led->id > 4) 208 + ret |= adp8860_set_bits(client, ADP8860_ISCT1, 209 + (led->flags & 0x3) << ((led->id - 5) * 2)); 210 + else 211 + ret |= adp8860_set_bits(client, ADP8860_ISCT2, 212 + (led->flags & 0x3) << ((led->id - 1) * 2)); 213 + 214 + return ret; 215 + } 216 + 217 + static int __devinit adp8860_led_probe(struct i2c_client *client) 218 + { 219 + struct adp8860_backlight_platform_data *pdata = 220 + client->dev.platform_data; 221 + struct adp8860_bl *data = i2c_get_clientdata(client); 222 + struct adp8860_led *led, *led_dat; 223 + struct led_info *cur_led; 224 + int ret, i; 225 + 226 + led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL); 227 + if (led == NULL) { 228 + dev_err(&client->dev, "failed to alloc memory\n"); 229 + return -ENOMEM; 230 + } 231 + 232 + ret = adp8860_write(client, ADP8860_ISCFR, pdata->led_fade_law); 233 + ret = adp8860_write(client, ADP8860_ISCT1, 234 + (pdata->led_on_time & 0x3) << 6); 235 + ret |= adp8860_write(client, ADP8860_ISCF, 236 + FADE_VAL(pdata->led_fade_in, pdata->led_fade_out)); 237 + 238 + if (ret) { 239 + dev_err(&client->dev, "failed to write\n"); 240 + goto err_free; 241 + } 242 + 243 + for (i = 0; i < pdata->num_leds; ++i) { 244 + cur_led = &pdata->leds[i]; 245 + led_dat = &led[i]; 246 + 247 + led_dat->id = cur_led->flags & ADP8860_FLAG_LED_MASK; 248 + 249 + if (led_dat->id > 7 || led_dat->id < 1) { 250 + dev_err(&client->dev, "Invalid LED ID %d\n", 251 + led_dat->id); 252 + goto err; 253 + } 254 + 255 + if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) { 256 + dev_err(&client->dev, "LED %d used by Backlight\n", 257 + led_dat->id); 258 + goto err; 259 + } 260 + 261 + led_dat->cdev.name = cur_led->name; 262 + led_dat->cdev.default_trigger = cur_led->default_trigger; 263 + led_dat->cdev.brightness_set = adp8860_led_set; 264 + led_dat->cdev.brightness = LED_OFF; 265 + led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT; 266 + led_dat->client = client; 267 + led_dat->new_brightness = LED_OFF; 268 + INIT_WORK(&led_dat->work, adp8860_led_work); 269 + 270 + ret = led_classdev_register(&client->dev, &led_dat->cdev); 271 + if (ret) { 272 + dev_err(&client->dev, "failed to register LED %d\n", 273 + led_dat->id); 274 + goto err; 275 + } 276 + 277 + ret = adp8860_led_setup(led_dat); 278 + if (ret) { 279 + dev_err(&client->dev, "failed to write\n"); 280 + i++; 281 + goto err; 282 + } 283 + } 284 + 285 + data->led = led; 286 + 287 + return 0; 288 + 289 + err: 290 + for (i = i - 1; i >= 0; --i) { 291 + led_classdev_unregister(&led[i].cdev); 292 + cancel_work_sync(&led[i].work); 293 + } 294 + 295 + err_free: 296 + kfree(led); 297 + 298 + return ret; 299 + } 300 + 301 + static int __devexit adp8860_led_remove(struct i2c_client *client) 302 + { 303 + struct adp8860_backlight_platform_data *pdata = 304 + client->dev.platform_data; 305 + struct adp8860_bl *data = i2c_get_clientdata(client); 306 + int i; 307 + 308 + for (i = 0; i < pdata->num_leds; i++) { 309 + led_classdev_unregister(&data->led[i].cdev); 310 + cancel_work_sync(&data->led[i].work); 311 + } 312 + 313 + kfree(data->led); 314 + return 0; 315 + } 316 + #else 317 + static int __devinit adp8860_led_probe(struct i2c_client *client) 318 + { 319 + return 0; 320 + } 321 + 322 + static int __devexit adp8860_led_remove(struct i2c_client *client) 323 + { 324 + return 0; 325 + } 326 + #endif 327 + 328 + static int adp8860_bl_set(struct backlight_device *bl, int brightness) 329 + { 330 + struct adp8860_bl *data = bl_get_data(bl); 331 + struct i2c_client *client = data->client; 332 + int ret = 0; 333 + 334 + if (data->en_ambl_sens) { 335 + if ((brightness > 0) && (brightness < ADP8860_MAX_BRIGHTNESS)) { 336 + /* Disable Ambient Light auto adjust */ 337 + ret |= adp8860_clr_bits(client, ADP8860_MDCR, 338 + CMP_AUTOEN); 339 + ret |= adp8860_write(client, ADP8860_BLMX1, brightness); 340 + } else { 341 + /* 342 + * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust 343 + * restore daylight l1 sysfs brightness 344 + */ 345 + ret |= adp8860_write(client, ADP8860_BLMX1, 346 + data->cached_daylight_max); 347 + ret |= adp8860_set_bits(client, ADP8860_MDCR, 348 + CMP_AUTOEN); 349 + } 350 + } else 351 + ret |= adp8860_write(client, ADP8860_BLMX1, brightness); 352 + 353 + if (data->current_brightness && brightness == 0) 354 + ret |= adp8860_set_bits(client, 355 + ADP8860_MDCR, DIM_EN); 356 + else if (data->current_brightness == 0 && brightness) 357 + ret |= adp8860_clr_bits(client, 358 + ADP8860_MDCR, DIM_EN); 359 + 360 + if (!ret) 361 + data->current_brightness = brightness; 362 + 363 + return ret; 364 + } 365 + 366 + static int adp8860_bl_update_status(struct backlight_device *bl) 367 + { 368 + int brightness = bl->props.brightness; 369 + if (bl->props.power != FB_BLANK_UNBLANK) 370 + brightness = 0; 371 + 372 + if (bl->props.fb_blank != FB_BLANK_UNBLANK) 373 + brightness = 0; 374 + 375 + return adp8860_bl_set(bl, brightness); 376 + } 377 + 378 + static int adp8860_bl_get_brightness(struct backlight_device *bl) 379 + { 380 + struct adp8860_bl *data = bl_get_data(bl); 381 + 382 + return data->current_brightness; 383 + } 384 + 385 + static const struct backlight_ops adp8860_bl_ops = { 386 + .update_status = adp8860_bl_update_status, 387 + .get_brightness = adp8860_bl_get_brightness, 388 + }; 389 + 390 + static int adp8860_bl_setup(struct backlight_device *bl) 391 + { 392 + struct adp8860_bl *data = bl_get_data(bl); 393 + struct i2c_client *client = data->client; 394 + struct adp8860_backlight_platform_data *pdata = data->pdata; 395 + int ret = 0; 396 + 397 + ret |= adp8860_write(client, ADP8860_BLSEN, ~pdata->bl_led_assign); 398 + ret |= adp8860_write(client, ADP8860_BLMX1, pdata->l1_daylight_max); 399 + ret |= adp8860_write(client, ADP8860_BLDM1, pdata->l1_daylight_dim); 400 + 401 + if (data->en_ambl_sens) { 402 + data->cached_daylight_max = pdata->l1_daylight_max; 403 + ret |= adp8860_write(client, ADP8860_BLMX2, 404 + pdata->l2_office_max); 405 + ret |= adp8860_write(client, ADP8860_BLDM2, 406 + pdata->l2_office_dim); 407 + ret |= adp8860_write(client, ADP8860_BLMX3, 408 + pdata->l3_dark_max); 409 + ret |= adp8860_write(client, ADP8860_BLDM3, 410 + pdata->l3_dark_dim); 411 + 412 + ret |= adp8860_write(client, ADP8860_L2_TRP, pdata->l2_trip); 413 + ret |= adp8860_write(client, ADP8860_L2_HYS, pdata->l2_hyst); 414 + ret |= adp8860_write(client, ADP8860_L3_TRP, pdata->l3_trip); 415 + ret |= adp8860_write(client, ADP8860_L3_HYS, pdata->l3_hyst); 416 + ret |= adp8860_write(client, ADP8860_CCFG, L2_EN | L3_EN | 417 + ALS_CCFG_VAL(pdata->abml_filt)); 418 + } 419 + 420 + ret |= adp8860_write(client, ADP8860_CFGR, 421 + BL_CFGR_VAL(pdata->bl_fade_law, 0)); 422 + 423 + ret |= adp8860_write(client, ADP8860_BLFR, FADE_VAL(pdata->bl_fade_in, 424 + pdata->bl_fade_out)); 425 + 426 + ret |= adp8860_set_bits(client, ADP8860_MDCR, BLEN | DIM_EN | NSTBY | 427 + (data->gdwn_dis ? GDWN_DIS : 0)); 428 + 429 + return ret; 430 + } 431 + 432 + static ssize_t adp8860_show(struct device *dev, char *buf, int reg) 433 + { 434 + struct adp8860_bl *data = dev_get_drvdata(dev); 435 + int error; 436 + uint8_t reg_val; 437 + 438 + mutex_lock(&data->lock); 439 + error = adp8860_read(data->client, reg, &reg_val); 440 + mutex_unlock(&data->lock); 441 + 442 + if (error < 0) 443 + return error; 444 + 445 + return sprintf(buf, "%u\n", reg_val); 446 + } 447 + 448 + static ssize_t adp8860_store(struct device *dev, const char *buf, 449 + size_t count, int reg) 450 + { 451 + struct adp8860_bl *data = dev_get_drvdata(dev); 452 + unsigned long val; 453 + int ret; 454 + 455 + ret = strict_strtoul(buf, 10, &val); 456 + if (ret) 457 + return ret; 458 + 459 + mutex_lock(&data->lock); 460 + adp8860_write(data->client, reg, val); 461 + mutex_unlock(&data->lock); 462 + 463 + return count; 464 + } 465 + 466 + static ssize_t adp8860_bl_l3_dark_max_show(struct device *dev, 467 + struct device_attribute *attr, char *buf) 468 + { 469 + return adp8860_show(dev, buf, ADP8860_BLMX3); 470 + } 471 + 472 + static ssize_t adp8860_bl_l3_dark_max_store(struct device *dev, 473 + struct device_attribute *attr, const char *buf, size_t count) 474 + { 475 + return adp8860_store(dev, buf, count, ADP8860_BLMX3); 476 + } 477 + 478 + static DEVICE_ATTR(l3_dark_max, 0664, adp8860_bl_l3_dark_max_show, 479 + adp8860_bl_l3_dark_max_store); 480 + 481 + static ssize_t adp8860_bl_l2_office_max_show(struct device *dev, 482 + struct device_attribute *attr, char *buf) 483 + { 484 + return adp8860_show(dev, buf, ADP8860_BLMX2); 485 + } 486 + 487 + static ssize_t adp8860_bl_l2_office_max_store(struct device *dev, 488 + struct device_attribute *attr, const char *buf, size_t count) 489 + { 490 + return adp8860_store(dev, buf, count, ADP8860_BLMX2); 491 + } 492 + static DEVICE_ATTR(l2_office_max, 0664, adp8860_bl_l2_office_max_show, 493 + adp8860_bl_l2_office_max_store); 494 + 495 + static ssize_t adp8860_bl_l1_daylight_max_show(struct device *dev, 496 + struct device_attribute *attr, char *buf) 497 + { 498 + return adp8860_show(dev, buf, ADP8860_BLMX1); 499 + } 500 + 501 + static ssize_t adp8860_bl_l1_daylight_max_store(struct device *dev, 502 + struct device_attribute *attr, const char *buf, size_t count) 503 + { 504 + struct adp8860_bl *data = dev_get_drvdata(dev); 505 + 506 + strict_strtoul(buf, 10, &data->cached_daylight_max); 507 + return adp8860_store(dev, buf, count, ADP8860_BLMX1); 508 + } 509 + static DEVICE_ATTR(l1_daylight_max, 0664, adp8860_bl_l1_daylight_max_show, 510 + adp8860_bl_l1_daylight_max_store); 511 + 512 + static ssize_t adp8860_bl_l3_dark_dim_show(struct device *dev, 513 + struct device_attribute *attr, char *buf) 514 + { 515 + return adp8860_show(dev, buf, ADP8860_BLDM3); 516 + } 517 + 518 + static ssize_t adp8860_bl_l3_dark_dim_store(struct device *dev, 519 + struct device_attribute *attr, 520 + const char *buf, size_t count) 521 + { 522 + return adp8860_store(dev, buf, count, ADP8860_BLDM3); 523 + } 524 + static DEVICE_ATTR(l3_dark_dim, 0664, adp8860_bl_l3_dark_dim_show, 525 + adp8860_bl_l3_dark_dim_store); 526 + 527 + static ssize_t adp8860_bl_l2_office_dim_show(struct device *dev, 528 + struct device_attribute *attr, char *buf) 529 + { 530 + return adp8860_show(dev, buf, ADP8860_BLDM2); 531 + } 532 + 533 + static ssize_t adp8860_bl_l2_office_dim_store(struct device *dev, 534 + struct device_attribute *attr, 535 + const char *buf, size_t count) 536 + { 537 + return adp8860_store(dev, buf, count, ADP8860_BLDM2); 538 + } 539 + static DEVICE_ATTR(l2_office_dim, 0664, adp8860_bl_l2_office_dim_show, 540 + adp8860_bl_l2_office_dim_store); 541 + 542 + static ssize_t adp8860_bl_l1_daylight_dim_show(struct device *dev, 543 + struct device_attribute *attr, char *buf) 544 + { 545 + return adp8860_show(dev, buf, ADP8860_BLDM1); 546 + } 547 + 548 + static ssize_t adp8860_bl_l1_daylight_dim_store(struct device *dev, 549 + struct device_attribute *attr, 550 + const char *buf, size_t count) 551 + { 552 + return adp8860_store(dev, buf, count, ADP8860_BLDM1); 553 + } 554 + static DEVICE_ATTR(l1_daylight_dim, 0664, adp8860_bl_l1_daylight_dim_show, 555 + adp8860_bl_l1_daylight_dim_store); 556 + 557 + #ifdef ADP8860_EXT_FEATURES 558 + static ssize_t adp8860_bl_ambient_light_level_show(struct device *dev, 559 + struct device_attribute *attr, char *buf) 560 + { 561 + struct adp8860_bl *data = dev_get_drvdata(dev); 562 + int error; 563 + uint8_t reg_val; 564 + uint16_t ret_val; 565 + 566 + mutex_lock(&data->lock); 567 + error = adp8860_read(data->client, ADP8860_PH1LEVL, &reg_val); 568 + ret_val = reg_val; 569 + error |= adp8860_read(data->client, ADP8860_PH1LEVH, &reg_val); 570 + mutex_unlock(&data->lock); 571 + 572 + if (error < 0) 573 + return error; 574 + 575 + /* Return 13-bit conversion value for the first light sensor */ 576 + ret_val += (reg_val & 0x1F) << 8; 577 + 578 + return sprintf(buf, "%u\n", ret_val); 579 + } 580 + static DEVICE_ATTR(ambient_light_level, 0444, 581 + adp8860_bl_ambient_light_level_show, NULL); 582 + 583 + static ssize_t adp8860_bl_ambient_light_zone_show(struct device *dev, 584 + struct device_attribute *attr, char *buf) 585 + { 586 + struct adp8860_bl *data = dev_get_drvdata(dev); 587 + int error; 588 + uint8_t reg_val; 589 + 590 + mutex_lock(&data->lock); 591 + error = adp8860_read(data->client, ADP8860_CFGR, &reg_val); 592 + mutex_unlock(&data->lock); 593 + 594 + if (error < 0) 595 + return error; 596 + 597 + return sprintf(buf, "%u\n", 598 + ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1); 599 + } 600 + 601 + static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev, 602 + struct device_attribute *attr, 603 + const char *buf, size_t count) 604 + { 605 + struct adp8860_bl *data = dev_get_drvdata(dev); 606 + unsigned long val; 607 + uint8_t reg_val; 608 + int ret; 609 + 610 + ret = strict_strtoul(buf, 10, &val); 611 + if (ret) 612 + return ret; 613 + 614 + if (val == 0) { 615 + /* Enable automatic ambient light sensing */ 616 + adp8860_set_bits(data->client, ADP8860_MDCR, CMP_AUTOEN); 617 + } else if ((val > 0) && (val < 6)) { 618 + /* Disable automatic ambient light sensing */ 619 + adp8860_clr_bits(data->client, ADP8860_MDCR, CMP_AUTOEN); 620 + 621 + /* Set user supplied ambient light zone */ 622 + mutex_lock(&data->lock); 623 + adp8860_read(data->client, ADP8860_CFGR, &reg_val); 624 + reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT); 625 + reg_val |= val << CFGR_BLV_SHIFT; 626 + adp8860_write(data->client, ADP8860_CFGR, reg_val); 627 + mutex_unlock(&data->lock); 628 + } 629 + 630 + return count; 631 + } 632 + static DEVICE_ATTR(ambient_light_zone, 0664, 633 + adp8860_bl_ambient_light_zone_show, 634 + adp8860_bl_ambient_light_zone_store); 635 + #endif 636 + 637 + static struct attribute *adp8860_bl_attributes[] = { 638 + &dev_attr_l3_dark_max.attr, 639 + &dev_attr_l3_dark_dim.attr, 640 + &dev_attr_l2_office_max.attr, 641 + &dev_attr_l2_office_dim.attr, 642 + &dev_attr_l1_daylight_max.attr, 643 + &dev_attr_l1_daylight_dim.attr, 644 + #ifdef ADP8860_EXT_FEATURES 645 + &dev_attr_ambient_light_level.attr, 646 + &dev_attr_ambient_light_zone.attr, 647 + #endif 648 + NULL 649 + }; 650 + 651 + static const struct attribute_group adp8860_bl_attr_group = { 652 + .attrs = adp8860_bl_attributes, 653 + }; 654 + 655 + static int __devinit adp8860_probe(struct i2c_client *client, 656 + const struct i2c_device_id *id) 657 + { 658 + struct backlight_device *bl; 659 + struct adp8860_bl *data; 660 + struct adp8860_backlight_platform_data *pdata = 661 + client->dev.platform_data; 662 + struct backlight_properties props; 663 + uint8_t reg_val; 664 + int ret; 665 + 666 + if (!i2c_check_functionality(client->adapter, 667 + I2C_FUNC_SMBUS_BYTE_DATA)) { 668 + dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); 669 + return -EIO; 670 + } 671 + 672 + if (!pdata) { 673 + dev_err(&client->dev, "no platform data?\n"); 674 + return -EINVAL; 675 + } 676 + 677 + data = kzalloc(sizeof(*data), GFP_KERNEL); 678 + if (data == NULL) 679 + return -ENOMEM; 680 + 681 + ret = adp8860_read(client, ADP8860_MFDVID, &reg_val); 682 + if (ret < 0) 683 + goto out2; 684 + 685 + switch (ADP8860_MANID(reg_val)) { 686 + case ADP8863_MANUFID: 687 + data->gdwn_dis = !!pdata->gdwn_dis; 688 + case ADP8860_MANUFID: 689 + data->en_ambl_sens = !!pdata->en_ambl_sens; 690 + break; 691 + case ADP8861_MANUFID: 692 + data->gdwn_dis = !!pdata->gdwn_dis; 693 + break; 694 + default: 695 + dev_err(&client->dev, "failed to probe\n"); 696 + ret = -ENODEV; 697 + goto out2; 698 + } 699 + 700 + /* It's confirmed that the DEVID field is actually a REVID */ 701 + 702 + data->revid = ADP8860_DEVID(reg_val); 703 + data->client = client; 704 + data->pdata = pdata; 705 + data->id = id->driver_data; 706 + data->current_brightness = 0; 707 + i2c_set_clientdata(client, data); 708 + 709 + memset(&props, 0, sizeof(props)); 710 + props.max_brightness = ADP8860_MAX_BRIGHTNESS; 711 + 712 + mutex_init(&data->lock); 713 + 714 + bl = backlight_device_register(dev_driver_string(&client->dev), 715 + &client->dev, data, &adp8860_bl_ops, &props); 716 + if (IS_ERR(bl)) { 717 + dev_err(&client->dev, "failed to register backlight\n"); 718 + ret = PTR_ERR(bl); 719 + goto out2; 720 + } 721 + 722 + bl->props.max_brightness = 723 + bl->props.brightness = ADP8860_MAX_BRIGHTNESS; 724 + 725 + data->bl = bl; 726 + 727 + if (data->en_ambl_sens) 728 + ret = sysfs_create_group(&bl->dev.kobj, 729 + &adp8860_bl_attr_group); 730 + 731 + if (ret) { 732 + dev_err(&client->dev, "failed to register sysfs\n"); 733 + goto out1; 734 + } 735 + 736 + ret = adp8860_bl_setup(bl); 737 + if (ret) { 738 + ret = -EIO; 739 + goto out; 740 + } 741 + 742 + backlight_update_status(bl); 743 + 744 + dev_info(&client->dev, "%s Rev.%d Backlight\n", 745 + client->name, data->revid); 746 + 747 + if (pdata->num_leds) 748 + adp8860_led_probe(client); 749 + 750 + return 0; 751 + 752 + out: 753 + if (data->en_ambl_sens) 754 + sysfs_remove_group(&data->bl->dev.kobj, 755 + &adp8860_bl_attr_group); 756 + out1: 757 + backlight_device_unregister(bl); 758 + out2: 759 + i2c_set_clientdata(client, NULL); 760 + kfree(data); 761 + 762 + return ret; 763 + } 764 + 765 + static int __devexit adp8860_remove(struct i2c_client *client) 766 + { 767 + struct adp8860_bl *data = i2c_get_clientdata(client); 768 + 769 + adp8860_clr_bits(client, ADP8860_MDCR, NSTBY); 770 + 771 + if (data->led) 772 + adp8860_led_remove(client); 773 + 774 + if (data->en_ambl_sens) 775 + sysfs_remove_group(&data->bl->dev.kobj, 776 + &adp8860_bl_attr_group); 777 + 778 + backlight_device_unregister(data->bl); 779 + i2c_set_clientdata(client, NULL); 780 + kfree(data); 781 + 782 + return 0; 783 + } 784 + 785 + #ifdef CONFIG_PM 786 + static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message) 787 + { 788 + adp8860_clr_bits(client, ADP8860_MDCR, NSTBY); 789 + 790 + return 0; 791 + } 792 + 793 + static int adp8860_i2c_resume(struct i2c_client *client) 794 + { 795 + adp8860_set_bits(client, ADP8860_MDCR, NSTBY); 796 + 797 + return 0; 798 + } 799 + #else 800 + #define adp8860_i2c_suspend NULL 801 + #define adp8860_i2c_resume NULL 802 + #endif 803 + 804 + static const struct i2c_device_id adp8860_id[] = { 805 + { "adp8860", adp8860 }, 806 + { "adp8861", adp8861 }, 807 + { "adp8863", adp8863 }, 808 + { } 809 + }; 810 + MODULE_DEVICE_TABLE(i2c, adp8860_id); 811 + 812 + static struct i2c_driver adp8860_driver = { 813 + .driver = { 814 + .name = KBUILD_MODNAME, 815 + }, 816 + .probe = adp8860_probe, 817 + .remove = __devexit_p(adp8860_remove), 818 + .suspend = adp8860_i2c_suspend, 819 + .resume = adp8860_i2c_resume, 820 + .id_table = adp8860_id, 821 + }; 822 + 823 + static int __init adp8860_init(void) 824 + { 825 + return i2c_add_driver(&adp8860_driver); 826 + } 827 + module_init(adp8860_init); 828 + 829 + static void __exit adp8860_exit(void) 830 + { 831 + i2c_del_driver(&adp8860_driver); 832 + } 833 + module_exit(adp8860_exit); 834 + 835 + MODULE_LICENSE("GPL v2"); 836 + MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 837 + MODULE_DESCRIPTION("ADP8860 Backlight driver"); 838 + MODULE_ALIAS("i2c:adp8860-backlight");
+2 -2
drivers/video/backlight/adx_bl.c
··· 107 107 props.max_brightness = 0xff; 108 108 bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, 109 109 bl, &adx_backlight_ops, &props); 110 - if (!bldev) { 111 - ret = -ENOMEM; 110 + if (IS_ERR(bldev)) { 111 + ret = PTR_ERR(bldev); 112 112 goto out; 113 113 } 114 114
+160
drivers/video/backlight/ep93xx_bl.c
··· 1 + /* 2 + * Driver for the Cirrus EP93xx lcd backlight 3 + * 4 + * Copyright (c) 2010 H Hartley Sweeten <hsweeten@visionengravers.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + * 10 + * This driver controls the pulse width modulated brightness control output, 11 + * BRIGHT, on the Cirrus EP9307, EP9312, and EP9315 processors. 12 + */ 13 + 14 + 15 + #include <linux/platform_device.h> 16 + #include <linux/io.h> 17 + #include <linux/fb.h> 18 + #include <linux/backlight.h> 19 + 20 + #include <mach/hardware.h> 21 + 22 + #define EP93XX_RASTER_REG(x) (EP93XX_RASTER_BASE + (x)) 23 + #define EP93XX_RASTER_BRIGHTNESS EP93XX_RASTER_REG(0x20) 24 + 25 + #define EP93XX_MAX_COUNT 255 26 + #define EP93XX_MAX_BRIGHT 255 27 + #define EP93XX_DEF_BRIGHT 128 28 + 29 + struct ep93xxbl { 30 + void __iomem *mmio; 31 + int brightness; 32 + }; 33 + 34 + static int ep93xxbl_set(struct backlight_device *bl, int brightness) 35 + { 36 + struct ep93xxbl *ep93xxbl = bl_get_data(bl); 37 + 38 + __raw_writel((brightness << 8) | EP93XX_MAX_COUNT, ep93xxbl->mmio); 39 + 40 + ep93xxbl->brightness = brightness; 41 + 42 + return 0; 43 + } 44 + 45 + static int ep93xxbl_update_status(struct backlight_device *bl) 46 + { 47 + int brightness = bl->props.brightness; 48 + 49 + if (bl->props.power != FB_BLANK_UNBLANK || 50 + bl->props.fb_blank != FB_BLANK_UNBLANK) 51 + brightness = 0; 52 + 53 + return ep93xxbl_set(bl, brightness); 54 + } 55 + 56 + static int ep93xxbl_get_brightness(struct backlight_device *bl) 57 + { 58 + struct ep93xxbl *ep93xxbl = bl_get_data(bl); 59 + 60 + return ep93xxbl->brightness; 61 + } 62 + 63 + static const struct backlight_ops ep93xxbl_ops = { 64 + .update_status = ep93xxbl_update_status, 65 + .get_brightness = ep93xxbl_get_brightness, 66 + }; 67 + 68 + static int __init ep93xxbl_probe(struct platform_device *dev) 69 + { 70 + struct ep93xxbl *ep93xxbl; 71 + struct backlight_device *bl; 72 + struct backlight_properties props; 73 + 74 + ep93xxbl = devm_kzalloc(&dev->dev, sizeof(*ep93xxbl), GFP_KERNEL); 75 + if (!ep93xxbl) 76 + return -ENOMEM; 77 + 78 + /* 79 + * This register is located in the range already ioremap'ed by 80 + * the framebuffer driver. A MFD driver seems a bit of overkill 81 + * to handle this so use the static I/O mapping; this address 82 + * is already virtual. 83 + * 84 + * NOTE: No locking is required; the framebuffer does not touch 85 + * this register. 86 + */ 87 + ep93xxbl->mmio = EP93XX_RASTER_BRIGHTNESS; 88 + 89 + memset(&props, 0, sizeof(struct backlight_properties)); 90 + props.max_brightness = EP93XX_MAX_BRIGHT; 91 + bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl, 92 + &ep93xxbl_ops, &props); 93 + if (IS_ERR(bl)) 94 + return PTR_ERR(bl); 95 + 96 + bl->props.brightness = EP93XX_DEF_BRIGHT; 97 + 98 + platform_set_drvdata(dev, bl); 99 + 100 + ep93xxbl_update_status(bl); 101 + 102 + return 0; 103 + } 104 + 105 + static int ep93xxbl_remove(struct platform_device *dev) 106 + { 107 + struct backlight_device *bl = platform_get_drvdata(dev); 108 + 109 + backlight_device_unregister(bl); 110 + platform_set_drvdata(dev, NULL); 111 + return 0; 112 + } 113 + 114 + #ifdef CONFIG_PM 115 + static int ep93xxbl_suspend(struct platform_device *dev, pm_message_t state) 116 + { 117 + struct backlight_device *bl = platform_get_drvdata(dev); 118 + 119 + return ep93xxbl_set(bl, 0); 120 + } 121 + 122 + static int ep93xxbl_resume(struct platform_device *dev) 123 + { 124 + struct backlight_device *bl = platform_get_drvdata(dev); 125 + 126 + backlight_update_status(bl); 127 + return 0; 128 + } 129 + #else 130 + #define ep93xxbl_suspend NULL 131 + #define ep93xxbl_resume NULL 132 + #endif 133 + 134 + static struct platform_driver ep93xxbl_driver = { 135 + .driver = { 136 + .name = "ep93xx-bl", 137 + .owner = THIS_MODULE, 138 + }, 139 + .probe = ep93xxbl_probe, 140 + .remove = __devexit_p(ep93xxbl_remove), 141 + .suspend = ep93xxbl_suspend, 142 + .resume = ep93xxbl_resume, 143 + }; 144 + 145 + static int __init ep93xxbl_init(void) 146 + { 147 + return platform_driver_register(&ep93xxbl_driver); 148 + } 149 + module_init(ep93xxbl_init); 150 + 151 + static void __exit ep93xxbl_exit(void) 152 + { 153 + platform_driver_unregister(&ep93xxbl_driver); 154 + } 155 + module_exit(ep93xxbl_exit); 156 + 157 + MODULE_DESCRIPTION("EP93xx Backlight Driver"); 158 + MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>"); 159 + MODULE_LICENSE("GPL"); 160 + MODULE_ALIAS("platform:ep93xx-bl");
+5 -6
drivers/video/backlight/l4f00242t03.c
··· 125 125 126 126 if (priv == NULL) { 127 127 dev_err(&spi->dev, "No memory for this device.\n"); 128 - ret = -ENOMEM; 129 - goto err; 128 + return -ENOMEM; 130 129 } 131 130 132 131 dev_set_drvdata(&spi->dev, priv); ··· 138 139 if (ret) { 139 140 dev_err(&spi->dev, 140 141 "Unable to get the lcd l4f00242t03 reset gpio.\n"); 141 - return ret; 142 + goto err; 142 143 } 143 144 144 145 ret = gpio_direction_output(pdata->reset_gpio, 1); ··· 150 151 if (ret) { 151 152 dev_err(&spi->dev, 152 153 "Unable to get the lcd l4f00242t03 data en gpio.\n"); 153 - return ret; 154 + goto err2; 154 155 } 155 156 156 157 ret = gpio_direction_output(pdata->data_enable_gpio, 0); ··· 221 222 gpio_free(pdata->reset_gpio); 222 223 223 224 if (priv->io_reg) 224 - regulator_put(priv->core_reg); 225 - if (priv->core_reg) 226 225 regulator_put(priv->io_reg); 226 + if (priv->core_reg) 227 + regulator_put(priv->core_reg); 227 228 228 229 kfree(priv); 229 230
+1
drivers/video/backlight/max8925_bl.c
··· 162 162 backlight_update_status(bl); 163 163 return 0; 164 164 out: 165 + backlight_device_unregister(bl); 165 166 kfree(data); 166 167 return ret; 167 168 }
+46 -1
drivers/video/backlight/mbp_nvidia_bl.c
··· 141 141 .callback = mbp_dmi_match, 142 142 .ident = "MacBook 1,1", 143 143 .matches = { 144 - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 144 + DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), 145 145 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), 146 146 }, 147 147 .driver_data = (void *)&intel_chipset_data, ··· 179 179 .matches = { 180 180 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 181 181 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,2"), 182 + }, 183 + .driver_data = (void *)&intel_chipset_data, 184 + }, 185 + { 186 + .callback = mbp_dmi_match, 187 + .ident = "MacBookPro 1,1", 188 + .matches = { 189 + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 190 + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"), 191 + }, 192 + .driver_data = (void *)&intel_chipset_data, 193 + }, 194 + { 195 + .callback = mbp_dmi_match, 196 + .ident = "MacBookPro 1,2", 197 + .matches = { 198 + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 199 + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,2"), 200 + }, 201 + .driver_data = (void *)&intel_chipset_data, 202 + }, 203 + { 204 + .callback = mbp_dmi_match, 205 + .ident = "MacBookPro 2,1", 206 + .matches = { 207 + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 208 + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,1"), 209 + }, 210 + .driver_data = (void *)&intel_chipset_data, 211 + }, 212 + { 213 + .callback = mbp_dmi_match, 214 + .ident = "MacBookPro 2,2", 215 + .matches = { 216 + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 217 + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"), 182 218 }, 183 219 .driver_data = (void *)&intel_chipset_data, 184 220 }, ··· 269 233 .matches = { 270 234 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 271 235 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,2"), 236 + }, 237 + .driver_data = (void *)&nvidia_chipset_data, 238 + }, 239 + { 240 + .callback = mbp_dmi_match, 241 + .ident = "MacBook 6,1", 242 + .matches = { 243 + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 244 + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook6,1"), 272 245 }, 273 246 .driver_data = (void *)&nvidia_chipset_data, 274 247 },
+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");
+920
drivers/video/backlight/s6e63m0.c
··· 1 + /* 2 + * S6E63M0 AMOLED LCD panel driver. 3 + * 4 + * Author: InKi Dae <inki.dae@samsung.com> 5 + * 6 + * Derived from drivers/video/omap/lcd-apollon.c 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, but 14 + * WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 + * General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License along 19 + * with this program; if not, write to the Free Software Foundation, Inc., 20 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 + */ 22 + 23 + #include <linux/wait.h> 24 + #include <linux/fb.h> 25 + #include <linux/delay.h> 26 + #include <linux/gpio.h> 27 + #include <linux/spi/spi.h> 28 + #include <linux/irq.h> 29 + #include <linux/interrupt.h> 30 + #include <linux/kernel.h> 31 + #include <linux/lcd.h> 32 + #include <linux/backlight.h> 33 + 34 + #include "s6e63m0_gamma.h" 35 + 36 + #define SLEEPMSEC 0x1000 37 + #define ENDDEF 0x2000 38 + #define DEFMASK 0xFF00 39 + #define COMMAND_ONLY 0xFE 40 + #define DATA_ONLY 0xFF 41 + 42 + #define MIN_BRIGHTNESS 0 43 + #define MAX_BRIGHTNESS 10 44 + 45 + #define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) 46 + 47 + struct s6e63m0 { 48 + struct device *dev; 49 + struct spi_device *spi; 50 + unsigned int power; 51 + unsigned int current_brightness; 52 + unsigned int gamma_mode; 53 + unsigned int gamma_table_count; 54 + struct lcd_device *ld; 55 + struct backlight_device *bd; 56 + struct lcd_platform_data *lcd_pd; 57 + }; 58 + 59 + static const unsigned short SEQ_PANEL_CONDITION_SET[] = { 60 + 0xF8, 0x01, 61 + DATA_ONLY, 0x27, 62 + DATA_ONLY, 0x27, 63 + DATA_ONLY, 0x07, 64 + DATA_ONLY, 0x07, 65 + DATA_ONLY, 0x54, 66 + DATA_ONLY, 0x9f, 67 + DATA_ONLY, 0x63, 68 + DATA_ONLY, 0x86, 69 + DATA_ONLY, 0x1a, 70 + DATA_ONLY, 0x33, 71 + DATA_ONLY, 0x0d, 72 + DATA_ONLY, 0x00, 73 + DATA_ONLY, 0x00, 74 + 75 + ENDDEF, 0x0000 76 + }; 77 + 78 + static const unsigned short SEQ_DISPLAY_CONDITION_SET[] = { 79 + 0xf2, 0x02, 80 + DATA_ONLY, 0x03, 81 + DATA_ONLY, 0x1c, 82 + DATA_ONLY, 0x10, 83 + DATA_ONLY, 0x10, 84 + 85 + 0xf7, 0x03, 86 + DATA_ONLY, 0x00, 87 + DATA_ONLY, 0x00, 88 + 89 + ENDDEF, 0x0000 90 + }; 91 + 92 + static const unsigned short SEQ_GAMMA_SETTING[] = { 93 + 0xfa, 0x00, 94 + DATA_ONLY, 0x18, 95 + DATA_ONLY, 0x08, 96 + DATA_ONLY, 0x24, 97 + DATA_ONLY, 0x64, 98 + DATA_ONLY, 0x56, 99 + DATA_ONLY, 0x33, 100 + DATA_ONLY, 0xb6, 101 + DATA_ONLY, 0xba, 102 + DATA_ONLY, 0xa8, 103 + DATA_ONLY, 0xac, 104 + DATA_ONLY, 0xb1, 105 + DATA_ONLY, 0x9d, 106 + DATA_ONLY, 0xc1, 107 + DATA_ONLY, 0xc1, 108 + DATA_ONLY, 0xb7, 109 + DATA_ONLY, 0x00, 110 + DATA_ONLY, 0x9c, 111 + DATA_ONLY, 0x00, 112 + DATA_ONLY, 0x9f, 113 + DATA_ONLY, 0x00, 114 + DATA_ONLY, 0xd6, 115 + 116 + 0xfa, 0x01, 117 + 118 + ENDDEF, 0x0000 119 + }; 120 + 121 + static const unsigned short SEQ_ETC_CONDITION_SET[] = { 122 + 0xf6, 0x00, 123 + DATA_ONLY, 0x8c, 124 + DATA_ONLY, 0x07, 125 + 126 + 0xb3, 0xc, 127 + 128 + 0xb5, 0x2c, 129 + DATA_ONLY, 0x12, 130 + DATA_ONLY, 0x0c, 131 + DATA_ONLY, 0x0a, 132 + DATA_ONLY, 0x10, 133 + DATA_ONLY, 0x0e, 134 + DATA_ONLY, 0x17, 135 + DATA_ONLY, 0x13, 136 + DATA_ONLY, 0x1f, 137 + DATA_ONLY, 0x1a, 138 + DATA_ONLY, 0x2a, 139 + DATA_ONLY, 0x24, 140 + DATA_ONLY, 0x1f, 141 + DATA_ONLY, 0x1b, 142 + DATA_ONLY, 0x1a, 143 + DATA_ONLY, 0x17, 144 + 145 + DATA_ONLY, 0x2b, 146 + DATA_ONLY, 0x26, 147 + DATA_ONLY, 0x22, 148 + DATA_ONLY, 0x20, 149 + DATA_ONLY, 0x3a, 150 + DATA_ONLY, 0x34, 151 + DATA_ONLY, 0x30, 152 + DATA_ONLY, 0x2c, 153 + DATA_ONLY, 0x29, 154 + DATA_ONLY, 0x26, 155 + DATA_ONLY, 0x25, 156 + DATA_ONLY, 0x23, 157 + DATA_ONLY, 0x21, 158 + DATA_ONLY, 0x20, 159 + DATA_ONLY, 0x1e, 160 + DATA_ONLY, 0x1e, 161 + 162 + 0xb6, 0x00, 163 + DATA_ONLY, 0x00, 164 + DATA_ONLY, 0x11, 165 + DATA_ONLY, 0x22, 166 + DATA_ONLY, 0x33, 167 + DATA_ONLY, 0x44, 168 + DATA_ONLY, 0x44, 169 + DATA_ONLY, 0x44, 170 + 171 + DATA_ONLY, 0x55, 172 + DATA_ONLY, 0x55, 173 + DATA_ONLY, 0x66, 174 + DATA_ONLY, 0x66, 175 + DATA_ONLY, 0x66, 176 + DATA_ONLY, 0x66, 177 + DATA_ONLY, 0x66, 178 + DATA_ONLY, 0x66, 179 + 180 + 0xb7, 0x2c, 181 + DATA_ONLY, 0x12, 182 + DATA_ONLY, 0x0c, 183 + DATA_ONLY, 0x0a, 184 + DATA_ONLY, 0x10, 185 + DATA_ONLY, 0x0e, 186 + DATA_ONLY, 0x17, 187 + DATA_ONLY, 0x13, 188 + DATA_ONLY, 0x1f, 189 + DATA_ONLY, 0x1a, 190 + DATA_ONLY, 0x2a, 191 + DATA_ONLY, 0x24, 192 + DATA_ONLY, 0x1f, 193 + DATA_ONLY, 0x1b, 194 + DATA_ONLY, 0x1a, 195 + DATA_ONLY, 0x17, 196 + 197 + DATA_ONLY, 0x2b, 198 + DATA_ONLY, 0x26, 199 + DATA_ONLY, 0x22, 200 + DATA_ONLY, 0x20, 201 + DATA_ONLY, 0x3a, 202 + DATA_ONLY, 0x34, 203 + DATA_ONLY, 0x30, 204 + DATA_ONLY, 0x2c, 205 + DATA_ONLY, 0x29, 206 + DATA_ONLY, 0x26, 207 + DATA_ONLY, 0x25, 208 + DATA_ONLY, 0x23, 209 + DATA_ONLY, 0x21, 210 + DATA_ONLY, 0x20, 211 + DATA_ONLY, 0x1e, 212 + DATA_ONLY, 0x1e, 213 + 214 + 0xb8, 0x00, 215 + DATA_ONLY, 0x00, 216 + DATA_ONLY, 0x11, 217 + DATA_ONLY, 0x22, 218 + DATA_ONLY, 0x33, 219 + DATA_ONLY, 0x44, 220 + DATA_ONLY, 0x44, 221 + DATA_ONLY, 0x44, 222 + 223 + DATA_ONLY, 0x55, 224 + DATA_ONLY, 0x55, 225 + DATA_ONLY, 0x66, 226 + DATA_ONLY, 0x66, 227 + DATA_ONLY, 0x66, 228 + DATA_ONLY, 0x66, 229 + DATA_ONLY, 0x66, 230 + DATA_ONLY, 0x66, 231 + 232 + 0xb9, 0x2c, 233 + DATA_ONLY, 0x12, 234 + DATA_ONLY, 0x0c, 235 + DATA_ONLY, 0x0a, 236 + DATA_ONLY, 0x10, 237 + DATA_ONLY, 0x0e, 238 + DATA_ONLY, 0x17, 239 + DATA_ONLY, 0x13, 240 + DATA_ONLY, 0x1f, 241 + DATA_ONLY, 0x1a, 242 + DATA_ONLY, 0x2a, 243 + DATA_ONLY, 0x24, 244 + DATA_ONLY, 0x1f, 245 + DATA_ONLY, 0x1b, 246 + DATA_ONLY, 0x1a, 247 + DATA_ONLY, 0x17, 248 + 249 + DATA_ONLY, 0x2b, 250 + DATA_ONLY, 0x26, 251 + DATA_ONLY, 0x22, 252 + DATA_ONLY, 0x20, 253 + DATA_ONLY, 0x3a, 254 + DATA_ONLY, 0x34, 255 + DATA_ONLY, 0x30, 256 + DATA_ONLY, 0x2c, 257 + DATA_ONLY, 0x29, 258 + DATA_ONLY, 0x26, 259 + DATA_ONLY, 0x25, 260 + DATA_ONLY, 0x23, 261 + DATA_ONLY, 0x21, 262 + DATA_ONLY, 0x20, 263 + DATA_ONLY, 0x1e, 264 + DATA_ONLY, 0x1e, 265 + 266 + 0xba, 0x00, 267 + DATA_ONLY, 0x00, 268 + DATA_ONLY, 0x11, 269 + DATA_ONLY, 0x22, 270 + DATA_ONLY, 0x33, 271 + DATA_ONLY, 0x44, 272 + DATA_ONLY, 0x44, 273 + DATA_ONLY, 0x44, 274 + 275 + DATA_ONLY, 0x55, 276 + DATA_ONLY, 0x55, 277 + DATA_ONLY, 0x66, 278 + DATA_ONLY, 0x66, 279 + DATA_ONLY, 0x66, 280 + DATA_ONLY, 0x66, 281 + DATA_ONLY, 0x66, 282 + DATA_ONLY, 0x66, 283 + 284 + 0xc1, 0x4d, 285 + DATA_ONLY, 0x96, 286 + DATA_ONLY, 0x1d, 287 + DATA_ONLY, 0x00, 288 + DATA_ONLY, 0x00, 289 + DATA_ONLY, 0x01, 290 + DATA_ONLY, 0xdf, 291 + DATA_ONLY, 0x00, 292 + DATA_ONLY, 0x00, 293 + DATA_ONLY, 0x03, 294 + DATA_ONLY, 0x1f, 295 + DATA_ONLY, 0x00, 296 + DATA_ONLY, 0x00, 297 + DATA_ONLY, 0x00, 298 + DATA_ONLY, 0x00, 299 + DATA_ONLY, 0x00, 300 + DATA_ONLY, 0x00, 301 + DATA_ONLY, 0x00, 302 + DATA_ONLY, 0x00, 303 + DATA_ONLY, 0x03, 304 + DATA_ONLY, 0x06, 305 + DATA_ONLY, 0x09, 306 + DATA_ONLY, 0x0d, 307 + DATA_ONLY, 0x0f, 308 + DATA_ONLY, 0x12, 309 + DATA_ONLY, 0x15, 310 + DATA_ONLY, 0x18, 311 + 312 + 0xb2, 0x10, 313 + DATA_ONLY, 0x10, 314 + DATA_ONLY, 0x0b, 315 + DATA_ONLY, 0x05, 316 + 317 + ENDDEF, 0x0000 318 + }; 319 + 320 + static const unsigned short SEQ_ACL_ON[] = { 321 + /* ACL on */ 322 + 0xc0, 0x01, 323 + 324 + ENDDEF, 0x0000 325 + }; 326 + 327 + static const unsigned short SEQ_ACL_OFF[] = { 328 + /* ACL off */ 329 + 0xc0, 0x00, 330 + 331 + ENDDEF, 0x0000 332 + }; 333 + 334 + static const unsigned short SEQ_ELVSS_ON[] = { 335 + /* ELVSS on */ 336 + 0xb1, 0x0b, 337 + 338 + ENDDEF, 0x0000 339 + }; 340 + 341 + static const unsigned short SEQ_ELVSS_OFF[] = { 342 + /* ELVSS off */ 343 + 0xb1, 0x0a, 344 + 345 + ENDDEF, 0x0000 346 + }; 347 + 348 + static const unsigned short SEQ_STAND_BY_OFF[] = { 349 + 0x11, COMMAND_ONLY, 350 + 351 + ENDDEF, 0x0000 352 + }; 353 + 354 + static const unsigned short SEQ_STAND_BY_ON[] = { 355 + 0x10, COMMAND_ONLY, 356 + 357 + ENDDEF, 0x0000 358 + }; 359 + 360 + static const unsigned short SEQ_DISPLAY_ON[] = { 361 + 0x29, COMMAND_ONLY, 362 + 363 + ENDDEF, 0x0000 364 + }; 365 + 366 + 367 + static int s6e63m0_spi_write_byte(struct s6e63m0 *lcd, int addr, int data) 368 + { 369 + u16 buf[1]; 370 + struct spi_message msg; 371 + 372 + struct spi_transfer xfer = { 373 + .len = 2, 374 + .tx_buf = buf, 375 + }; 376 + 377 + buf[0] = (addr << 8) | data; 378 + 379 + spi_message_init(&msg); 380 + spi_message_add_tail(&xfer, &msg); 381 + 382 + return spi_sync(lcd->spi, &msg); 383 + } 384 + 385 + static int s6e63m0_spi_write(struct s6e63m0 *lcd, unsigned char address, 386 + unsigned char command) 387 + { 388 + int ret = 0; 389 + 390 + if (address != DATA_ONLY) 391 + ret = s6e63m0_spi_write_byte(lcd, 0x0, address); 392 + if (command != COMMAND_ONLY) 393 + ret = s6e63m0_spi_write_byte(lcd, 0x1, command); 394 + 395 + return ret; 396 + } 397 + 398 + static int s6e63m0_panel_send_sequence(struct s6e63m0 *lcd, 399 + const unsigned short *wbuf) 400 + { 401 + int ret = 0, i = 0; 402 + 403 + while ((wbuf[i] & DEFMASK) != ENDDEF) { 404 + if ((wbuf[i] & DEFMASK) != SLEEPMSEC) { 405 + ret = s6e63m0_spi_write(lcd, wbuf[i], wbuf[i+1]); 406 + if (ret) 407 + break; 408 + } else 409 + udelay(wbuf[i+1]*1000); 410 + i += 2; 411 + } 412 + 413 + return ret; 414 + } 415 + 416 + static int _s6e63m0_gamma_ctl(struct s6e63m0 *lcd, const unsigned int *gamma) 417 + { 418 + unsigned int i = 0; 419 + int ret = 0; 420 + 421 + /* disable gamma table updating. */ 422 + ret = s6e63m0_spi_write(lcd, 0xfa, 0x00); 423 + if (ret) { 424 + dev_err(lcd->dev, "failed to disable gamma table updating.\n"); 425 + goto gamma_err; 426 + } 427 + 428 + for (i = 0 ; i < GAMMA_TABLE_COUNT; i++) { 429 + ret = s6e63m0_spi_write(lcd, DATA_ONLY, gamma[i]); 430 + if (ret) { 431 + dev_err(lcd->dev, "failed to set gamma table.\n"); 432 + goto gamma_err; 433 + } 434 + } 435 + 436 + /* update gamma table. */ 437 + ret = s6e63m0_spi_write(lcd, 0xfa, 0x01); 438 + if (ret) 439 + dev_err(lcd->dev, "failed to update gamma table.\n"); 440 + 441 + gamma_err: 442 + return ret; 443 + } 444 + 445 + static int s6e63m0_gamma_ctl(struct s6e63m0 *lcd, int gamma) 446 + { 447 + int ret = 0; 448 + 449 + ret = _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]); 450 + 451 + return ret; 452 + } 453 + 454 + 455 + static int s6e63m0_ldi_init(struct s6e63m0 *lcd) 456 + { 457 + int ret, i; 458 + const unsigned short *init_seq[] = { 459 + SEQ_PANEL_CONDITION_SET, 460 + SEQ_DISPLAY_CONDITION_SET, 461 + SEQ_GAMMA_SETTING, 462 + SEQ_ETC_CONDITION_SET, 463 + SEQ_ACL_ON, 464 + SEQ_ELVSS_ON, 465 + }; 466 + 467 + for (i = 0; i < ARRAY_SIZE(init_seq); i++) { 468 + ret = s6e63m0_panel_send_sequence(lcd, init_seq[i]); 469 + if (ret) 470 + break; 471 + } 472 + 473 + return ret; 474 + } 475 + 476 + static int s6e63m0_ldi_enable(struct s6e63m0 *lcd) 477 + { 478 + int ret = 0, i; 479 + const unsigned short *enable_seq[] = { 480 + SEQ_STAND_BY_OFF, 481 + SEQ_DISPLAY_ON, 482 + }; 483 + 484 + for (i = 0; i < ARRAY_SIZE(enable_seq); i++) { 485 + ret = s6e63m0_panel_send_sequence(lcd, enable_seq[i]); 486 + if (ret) 487 + break; 488 + } 489 + 490 + return ret; 491 + } 492 + 493 + static int s6e63m0_ldi_disable(struct s6e63m0 *lcd) 494 + { 495 + int ret; 496 + 497 + ret = s6e63m0_panel_send_sequence(lcd, SEQ_STAND_BY_ON); 498 + 499 + return ret; 500 + } 501 + 502 + static int s6e63m0_power_on(struct s6e63m0 *lcd) 503 + { 504 + int ret = 0; 505 + struct lcd_platform_data *pd = NULL; 506 + struct backlight_device *bd = NULL; 507 + 508 + pd = lcd->lcd_pd; 509 + if (!pd) { 510 + dev_err(lcd->dev, "platform data is NULL.\n"); 511 + return -EFAULT; 512 + } 513 + 514 + bd = lcd->bd; 515 + if (!bd) { 516 + dev_err(lcd->dev, "backlight device is NULL.\n"); 517 + return -EFAULT; 518 + } 519 + 520 + if (!pd->power_on) { 521 + dev_err(lcd->dev, "power_on is NULL.\n"); 522 + return -EFAULT; 523 + } else { 524 + pd->power_on(lcd->ld, 1); 525 + mdelay(pd->power_on_delay); 526 + } 527 + 528 + if (!pd->reset) { 529 + dev_err(lcd->dev, "reset is NULL.\n"); 530 + return -EFAULT; 531 + } else { 532 + pd->reset(lcd->ld); 533 + mdelay(pd->reset_delay); 534 + } 535 + 536 + ret = s6e63m0_ldi_init(lcd); 537 + if (ret) { 538 + dev_err(lcd->dev, "failed to initialize ldi.\n"); 539 + return ret; 540 + } 541 + 542 + ret = s6e63m0_ldi_enable(lcd); 543 + if (ret) { 544 + dev_err(lcd->dev, "failed to enable ldi.\n"); 545 + return ret; 546 + } 547 + 548 + /* set brightness to current value after power on or resume. */ 549 + ret = s6e63m0_gamma_ctl(lcd, bd->props.brightness); 550 + if (ret) { 551 + dev_err(lcd->dev, "lcd gamma setting failed.\n"); 552 + return ret; 553 + } 554 + 555 + return 0; 556 + } 557 + 558 + static int s6e63m0_power_off(struct s6e63m0 *lcd) 559 + { 560 + int ret = 0; 561 + struct lcd_platform_data *pd = NULL; 562 + 563 + pd = lcd->lcd_pd; 564 + if (!pd) { 565 + dev_err(lcd->dev, "platform data is NULL.\n"); 566 + return -EFAULT; 567 + } 568 + 569 + ret = s6e63m0_ldi_disable(lcd); 570 + if (ret) { 571 + dev_err(lcd->dev, "lcd setting failed.\n"); 572 + return -EIO; 573 + } 574 + 575 + mdelay(pd->power_off_delay); 576 + 577 + if (!pd->power_on) { 578 + dev_err(lcd->dev, "power_on is NULL.\n"); 579 + return -EFAULT; 580 + } else 581 + pd->power_on(lcd->ld, 0); 582 + 583 + return 0; 584 + } 585 + 586 + static int s6e63m0_power(struct s6e63m0 *lcd, int power) 587 + { 588 + int ret = 0; 589 + 590 + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) 591 + ret = s6e63m0_power_on(lcd); 592 + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) 593 + ret = s6e63m0_power_off(lcd); 594 + 595 + if (!ret) 596 + lcd->power = power; 597 + 598 + return ret; 599 + } 600 + 601 + static int s6e63m0_set_power(struct lcd_device *ld, int power) 602 + { 603 + struct s6e63m0 *lcd = lcd_get_data(ld); 604 + 605 + if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && 606 + power != FB_BLANK_NORMAL) { 607 + dev_err(lcd->dev, "power value should be 0, 1 or 4.\n"); 608 + return -EINVAL; 609 + } 610 + 611 + return s6e63m0_power(lcd, power); 612 + } 613 + 614 + static int s6e63m0_get_power(struct lcd_device *ld) 615 + { 616 + struct s6e63m0 *lcd = lcd_get_data(ld); 617 + 618 + return lcd->power; 619 + } 620 + 621 + static int s6e63m0_get_brightness(struct backlight_device *bd) 622 + { 623 + return bd->props.brightness; 624 + } 625 + 626 + static int s6e63m0_set_brightness(struct backlight_device *bd) 627 + { 628 + int ret = 0, brightness = bd->props.brightness; 629 + struct s6e63m0 *lcd = bl_get_data(bd); 630 + 631 + if (brightness < MIN_BRIGHTNESS || 632 + brightness > bd->props.max_brightness) { 633 + dev_err(&bd->dev, "lcd brightness should be %d to %d.\n", 634 + MIN_BRIGHTNESS, MAX_BRIGHTNESS); 635 + return -EINVAL; 636 + } 637 + 638 + ret = s6e63m0_gamma_ctl(lcd, bd->props.brightness); 639 + if (ret) { 640 + dev_err(&bd->dev, "lcd brightness setting failed.\n"); 641 + return -EIO; 642 + } 643 + 644 + return ret; 645 + } 646 + 647 + static struct lcd_ops s6e63m0_lcd_ops = { 648 + .set_power = s6e63m0_set_power, 649 + .get_power = s6e63m0_get_power, 650 + }; 651 + 652 + static const struct backlight_ops s6e63m0_backlight_ops = { 653 + .get_brightness = s6e63m0_get_brightness, 654 + .update_status = s6e63m0_set_brightness, 655 + }; 656 + 657 + static ssize_t s6e63m0_sysfs_show_gamma_mode(struct device *dev, 658 + struct device_attribute *attr, char *buf) 659 + { 660 + struct s6e63m0 *lcd = dev_get_drvdata(dev); 661 + char temp[10]; 662 + 663 + switch (lcd->gamma_mode) { 664 + case 0: 665 + sprintf(temp, "2.2 mode\n"); 666 + strcat(buf, temp); 667 + break; 668 + case 1: 669 + sprintf(temp, "1.9 mode\n"); 670 + strcat(buf, temp); 671 + break; 672 + case 2: 673 + sprintf(temp, "1.7 mode\n"); 674 + strcat(buf, temp); 675 + break; 676 + default: 677 + dev_info(dev, "gamma mode could be 0:2.2, 1:1.9 or 2:1.7)n"); 678 + break; 679 + } 680 + 681 + return strlen(buf); 682 + } 683 + 684 + static ssize_t s6e63m0_sysfs_store_gamma_mode(struct device *dev, 685 + struct device_attribute *attr, 686 + const char *buf, size_t len) 687 + { 688 + struct s6e63m0 *lcd = dev_get_drvdata(dev); 689 + struct backlight_device *bd = NULL; 690 + int brightness, rc; 691 + 692 + rc = strict_strtoul(buf, 0, (unsigned long *)&lcd->gamma_mode); 693 + if (rc < 0) 694 + return rc; 695 + 696 + bd = lcd->bd; 697 + 698 + brightness = bd->props.brightness; 699 + 700 + switch (lcd->gamma_mode) { 701 + case 0: 702 + _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[brightness]); 703 + break; 704 + case 1: 705 + _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_19_table[brightness]); 706 + break; 707 + case 2: 708 + _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_17_table[brightness]); 709 + break; 710 + default: 711 + dev_info(dev, "gamma mode could be 0:2.2, 1:1.9 or 2:1.7\n"); 712 + _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[brightness]); 713 + break; 714 + } 715 + return len; 716 + } 717 + 718 + static DEVICE_ATTR(gamma_mode, 0644, 719 + s6e63m0_sysfs_show_gamma_mode, s6e63m0_sysfs_store_gamma_mode); 720 + 721 + static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev, 722 + struct device_attribute *attr, char *buf) 723 + { 724 + struct s6e63m0 *lcd = dev_get_drvdata(dev); 725 + char temp[3]; 726 + 727 + sprintf(temp, "%d\n", lcd->gamma_table_count); 728 + strcpy(buf, temp); 729 + 730 + return strlen(buf); 731 + } 732 + static DEVICE_ATTR(gamma_table, 0644, 733 + s6e63m0_sysfs_show_gamma_table, NULL); 734 + 735 + static int __init s6e63m0_probe(struct spi_device *spi) 736 + { 737 + int ret = 0; 738 + struct s6e63m0 *lcd = NULL; 739 + struct lcd_device *ld = NULL; 740 + struct backlight_device *bd = NULL; 741 + 742 + lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL); 743 + if (!lcd) 744 + return -ENOMEM; 745 + 746 + /* s6e63m0 lcd panel uses 3-wire 9bits SPI Mode. */ 747 + spi->bits_per_word = 9; 748 + 749 + ret = spi_setup(spi); 750 + if (ret < 0) { 751 + dev_err(&spi->dev, "spi setup failed.\n"); 752 + goto out_free_lcd; 753 + } 754 + 755 + lcd->spi = spi; 756 + lcd->dev = &spi->dev; 757 + 758 + lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data; 759 + if (!lcd->lcd_pd) { 760 + dev_err(&spi->dev, "platform data is NULL.\n"); 761 + goto out_free_lcd; 762 + } 763 + 764 + ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops); 765 + if (IS_ERR(ld)) { 766 + ret = PTR_ERR(ld); 767 + goto out_free_lcd; 768 + } 769 + 770 + lcd->ld = ld; 771 + 772 + bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd, 773 + &s6e63m0_backlight_ops, NULL); 774 + if (IS_ERR(bd)) { 775 + ret = PTR_ERR(bd); 776 + goto out_lcd_unregister; 777 + } 778 + 779 + bd->props.max_brightness = MAX_BRIGHTNESS; 780 + bd->props.brightness = MAX_BRIGHTNESS; 781 + lcd->bd = bd; 782 + 783 + /* 784 + * it gets gamma table count available so it gets user 785 + * know that. 786 + */ 787 + lcd->gamma_table_count = 788 + sizeof(gamma_table) / (MAX_GAMMA_LEVEL * sizeof(int)); 789 + 790 + ret = device_create_file(&(spi->dev), &dev_attr_gamma_mode); 791 + if (ret < 0) 792 + dev_err(&(spi->dev), "failed to add sysfs entries\n"); 793 + 794 + ret = device_create_file(&(spi->dev), &dev_attr_gamma_table); 795 + if (ret < 0) 796 + dev_err(&(spi->dev), "failed to add sysfs entries\n"); 797 + 798 + /* 799 + * if lcd panel was on from bootloader like u-boot then 800 + * do not lcd on. 801 + */ 802 + if (!lcd->lcd_pd->lcd_enabled) { 803 + /* 804 + * if lcd panel was off from bootloader then 805 + * current lcd status is powerdown and then 806 + * it enables lcd panel. 807 + */ 808 + lcd->power = FB_BLANK_POWERDOWN; 809 + 810 + s6e63m0_power(lcd, FB_BLANK_UNBLANK); 811 + } else 812 + lcd->power = FB_BLANK_UNBLANK; 813 + 814 + dev_set_drvdata(&spi->dev, lcd); 815 + 816 + dev_info(&spi->dev, "s6e63m0 panel driver has been probed.\n"); 817 + 818 + return 0; 819 + 820 + out_lcd_unregister: 821 + lcd_device_unregister(ld); 822 + out_free_lcd: 823 + kfree(lcd); 824 + return ret; 825 + } 826 + 827 + static int __devexit s6e63m0_remove(struct spi_device *spi) 828 + { 829 + struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); 830 + 831 + s6e63m0_power(lcd, FB_BLANK_POWERDOWN); 832 + lcd_device_unregister(lcd->ld); 833 + kfree(lcd); 834 + 835 + return 0; 836 + } 837 + 838 + #if defined(CONFIG_PM) 839 + unsigned int before_power; 840 + 841 + static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) 842 + { 843 + int ret = 0; 844 + struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); 845 + 846 + dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); 847 + 848 + before_power = lcd->power; 849 + 850 + /* 851 + * when lcd panel is suspend, lcd panel becomes off 852 + * regardless of status. 853 + */ 854 + ret = s6e63m0_power(lcd, FB_BLANK_POWERDOWN); 855 + 856 + return ret; 857 + } 858 + 859 + static int s6e63m0_resume(struct spi_device *spi) 860 + { 861 + int ret = 0; 862 + struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); 863 + 864 + /* 865 + * after suspended, if lcd panel status is FB_BLANK_UNBLANK 866 + * (at that time, before_power is FB_BLANK_UNBLANK) then 867 + * it changes that status to FB_BLANK_POWERDOWN to get lcd on. 868 + */ 869 + if (before_power == FB_BLANK_UNBLANK) 870 + lcd->power = FB_BLANK_POWERDOWN; 871 + 872 + dev_dbg(&spi->dev, "before_power = %d\n", before_power); 873 + 874 + ret = s6e63m0_power(lcd, before_power); 875 + 876 + return ret; 877 + } 878 + #else 879 + #define s6e63m0_suspend NULL 880 + #define s6e63m0_resume NULL 881 + #endif 882 + 883 + /* Power down all displays on reboot, poweroff or halt. */ 884 + static void s6e63m0_shutdown(struct spi_device *spi) 885 + { 886 + struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); 887 + 888 + s6e63m0_power(lcd, FB_BLANK_POWERDOWN); 889 + } 890 + 891 + static struct spi_driver s6e63m0_driver = { 892 + .driver = { 893 + .name = "s6e63m0", 894 + .bus = &spi_bus_type, 895 + .owner = THIS_MODULE, 896 + }, 897 + .probe = s6e63m0_probe, 898 + .remove = __devexit_p(s6e63m0_remove), 899 + .shutdown = s6e63m0_shutdown, 900 + .suspend = s6e63m0_suspend, 901 + .resume = s6e63m0_resume, 902 + }; 903 + 904 + static int __init s6e63m0_init(void) 905 + { 906 + return spi_register_driver(&s6e63m0_driver); 907 + } 908 + 909 + static void __exit s6e63m0_exit(void) 910 + { 911 + spi_unregister_driver(&s6e63m0_driver); 912 + } 913 + 914 + module_init(s6e63m0_init); 915 + module_exit(s6e63m0_exit); 916 + 917 + MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>"); 918 + MODULE_DESCRIPTION("S6E63M0 LCD Driver"); 919 + MODULE_LICENSE("GPL"); 920 +
+266
drivers/video/backlight/s6e63m0_gamma.h
··· 1 + /* linux/drivers/video/samsung/s6e63m0_brightness.h 2 + * 3 + * Gamma level definitions. 4 + * 5 + * Copyright (c) 2009 Samsung Electronics 6 + * InKi Dae <inki.dae@samsung.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + #ifndef _S6E63M0_BRIGHTNESS_H 14 + #define _S6E63M0_BRIGHTNESS_H 15 + 16 + #define MAX_GAMMA_LEVEL 11 17 + #define GAMMA_TABLE_COUNT 21 18 + 19 + /* gamma value: 2.2 */ 20 + static const unsigned int s6e63m0_22_300[] = { 21 + 0x18, 0x08, 0x24, 0x5f, 0x50, 0x2d, 0xB6, 22 + 0xB9, 0xA7, 0xAd, 0xB1, 0x9f, 0xbe, 0xC0, 23 + 0xB5, 0x00, 0xa0, 0x00, 0xa4, 0x00, 0xdb 24 + }; 25 + 26 + static const unsigned int s6e63m0_22_280[] = { 27 + 0x18, 0x08, 0x24, 0x64, 0x56, 0x33, 0xB6, 28 + 0xBA, 0xA8, 0xAC, 0xB1, 0x9D, 0xC1, 0xC1, 29 + 0xB7, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6 30 + }; 31 + 32 + static const unsigned int s6e63m0_22_260[] = { 33 + 0x18, 0x08, 0x24, 0x66, 0x58, 0x34, 0xB6, 34 + 0xBA, 0xA7, 0xAF, 0xB3, 0xA0, 0xC1, 0xC2, 35 + 0xB7, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1 36 + 37 + }; 38 + 39 + static const unsigned int s6e63m0_22_240[] = { 40 + 0x18, 0x08, 0x24, 0x62, 0x54, 0x30, 0xB9, 41 + 0xBB, 0xA9, 0xB0, 0xB3, 0xA1, 0xC1, 0xC3, 42 + 0xB7, 0x00, 0x91, 0x00, 0x95, 0x00, 0xDA 43 + 44 + }; 45 + static const unsigned int s6e63m0_22_220[] = { 46 + 0x18, 0x08, 0x24, 0x63, 0x53, 0x31, 0xB8, 47 + 0xBC, 0xA9, 0xB0, 0xB5, 0xA2, 0xC4, 0xC4, 48 + 0xB8, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2 49 + }; 50 + 51 + static const unsigned int s6e63m0_22_200[] = { 52 + 0x18, 0x08, 0x24, 0x66, 0x55, 0x34, 0xBA, 53 + 0xBD, 0xAB, 0xB1, 0xB5, 0xA3, 0xC5, 0xC6, 54 + 0xB9, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA 55 + }; 56 + 57 + static const unsigned int s6e63m0_22_170[] = { 58 + 0x18, 0x08, 0x24, 0x69, 0x54, 0x37, 0xBB, 59 + 0xBE, 0xAC, 0xB4, 0xB7, 0xA6, 0xC7, 0xC8, 60 + 0xBC, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB 61 + }; 62 + 63 + static const unsigned int s6e63m0_22_140[] = { 64 + 0x18, 0x08, 0x24, 0x6C, 0x54, 0x3A, 0xBC, 65 + 0xBF, 0xAC, 0xB7, 0xBB, 0xA9, 0xC9, 0xC9, 66 + 0xBE, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E 67 + }; 68 + 69 + static const unsigned int s6e63m0_22_110[] = { 70 + 0x18, 0x08, 0x24, 0x70, 0x51, 0x3E, 0xBF, 71 + 0xC1, 0xAF, 0xB9, 0xBC, 0xAB, 0xCC, 0xCC, 72 + 0xC2, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D 73 + }; 74 + 75 + static const unsigned int s6e63m0_22_90[] = { 76 + 0x18, 0x08, 0x24, 0x73, 0x4A, 0x3D, 0xC0, 77 + 0xC2, 0xB1, 0xBB, 0xBE, 0xAC, 0xCE, 0xCF, 78 + 0xC5, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82 79 + }; 80 + 81 + static const unsigned int s6e63m0_22_30[] = { 82 + 0x18, 0x08, 0x24, 0x78, 0xEC, 0x3D, 0xC8, 83 + 0xC2, 0xB6, 0xC4, 0xC7, 0xB6, 0xD5, 0xD7, 84 + 0xCC, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51 85 + }; 86 + 87 + /* gamma value: 1.9 */ 88 + static const unsigned int s6e63m0_19_300[] = { 89 + 0x18, 0x08, 0x24, 0x61, 0x5F, 0x39, 0xBA, 90 + 0xBD, 0xAD, 0xB1, 0xB6, 0xA5, 0xC4, 0xC5, 91 + 0xBC, 0x00, 0xA0, 0x00, 0xA4, 0x00, 0xDB 92 + }; 93 + 94 + static const unsigned int s6e63m0_19_280[] = { 95 + 0x18, 0x08, 0x24, 0x61, 0x60, 0x39, 0xBB, 96 + 0xBE, 0xAD, 0xB2, 0xB6, 0xA6, 0xC5, 0xC7, 97 + 0xBD, 0x00, 0x9B, 0x00, 0x9E, 0x00, 0xD5 98 + }; 99 + 100 + static const unsigned int s6e63m0_19_260[] = { 101 + 0x18, 0x08, 0x24, 0x63, 0x61, 0x3B, 0xBA, 102 + 0xBE, 0xAC, 0xB3, 0xB8, 0xA7, 0xC6, 0xC8, 103 + 0xBD, 0x00, 0x96, 0x00, 0x98, 0x00, 0xCF 104 + }; 105 + 106 + static const unsigned int s6e63m0_19_240[] = { 107 + 0x18, 0x08, 0x24, 0x67, 0x64, 0x3F, 0xBB, 108 + 0xBE, 0xAD, 0xB3, 0xB9, 0xA7, 0xC8, 0xC9, 109 + 0xBE, 0x00, 0x90, 0x00, 0x92, 0x00, 0xC8 110 + }; 111 + 112 + static const unsigned int s6e63m0_19_220[] = { 113 + 0x18, 0x08, 0x24, 0x68, 0x64, 0x40, 0xBC, 114 + 0xBF, 0xAF, 0xB4, 0xBA, 0xA9, 0xC8, 0xCA, 115 + 0xBE, 0x00, 0x8B, 0x00, 0x8C, 0x00, 0xC0 116 + }; 117 + 118 + static const unsigned int s6e63m0_19_200[] = { 119 + 0x18, 0x08, 0x24, 0x68, 0x64, 0x3F, 0xBE, 120 + 0xC0, 0xB0, 0xB6, 0xBB, 0xAB, 0xC8, 0xCB, 121 + 0xBF, 0x00, 0x85, 0x00, 0x86, 0x00, 0xB8 122 + }; 123 + 124 + static const unsigned int s6e63m0_19_170[] = { 125 + 0x18, 0x08, 0x24, 0x69, 0x64, 0x40, 0xBF, 126 + 0xC1, 0xB0, 0xB9, 0xBE, 0xAD, 0xCB, 0xCD, 127 + 0xC2, 0x00, 0x7A, 0x00, 0x7B, 0x00, 0xAA 128 + }; 129 + 130 + static const unsigned int s6e63m0_19_140[] = { 131 + 0x18, 0x08, 0x24, 0x6E, 0x65, 0x45, 0xC0, 132 + 0xC3, 0xB2, 0xBA, 0xBE, 0xAE, 0xCD, 0xD0, 133 + 0xC4, 0x00, 0x70, 0x00, 0x70, 0x00, 0x9C 134 + }; 135 + 136 + static const unsigned int s6e63m0_19_110[] = { 137 + 0x18, 0x08, 0x24, 0x6F, 0x65, 0x46, 0xC2, 138 + 0xC4, 0xB3, 0xBF, 0xC2, 0xB2, 0xCF, 0xD1, 139 + 0xC6, 0x00, 0x64, 0x00, 0x64, 0x00, 0x8D 140 + }; 141 + 142 + static const unsigned int s6e63m0_19_90[] = { 143 + 0x18, 0x08, 0x24, 0x74, 0x60, 0x4A, 0xC3, 144 + 0xC6, 0xB5, 0xBF, 0xC3, 0xB2, 0xD2, 0xD3, 145 + 0xC8, 0x00, 0x5B, 0x00, 0x5B, 0x00, 0x81 146 + }; 147 + 148 + static const unsigned int s6e63m0_19_30[] = { 149 + 0x18, 0x08, 0x24, 0x84, 0x45, 0x4F, 0xCA, 150 + 0xCB, 0xBC, 0xC9, 0xCB, 0xBC, 0xDA, 0xDA, 151 + 0xD0, 0x00, 0x35, 0x00, 0x34, 0x00, 0x4E 152 + }; 153 + 154 + /* gamma value: 1.7 */ 155 + static const unsigned int s6e63m0_17_300[] = { 156 + 0x18, 0x08, 0x24, 0x70, 0x70, 0x4F, 0xBF, 157 + 0xC2, 0xB2, 0xB8, 0xBC, 0xAC, 0xCB, 0xCD, 158 + 0xC3, 0x00, 0xA0, 0x00, 0xA4, 0x00, 0xDB 159 + }; 160 + 161 + static const unsigned int s6e63m0_17_280[] = { 162 + 0x18, 0x08, 0x24, 0x71, 0x71, 0x50, 0xBF, 163 + 0xC2, 0xB2, 0xBA, 0xBE, 0xAE, 0xCB, 0xCD, 164 + 0xC3, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6 165 + }; 166 + 167 + static const unsigned int s6e63m0_17_260[] = { 168 + 0x18, 0x08, 0x24, 0x72, 0x72, 0x50, 0xC0, 169 + 0xC3, 0xB4, 0xB9, 0xBE, 0xAE, 0xCC, 0xCF, 170 + 0xC4, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1 171 + }; 172 + 173 + static const unsigned int s6e63m0_17_240[] = { 174 + 0x18, 0x08, 0x24, 0x71, 0x72, 0x4F, 0xC2, 175 + 0xC4, 0xB5, 0xBB, 0xBF, 0xB0, 0xCC, 0xCF, 176 + 0xC3, 0x00, 0x91, 0x00, 0x95, 0x00, 0xCA 177 + }; 178 + 179 + static const unsigned int s6e63m0_17_220[] = { 180 + 0x18, 0x08, 0x24, 0x71, 0x73, 0x4F, 0xC2, 181 + 0xC5, 0xB5, 0xBD, 0xC0, 0xB2, 0xCD, 0xD1, 182 + 0xC5, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2 183 + }; 184 + 185 + static const unsigned int s6e63m0_17_200[] = { 186 + 0x18, 0x08, 0x24, 0x72, 0x75, 0x51, 0xC2, 187 + 0xC6, 0xB5, 0xBF, 0xC1, 0xB3, 0xCE, 0xD1, 188 + 0xC6, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA 189 + }; 190 + 191 + static const unsigned int s6e63m0_17_170[] = { 192 + 0x18, 0x08, 0x24, 0x75, 0x77, 0x54, 0xC3, 193 + 0xC7, 0xB7, 0xC0, 0xC3, 0xB4, 0xD1, 0xD3, 194 + 0xC9, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB 195 + }; 196 + 197 + static const unsigned int s6e63m0_17_140[] = { 198 + 0x18, 0x08, 0x24, 0x7B, 0x77, 0x58, 0xC3, 199 + 0xC8, 0xB8, 0xC2, 0xC6, 0xB6, 0xD3, 0xD4, 200 + 0xCA, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E 201 + }; 202 + 203 + static const unsigned int s6e63m0_17_110[] = { 204 + 0x18, 0x08, 0x24, 0x81, 0x7B, 0x5D, 0xC6, 205 + 0xCA, 0xBB, 0xC3, 0xC7, 0xB8, 0xD6, 0xD8, 206 + 0xCD, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D 207 + }; 208 + 209 + static const unsigned int s6e63m0_17_90[] = { 210 + 0x18, 0x08, 0x24, 0x82, 0x7A, 0x5B, 0xC8, 211 + 0xCB, 0xBD, 0xC5, 0xCA, 0xBA, 0xD6, 0xD8, 212 + 0xCE, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82 213 + }; 214 + 215 + static const unsigned int s6e63m0_17_30[] = { 216 + 0x18, 0x08, 0x24, 0x8F, 0x73, 0x63, 0xD1, 217 + 0xD0, 0xC5, 0xCC, 0xD1, 0xC2, 0xDE, 0xE0, 218 + 0xD6, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51 219 + }; 220 + 221 + struct s6e63m0_gamma { 222 + unsigned int *gamma_22_table[MAX_GAMMA_LEVEL]; 223 + unsigned int *gamma_19_table[MAX_GAMMA_LEVEL]; 224 + unsigned int *gamma_17_table[MAX_GAMMA_LEVEL]; 225 + }; 226 + 227 + static struct s6e63m0_gamma gamma_table = { 228 + .gamma_22_table[0] = (unsigned int *)&s6e63m0_22_30, 229 + .gamma_22_table[1] = (unsigned int *)&s6e63m0_22_90, 230 + .gamma_22_table[2] = (unsigned int *)&s6e63m0_22_110, 231 + .gamma_22_table[3] = (unsigned int *)&s6e63m0_22_140, 232 + .gamma_22_table[4] = (unsigned int *)&s6e63m0_22_170, 233 + .gamma_22_table[5] = (unsigned int *)&s6e63m0_22_200, 234 + .gamma_22_table[6] = (unsigned int *)&s6e63m0_22_220, 235 + .gamma_22_table[7] = (unsigned int *)&s6e63m0_22_240, 236 + .gamma_22_table[8] = (unsigned int *)&s6e63m0_22_260, 237 + .gamma_22_table[9] = (unsigned int *)&s6e63m0_22_280, 238 + .gamma_22_table[10] = (unsigned int *)&s6e63m0_22_300, 239 + 240 + .gamma_19_table[0] = (unsigned int *)&s6e63m0_19_30, 241 + .gamma_19_table[1] = (unsigned int *)&s6e63m0_19_90, 242 + .gamma_19_table[2] = (unsigned int *)&s6e63m0_19_110, 243 + .gamma_19_table[3] = (unsigned int *)&s6e63m0_19_140, 244 + .gamma_19_table[4] = (unsigned int *)&s6e63m0_19_170, 245 + .gamma_19_table[5] = (unsigned int *)&s6e63m0_19_200, 246 + .gamma_19_table[6] = (unsigned int *)&s6e63m0_19_220, 247 + .gamma_19_table[7] = (unsigned int *)&s6e63m0_19_240, 248 + .gamma_19_table[8] = (unsigned int *)&s6e63m0_19_260, 249 + .gamma_19_table[9] = (unsigned int *)&s6e63m0_19_280, 250 + .gamma_19_table[10] = (unsigned int *)&s6e63m0_19_300, 251 + 252 + .gamma_17_table[0] = (unsigned int *)&s6e63m0_17_30, 253 + .gamma_17_table[1] = (unsigned int *)&s6e63m0_17_90, 254 + .gamma_17_table[2] = (unsigned int *)&s6e63m0_17_110, 255 + .gamma_17_table[3] = (unsigned int *)&s6e63m0_17_140, 256 + .gamma_17_table[4] = (unsigned int *)&s6e63m0_17_170, 257 + .gamma_17_table[5] = (unsigned int *)&s6e63m0_17_200, 258 + .gamma_17_table[6] = (unsigned int *)&s6e63m0_17_220, 259 + .gamma_17_table[7] = (unsigned int *)&s6e63m0_17_240, 260 + .gamma_17_table[8] = (unsigned int *)&s6e63m0_17_260, 261 + .gamma_17_table[9] = (unsigned int *)&s6e63m0_17_280, 262 + .gamma_17_table[10] = (unsigned int *)&s6e63m0_17_300, 263 + }; 264 + 265 + #endif 266 +
+154
include/linux/i2c/adp8860.h
··· 1 + /* 2 + * Definitions and platform data for Analog Devices 3 + * Backlight drivers ADP8860 4 + * 5 + * Copyright 2009-2010 Analog Devices Inc. 6 + * 7 + * Licensed under the GPL-2 or later. 8 + */ 9 + 10 + #ifndef __LINUX_I2C_ADP8860_H 11 + #define __LINUX_I2C_ADP8860_H 12 + 13 + #include <linux/leds.h> 14 + #include <linux/types.h> 15 + 16 + #define ID_ADP8860 8860 17 + 18 + #define ADP8860_MAX_BRIGHTNESS 0x7F 19 + #define FLAG_OFFT_SHIFT 8 20 + 21 + /* 22 + * LEDs subdevice platform data 23 + */ 24 + 25 + #define ADP8860_LED_DIS_BLINK (0 << FLAG_OFFT_SHIFT) 26 + #define ADP8860_LED_OFFT_600ms (1 << FLAG_OFFT_SHIFT) 27 + #define ADP8860_LED_OFFT_1200ms (2 << FLAG_OFFT_SHIFT) 28 + #define ADP8860_LED_OFFT_1800ms (3 << FLAG_OFFT_SHIFT) 29 + 30 + #define ADP8860_LED_ONT_200ms 0 31 + #define ADP8860_LED_ONT_600ms 1 32 + #define ADP8860_LED_ONT_800ms 2 33 + #define ADP8860_LED_ONT_1200ms 3 34 + 35 + #define ADP8860_LED_D7 (7) 36 + #define ADP8860_LED_D6 (6) 37 + #define ADP8860_LED_D5 (5) 38 + #define ADP8860_LED_D4 (4) 39 + #define ADP8860_LED_D3 (3) 40 + #define ADP8860_LED_D2 (2) 41 + #define ADP8860_LED_D1 (1) 42 + 43 + /* 44 + * Backlight subdevice platform data 45 + */ 46 + 47 + #define ADP8860_BL_D7 (1 << 6) 48 + #define ADP8860_BL_D6 (1 << 5) 49 + #define ADP8860_BL_D5 (1 << 4) 50 + #define ADP8860_BL_D4 (1 << 3) 51 + #define ADP8860_BL_D3 (1 << 2) 52 + #define ADP8860_BL_D2 (1 << 1) 53 + #define ADP8860_BL_D1 (1 << 0) 54 + 55 + #define ADP8860_FADE_T_DIS 0 /* Fade Timer Disabled */ 56 + #define ADP8860_FADE_T_300ms 1 /* 0.3 Sec */ 57 + #define ADP8860_FADE_T_600ms 2 58 + #define ADP8860_FADE_T_900ms 3 59 + #define ADP8860_FADE_T_1200ms 4 60 + #define ADP8860_FADE_T_1500ms 5 61 + #define ADP8860_FADE_T_1800ms 6 62 + #define ADP8860_FADE_T_2100ms 7 63 + #define ADP8860_FADE_T_2400ms 8 64 + #define ADP8860_FADE_T_2700ms 9 65 + #define ADP8860_FADE_T_3000ms 10 66 + #define ADP8860_FADE_T_3500ms 11 67 + #define ADP8860_FADE_T_4000ms 12 68 + #define ADP8860_FADE_T_4500ms 13 69 + #define ADP8860_FADE_T_5000ms 14 70 + #define ADP8860_FADE_T_5500ms 15 /* 5.5 Sec */ 71 + 72 + #define ADP8860_FADE_LAW_LINEAR 0 73 + #define ADP8860_FADE_LAW_SQUARE 1 74 + #define ADP8860_FADE_LAW_CUBIC1 2 75 + #define ADP8860_FADE_LAW_CUBIC2 3 76 + 77 + #define ADP8860_BL_AMBL_FILT_80ms 0 /* Light sensor filter time */ 78 + #define ADP8860_BL_AMBL_FILT_160ms 1 79 + #define ADP8860_BL_AMBL_FILT_320ms 2 80 + #define ADP8860_BL_AMBL_FILT_640ms 3 81 + #define ADP8860_BL_AMBL_FILT_1280ms 4 82 + #define ADP8860_BL_AMBL_FILT_2560ms 5 83 + #define ADP8860_BL_AMBL_FILT_5120ms 6 84 + #define ADP8860_BL_AMBL_FILT_10240ms 7 /* 10.24 sec */ 85 + 86 + /* 87 + * Blacklight current 0..30mA 88 + */ 89 + #define ADP8860_BL_CUR_mA(I) ((I * 127) / 30) 90 + 91 + /* 92 + * L2 comparator current 0..1106uA 93 + */ 94 + #define ADP8860_L2_COMP_CURR_uA(I) ((I * 255) / 1106) 95 + 96 + /* 97 + * L3 comparator current 0..138uA 98 + */ 99 + #define ADP8860_L3_COMP_CURR_uA(I) ((I * 255) / 138) 100 + 101 + struct adp8860_backlight_platform_data { 102 + u8 bl_led_assign; /* 1 = Backlight 0 = Individual LED */ 103 + 104 + u8 bl_fade_in; /* Backlight Fade-In Timer */ 105 + u8 bl_fade_out; /* Backlight Fade-Out Timer */ 106 + u8 bl_fade_law; /* fade-on/fade-off transfer characteristic */ 107 + 108 + u8 en_ambl_sens; /* 1 = enable ambient light sensor */ 109 + u8 abml_filt; /* Light sensor filter time */ 110 + 111 + u8 l1_daylight_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ 112 + u8 l1_daylight_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ 113 + u8 l2_office_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ 114 + u8 l2_office_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ 115 + u8 l3_dark_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ 116 + u8 l3_dark_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ 117 + 118 + u8 l2_trip; /* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */ 119 + u8 l2_hyst; /* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */ 120 + u8 l3_trip; /* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */ 121 + u8 l3_hyst; /* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */ 122 + 123 + /** 124 + * Independent Current Sinks / LEDS 125 + * Sinks not assigned to the Backlight can be exposed to 126 + * user space using the LEDS CLASS interface 127 + */ 128 + 129 + int num_leds; 130 + struct led_info *leds; 131 + u8 led_fade_in; /* LED Fade-In Timer */ 132 + u8 led_fade_out; /* LED Fade-Out Timer */ 133 + u8 led_fade_law; /* fade-on/fade-off transfer characteristic */ 134 + u8 led_on_time; 135 + 136 + /** 137 + * Gain down disable. Setting this option does not allow the 138 + * charge pump to switch to lower gains. NOT AVAILABLE on ADP8860 139 + * 1 = the charge pump doesn't switch down in gain until all LEDs are 0. 140 + * The charge pump switches up in gain as needed. This feature is 141 + * useful if the ADP8863 charge pump is used to drive an external load. 142 + * This feature must be used when utilizing small fly capacitors 143 + * (0402 or smaller). 144 + * 0 = the charge pump automatically switches up and down in gain. 145 + * This provides optimal efficiency, but is not suitable for driving 146 + * loads that are not connected through the ADP8863 diode drivers. 147 + * Additionally, the charge pump fly capacitors should be low ESR 148 + * and sized 0603 or greater. 149 + */ 150 + 151 + u8 gdwn_dis; 152 + }; 153 + 154 + #endif /* __LINUX_I2C_ADP8860_H */
+23
include/linux/lcd.h
··· 69 69 struct device dev; 70 70 }; 71 71 72 + struct lcd_platform_data { 73 + /* reset lcd panel device. */ 74 + int (*reset)(struct lcd_device *ld); 75 + /* on or off to lcd panel. if 'enable' is 0 then 76 + lcd power off and 1, lcd power on. */ 77 + int (*power_on)(struct lcd_device *ld, int enable); 78 + 79 + /* it indicates whether lcd panel was enabled 80 + from bootloader or not. */ 81 + int lcd_enabled; 82 + /* it means delay for stable time when it becomes low to high 83 + or high to low that is dependent on whether reset gpio is 84 + low active or high active. */ 85 + unsigned int reset_delay; 86 + /* stable time needing to become lcd power on. */ 87 + unsigned int power_on_delay; 88 + /* stable time needing to become lcd power off. */ 89 + unsigned int power_off_delay; 90 + 91 + /* it could be used for any purpose. */ 92 + void *pdata; 93 + }; 94 + 72 95 static inline void lcd_set_power(struct lcd_device *ld, int power) 73 96 { 74 97 mutex_lock(&ld->update_lock);
+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 +
+4
include/linux/mfd/pcf50633/core.h
··· 18 18 #include <linux/regulator/driver.h> 19 19 #include <linux/regulator/machine.h> 20 20 #include <linux/power_supply.h> 21 + #include <linux/mfd/pcf50633/backlight.h> 21 22 22 23 struct pcf50633; 23 24 ··· 44 43 void (*force_shutdown)(struct pcf50633 *); 45 44 46 45 u8 resumers[5]; 46 + 47 + struct pcf50633_bl_platform_data *backlight_data; 47 48 }; 48 49 49 50 struct pcf50633_irq { ··· 155 152 struct platform_device *mbc_pdev; 156 153 struct platform_device *adc_pdev; 157 154 struct platform_device *input_pdev; 155 + struct platform_device *bl_pdev; 158 156 struct platform_device *regulator_pdev[PCF50633_NUM_REGULATORS]; 159 157 }; 160 158