#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+#include <linux/spinlock.h>
#include <linux/earlysuspend.h>
#include <asm/intel_kpd_gpio_led.h>
static int gpio;
+static spinlock_t lock;
static void intel_keypad_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
- if (value > 0)
- gpio_set_value(gpio, 1);
- else
+ int i, level;
+ u32 elapsed, needed;
+ unsigned long flags;
+ static ktime_t out;
+
+ elapsed = ktime_to_us(ktime_sub(ktime_get(), out));
+ if (unlikely(elapsed < 500)) {
+ needed = 500 - elapsed;
+ usleep_range(needed, needed + 50);
+ }
+
+ /* According to the AHK3292 Datasheet, AHK3292 has 32 level output
+ * current settings, range from 1 ~ 32, 1 is the highest and 32 is
+ * the lowest.*/
+ if (value > 0) {
+ level = ((100 - value) * 32 / 100) + 1;
+ spin_lock_irqsave(&lock, flags);
+ for (i = 0; i < level; i++) {
+ gpio_set_value(gpio, 0);
+ udelay(1);
+ gpio_set_value(gpio, 1);
+ udelay(1);
+ }
+ spin_unlock_irqrestore(&lock, flags);
+ } else {
gpio_set_value(gpio, 0);
+ }
+
+ out = ktime_get();
}
static struct led_classdev intel_kpd_led = {
.name = "intel_keypad_led",
.brightness_set = intel_keypad_led_set,
.brightness = LED_OFF,
- .max_brightness = LED_FULL,
+ .max_brightness = 15,
};
static void intel_kpd_led_early_suspend(struct early_suspend *h)
int ret;
struct intel_kpd_gpio_led_pdata *pdata;
+ spin_lock_init(&lock);
+
pdata = pdev->dev.platform_data;
if (!pdata)
return -EINVAL;