Skip to content

Instantly share code, notes, and snippets.

@fat-tire
Created June 2, 2012 19:48
Show Gist options
  • Save fat-tire/2859735 to your computer and use it in GitHub Desktop.
Save fat-tire/2859735 to your computer and use it in GitHub Desktop.
patch to new led driver for encore
$ git diff
diff --git a/arch/arm/mach-omap2/board-encore-display.c b/arch/arm/mach-omap2/board-encore-display.c
index b055e71..22ecb2c 100644
--- a/arch/arm/mach-omap2/board-encore-display.c
+++ b/arch/arm/mach-omap2/board-encore-display.c
@@ -31,7 +31,7 @@
#define LCD_CABC1_GPIO 45
#define LCD_BACKLIGHT_EN_EVT2 47
-#define DEFAULT_BACKLIGHT_BRIGHTNESS 105
+#define DEFAULT_BACKLIGHT_BRIGHTNESS 75
/*---backlight--------------------------------------------------------------------*/
static void boxer_backlight_set_power(struct omap_pwm_led_platform_data *self, int on_off)
@@ -46,7 +46,7 @@ static struct omap_pwm_led_platform_data boxer_backlight_data = {
.bkl_max = 254,
.bkl_min = 5,
.bkl_freq = 128,
- .invert = 1,
+ .invert = 0,
.def_brightness = DEFAULT_BACKLIGHT_BRIGHTNESS,
.set_power = boxer_backlight_set_power,
};
@@ -62,17 +62,12 @@ static struct platform_device boxer_backlight_led_device = {
static void __init boxer_backlight_init(void)
{
printk("Enabling backlight PWM for LCD\n");
- //boxer_backlight_data.def_on = 1; // change the PWM polarity
- gpio_request(LCD_BACKLIGHT_EN_EVT2, "lcd backlight evt2");
-
- gpio_request(LCD_CABC0_GPIO, "lcd CABC0");
- gpio_direction_output(LCD_CABC0_GPIO,0);
- gpio_set_value(LCD_CABC0_GPIO,0);
-
- gpio_request(LCD_CABC1_GPIO, "lcd CABC1");
- gpio_direction_output(LCD_CABC1_GPIO,0);
- gpio_set_value(LCD_CABC1_GPIO,0);
+ omap_mux_init_signal("usbb1_ulpitll_dat4.gpio_92", OMAP_MUX_MODE3);
+ if (gpio_request(92, "EVT1 BACKLIGHT"))
+ printk(KERN_ERR "ERROR: failed to request backlight gpio\n");
+ else
+ gpio_direction_output(92, 0);
}
/*--------------------------------------------------------------------------*/
@@ -132,9 +127,6 @@ void __init encore_display_init(void)
boxer_backlight_init();
spi_register_board_info(evt_spi_board_info,
ARRAY_SIZE(evt_spi_board_info));
-
- platform_add_devices(evt_panel_devices, ARRAY_SIZE(evt_panel_devices));
omap_display_init(&evt_dss_data);
-
+ platform_add_devices(evt_panel_devices, ARRAY_SIZE(evt_panel_devices));
}
-
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index e807a61..591d75c 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -54,6 +54,7 @@
#define _OMAP_TIMER_STAT_OFFSET 0x18
#define _OMAP_TIMER_INT_EN_OFFSET 0x1c
#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20
+#define _OMAP_TIMER_INT_CLR_OFFSET 0x30
#define _OMAP_TIMER_CTRL_OFFSET 0x24
#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13)
@@ -111,6 +112,9 @@
#define OMAP_TIMER_INT_EN_REG (_OMAP_TIMER_INT_EN_OFFSET \
| (WP_NONE << WPSHIFT))
+#define OMAP_TIMER_INT_CLR_REG (_OMAP_TIMER_INT_CLR_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \
| (WP_NONE << WPSHIFT))
@@ -753,6 +757,13 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
+unsigned int omap_dm_timer_get_match(struct omap_dm_timer *timer)
+{
+ return omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG);
+}
+
+EXPORT_SYMBOL_GPL(omap_dm_timer_get_match);
+
int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
int toggle, int trigger)
{
@@ -823,6 +834,27 @@ int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
+void omap_dm_timer_set_int_disable(struct omap_dm_timer *timer,
+ unsigned int value)
+{
+ u32 l;
+ struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
+ omap_dm_timer_enable(timer);
+
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG);
+ if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
+ l |= value;
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_CLR_REG, value);
+ } else {
+ l &= ~value;
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, l);
+ }
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable);
+
+
unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
{
unsigned long flags;
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index aaa676f..6b57180 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -155,6 +155,9 @@ int omap_dm_timer_write_counter(struct omap_dm_timer *timer,
unsigned int value);
int omap_dm_timers_active(void);
+void omap_dm_timer_set_int_disable(struct omap_dm_timer *, unsigned int);
+
+unsigned int omap_dm_timer_get_match(struct omap_dm_timer *timer);
#endif /* __ASM_ARCH_DMTIMER_H */
diff --git a/drivers/leds/leds-omap-pwm.c b/drivers/leds/leds-omap-pwm.c
index f01b4c8..197cb33 100644
--- a/drivers/leds/leds-omap-pwm.c
+++ b/drivers/leds/leds-omap-pwm.c
@@ -9,34 +9,56 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#define DEBUG
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/earlysuspend.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/ctype.h>
#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
#include <linux/clk.h>
-#include <asm/delay.h>
#include <plat/board.h>
#include <plat/dmtimer.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
+#include "leds-omap-pwm.h"
-#define MAX_GPTIMER_ID 12
+/* 38400000 / (1 << (COUNTER_DEVIDER + 1)) */
+#define COUNTER_DEVIDER 5 /* 600000 Hz counter in freq */
+#define COUNTER_LOAD_VAL (0xFFFFFFFF - 4687 - 4) /* 128 Hz PWM out freq */
+#define COUNTER_TO_MATCH_GUARD 80
+
+#define TIMER_INT_FLAGS (OMAP_TIMER_INT_MATCH | \
+ OMAP_TIMER_INT_OVERFLOW)
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void omap_pwm_led_early_suspend(struct early_suspend *handler);
+static void omap_pwm_led_late_resume(struct early_suspend *handler);
+#endif
struct omap_pwm_led {
struct led_classdev cdev;
+ struct work_struct work;
struct omap_pwm_led_platform_data *pdata;
struct omap_dm_timer *intensity_timer;
struct omap_dm_timer *blink_timer;
int powered;
unsigned int on_period, off_period;
enum led_brightness brightness;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ atomic_t cached_match_val;
};
+static inline unsigned int get_match_val(unsigned char index)
+{
+ return match_data[index];
+}
+
static inline struct omap_pwm_led *pdev_to_omap_pwm_led(struct platform_device *pdev)
{
return platform_get_drvdata(pdev);
@@ -47,8 +69,18 @@ static inline struct omap_pwm_led *cdev_to_omap_pwm_led(struct led_classdev *led
return container_of(led_cdev, struct omap_pwm_led, cdev);
}
+static inline struct omap_pwm_led *work_to_omap_pwm_led(struct work_struct *work)
+{
+ return container_of(work, struct omap_pwm_led, work);
+}
+
static void omap_pwm_led_set_blink(struct omap_pwm_led *led)
{
+ int invert = 1;
+
+ if (led->pdata)
+ invert = led->pdata->invert;
+
if (!led->powered)
return;
@@ -56,136 +88,181 @@ static void omap_pwm_led_set_blink(struct omap_pwm_led *led)
unsigned long load_reg, cmp_reg;
load_reg = 32768 * (led->on_period + led->off_period) / 1000;
- cmp_reg = 32768 * (led->on_period) / 1000;
+ cmp_reg = 32768 * led->on_period / 1000;
omap_dm_timer_stop(led->blink_timer);
omap_dm_timer_set_load(led->blink_timer, 1, -load_reg);
omap_dm_timer_set_match(led->blink_timer, 1, -cmp_reg);
- omap_dm_timer_set_pwm(led->blink_timer, 1, 1,
+ omap_dm_timer_set_pwm(led->blink_timer,
+ invert, 1,
OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
omap_dm_timer_write_counter(led->blink_timer, -2);
omap_dm_timer_start(led->blink_timer);
} else {
- omap_dm_timer_set_pwm(led->blink_timer, 1, 1,
+ omap_dm_timer_set_pwm(led->blink_timer,
+ invert, 1,
OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
omap_dm_timer_stop(led->blink_timer);
}
}
-static void omap_pwm_led_pad_enable(struct omap_pwm_led *led)
+static inline void omap_pwm_set_match(struct omap_dm_timer *timer,
+ unsigned int val)
{
- if (led->pdata->set_pad)
- led->pdata->set_pad(led->pdata, 1);
+ omap_dm_timer_set_match(timer, 1, val);
+ omap_dm_timer_set_int_disable(timer, TIMER_INT_FLAGS);
}
-static void omap_pwm_led_pad_disable(struct omap_pwm_led *led)
+static irqreturn_t intensity_timer_match_interrupt(int irq, void *arg)
{
- if (led->pdata->set_pad)
- led->pdata->set_pad(led->pdata, 0);
+ struct omap_pwm_led *led;
+ struct omap_dm_timer *timer;
+ unsigned int counter;
+ unsigned int match_val;
+ unsigned int current_match_val;
+ unsigned int status;
+
+ led = (struct omap_pwm_led *) arg;
+ timer = (struct omap_dm_timer *) led->intensity_timer;
+ match_val = atomic_read(&led->cached_match_val);
+
+ /* disable interrupts */
+ local_irq_disable();
+
+ /* get int status */
+ status = omap_dm_timer_read_status(timer);
+
+ /* get current match value */
+ current_match_val = omap_dm_timer_get_match(timer);
+
+ /* We must update match register only in case:
+ * - new match value is bigger than old one
+ * - when old match value is bigger than new one, current
+ * counter value must be bigger than old match value or
+ * lower than new match value.
+ *
+ * If this conditions are not met, we will write a match value,
+ * at moment when match event doesn't trigered yet and the new
+ * match value is lower than counter. This will result in missing
+ * the match event for this period.
+ */
+ counter = omap_dm_timer_read_counter(timer);
+
+ if ((counter + COUNTER_TO_MATCH_GUARD) < match_val)
+ omap_pwm_set_match(timer, match_val);
+ else if (counter > current_match_val)
+ omap_pwm_set_match(timer, match_val);
+
+ /* acknowledge interrupts */
+ omap_dm_timer_write_status(timer, status);
+
+ /* enable interrupts */
+ local_irq_enable();
+
+ return IRQ_HANDLED;
}
-static void omap_pwm_led_power_on(struct omap_pwm_led *led)
+static void omap_pwm_led_set_pwm_cycle(struct omap_pwm_led *led, int cycle)
{
- u32 val;
- u32 period;
- struct clk *timer_fclk;
- pr_debug("%s: start \n",__func__);
- if (led->powered)
- return;
- led->powered = 1;
+ struct omap_dm_timer *timer;
+ unsigned int match_val;
+ unsigned int current_match_val;
- pr_debug("%s: brightness: %i\n",
- __func__, led->brightness);
+ timer = (struct omap_dm_timer *) led->intensity_timer;
- /* Select clock */
- omap_dm_timer_set_source(led->intensity_timer, OMAP_TIMER_SRC_SYS_CLK);
-
- /* Turn voltage on */
- if (led->pdata->set_power != NULL)
- led->pdata->set_power(led->pdata, 1);
+ current_match_val = atomic_read(&led->cached_match_val);
+ match_val = get_match_val(cycle);
- /* explicitly enable the timer, saves some SAR later */
- omap_dm_timer_enable(led->intensity_timer);
- omap_dm_timer_start(led->intensity_timer);
+ if (current_match_val < match_val) {
+ omap_dm_timer_set_match(timer, 1, match_val);
+ atomic_set(&led->cached_match_val, match_val);
+ } else {
+ atomic_set(&led->cached_match_val, match_val);
+ omap_dm_timer_set_int_enable(timer, TIMER_INT_FLAGS);
+ }
+}
- omap_dm_timer_set_pwm(led->intensity_timer, led->pdata->invert ? 1 : 0, 1,
- OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+static void omap_pwm_led_power_on(struct omap_pwm_led *led)
+{
+ int invert = 1;
+ unsigned int timerval;
+ int err;
- timer_fclk = omap_dm_timer_get_fclk(led->intensity_timer);
- period = clk_get_rate(timer_fclk) / 128;
+ if (led->pdata)
+ invert = led->pdata->invert;
- val = 0xFFFFFFFF+1-period;
- omap_dm_timer_set_load(led->intensity_timer, 1, val);
+ if (led->powered)
+ return;
+ led->powered = 1;
+ /* Select clock source */
+ omap_dm_timer_enable(led->intensity_timer);
+ omap_dm_timer_set_source(led->intensity_timer, OMAP_TIMER_SRC_SYS_CLK);
+ omap_dm_timer_set_prescaler(led->intensity_timer, COUNTER_DEVIDER);
/* Enable PWM timers */
if (led->blink_timer != NULL) {
+ omap_dm_timer_enable(led->blink_timer);
omap_dm_timer_set_source(led->blink_timer,
OMAP_TIMER_SRC_32_KHZ);
omap_pwm_led_set_blink(led);
}
- pr_debug("%s: end \n",__func__);
+
+ omap_dm_timer_set_pwm(led->intensity_timer, invert ? 0 : 1, 1,
+ OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+
+ omap_dm_timer_set_load(led->intensity_timer, 1, COUNTER_LOAD_VAL);
+ omap_dm_timer_start(led->intensity_timer);
+ omap_pwm_led_set_pwm_cycle(led, 0);
+
+ timerval = omap_dm_timer_read_counter(led->intensity_timer);
+ if (timerval < COUNTER_LOAD_VAL)
+ omap_dm_timer_write_counter(led->intensity_timer, -2);
+
+ /* Turn voltage on */
+ if (led->pdata->set_power != NULL)
+ led->pdata->set_power(led->pdata, 1);
+
+ /* register timer match and overflow interrupts */
+ err = request_irq(omap_dm_timer_get_irq(led->intensity_timer),
+ intensity_timer_match_interrupt,
+ IRQF_DISABLED, "led intensity timer", (void *)led);
+ if (err) {
+ printk(KERN_ERR "%s(%s) : unable to get gptimer%d IRQ\n",
+ __func__, __FILE__, led->pdata->intensity_timer);
+ }
}
static void omap_pwm_led_power_off(struct omap_pwm_led *led)
{
-
+ int invert = 1;
if (!led->powered)
return;
led->powered = 0;
- pr_debug("%s: brightness: %i\n",
- __func__, led->brightness);
-
if (led->pdata->set_power != NULL)
led->pdata->set_power(led->pdata, 0);
+ /* disable timer match interrupt */
+ omap_dm_timer_set_int_disable(led->intensity_timer,
+ OMAP_TIMER_INT_MATCH);
+ free_irq(omap_dm_timer_get_irq(led->intensity_timer), (void *)led);
+ if (led->pdata)
+ invert = led->pdata->invert;
+
/* Everything off */
+ omap_dm_timer_set_pwm(led->intensity_timer,
+ invert ? 0 : 1, 1,
+ OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
omap_dm_timer_stop(led->intensity_timer);
+ omap_dm_timer_disable(led->intensity_timer);
- if (led->blink_timer != NULL)
+ if (led->blink_timer != NULL) {
omap_dm_timer_stop(led->blink_timer);
- pr_debug("%s: end \n",__func__);
-}
-
-static void pwm_set_speed(struct omap_dm_timer *gpt,
- int frequency, int duty_cycle)
-{
- u32 val;
- u32 period;
- struct clk *timer_fclk;
-
- /* and you will have an overflow in 1 sec */
- /* so, */
- /* freq_timer -> 1s */
- /* carrier_period -> 1/carrier_freq */
- /* => carrier_period = freq_timer/carrier_freq */
-
- timer_fclk = omap_dm_timer_get_fclk(gpt);
- period = clk_get_rate(timer_fclk) / frequency;
-
- val = 0xFFFFFFFF+1-(period*duty_cycle/256);
- omap_dm_timer_set_match(gpt, 1, val);
-}
-
-static void omap_pwm_led_set_pwm_cycle(struct omap_pwm_led *led, int cycle)
-{
- int pwm_frequency = 10000;
-
- pr_debug("%s: cycle: %i\n",
- __func__, cycle);
-
- if (led->pdata->bkl_max)
- cycle = ( (cycle * led->pdata->bkl_max ) / 255);
-
- if (cycle < led->pdata->bkl_min)
- cycle = led->pdata->bkl_min;
-
- if (led->pdata->bkl_freq)
- pwm_frequency = led->pdata->bkl_freq;
+ omap_dm_timer_disable(led->blink_timer);
+ }
- if (cycle != LED_FULL)
- pwm_set_speed(led->intensity_timer, pwm_frequency, 256-cycle);
+ atomic_set(&led->cached_match_val, 0);
}
static void omap_pwm_led_set(struct led_classdev *led_cdev,
@@ -193,29 +270,22 @@ static void omap_pwm_led_set(struct led_classdev *led_cdev,
{
struct omap_pwm_led *led = cdev_to_omap_pwm_led(led_cdev);
- pr_debug("%s: brightness: %i\n", __func__, value);
-
- if (led->brightness != value) {
- if (led->brightness < led->pdata->bkl_min ||
- led_cdev->flags & LED_SUSPENDED) {
- /* LED currently OFF */
- if (value >= led->pdata->bkl_min) {
- omap_pwm_led_power_on(led);
- omap_pwm_led_set_pwm_cycle(led, value);
- omap_pwm_led_pad_enable(led);
- }
- } else {
- /* just set the new cycle */
- omap_pwm_led_set_pwm_cycle(led, value);
- }
-
- if (value < led->pdata->bkl_min && led->brightness >= led->pdata->bkl_min) {
- /* LED now suspended */
- omap_pwm_led_pad_disable(led);
- // omap_pwm_led_set_pwm_cycle(led, value);
- omap_pwm_led_power_off(led);
- }
+ if (value != led->brightness) {
led->brightness = value;
+ schedule_work(&led->work);
+ }
+}
+
+static void omap_pwm_led_work(struct work_struct *work)
+{
+ struct omap_pwm_led *led = work_to_omap_pwm_led(work);
+
+ if (led->brightness != LED_OFF) {
+ omap_pwm_led_power_on(led);
+ omap_pwm_led_set_pwm_cycle(led, led->brightness);
+ } else {
+ omap_pwm_led_set_pwm_cycle(led, led->brightness);
+ omap_pwm_led_power_off(led);
}
}
@@ -298,12 +368,6 @@ static int omap_pwm_led_probe(struct platform_device *pdev)
struct omap_pwm_led *led;
int ret;
- if (pdata->intensity_timer < 1 || pdata->intensity_timer > MAX_GPTIMER_ID)
- return -EINVAL;
-
- if (pdata->blink_timer != 0 || pdata->blink_timer > MAX_GPTIMER_ID)
- return -EINVAL;
-
led = kzalloc(sizeof(struct omap_pwm_led), GFP_KERNEL);
if (led == NULL) {
dev_err(&pdev->dev, "No memory for device\n");
@@ -312,14 +376,18 @@ static int omap_pwm_led_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, led);
led->cdev.brightness_set = omap_pwm_led_set;
- led->cdev.default_trigger = pdata->default_trigger;
+ led->cdev.default_trigger = NULL;
led->cdev.name = pdata->name;
led->pdata = pdata;
- led->brightness = LED_OFF;
+ led->brightness = pdata->def_brightness;
+ INIT_WORK(&led->work, omap_pwm_led_work);
dev_info(&pdev->dev, "OMAP PWM LED (%s) at GP timer %d/%d\n",
pdata->name, pdata->intensity_timer, pdata->blink_timer);
+ if (pdata->def_brightness)
+ led->cdev.brightness = pdata->def_brightness;
+
/* register our new led device */
ret = led_classdev_register(&pdev->dev, &led->cdev);
if (ret < 0) {
@@ -334,33 +402,42 @@ static int omap_pwm_led_probe(struct platform_device *pdev)
ret = -ENODEV;
goto error_intensity;
}
-
- if (led->pdata->invert)
- omap_dm_timer_set_pwm(led->intensity_timer, 1, 1,
- OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+ omap_dm_timer_disable(led->intensity_timer);
if (pdata->blink_timer != 0) {
led->blink_timer = omap_dm_timer_request_specific(pdata->blink_timer);
if (led->blink_timer == NULL) {
- dev_err(&pdev->dev, "failed to request blinking pwm timer\n");
+ dev_err(&pdev->dev,
+ "failed to request blinking pwm timer\n");
ret = -ENODEV;
goto error_blink1;
}
+ omap_dm_timer_disable(led->blink_timer);
+
ret = device_create_file(led->cdev.dev,
&dev_attr_on_period);
- if(ret)
+ if (ret)
goto error_blink2;
ret = device_create_file(led->cdev.dev,
&dev_attr_off_period);
- if(ret)
+ if (ret)
goto error_blink3;
}
+ if (led->brightness) {
+ schedule_work(&led->work);
+ } else {
+ omap_pwm_led_power_on(led);
+ omap_pwm_led_power_off(led);
+ }
- if(pdata->def_brightness)
- omap_pwm_led_set(&led->cdev, pdata->def_brightness);
-
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ led->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 1;
+ led->early_suspend.suspend = omap_pwm_led_early_suspend;
+ led->early_suspend.resume = omap_pwm_led_late_resume;
+ register_early_suspend(&led->early_suspend);
+#endif
return 0;
error_blink3:
@@ -379,8 +456,13 @@ error_classdev:
static int omap_pwm_led_remove(struct platform_device *pdev)
{
+
struct omap_pwm_led *led = pdev_to_omap_pwm_led(pdev);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&led->early_suspend);
+#endif
+
device_remove_file(led->cdev.dev,
&dev_attr_on_period);
device_remove_file(led->cdev.dev,
@@ -396,13 +478,36 @@ static int omap_pwm_led_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-static int omap_pwm_led_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void omap_pwm_led_early_suspend(struct early_suspend *handler)
+{
+ struct omap_pwm_led *led;
+
+ led = container_of(handler, struct omap_pwm_led, early_suspend);
+
+ flush_work(&led->work);
+ /* Make sure the led is switched OFF NOW in this current thread!!! */
+ omap_pwm_led_power_off(led);
+
+ led_classdev_suspend(&led->cdev);
+}
+
+static void omap_pwm_led_late_resume(struct early_suspend *handler)
+{
+ struct omap_pwm_led *led;
+
+ led = container_of(handler, struct omap_pwm_led, early_suspend);
+
+ led_classdev_resume(&led->cdev);
+}
+#endif
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int omap_pwm_led_suspend(struct platform_device *pdev,
+ pm_message_t state)
{
struct omap_pwm_led *led = pdev_to_omap_pwm_led(pdev);
- pr_debug("%s: brightness: %i\n", __func__,
- led->brightness);
led_classdev_suspend(&led->cdev);
return 0;
}
@@ -411,8 +516,6 @@ static int omap_pwm_led_resume(struct platform_device *pdev)
{
struct omap_pwm_led *led = pdev_to_omap_pwm_led(pdev);
- pr_debug("%s: brightness: %i\n", __func__,
- led->brightness);
led_classdev_resume(&led->cdev);
return 0;
}
@@ -424,8 +527,10 @@ static int omap_pwm_led_resume(struct platform_device *pdev)
static struct platform_driver omap_pwm_led_driver = {
.probe = omap_pwm_led_probe,
.remove = omap_pwm_led_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = omap_pwm_led_suspend,
.resume = omap_pwm_led_resume,
+#endif
.driver = {
.name = "omap_pwm_led",
.owner = THIS_MODULE,
(END)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment