diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-05 14:09:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-05 14:09:16 -0400 |
commit | 11126c611e10abb18b6f1ed0300c0548c3906b54 (patch) | |
tree | 246227ad730c1e68f5a9c03db57cd4592abe7687 /drivers/video/backlight | |
parent | 67966e088b0c7dc926f4ce19565ebf208e18d058 (diff) | |
parent | 33e2a4227ddff7c18921ac175fae3ab0e3ff8a76 (diff) |
Merge branch 'akpm' (Andrew's patch-bomb)
Merge misc patches from Andrew Morton:
"The MM tree is rather stuck while I wait to find out what the heck is
happening with sched/numa. Probably I'll need to route around all the
code which was added to -next, sigh.
So this is "everything else", or at least most of it - other small
bits are still awaiting resolutions of various kinds."
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (180 commits)
lib/decompress.c add __init to decompress_method and data
kernel/resource.c: fix stack overflow in __reserve_region_with_split()
omfs: convert to use beXX_add_cpu()
taskstats: cgroupstats_user_cmd() may leak on error
aoe: update aoe-internal version number to 50
aoe: update documentation to better reflect aoe-plus-udev usage
aoe: remove unused code
aoe: make dynamic block minor numbers the default
aoe: update and specify AoE address guards and error messages
aoe: retain static block device numbers for backwards compatibility
aoe: support more AoE addresses with dynamic block device minor numbers
aoe: update documentation with new URL and VM settings reference
aoe: update copyright year in touched files
aoe: update internal version number to 49
aoe: remove unused code and add cosmetic improvements
aoe: increase net_device reference count while using it
aoe: associate frames with the AoE storage target
aoe: disallow unsupported AoE minor addresses
aoe: do revalidation steps in order
aoe: failover remote interface based on aoe_deadsecs parameter
...
Diffstat (limited to 'drivers/video/backlight')
-rw-r--r-- | drivers/video/backlight/Kconfig | 23 | ||||
-rw-r--r-- | drivers/video/backlight/Makefile | 3 | ||||
-rw-r--r-- | drivers/video/backlight/da9052_bl.c | 4 | ||||
-rw-r--r-- | drivers/video/backlight/kb3886_bl.c | 4 | ||||
-rw-r--r-- | drivers/video/backlight/lm3630_bl.c | 475 | ||||
-rw-r--r-- | drivers/video/backlight/lm3639_bl.c | 437 | ||||
-rw-r--r-- | drivers/video/backlight/ltv350qv.c | 6 | ||||
-rw-r--r-- | drivers/video/backlight/platform_lcd.c | 10 | ||||
-rw-r--r-- | drivers/video/backlight/progear_bl.c | 162 |
9 files changed, 946 insertions, 178 deletions
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 63cee2e9d622..c101697a4ba7 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -229,13 +229,6 @@ config BACKLIGHT_HP700 | |||
229 | If you have an HP Jornada 700 series, | 229 | If you have an HP Jornada 700 series, |
230 | say Y to include backlight control driver. | 230 | say Y to include backlight control driver. |
231 | 231 | ||
232 | config BACKLIGHT_PROGEAR | ||
233 | tristate "Frontpath ProGear Backlight Driver" | ||
234 | depends on PCI && X86 | ||
235 | help | ||
236 | If you have a Frontpath ProGear say Y to enable the | ||
237 | backlight driver. | ||
238 | |||
239 | config BACKLIGHT_CARILLO_RANCH | 232 | config BACKLIGHT_CARILLO_RANCH |
240 | tristate "Intel Carillo Ranch Backlight Driver" | 233 | tristate "Intel Carillo Ranch Backlight Driver" |
241 | depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 | 234 | depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 |
@@ -352,6 +345,22 @@ config BACKLIGHT_AAT2870 | |||
352 | If you have a AnalogicTech AAT2870 say Y to enable the | 345 | If you have a AnalogicTech AAT2870 say Y to enable the |
353 | backlight driver. | 346 | backlight driver. |
354 | 347 | ||
348 | config BACKLIGHT_LM3630 | ||
349 | tristate "Backlight Driver for LM3630" | ||
350 | depends on BACKLIGHT_CLASS_DEVICE && I2C | ||
351 | select REGMAP_I2C | ||
352 | help | ||
353 | This supports TI LM3630 Backlight Driver | ||
354 | |||
355 | config BACKLIGHT_LM3639 | ||
356 | tristate "Backlight Driver for LM3639" | ||
357 | depends on BACKLIGHT_CLASS_DEVICE && I2C | ||
358 | select REGMAP_I2C | ||
359 | select NEW_LEDS | ||
360 | select LEDS_CLASS | ||
361 | help | ||
362 | This supports TI LM3639 Backlight + 1.5A Flash LED Driver | ||
363 | |||
355 | config BACKLIGHT_LP855X | 364 | config BACKLIGHT_LP855X |
356 | tristate "Backlight driver for TI LP855X" | 365 | tristate "Backlight driver for TI LP855X" |
357 | depends on BACKLIGHT_CLASS_DEVICE && I2C | 366 | depends on BACKLIGHT_CLASS_DEVICE && I2C |
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 00223a62ec12..e7ce7291635d 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
@@ -23,10 +23,11 @@ obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o | |||
23 | obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o | 23 | obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o |
24 | obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o | 24 | obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o |
25 | obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o | 25 | obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o |
26 | obj-$(CONFIG_BACKLIGHT_LM3630) += lm3630_bl.o | ||
27 | obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o | ||
26 | obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o | 28 | obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o |
27 | obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o | 29 | obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o |
28 | obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o | 30 | obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o |
29 | obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o | ||
30 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o | 31 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o |
31 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o | 32 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o |
32 | obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o | 33 | obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o |
diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c index b628d68f5162..ac196181fe45 100644 --- a/drivers/video/backlight/da9052_bl.c +++ b/drivers/video/backlight/da9052_bl.c | |||
@@ -72,7 +72,7 @@ static int da9052_adjust_wled_brightness(struct da9052_bl *wleds) | |||
72 | if (ret < 0) | 72 | if (ret < 0) |
73 | return ret; | 73 | return ret; |
74 | 74 | ||
75 | msleep(10); | 75 | usleep_range(10000, 11000); |
76 | 76 | ||
77 | if (wleds->brightness) { | 77 | if (wleds->brightness) { |
78 | ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], | 78 | ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], |
@@ -129,7 +129,6 @@ static int da9052_backlight_probe(struct platform_device *pdev) | |||
129 | &da9052_backlight_ops, &props); | 129 | &da9052_backlight_ops, &props); |
130 | if (IS_ERR(bl)) { | 130 | if (IS_ERR(bl)) { |
131 | dev_err(&pdev->dev, "Failed to register backlight\n"); | 131 | dev_err(&pdev->dev, "Failed to register backlight\n"); |
132 | devm_kfree(&pdev->dev, wleds); | ||
133 | return PTR_ERR(bl); | 132 | return PTR_ERR(bl); |
134 | } | 133 | } |
135 | 134 | ||
@@ -149,7 +148,6 @@ static int da9052_backlight_remove(struct platform_device *pdev) | |||
149 | wleds->state = DA9052_WLEDS_OFF; | 148 | wleds->state = DA9052_WLEDS_OFF; |
150 | da9052_adjust_wled_brightness(wleds); | 149 | da9052_adjust_wled_brightness(wleds); |
151 | backlight_device_unregister(bl); | 150 | backlight_device_unregister(bl); |
152 | devm_kfree(&pdev->dev, wleds); | ||
153 | 151 | ||
154 | return 0; | 152 | return 0; |
155 | } | 153 | } |
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c index 72dd5556a35b..6c5ed6b242cc 100644 --- a/drivers/video/backlight/kb3886_bl.c +++ b/drivers/video/backlight/kb3886_bl.c | |||
@@ -34,9 +34,9 @@ static void kb3886_bl_set_intensity(int intensity) | |||
34 | mutex_lock(&bl_mutex); | 34 | mutex_lock(&bl_mutex); |
35 | intensity = intensity&0xff; | 35 | intensity = intensity&0xff; |
36 | outb(KB3886_ADC_DAC_PWM, KB3886_PARENT); | 36 | outb(KB3886_ADC_DAC_PWM, KB3886_PARENT); |
37 | msleep(10); | 37 | usleep_range(10000, 11000); |
38 | outb(KB3886_PWM0_WRITE, KB3886_IO); | 38 | outb(KB3886_PWM0_WRITE, KB3886_IO); |
39 | msleep(10); | 39 | usleep_range(10000, 11000); |
40 | outb(intensity, KB3886_IO); | 40 | outb(intensity, KB3886_IO); |
41 | mutex_unlock(&bl_mutex); | 41 | mutex_unlock(&bl_mutex); |
42 | } | 42 | } |
diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c new file mode 100644 index 000000000000..dc191441796f --- /dev/null +++ b/drivers/video/backlight/lm3630_bl.c | |||
@@ -0,0 +1,475 @@ | |||
1 | /* | ||
2 | * Simple driver for Texas Instruments LM3630 Backlight driver chip | ||
3 | * Copyright (C) 2012 Texas Instruments | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/backlight.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/uaccess.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <linux/platform_data/lm3630_bl.h> | ||
20 | |||
21 | #define REG_CTRL 0x00 | ||
22 | #define REG_CONFIG 0x01 | ||
23 | #define REG_BRT_A 0x03 | ||
24 | #define REG_BRT_B 0x04 | ||
25 | #define REG_INT_STATUS 0x09 | ||
26 | #define REG_INT_EN 0x0A | ||
27 | #define REG_FAULT 0x0B | ||
28 | #define REG_PWM_OUTLOW 0x12 | ||
29 | #define REG_PWM_OUTHIGH 0x13 | ||
30 | #define REG_MAX 0x1F | ||
31 | |||
32 | #define INT_DEBOUNCE_MSEC 10 | ||
33 | |||
34 | enum lm3630_leds { | ||
35 | BLED_ALL = 0, | ||
36 | BLED_1, | ||
37 | BLED_2 | ||
38 | }; | ||
39 | |||
40 | static const char *bled_name[] = { | ||
41 | [BLED_ALL] = "lm3630_bled", /*Bank1 controls all string */ | ||
42 | [BLED_1] = "lm3630_bled1", /*Bank1 controls bled1 */ | ||
43 | [BLED_2] = "lm3630_bled2", /*Bank1 or 2 controls bled2 */ | ||
44 | }; | ||
45 | |||
46 | struct lm3630_chip_data { | ||
47 | struct device *dev; | ||
48 | struct delayed_work work; | ||
49 | int irq; | ||
50 | struct workqueue_struct *irqthread; | ||
51 | struct lm3630_platform_data *pdata; | ||
52 | struct backlight_device *bled1; | ||
53 | struct backlight_device *bled2; | ||
54 | struct regmap *regmap; | ||
55 | }; | ||
56 | |||
57 | /* initialize chip */ | ||
58 | static int __devinit lm3630_chip_init(struct lm3630_chip_data *pchip) | ||
59 | { | ||
60 | int ret; | ||
61 | unsigned int reg_val; | ||
62 | struct lm3630_platform_data *pdata = pchip->pdata; | ||
63 | |||
64 | /*pwm control */ | ||
65 | reg_val = ((pdata->pwm_active & 0x01) << 2) | (pdata->pwm_ctrl & 0x03); | ||
66 | ret = regmap_update_bits(pchip->regmap, REG_CONFIG, 0x07, reg_val); | ||
67 | if (ret < 0) | ||
68 | goto out; | ||
69 | |||
70 | /* bank control */ | ||
71 | reg_val = ((pdata->bank_b_ctrl & 0x01) << 1) | | ||
72 | (pdata->bank_a_ctrl & 0x07); | ||
73 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x07, reg_val); | ||
74 | if (ret < 0) | ||
75 | goto out; | ||
76 | |||
77 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
78 | if (ret < 0) | ||
79 | goto out; | ||
80 | |||
81 | /* set initial brightness */ | ||
82 | if (pdata->bank_a_ctrl != BANK_A_CTRL_DISABLE) { | ||
83 | ret = regmap_write(pchip->regmap, | ||
84 | REG_BRT_A, pdata->init_brt_led1); | ||
85 | if (ret < 0) | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | if (pdata->bank_b_ctrl != BANK_B_CTRL_DISABLE) { | ||
90 | ret = regmap_write(pchip->regmap, | ||
91 | REG_BRT_B, pdata->init_brt_led2); | ||
92 | if (ret < 0) | ||
93 | goto out; | ||
94 | } | ||
95 | return ret; | ||
96 | |||
97 | out: | ||
98 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | /* interrupt handling */ | ||
103 | static void lm3630_delayed_func(struct work_struct *work) | ||
104 | { | ||
105 | int ret; | ||
106 | unsigned int reg_val; | ||
107 | struct lm3630_chip_data *pchip; | ||
108 | |||
109 | pchip = container_of(work, struct lm3630_chip_data, work.work); | ||
110 | |||
111 | ret = regmap_read(pchip->regmap, REG_INT_STATUS, ®_val); | ||
112 | if (ret < 0) { | ||
113 | dev_err(pchip->dev, | ||
114 | "i2c failed to access REG_INT_STATUS Register\n"); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", reg_val); | ||
119 | } | ||
120 | |||
121 | static irqreturn_t lm3630_isr_func(int irq, void *chip) | ||
122 | { | ||
123 | int ret; | ||
124 | struct lm3630_chip_data *pchip = chip; | ||
125 | unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC); | ||
126 | |||
127 | queue_delayed_work(pchip->irqthread, &pchip->work, delay); | ||
128 | |||
129 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
130 | if (ret < 0) | ||
131 | goto out; | ||
132 | |||
133 | return IRQ_HANDLED; | ||
134 | out: | ||
135 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
136 | return IRQ_HANDLED; | ||
137 | } | ||
138 | |||
139 | static int lm3630_intr_config(struct lm3630_chip_data *pchip) | ||
140 | { | ||
141 | INIT_DELAYED_WORK(&pchip->work, lm3630_delayed_func); | ||
142 | pchip->irqthread = create_singlethread_workqueue("lm3630-irqthd"); | ||
143 | if (!pchip->irqthread) { | ||
144 | dev_err(pchip->dev, "create irq thread fail...\n"); | ||
145 | return -1; | ||
146 | } | ||
147 | if (request_threaded_irq | ||
148 | (pchip->irq, NULL, lm3630_isr_func, | ||
149 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "lm3630_irq", pchip)) { | ||
150 | dev_err(pchip->dev, "request threaded irq fail..\n"); | ||
151 | return -1; | ||
152 | } | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static bool | ||
157 | set_intensity(struct backlight_device *bl, struct lm3630_chip_data *pchip) | ||
158 | { | ||
159 | if (!pchip->pdata->pwm_set_intensity) | ||
160 | return false; | ||
161 | pchip->pdata->pwm_set_intensity(bl->props.brightness - 1, | ||
162 | pchip->pdata->pwm_period); | ||
163 | return true; | ||
164 | } | ||
165 | |||
166 | /* update and get brightness */ | ||
167 | static int lm3630_bank_a_update_status(struct backlight_device *bl) | ||
168 | { | ||
169 | int ret; | ||
170 | struct lm3630_chip_data *pchip = bl_get_data(bl); | ||
171 | enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; | ||
172 | |||
173 | /* brightness 0 means disable */ | ||
174 | if (!bl->props.brightness) { | ||
175 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x04, 0x00); | ||
176 | if (ret < 0) | ||
177 | goto out; | ||
178 | return bl->props.brightness; | ||
179 | } | ||
180 | |||
181 | /* pwm control */ | ||
182 | if (pwm_ctrl == PWM_CTRL_BANK_A || pwm_ctrl == PWM_CTRL_BANK_ALL) { | ||
183 | if (!set_intensity(bl, pchip)) | ||
184 | dev_err(pchip->dev, "No pwm control func. in plat-data\n"); | ||
185 | } else { | ||
186 | |||
187 | /* i2c control */ | ||
188 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
189 | if (ret < 0) | ||
190 | goto out; | ||
191 | mdelay(1); | ||
192 | ret = regmap_write(pchip->regmap, | ||
193 | REG_BRT_A, bl->props.brightness - 1); | ||
194 | if (ret < 0) | ||
195 | goto out; | ||
196 | } | ||
197 | return bl->props.brightness; | ||
198 | out: | ||
199 | dev_err(pchip->dev, "i2c failed to access REG_CTRL\n"); | ||
200 | return bl->props.brightness; | ||
201 | } | ||
202 | |||
203 | static int lm3630_bank_a_get_brightness(struct backlight_device *bl) | ||
204 | { | ||
205 | unsigned int reg_val; | ||
206 | int brightness, ret; | ||
207 | struct lm3630_chip_data *pchip = bl_get_data(bl); | ||
208 | enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; | ||
209 | |||
210 | if (pwm_ctrl == PWM_CTRL_BANK_A || pwm_ctrl == PWM_CTRL_BANK_ALL) { | ||
211 | ret = regmap_read(pchip->regmap, REG_PWM_OUTHIGH, ®_val); | ||
212 | if (ret < 0) | ||
213 | goto out; | ||
214 | brightness = reg_val & 0x01; | ||
215 | ret = regmap_read(pchip->regmap, REG_PWM_OUTLOW, ®_val); | ||
216 | if (ret < 0) | ||
217 | goto out; | ||
218 | brightness = ((brightness << 8) | reg_val) + 1; | ||
219 | } else { | ||
220 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
221 | if (ret < 0) | ||
222 | goto out; | ||
223 | mdelay(1); | ||
224 | ret = regmap_read(pchip->regmap, REG_BRT_A, ®_val); | ||
225 | if (ret < 0) | ||
226 | goto out; | ||
227 | brightness = reg_val + 1; | ||
228 | } | ||
229 | bl->props.brightness = brightness; | ||
230 | return bl->props.brightness; | ||
231 | out: | ||
232 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static const struct backlight_ops lm3630_bank_a_ops = { | ||
237 | .options = BL_CORE_SUSPENDRESUME, | ||
238 | .update_status = lm3630_bank_a_update_status, | ||
239 | .get_brightness = lm3630_bank_a_get_brightness, | ||
240 | }; | ||
241 | |||
242 | static int lm3630_bank_b_update_status(struct backlight_device *bl) | ||
243 | { | ||
244 | int ret; | ||
245 | struct lm3630_chip_data *pchip = bl_get_data(bl); | ||
246 | enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; | ||
247 | |||
248 | if (pwm_ctrl == PWM_CTRL_BANK_B || pwm_ctrl == PWM_CTRL_BANK_ALL) { | ||
249 | if (!set_intensity(bl, pchip)) | ||
250 | dev_err(pchip->dev, | ||
251 | "no pwm control func. in plat-data\n"); | ||
252 | } else { | ||
253 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
254 | if (ret < 0) | ||
255 | goto out; | ||
256 | mdelay(1); | ||
257 | ret = regmap_write(pchip->regmap, | ||
258 | REG_BRT_B, bl->props.brightness - 1); | ||
259 | } | ||
260 | return bl->props.brightness; | ||
261 | out: | ||
262 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
263 | return bl->props.brightness; | ||
264 | } | ||
265 | |||
266 | static int lm3630_bank_b_get_brightness(struct backlight_device *bl) | ||
267 | { | ||
268 | unsigned int reg_val; | ||
269 | int brightness, ret; | ||
270 | struct lm3630_chip_data *pchip = bl_get_data(bl); | ||
271 | enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; | ||
272 | |||
273 | if (pwm_ctrl == PWM_CTRL_BANK_B || pwm_ctrl == PWM_CTRL_BANK_ALL) { | ||
274 | ret = regmap_read(pchip->regmap, REG_PWM_OUTHIGH, ®_val); | ||
275 | if (ret < 0) | ||
276 | goto out; | ||
277 | brightness = reg_val & 0x01; | ||
278 | ret = regmap_read(pchip->regmap, REG_PWM_OUTLOW, ®_val); | ||
279 | if (ret < 0) | ||
280 | goto out; | ||
281 | brightness = ((brightness << 8) | reg_val) + 1; | ||
282 | } else { | ||
283 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
284 | if (ret < 0) | ||
285 | goto out; | ||
286 | mdelay(1); | ||
287 | ret = regmap_read(pchip->regmap, REG_BRT_B, ®_val); | ||
288 | if (ret < 0) | ||
289 | goto out; | ||
290 | brightness = reg_val + 1; | ||
291 | } | ||
292 | bl->props.brightness = brightness; | ||
293 | |||
294 | return bl->props.brightness; | ||
295 | out: | ||
296 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
297 | return bl->props.brightness; | ||
298 | } | ||
299 | |||
300 | static const struct backlight_ops lm3630_bank_b_ops = { | ||
301 | .options = BL_CORE_SUSPENDRESUME, | ||
302 | .update_status = lm3630_bank_b_update_status, | ||
303 | .get_brightness = lm3630_bank_b_get_brightness, | ||
304 | }; | ||
305 | |||
306 | static int lm3630_backlight_register(struct lm3630_chip_data *pchip, | ||
307 | enum lm3630_leds ledno) | ||
308 | { | ||
309 | const char *name = bled_name[ledno]; | ||
310 | struct backlight_properties props; | ||
311 | struct lm3630_platform_data *pdata = pchip->pdata; | ||
312 | |||
313 | props.type = BACKLIGHT_RAW; | ||
314 | switch (ledno) { | ||
315 | case BLED_1: | ||
316 | case BLED_ALL: | ||
317 | props.brightness = pdata->init_brt_led1; | ||
318 | props.max_brightness = pdata->max_brt_led1; | ||
319 | pchip->bled1 = | ||
320 | backlight_device_register(name, pchip->dev, pchip, | ||
321 | &lm3630_bank_a_ops, &props); | ||
322 | if (IS_ERR(pchip->bled1)) | ||
323 | return -EIO; | ||
324 | break; | ||
325 | case BLED_2: | ||
326 | props.brightness = pdata->init_brt_led2; | ||
327 | props.max_brightness = pdata->max_brt_led2; | ||
328 | pchip->bled2 = | ||
329 | backlight_device_register(name, pchip->dev, pchip, | ||
330 | &lm3630_bank_b_ops, &props); | ||
331 | if (IS_ERR(pchip->bled2)) | ||
332 | return -EIO; | ||
333 | break; | ||
334 | } | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static void lm3630_backlight_unregister(struct lm3630_chip_data *pchip) | ||
339 | { | ||
340 | if (pchip->bled1) | ||
341 | backlight_device_unregister(pchip->bled1); | ||
342 | if (pchip->bled2) | ||
343 | backlight_device_unregister(pchip->bled2); | ||
344 | } | ||
345 | |||
346 | static const struct regmap_config lm3630_regmap = { | ||
347 | .reg_bits = 8, | ||
348 | .val_bits = 8, | ||
349 | .max_register = REG_MAX, | ||
350 | }; | ||
351 | |||
352 | static int __devinit lm3630_probe(struct i2c_client *client, | ||
353 | const struct i2c_device_id *id) | ||
354 | { | ||
355 | struct lm3630_platform_data *pdata = client->dev.platform_data; | ||
356 | struct lm3630_chip_data *pchip; | ||
357 | int ret; | ||
358 | |||
359 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
360 | dev_err(&client->dev, "fail : i2c functionality check...\n"); | ||
361 | return -EOPNOTSUPP; | ||
362 | } | ||
363 | |||
364 | if (pdata == NULL) { | ||
365 | dev_err(&client->dev, "fail : no platform data.\n"); | ||
366 | return -ENODATA; | ||
367 | } | ||
368 | |||
369 | pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630_chip_data), | ||
370 | GFP_KERNEL); | ||
371 | if (!pchip) | ||
372 | return -ENOMEM; | ||
373 | pchip->pdata = pdata; | ||
374 | pchip->dev = &client->dev; | ||
375 | |||
376 | pchip->regmap = devm_regmap_init_i2c(client, &lm3630_regmap); | ||
377 | if (IS_ERR(pchip->regmap)) { | ||
378 | ret = PTR_ERR(pchip->regmap); | ||
379 | dev_err(&client->dev, "fail : allocate register map: %d\n", | ||
380 | ret); | ||
381 | return ret; | ||
382 | } | ||
383 | i2c_set_clientdata(client, pchip); | ||
384 | |||
385 | /* chip initialize */ | ||
386 | ret = lm3630_chip_init(pchip); | ||
387 | if (ret < 0) { | ||
388 | dev_err(&client->dev, "fail : init chip\n"); | ||
389 | goto err_chip_init; | ||
390 | } | ||
391 | |||
392 | switch (pdata->bank_a_ctrl) { | ||
393 | case BANK_A_CTRL_ALL: | ||
394 | ret = lm3630_backlight_register(pchip, BLED_ALL); | ||
395 | pdata->bank_b_ctrl = BANK_B_CTRL_DISABLE; | ||
396 | break; | ||
397 | case BANK_A_CTRL_LED1: | ||
398 | ret = lm3630_backlight_register(pchip, BLED_1); | ||
399 | break; | ||
400 | case BANK_A_CTRL_LED2: | ||
401 | ret = lm3630_backlight_register(pchip, BLED_2); | ||
402 | pdata->bank_b_ctrl = BANK_B_CTRL_DISABLE; | ||
403 | break; | ||
404 | default: | ||
405 | break; | ||
406 | } | ||
407 | |||
408 | if (ret < 0) | ||
409 | goto err_bl_reg; | ||
410 | |||
411 | if (pdata->bank_b_ctrl && pchip->bled2 == NULL) { | ||
412 | ret = lm3630_backlight_register(pchip, BLED_2); | ||
413 | if (ret < 0) | ||
414 | goto err_bl_reg; | ||
415 | } | ||
416 | |||
417 | /* interrupt enable : irq 0 is not allowed for lm3630 */ | ||
418 | pchip->irq = client->irq; | ||
419 | if (pchip->irq) | ||
420 | lm3630_intr_config(pchip); | ||
421 | |||
422 | dev_info(&client->dev, "LM3630 backlight register OK.\n"); | ||
423 | return 0; | ||
424 | |||
425 | err_bl_reg: | ||
426 | dev_err(&client->dev, "fail : backlight register.\n"); | ||
427 | lm3630_backlight_unregister(pchip); | ||
428 | err_chip_init: | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static int __devexit lm3630_remove(struct i2c_client *client) | ||
433 | { | ||
434 | int ret; | ||
435 | struct lm3630_chip_data *pchip = i2c_get_clientdata(client); | ||
436 | |||
437 | ret = regmap_write(pchip->regmap, REG_BRT_A, 0); | ||
438 | if (ret < 0) | ||
439 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
440 | |||
441 | ret = regmap_write(pchip->regmap, REG_BRT_B, 0); | ||
442 | if (ret < 0) | ||
443 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
444 | |||
445 | lm3630_backlight_unregister(pchip); | ||
446 | if (pchip->irq) { | ||
447 | free_irq(pchip->irq, pchip); | ||
448 | flush_workqueue(pchip->irqthread); | ||
449 | destroy_workqueue(pchip->irqthread); | ||
450 | } | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static const struct i2c_device_id lm3630_id[] = { | ||
455 | {LM3630_NAME, 0}, | ||
456 | {} | ||
457 | }; | ||
458 | |||
459 | MODULE_DEVICE_TABLE(i2c, lm3630_id); | ||
460 | |||
461 | static struct i2c_driver lm3630_i2c_driver = { | ||
462 | .driver = { | ||
463 | .name = LM3630_NAME, | ||
464 | }, | ||
465 | .probe = lm3630_probe, | ||
466 | .remove = __devexit_p(lm3630_remove), | ||
467 | .id_table = lm3630_id, | ||
468 | }; | ||
469 | |||
470 | module_i2c_driver(lm3630_i2c_driver); | ||
471 | |||
472 | MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3630"); | ||
473 | MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); | ||
474 | MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); | ||
475 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c new file mode 100644 index 000000000000..c6915c6c3cd1 --- /dev/null +++ b/drivers/video/backlight/lm3639_bl.c | |||
@@ -0,0 +1,437 @@ | |||
1 | /* | ||
2 | * Simple driver for Texas Instruments LM3639 Backlight + Flash LED driver chip | ||
3 | * Copyright (C) 2012 Texas Instruments | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/leds.h> | ||
14 | #include <linux/backlight.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/uaccess.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <linux/platform_data/lm3639_bl.h> | ||
21 | |||
22 | #define REG_DEV_ID 0x00 | ||
23 | #define REG_CHECKSUM 0x01 | ||
24 | #define REG_BL_CONF_1 0x02 | ||
25 | #define REG_BL_CONF_2 0x03 | ||
26 | #define REG_BL_CONF_3 0x04 | ||
27 | #define REG_BL_CONF_4 0x05 | ||
28 | #define REG_FL_CONF_1 0x06 | ||
29 | #define REG_FL_CONF_2 0x07 | ||
30 | #define REG_FL_CONF_3 0x08 | ||
31 | #define REG_IO_CTRL 0x09 | ||
32 | #define REG_ENABLE 0x0A | ||
33 | #define REG_FLAG 0x0B | ||
34 | #define REG_MAX REG_FLAG | ||
35 | |||
36 | struct lm3639_chip_data { | ||
37 | struct device *dev; | ||
38 | struct lm3639_platform_data *pdata; | ||
39 | |||
40 | struct backlight_device *bled; | ||
41 | struct led_classdev cdev_flash; | ||
42 | struct led_classdev cdev_torch; | ||
43 | struct regmap *regmap; | ||
44 | |||
45 | unsigned int bled_mode; | ||
46 | unsigned int bled_map; | ||
47 | unsigned int last_flag; | ||
48 | }; | ||
49 | |||
50 | /* initialize chip */ | ||
51 | static int __devinit lm3639_chip_init(struct lm3639_chip_data *pchip) | ||
52 | { | ||
53 | int ret; | ||
54 | unsigned int reg_val; | ||
55 | struct lm3639_platform_data *pdata = pchip->pdata; | ||
56 | |||
57 | /* input pins config. */ | ||
58 | ret = | ||
59 | regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x08, | ||
60 | pdata->pin_pwm); | ||
61 | if (ret < 0) | ||
62 | goto out; | ||
63 | |||
64 | reg_val = (pdata->pin_pwm & 0x40) | pdata->pin_strobe | pdata->pin_tx; | ||
65 | ret = regmap_update_bits(pchip->regmap, REG_IO_CTRL, 0x7C, reg_val); | ||
66 | if (ret < 0) | ||
67 | goto out; | ||
68 | |||
69 | /* init brightness */ | ||
70 | ret = regmap_write(pchip->regmap, REG_BL_CONF_4, pdata->init_brt_led); | ||
71 | if (ret < 0) | ||
72 | goto out; | ||
73 | |||
74 | ret = regmap_write(pchip->regmap, REG_BL_CONF_3, pdata->init_brt_led); | ||
75 | if (ret < 0) | ||
76 | goto out; | ||
77 | |||
78 | /* output pins config. */ | ||
79 | if (!pdata->init_brt_led) | ||
80 | reg_val = pdata->fled_pins | pdata->bled_pins; | ||
81 | else | ||
82 | reg_val = pdata->fled_pins | pdata->bled_pins | 0x01; | ||
83 | |||
84 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x79, reg_val); | ||
85 | if (ret < 0) | ||
86 | goto out; | ||
87 | |||
88 | return ret; | ||
89 | out: | ||
90 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | /* update and get brightness */ | ||
95 | static int lm3639_bled_update_status(struct backlight_device *bl) | ||
96 | { | ||
97 | int ret; | ||
98 | unsigned int reg_val; | ||
99 | struct lm3639_chip_data *pchip = bl_get_data(bl); | ||
100 | struct lm3639_platform_data *pdata = pchip->pdata; | ||
101 | |||
102 | ret = regmap_read(pchip->regmap, REG_FLAG, ®_val); | ||
103 | if (ret < 0) | ||
104 | goto out; | ||
105 | |||
106 | if (reg_val != 0) | ||
107 | dev_info(pchip->dev, "last flag is 0x%x\n", reg_val); | ||
108 | |||
109 | /* pwm control */ | ||
110 | if (pdata->pin_pwm) { | ||
111 | if (pdata->pwm_set_intensity) | ||
112 | pdata->pwm_set_intensity(bl->props.brightness, | ||
113 | pdata->max_brt_led); | ||
114 | else | ||
115 | dev_err(pchip->dev, | ||
116 | "No pwm control func. in plat-data\n"); | ||
117 | return bl->props.brightness; | ||
118 | } | ||
119 | |||
120 | /* i2c control and set brigtness */ | ||
121 | ret = regmap_write(pchip->regmap, REG_BL_CONF_4, bl->props.brightness); | ||
122 | if (ret < 0) | ||
123 | goto out; | ||
124 | ret = regmap_write(pchip->regmap, REG_BL_CONF_3, bl->props.brightness); | ||
125 | if (ret < 0) | ||
126 | goto out; | ||
127 | |||
128 | if (!bl->props.brightness) | ||
129 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x01, 0x00); | ||
130 | else | ||
131 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x01, 0x01); | ||
132 | if (ret < 0) | ||
133 | goto out; | ||
134 | |||
135 | return bl->props.brightness; | ||
136 | out: | ||
137 | dev_err(pchip->dev, "i2c failed to access registers\n"); | ||
138 | return bl->props.brightness; | ||
139 | } | ||
140 | |||
141 | static int lm3639_bled_get_brightness(struct backlight_device *bl) | ||
142 | { | ||
143 | int ret; | ||
144 | unsigned int reg_val; | ||
145 | struct lm3639_chip_data *pchip = bl_get_data(bl); | ||
146 | struct lm3639_platform_data *pdata = pchip->pdata; | ||
147 | |||
148 | if (pdata->pin_pwm) { | ||
149 | if (pdata->pwm_get_intensity) | ||
150 | bl->props.brightness = pdata->pwm_get_intensity(); | ||
151 | else | ||
152 | dev_err(pchip->dev, | ||
153 | "No pwm control func. in plat-data\n"); | ||
154 | return bl->props.brightness; | ||
155 | } | ||
156 | |||
157 | ret = regmap_read(pchip->regmap, REG_BL_CONF_1, ®_val); | ||
158 | if (ret < 0) | ||
159 | goto out; | ||
160 | if (reg_val & 0x10) | ||
161 | ret = regmap_read(pchip->regmap, REG_BL_CONF_4, ®_val); | ||
162 | else | ||
163 | ret = regmap_read(pchip->regmap, REG_BL_CONF_3, ®_val); | ||
164 | if (ret < 0) | ||
165 | goto out; | ||
166 | bl->props.brightness = reg_val; | ||
167 | |||
168 | return bl->props.brightness; | ||
169 | out: | ||
170 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
171 | return bl->props.brightness; | ||
172 | } | ||
173 | |||
174 | static const struct backlight_ops lm3639_bled_ops = { | ||
175 | .options = BL_CORE_SUSPENDRESUME, | ||
176 | .update_status = lm3639_bled_update_status, | ||
177 | .get_brightness = lm3639_bled_get_brightness, | ||
178 | }; | ||
179 | |||
180 | /* backlight mapping mode */ | ||
181 | static ssize_t lm3639_bled_mode_store(struct device *dev, | ||
182 | struct device_attribute *devAttr, | ||
183 | const char *buf, size_t size) | ||
184 | { | ||
185 | ssize_t ret; | ||
186 | struct lm3639_chip_data *pchip = dev_get_drvdata(dev); | ||
187 | unsigned int state; | ||
188 | |||
189 | ret = kstrtouint(buf, 10, &state); | ||
190 | if (ret) | ||
191 | goto out_input; | ||
192 | |||
193 | if (!state) | ||
194 | ret = | ||
195 | regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x10, | ||
196 | 0x00); | ||
197 | else | ||
198 | ret = | ||
199 | regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x10, | ||
200 | 0x10); | ||
201 | |||
202 | if (ret < 0) | ||
203 | goto out; | ||
204 | |||
205 | return size; | ||
206 | |||
207 | out: | ||
208 | dev_err(pchip->dev, "%s:i2c access fail to register\n", __func__); | ||
209 | return size; | ||
210 | |||
211 | out_input: | ||
212 | dev_err(pchip->dev, "%s:input conversion fail\n", __func__); | ||
213 | return size; | ||
214 | |||
215 | } | ||
216 | |||
217 | static DEVICE_ATTR(bled_mode, 0666, NULL, lm3639_bled_mode_store); | ||
218 | |||
219 | /* torch */ | ||
220 | static void lm3639_torch_brightness_set(struct led_classdev *cdev, | ||
221 | enum led_brightness brightness) | ||
222 | { | ||
223 | int ret; | ||
224 | unsigned int reg_val; | ||
225 | struct lm3639_chip_data *pchip; | ||
226 | |||
227 | pchip = container_of(cdev, struct lm3639_chip_data, cdev_torch); | ||
228 | |||
229 | ret = regmap_read(pchip->regmap, REG_FLAG, ®_val); | ||
230 | if (ret < 0) | ||
231 | goto out; | ||
232 | if (reg_val != 0) | ||
233 | dev_info(pchip->dev, "last flag is 0x%x\n", reg_val); | ||
234 | |||
235 | /* brightness 0 means off state */ | ||
236 | if (!brightness) { | ||
237 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x00); | ||
238 | if (ret < 0) | ||
239 | goto out; | ||
240 | return; | ||
241 | } | ||
242 | |||
243 | ret = regmap_update_bits(pchip->regmap, | ||
244 | REG_FL_CONF_1, 0x70, (brightness - 1) << 4); | ||
245 | if (ret < 0) | ||
246 | goto out; | ||
247 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x02); | ||
248 | if (ret < 0) | ||
249 | goto out; | ||
250 | |||
251 | return; | ||
252 | out: | ||
253 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
254 | return; | ||
255 | } | ||
256 | |||
257 | /* flash */ | ||
258 | static void lm3639_flash_brightness_set(struct led_classdev *cdev, | ||
259 | enum led_brightness brightness) | ||
260 | { | ||
261 | int ret; | ||
262 | unsigned int reg_val; | ||
263 | struct lm3639_chip_data *pchip; | ||
264 | |||
265 | pchip = container_of(cdev, struct lm3639_chip_data, cdev_flash); | ||
266 | |||
267 | ret = regmap_read(pchip->regmap, REG_FLAG, ®_val); | ||
268 | if (ret < 0) | ||
269 | goto out; | ||
270 | if (reg_val != 0) | ||
271 | dev_info(pchip->dev, "last flag is 0x%x\n", reg_val); | ||
272 | |||
273 | /* torch off before flash control */ | ||
274 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x00); | ||
275 | if (ret < 0) | ||
276 | goto out; | ||
277 | |||
278 | /* brightness 0 means off state */ | ||
279 | if (!brightness) | ||
280 | return; | ||
281 | |||
282 | ret = regmap_update_bits(pchip->regmap, | ||
283 | REG_FL_CONF_1, 0x0F, brightness - 1); | ||
284 | if (ret < 0) | ||
285 | goto out; | ||
286 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x06); | ||
287 | if (ret < 0) | ||
288 | goto out; | ||
289 | |||
290 | return; | ||
291 | out: | ||
292 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
293 | return; | ||
294 | } | ||
295 | |||
296 | static const struct regmap_config lm3639_regmap = { | ||
297 | .reg_bits = 8, | ||
298 | .val_bits = 8, | ||
299 | .max_register = REG_MAX, | ||
300 | }; | ||
301 | |||
302 | static int __devinit lm3639_probe(struct i2c_client *client, | ||
303 | const struct i2c_device_id *id) | ||
304 | { | ||
305 | int ret; | ||
306 | struct lm3639_chip_data *pchip; | ||
307 | struct lm3639_platform_data *pdata = client->dev.platform_data; | ||
308 | struct backlight_properties props; | ||
309 | |||
310 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
311 | dev_err(&client->dev, "i2c functionality check fail.\n"); | ||
312 | return -EOPNOTSUPP; | ||
313 | } | ||
314 | |||
315 | if (pdata == NULL) { | ||
316 | dev_err(&client->dev, "Needs Platform Data.\n"); | ||
317 | return -ENODATA; | ||
318 | } | ||
319 | |||
320 | pchip = devm_kzalloc(&client->dev, | ||
321 | sizeof(struct lm3639_chip_data), GFP_KERNEL); | ||
322 | if (!pchip) | ||
323 | return -ENOMEM; | ||
324 | |||
325 | pchip->pdata = pdata; | ||
326 | pchip->dev = &client->dev; | ||
327 | |||
328 | pchip->regmap = devm_regmap_init_i2c(client, &lm3639_regmap); | ||
329 | if (IS_ERR(pchip->regmap)) { | ||
330 | ret = PTR_ERR(pchip->regmap); | ||
331 | dev_err(&client->dev, "fail : allocate register map: %d\n", | ||
332 | ret); | ||
333 | return ret; | ||
334 | } | ||
335 | i2c_set_clientdata(client, pchip); | ||
336 | |||
337 | /* chip initialize */ | ||
338 | ret = lm3639_chip_init(pchip); | ||
339 | if (ret < 0) { | ||
340 | dev_err(&client->dev, "fail : chip init\n"); | ||
341 | goto err_out; | ||
342 | } | ||
343 | |||
344 | /* backlight */ | ||
345 | props.type = BACKLIGHT_RAW; | ||
346 | props.brightness = pdata->init_brt_led; | ||
347 | props.max_brightness = pdata->max_brt_led; | ||
348 | pchip->bled = | ||
349 | backlight_device_register("lm3639_bled", pchip->dev, pchip, | ||
350 | &lm3639_bled_ops, &props); | ||
351 | if (IS_ERR(pchip->bled)) { | ||
352 | dev_err(&client->dev, "fail : backlight register\n"); | ||
353 | ret = -EIO; | ||
354 | goto err_out; | ||
355 | } | ||
356 | |||
357 | ret = device_create_file(&(pchip->bled->dev), &dev_attr_bled_mode); | ||
358 | if (ret < 0) { | ||
359 | dev_err(&client->dev, "failed : add sysfs entries\n"); | ||
360 | ret = -EIO; | ||
361 | goto err_bled_mode; | ||
362 | } | ||
363 | |||
364 | /* flash */ | ||
365 | pchip->cdev_flash.name = "lm3639_flash"; | ||
366 | pchip->cdev_flash.max_brightness = 16; | ||
367 | pchip->cdev_flash.brightness_set = lm3639_flash_brightness_set; | ||
368 | ret = led_classdev_register((struct device *) | ||
369 | &client->dev, &pchip->cdev_flash); | ||
370 | if (ret < 0) { | ||
371 | dev_err(&client->dev, "fail : flash register\n"); | ||
372 | ret = -EIO; | ||
373 | goto err_flash; | ||
374 | } | ||
375 | |||
376 | /* torch */ | ||
377 | pchip->cdev_torch.name = "lm3639_torch"; | ||
378 | pchip->cdev_torch.max_brightness = 8; | ||
379 | pchip->cdev_torch.brightness_set = lm3639_torch_brightness_set; | ||
380 | ret = led_classdev_register((struct device *) | ||
381 | &client->dev, &pchip->cdev_torch); | ||
382 | if (ret < 0) { | ||
383 | dev_err(&client->dev, "fail : torch register\n"); | ||
384 | ret = -EIO; | ||
385 | goto err_torch; | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | |||
390 | err_torch: | ||
391 | led_classdev_unregister(&pchip->cdev_flash); | ||
392 | err_flash: | ||
393 | device_remove_file(&(pchip->bled->dev), &dev_attr_bled_mode); | ||
394 | err_bled_mode: | ||
395 | backlight_device_unregister(pchip->bled); | ||
396 | err_out: | ||
397 | return ret; | ||
398 | } | ||
399 | |||
400 | static int __devexit lm3639_remove(struct i2c_client *client) | ||
401 | { | ||
402 | struct lm3639_chip_data *pchip = i2c_get_clientdata(client); | ||
403 | |||
404 | regmap_write(pchip->regmap, REG_ENABLE, 0x00); | ||
405 | |||
406 | if (&pchip->cdev_torch) | ||
407 | led_classdev_unregister(&pchip->cdev_torch); | ||
408 | if (&pchip->cdev_flash) | ||
409 | led_classdev_unregister(&pchip->cdev_flash); | ||
410 | if (pchip->bled) { | ||
411 | device_remove_file(&(pchip->bled->dev), &dev_attr_bled_mode); | ||
412 | backlight_device_unregister(pchip->bled); | ||
413 | } | ||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static const struct i2c_device_id lm3639_id[] = { | ||
418 | {LM3639_NAME, 0}, | ||
419 | {} | ||
420 | }; | ||
421 | |||
422 | MODULE_DEVICE_TABLE(i2c, lm3639_id); | ||
423 | static struct i2c_driver lm3639_i2c_driver = { | ||
424 | .driver = { | ||
425 | .name = LM3639_NAME, | ||
426 | }, | ||
427 | .probe = lm3639_probe, | ||
428 | .remove = __devexit_p(lm3639_remove), | ||
429 | .id_table = lm3639_id, | ||
430 | }; | ||
431 | |||
432 | module_i2c_driver(lm3639_i2c_driver); | ||
433 | |||
434 | MODULE_DESCRIPTION("Texas Instruments Backlight+Flash LED driver for LM3639"); | ||
435 | MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); | ||
436 | MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); | ||
437 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c index 6c0f1ac0d32a..4066a5bbd826 100644 --- a/drivers/video/backlight/ltv350qv.c +++ b/drivers/video/backlight/ltv350qv.c | |||
@@ -75,7 +75,7 @@ static int ltv350qv_power_on(struct ltv350qv *lcd) | |||
75 | /* Power On Reset Display off State */ | 75 | /* Power On Reset Display off State */ |
76 | if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, 0x0000)) | 76 | if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, 0x0000)) |
77 | goto err; | 77 | goto err; |
78 | msleep(15); | 78 | usleep_range(15000, 16000); |
79 | 79 | ||
80 | /* Power Setting Function 1 */ | 80 | /* Power Setting Function 1 */ |
81 | if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE)) | 81 | if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE)) |
@@ -153,7 +153,7 @@ err_settings: | |||
153 | err_power2: | 153 | err_power2: |
154 | err_power1: | 154 | err_power1: |
155 | ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); | 155 | ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); |
156 | msleep(1); | 156 | usleep_range(1000, 1100); |
157 | err: | 157 | err: |
158 | ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); | 158 | ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); |
159 | return -EIO; | 159 | return -EIO; |
@@ -175,7 +175,7 @@ static int ltv350qv_power_off(struct ltv350qv *lcd) | |||
175 | ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); | 175 | ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); |
176 | 176 | ||
177 | /* Wait at least 1 ms */ | 177 | /* Wait at least 1 ms */ |
178 | msleep(1); | 178 | usleep_range(1000, 1100); |
179 | 179 | ||
180 | /* Power down setting 2 */ | 180 | /* Power down setting 2 */ |
181 | ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); | 181 | ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); |
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c index b6672340d6c7..ca4f5d70fe10 100644 --- a/drivers/video/backlight/platform_lcd.c +++ b/drivers/video/backlight/platform_lcd.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/fb.h> | 16 | #include <linux/fb.h> |
17 | #include <linux/backlight.h> | 17 | #include <linux/backlight.h> |
18 | #include <linux/lcd.h> | 18 | #include <linux/lcd.h> |
19 | #include <linux/of.h> | ||
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | 21 | ||
21 | #include <video/platform_lcd.h> | 22 | #include <video/platform_lcd.h> |
@@ -145,6 +146,14 @@ static SIMPLE_DEV_PM_OPS(platform_lcd_pm_ops, platform_lcd_suspend, | |||
145 | platform_lcd_resume); | 146 | platform_lcd_resume); |
146 | #endif | 147 | #endif |
147 | 148 | ||
149 | #ifdef CONFIG_OF | ||
150 | static const struct of_device_id platform_lcd_of_match[] = { | ||
151 | { .compatible = "platform-lcd" }, | ||
152 | {}, | ||
153 | }; | ||
154 | MODULE_DEVICE_TABLE(of, platform_lcd_of_match); | ||
155 | #endif | ||
156 | |||
148 | static struct platform_driver platform_lcd_driver = { | 157 | static struct platform_driver platform_lcd_driver = { |
149 | .driver = { | 158 | .driver = { |
150 | .name = "platform-lcd", | 159 | .name = "platform-lcd", |
@@ -152,6 +161,7 @@ static struct platform_driver platform_lcd_driver = { | |||
152 | #ifdef CONFIG_PM | 161 | #ifdef CONFIG_PM |
153 | .pm = &platform_lcd_pm_ops, | 162 | .pm = &platform_lcd_pm_ops, |
154 | #endif | 163 | #endif |
164 | .of_match_table = of_match_ptr(platform_lcd_of_match), | ||
155 | }, | 165 | }, |
156 | .probe = platform_lcd_probe, | 166 | .probe = platform_lcd_probe, |
157 | .remove = __devexit_p(platform_lcd_remove), | 167 | .remove = __devexit_p(platform_lcd_remove), |
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c deleted file mode 100644 index 69b35f02929e..000000000000 --- a/drivers/video/backlight/progear_bl.c +++ /dev/null | |||
@@ -1,162 +0,0 @@ | |||
1 | /* | ||
2 | * Backlight Driver for Frontpath ProGear HX1050+ | ||
3 | * | ||
4 | * Copyright (c) 2006 Marcin Juszkiewicz | ||
5 | * | ||
6 | * Based on Progear LCD driver by M Schacht | ||
7 | * <mschacht at alumni dot washington dot edu> | ||
8 | * | ||
9 | * Based on Sharp's Corgi Backlight Driver | ||
10 | * Based on Backlight Driver for HP Jornada 680 | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/mutex.h> | ||
25 | #include <linux/fb.h> | ||
26 | #include <linux/backlight.h> | ||
27 | #include <linux/pci.h> | ||
28 | |||
29 | #define PMU_LPCR 0xB0 | ||
30 | #define SB_MPS1 0x61 | ||
31 | #define HW_LEVEL_MAX 0x77 | ||
32 | #define HW_LEVEL_MIN 0x4f | ||
33 | |||
34 | static struct pci_dev *pmu_dev = NULL; | ||
35 | static struct pci_dev *sb_dev = NULL; | ||
36 | |||
37 | static int progearbl_set_intensity(struct backlight_device *bd) | ||
38 | { | ||
39 | int intensity = bd->props.brightness; | ||
40 | |||
41 | if (bd->props.power != FB_BLANK_UNBLANK) | ||
42 | intensity = 0; | ||
43 | if (bd->props.fb_blank != FB_BLANK_UNBLANK) | ||
44 | intensity = 0; | ||
45 | |||
46 | pci_write_config_byte(pmu_dev, PMU_LPCR, intensity + HW_LEVEL_MIN); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static int progearbl_get_intensity(struct backlight_device *bd) | ||
52 | { | ||
53 | u8 intensity; | ||
54 | pci_read_config_byte(pmu_dev, PMU_LPCR, &intensity); | ||
55 | |||
56 | return intensity - HW_LEVEL_MIN; | ||
57 | } | ||
58 | |||
59 | static const struct backlight_ops progearbl_ops = { | ||
60 | .get_brightness = progearbl_get_intensity, | ||
61 | .update_status = progearbl_set_intensity, | ||
62 | }; | ||
63 | |||
64 | static int progearbl_probe(struct platform_device *pdev) | ||
65 | { | ||
66 | struct backlight_properties props; | ||
67 | u8 temp; | ||
68 | struct backlight_device *progear_backlight_device; | ||
69 | int ret; | ||
70 | |||
71 | pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); | ||
72 | if (!pmu_dev) { | ||
73 | pr_err("ALI M7101 PMU not found.\n"); | ||
74 | return -ENODEV; | ||
75 | } | ||
76 | |||
77 | sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); | ||
78 | if (!sb_dev) { | ||
79 | pr_err("ALI 1533 SB not found.\n"); | ||
80 | ret = -ENODEV; | ||
81 | goto put_pmu; | ||
82 | } | ||
83 | |||
84 | /* Set SB_MPS1 to enable brightness control. */ | ||
85 | pci_read_config_byte(sb_dev, SB_MPS1, &temp); | ||
86 | pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20); | ||
87 | |||
88 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
89 | props.type = BACKLIGHT_RAW; | ||
90 | props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; | ||
91 | progear_backlight_device = backlight_device_register("progear-bl", | ||
92 | &pdev->dev, NULL, | ||
93 | &progearbl_ops, | ||
94 | &props); | ||
95 | if (IS_ERR(progear_backlight_device)) { | ||
96 | ret = PTR_ERR(progear_backlight_device); | ||
97 | goto put_sb; | ||
98 | } | ||
99 | |||
100 | platform_set_drvdata(pdev, progear_backlight_device); | ||
101 | |||
102 | progear_backlight_device->props.power = FB_BLANK_UNBLANK; | ||
103 | progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; | ||
104 | progearbl_set_intensity(progear_backlight_device); | ||
105 | |||
106 | return 0; | ||
107 | put_sb: | ||
108 | pci_dev_put(sb_dev); | ||
109 | put_pmu: | ||
110 | pci_dev_put(pmu_dev); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | static int progearbl_remove(struct platform_device *pdev) | ||
115 | { | ||
116 | struct backlight_device *bd = platform_get_drvdata(pdev); | ||
117 | backlight_device_unregister(bd); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static struct platform_driver progearbl_driver = { | ||
123 | .probe = progearbl_probe, | ||
124 | .remove = progearbl_remove, | ||
125 | .driver = { | ||
126 | .name = "progear-bl", | ||
127 | }, | ||
128 | }; | ||
129 | |||
130 | static struct platform_device *progearbl_device; | ||
131 | |||
132 | static int __init progearbl_init(void) | ||
133 | { | ||
134 | int ret = platform_driver_register(&progearbl_driver); | ||
135 | |||
136 | if (ret) | ||
137 | return ret; | ||
138 | progearbl_device = platform_device_register_simple("progear-bl", -1, | ||
139 | NULL, 0); | ||
140 | if (IS_ERR(progearbl_device)) { | ||
141 | platform_driver_unregister(&progearbl_driver); | ||
142 | return PTR_ERR(progearbl_device); | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static void __exit progearbl_exit(void) | ||
149 | { | ||
150 | pci_dev_put(pmu_dev); | ||
151 | pci_dev_put(sb_dev); | ||
152 | |||
153 | platform_device_unregister(progearbl_device); | ||
154 | platform_driver_unregister(&progearbl_driver); | ||
155 | } | ||
156 | |||
157 | module_init(progearbl_init); | ||
158 | module_exit(progearbl_exit); | ||
159 | |||
160 | MODULE_AUTHOR("Marcin Juszkiewicz <linux@hrw.one.pl>"); | ||
161 | MODULE_DESCRIPTION("ProGear Backlight Driver"); | ||
162 | MODULE_LICENSE("GPL"); | ||