diff options
-rw-r--r-- | drivers/leds/leds-lm3530.c | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index b37e6186d0fa..4d7ce7631acf 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/input.h> | 17 | #include <linux/input.h> |
18 | #include <linux/led-lm3530.h> | 18 | #include <linux/led-lm3530.h> |
19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | #include <linux/regulator/consumer.h> | ||
20 | 21 | ||
21 | #define LM3530_LED_DEV "lcd-backlight" | 22 | #define LM3530_LED_DEV "lcd-backlight" |
22 | #define LM3530_NAME "lm3530-led" | 23 | #define LM3530_NAME "lm3530-led" |
@@ -96,12 +97,18 @@ static struct lm3530_mode_map mode_map[] = { | |||
96 | * @client: i2c client | 97 | * @client: i2c client |
97 | * @pdata: LM3530 platform data | 98 | * @pdata: LM3530 platform data |
98 | * @mode: mode of operation - manual, ALS, PWM | 99 | * @mode: mode of operation - manual, ALS, PWM |
100 | * @regulator: regulator | ||
101 | * @brighness: previous brightness value | ||
102 | * @enable: regulator is enabled | ||
99 | */ | 103 | */ |
100 | struct lm3530_data { | 104 | struct lm3530_data { |
101 | struct led_classdev led_dev; | 105 | struct led_classdev led_dev; |
102 | struct i2c_client *client; | 106 | struct i2c_client *client; |
103 | struct lm3530_platform_data *pdata; | 107 | struct lm3530_platform_data *pdata; |
104 | enum lm3530_mode mode; | 108 | enum lm3530_mode mode; |
109 | struct regulator *regulator; | ||
110 | enum led_brightness brightness; | ||
111 | bool enable; | ||
105 | }; | 112 | }; |
106 | 113 | ||
107 | static const u8 lm3530_reg[LM3530_REG_MAX] = { | 114 | static const u8 lm3530_reg[LM3530_REG_MAX] = { |
@@ -172,7 +179,10 @@ static int lm3530_init_registers(struct lm3530_data *drvdata) | |||
172 | brt_ramp = (pltfm->brt_ramp_fall << LM3530_BRT_RAMP_FALL_SHIFT) | | 179 | brt_ramp = (pltfm->brt_ramp_fall << LM3530_BRT_RAMP_FALL_SHIFT) | |
173 | (pltfm->brt_ramp_rise << LM3530_BRT_RAMP_RISE_SHIFT); | 180 | (pltfm->brt_ramp_rise << LM3530_BRT_RAMP_RISE_SHIFT); |
174 | 181 | ||
175 | brightness = pltfm->brt_val; | 182 | if (drvdata->brightness) |
183 | brightness = drvdata->brightness; | ||
184 | else | ||
185 | brightness = drvdata->brightness = pltfm->brt_val; | ||
176 | 186 | ||
177 | reg_val[0] = gen_config; /* LM3530_GEN_CONFIG */ | 187 | reg_val[0] = gen_config; /* LM3530_GEN_CONFIG */ |
178 | reg_val[1] = als_config; /* LM3530_ALS_CONFIG */ | 188 | reg_val[1] = als_config; /* LM3530_ALS_CONFIG */ |
@@ -190,6 +200,16 @@ static int lm3530_init_registers(struct lm3530_data *drvdata) | |||
190 | reg_val[13] = LM3530_DEF_ZT_3; /* LM3530_ALS_Z3T_REG */ | 200 | reg_val[13] = LM3530_DEF_ZT_3; /* LM3530_ALS_Z3T_REG */ |
191 | reg_val[14] = LM3530_DEF_ZT_4; /* LM3530_ALS_Z4T_REG */ | 201 | reg_val[14] = LM3530_DEF_ZT_4; /* LM3530_ALS_Z4T_REG */ |
192 | 202 | ||
203 | if (!drvdata->enable) { | ||
204 | ret = regulator_enable(drvdata->regulator); | ||
205 | if (ret) { | ||
206 | dev_err(&drvdata->client->dev, | ||
207 | "Enable regulator failed\n"); | ||
208 | return ret; | ||
209 | } | ||
210 | drvdata->enable = true; | ||
211 | } | ||
212 | |||
193 | for (i = 0; i < LM3530_REG_MAX; i++) { | 213 | for (i = 0; i < LM3530_REG_MAX; i++) { |
194 | ret = i2c_smbus_write_byte_data(client, | 214 | ret = i2c_smbus_write_byte_data(client, |
195 | lm3530_reg[i], reg_val[i]); | 215 | lm3530_reg[i], reg_val[i]); |
@@ -210,12 +230,31 @@ static void lm3530_brightness_set(struct led_classdev *led_cdev, | |||
210 | switch (drvdata->mode) { | 230 | switch (drvdata->mode) { |
211 | case LM3530_BL_MODE_MANUAL: | 231 | case LM3530_BL_MODE_MANUAL: |
212 | 232 | ||
233 | if (!drvdata->enable) { | ||
234 | err = lm3530_init_registers(drvdata); | ||
235 | if (err) { | ||
236 | dev_err(&drvdata->client->dev, | ||
237 | "Register Init failed: %d\n", err); | ||
238 | break; | ||
239 | } | ||
240 | } | ||
241 | |||
213 | /* set the brightness in brightness control register*/ | 242 | /* set the brightness in brightness control register*/ |
214 | err = i2c_smbus_write_byte_data(drvdata->client, | 243 | err = i2c_smbus_write_byte_data(drvdata->client, |
215 | LM3530_BRT_CTRL_REG, brt_val / 2); | 244 | LM3530_BRT_CTRL_REG, brt_val / 2); |
216 | if (err) | 245 | if (err) |
217 | dev_err(&drvdata->client->dev, | 246 | dev_err(&drvdata->client->dev, |
218 | "Unable to set brightness: %d\n", err); | 247 | "Unable to set brightness: %d\n", err); |
248 | else | ||
249 | drvdata->brightness = brt_val / 2; | ||
250 | |||
251 | if (brt_val == 0) { | ||
252 | err = regulator_disable(drvdata->regulator); | ||
253 | if (err) | ||
254 | dev_err(&drvdata->client->dev, | ||
255 | "Disable regulator failed\n"); | ||
256 | drvdata->enable = false; | ||
257 | } | ||
219 | break; | 258 | break; |
220 | case LM3530_BL_MODE_ALS: | 259 | case LM3530_BL_MODE_ALS: |
221 | break; | 260 | break; |
@@ -297,20 +336,31 @@ static int __devinit lm3530_probe(struct i2c_client *client, | |||
297 | drvdata->mode = pdata->mode; | 336 | drvdata->mode = pdata->mode; |
298 | drvdata->client = client; | 337 | drvdata->client = client; |
299 | drvdata->pdata = pdata; | 338 | drvdata->pdata = pdata; |
339 | drvdata->brightness = LED_OFF; | ||
340 | drvdata->enable = false; | ||
300 | drvdata->led_dev.name = LM3530_LED_DEV; | 341 | drvdata->led_dev.name = LM3530_LED_DEV; |
301 | drvdata->led_dev.brightness_set = lm3530_brightness_set; | 342 | drvdata->led_dev.brightness_set = lm3530_brightness_set; |
302 | 343 | ||
303 | i2c_set_clientdata(client, drvdata); | 344 | i2c_set_clientdata(client, drvdata); |
304 | 345 | ||
305 | err = lm3530_init_registers(drvdata); | 346 | drvdata->regulator = regulator_get(&client->dev, "vin"); |
306 | if (err < 0) { | 347 | if (IS_ERR(drvdata->regulator)) { |
307 | dev_err(&client->dev, "Register Init failed: %d\n", err); | 348 | dev_err(&client->dev, "regulator get failed\n"); |
308 | err = -ENODEV; | 349 | err = PTR_ERR(drvdata->regulator); |
309 | goto err_reg_init; | 350 | drvdata->regulator = NULL; |
351 | goto err_regulator_get; | ||
310 | } | 352 | } |
311 | 353 | ||
312 | err = led_classdev_register((struct device *) | 354 | if (drvdata->pdata->brt_val) { |
313 | &client->dev, &drvdata->led_dev); | 355 | err = lm3530_init_registers(drvdata); |
356 | if (err < 0) { | ||
357 | dev_err(&client->dev, | ||
358 | "Register Init failed: %d\n", err); | ||
359 | err = -ENODEV; | ||
360 | goto err_reg_init; | ||
361 | } | ||
362 | } | ||
363 | err = led_classdev_register(&client->dev, &drvdata->led_dev); | ||
314 | if (err < 0) { | 364 | if (err < 0) { |
315 | dev_err(&client->dev, "Register led class failed: %d\n", err); | 365 | dev_err(&client->dev, "Register led class failed: %d\n", err); |
316 | err = -ENODEV; | 366 | err = -ENODEV; |
@@ -330,6 +380,9 @@ err_create_file: | |||
330 | led_classdev_unregister(&drvdata->led_dev); | 380 | led_classdev_unregister(&drvdata->led_dev); |
331 | err_class_register: | 381 | err_class_register: |
332 | err_reg_init: | 382 | err_reg_init: |
383 | regulator_put(drvdata->regulator); | ||
384 | err_regulator_get: | ||
385 | i2c_set_clientdata(client, NULL); | ||
333 | kfree(drvdata); | 386 | kfree(drvdata); |
334 | err_out: | 387 | err_out: |
335 | return err; | 388 | return err; |
@@ -340,6 +393,10 @@ static int __devexit lm3530_remove(struct i2c_client *client) | |||
340 | struct lm3530_data *drvdata = i2c_get_clientdata(client); | 393 | struct lm3530_data *drvdata = i2c_get_clientdata(client); |
341 | 394 | ||
342 | device_remove_file(drvdata->led_dev.dev, &dev_attr_mode); | 395 | device_remove_file(drvdata->led_dev.dev, &dev_attr_mode); |
396 | |||
397 | if (drvdata->enable) | ||
398 | regulator_disable(drvdata->regulator); | ||
399 | regulator_put(drvdata->regulator); | ||
343 | led_classdev_unregister(&drvdata->led_dev); | 400 | led_classdev_unregister(&drvdata->led_dev); |
344 | kfree(drvdata); | 401 | kfree(drvdata); |
345 | return 0; | 402 | return 0; |