aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds/leds-max77693.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/leds/leds-max77693.c')
-rw-r--r--drivers/leds/leds-max77693.c101
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,
},
};