diff options
Diffstat (limited to 'drivers/leds/leds-max77693.c')
-rw-r--r-- | drivers/leds/leds-max77693.c | 101 |
1 files changed, 85 insertions, 16 deletions
diff --git a/drivers/leds/leds-max77693.c b/drivers/leds/leds-max77693.c index bdbb953..05499b8 100644 --- a/drivers/leds/leds-max77693.c +++ b/drivers/leds/leds-max77693.c @@ -18,6 +18,12 @@ #include <linux/mfd/max77693.h> #include <linux/mfd/max77693-private.h> #include <linux/leds-max77693.h> +#include <linux/ctype.h> + +#ifdef CONFIG_LEDS_SWITCH +#include <linux/gpio.h> +#define FLASH_SWITCH_REMOVED_REVISION 0x05 +#endif struct max77693_led_data { struct led_classdev led; @@ -73,6 +79,9 @@ static u8 led_current_shift[MAX77693_LED_MAX] = { 4, }; +extern struct class *camera_class; /*sys/class/camera*/ +struct device *flash_dev; + static int max77693_set_bits(struct i2c_client *client, const u8 reg, const u8 mask, const u8 inval) { @@ -104,14 +113,17 @@ static void print_all_reg_value(struct i2c_client *client) static int max77693_led_get_en_value(struct max77693_led_data *led_data, int on) { if (on) - return 0x03; + return 0x03; /*triggered via serial interface*/ +#if 0 if (led_data->data->cntrl_mode == MAX77693_LED_CTRL_BY_I2C) return 0x00; - else if (led_data->data->id < 2) - return 0x01; +#endif + + if (led_data->data->id < 2) + return 0x01; /*Flash triggered via FLASHEN*/ else - return 0x02; + return 0x02; /*Torch triggered via TORCHEN*/ } static void max77693_led_set(struct led_classdev *led_cdev, enum led_brightness value) @@ -163,8 +175,8 @@ static void led_set(struct max77693_led_data *led_data) if (unlikely(ret)) goto error_set_bits; - /* Turn off LED */ - value = max77693_led_get_en_value(led_data, 0); + /* Turn on LED */ + value = max77693_led_get_en_value(led_data, 1); ret = max77693_set_bits(led_data->i2c, MAX77693_LED_REG_FLASH_EN, led_en_mask[id], value << led_en_shift[id]); @@ -172,13 +184,6 @@ static void led_set(struct max77693_led_data *led_data) if (unlikely(ret)) goto error_set_bits; - /* Turn on LED */ - ret = max77693_set_bits(led_data->i2c, MAX77693_LED_REG_FLASH_EN, - led_en_mask[id], led_en_mask[id]); - - if (unlikely(ret)) - goto error_set_bits; - return; error_set_bits: @@ -211,7 +216,7 @@ static int max77693_led_setup(struct max77693_led_data *led_data) ret |= max77693_write_reg(led_data->i2c, MAX77693_LED_REG_VOUT_FLASH1, MAX77693_BOOST_VOUT_FLASH_FROM_VOLT(5000)); ret |= max77693_write_reg(led_data->i2c, - MAX77693_LED_REG_MAX_FLASH1, 0xEC); + MAX77693_LED_REG_MAX_FLASH1, 0x80); ret |= max77693_write_reg(led_data->i2c, MAX77693_LED_REG_MAX_FLASH2, 0x00); @@ -227,7 +232,7 @@ static int max77693_led_setup(struct max77693_led_data *led_data) (data->timer | data->timer_mode << 7)); } else { ret |= max77693_write_reg(led_data->i2c, reg_led_timer[id], - 0xC0); + 0x40); } /* Set current */ @@ -238,6 +243,34 @@ static int max77693_led_setup(struct max77693_led_data *led_data) return ret; } +static ssize_t max77693_flash(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + ssize_t ret = -EINVAL; + char *after; + unsigned long state = simple_strtoul(buf, &after, 10); + size_t count = after - buf; + + if (isspace(*after)) + count++; + + if (count == size) { + ret = count; + + if (state > led_cdev->max_brightness) + state = led_cdev->max_brightness; + led_cdev->brightness = state; + if (!(led_cdev->flags & LED_SUSPENDED)) + led_cdev->brightness_set(led_cdev, state); + } + + return ret; +} + +static DEVICE_ATTR(rear_flash, S_IWUSR|S_IWGRP|S_IROTH, + NULL, max77693_flash); + static int max77693_led_probe(struct platform_device *pdev) { int ret = 0; @@ -284,7 +317,7 @@ static int max77693_led_probe(struct platform_device *pdev) led_data->led.brightness_set = max77693_led_set; led_data->led.brightness = LED_OFF; led_data->brightness = data->brightness; - led_data->led.flags = LED_CORE_SUSPENDRESUME; + led_data->led.flags = 0; led_data->led.max_brightness = data->id < 2 ? MAX_FLASH_DRV_LEVEL : MAX_TORCH_DRV_LEVEL; @@ -303,12 +336,32 @@ static int max77693_led_probe(struct platform_device *pdev) ret = max77693_led_setup(led_data); if (unlikely(ret)) { pr_err("unable to register LED\n"); + mutex_destroy(&led_data->lock); led_classdev_unregister(&led_data->led); kfree(led_data); ret = -EFAULT; } } /* print_all_reg_value(max77693->i2c); */ + + flash_dev = device_create(camera_class, NULL, 0, led_datas[2], "flash"); + if (flash_dev < 0) + pr_err("Failed to create device(flash)!\n"); + + if (device_create_file(flash_dev, &dev_attr_rear_flash) < 0) { + pr_err("failed to create device file, %s\n", + dev_attr_rear_flash.attr.name); + } + +#ifdef CONFIG_LEDS_SWITCH + if (system_rev < FLASH_SWITCH_REMOVED_REVISION) { + if (gpio_request(GPIO_CAM_SW_EN, "CAM_SW_EN")) + pr_err("failed to request CAM_SW_EN\n"); + else + gpio_direction_output(GPIO_CAM_SW_EN, 1); + } +#endif + return ret; } @@ -328,9 +381,24 @@ static int __devexit max77693_led_remove(struct platform_device *pdev) } kfree(led_datas); + device_remove_file(flash_dev, &dev_attr_rear_flash); + device_destroy(camera_class, 0); + class_destroy(camera_class); + return 0; } +void max77693_led_shutdown(struct device *dev) +{ + struct max77693_led_data **led_datas = dev_get_drvdata(dev); + + /* Turn off LED */ + max77693_set_bits(led_datas[2]->i2c, + MAX77693_LED_REG_FLASH_EN, + led_en_mask[2], + 0x02 << led_en_shift[2]); +} + static struct platform_driver max77693_led_driver = { .probe = max77693_led_probe, @@ -339,6 +407,7 @@ static struct platform_driver max77693_led_driver = { .name = "max77693-led", .owner = THIS_MODULE, + .shutdown = max77693_led_shutdown, }, }; |