Commit fda4ae18 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Greg Kroah-Hartman

misc: panel: Abstract temporary backlight handling

Currently the periodic scan timer is used for three purposes,
entangling keypad and display handling, which are both optional:
  1. Scanning the keypad,
  2. Flashing the backlight when a key is pressed,
  3. Disabling temporary backlighting after a fixed period of time.

Abstract the second purpose using a new lcd_poke() function.
Make the non-periodic temporary backlight handling independent from
keypad handling by converting it to a delayed workqueue.
Signed-off-by: default avatarGeert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 204a4f6d
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/workqueue.h>
#include <generated/utsrelease.h> #include <generated/utsrelease.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -75,8 +76,8 @@ ...@@ -75,8 +76,8 @@
/* a key repeats this times INPUT_POLL_TIME */ /* a key repeats this times INPUT_POLL_TIME */
#define KEYPAD_REP_DELAY (2) #define KEYPAD_REP_DELAY (2)
/* keep the light on this times INPUT_POLL_TIME for each flash */ /* keep the light on this many seconds for each flash */
#define FLASH_LIGHT_TEMPO (200) #define FLASH_LIGHT_TEMPO (4)
/* converts an r_str() input to an active high, bits string : 000BAOSE */ /* converts an r_str() input to an active high, bits string : 000BAOSE */
#define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3) #define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3)
...@@ -252,7 +253,10 @@ static struct { ...@@ -252,7 +253,10 @@ static struct {
int hwidth; int hwidth;
int charset; int charset;
int proto; int proto;
int light_tempo;
struct delayed_work bl_work;
struct mutex bl_tempo_lock; /* Protects access to bl_tempo */
bool bl_tempo;
/* TODO: use union here? */ /* TODO: use union here? */
struct { struct {
...@@ -657,8 +661,6 @@ static void lcd_get_bits(unsigned int port, int *val) ...@@ -657,8 +661,6 @@ static void lcd_get_bits(unsigned int port, int *val)
} }
} }
static void init_scan_timer(void);
/* sets data port bits according to current signals values */ /* sets data port bits according to current signals values */
static int set_data_bits(void) static int set_data_bits(void)
{ {
...@@ -790,11 +792,8 @@ static void lcd_send_serial(int byte) ...@@ -790,11 +792,8 @@ static void lcd_send_serial(int byte)
} }
/* turn the backlight on or off */ /* turn the backlight on or off */
static void lcd_backlight(int on) static void __lcd_backlight(int on)
{ {
if (lcd.pins.bl == PIN_NONE)
return;
/* The backlight is activated by setting the AUTOFEED line to +5V */ /* The backlight is activated by setting the AUTOFEED line to +5V */
spin_lock_irq(&pprt_lock); spin_lock_irq(&pprt_lock);
if (on) if (on)
...@@ -805,6 +804,44 @@ static void lcd_backlight(int on) ...@@ -805,6 +804,44 @@ static void lcd_backlight(int on)
spin_unlock_irq(&pprt_lock); spin_unlock_irq(&pprt_lock);
} }
static void lcd_backlight(int on)
{
if (lcd.pins.bl == PIN_NONE)
return;
mutex_lock(&lcd.bl_tempo_lock);
if (!lcd.bl_tempo)
__lcd_backlight(on);
mutex_unlock(&lcd.bl_tempo_lock);
}
static void lcd_bl_off(struct work_struct *work)
{
mutex_lock(&lcd.bl_tempo_lock);
if (lcd.bl_tempo) {
lcd.bl_tempo = false;
if (!(lcd.flags & LCD_FLAG_L))
__lcd_backlight(0);
}
mutex_unlock(&lcd.bl_tempo_lock);
}
/* turn the backlight on for a little while */
static void lcd_poke(void)
{
if (lcd.pins.bl == PIN_NONE)
return;
cancel_delayed_work_sync(&lcd.bl_work);
mutex_lock(&lcd.bl_tempo_lock);
if (!lcd.bl_tempo && !(lcd.flags & LCD_FLAG_L))
__lcd_backlight(1);
lcd.bl_tempo = true;
schedule_delayed_work(&lcd.bl_work, FLASH_LIGHT_TEMPO * HZ);
mutex_unlock(&lcd.bl_tempo_lock);
}
/* send a command to the LCD panel in serial mode */ /* send a command to the LCD panel in serial mode */
static void lcd_write_cmd_s(int cmd) static void lcd_write_cmd_s(int cmd)
{ {
...@@ -1099,13 +1136,8 @@ static inline int handle_lcd_special_code(void) ...@@ -1099,13 +1136,8 @@ static inline int handle_lcd_special_code(void)
processed = 1; processed = 1;
break; break;
case '*': case '*':
/* flash back light using the keypad timer */ /* flash back light */
if (scan_timer.function) { lcd_poke();
if (lcd.light_tempo == 0 &&
((lcd.flags & LCD_FLAG_L) == 0))
lcd_backlight(1);
lcd.light_tempo = FLASH_LIGHT_TEMPO;
}
processed = 1; processed = 1;
break; break;
case 'f': /* Small Font */ case 'f': /* Small Font */
...@@ -1275,16 +1307,8 @@ static inline int handle_lcd_special_code(void) ...@@ -1275,16 +1307,8 @@ static inline int handle_lcd_special_code(void)
? LCD_CMD_TWO_LINES ? LCD_CMD_TWO_LINES
: 0)); : 0));
/* check whether L flag was changed */ /* check whether L flag was changed */
else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L)) { else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L))
if (lcd.flags & (LCD_FLAG_L)) lcd_backlight(!!(lcd.flags & LCD_FLAG_L));
lcd_backlight(1);
else if (lcd.light_tempo == 0)
/*
* switch off the light only when the tempo
* lighting is gone
*/
lcd_backlight(0);
}
} }
return processed; return processed;
...@@ -1615,8 +1639,10 @@ static void lcd_init(void) ...@@ -1615,8 +1639,10 @@ static void lcd_init(void)
else else
lcd_char_conv = NULL; lcd_char_conv = NULL;
if (lcd.pins.bl != PIN_NONE) if (lcd.pins.bl != PIN_NONE) {
init_scan_timer(); mutex_init(&lcd.bl_tempo_lock);
INIT_DELAYED_WORK(&lcd.bl_work, lcd_bl_off);
}
pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E], pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E],
lcd_bits[LCD_PORT_C][LCD_BIT_E]); lcd_bits[LCD_PORT_C][LCD_BIT_E]);
...@@ -1984,19 +2010,8 @@ static void panel_scan_timer(void) ...@@ -1984,19 +2010,8 @@ static void panel_scan_timer(void)
panel_process_inputs(); panel_process_inputs();
} }
if (lcd.enabled && lcd.initialized) { if (keypressed && lcd.enabled && lcd.initialized)
if (keypressed) { lcd_poke();
if (lcd.light_tempo == 0 &&
((lcd.flags & LCD_FLAG_L) == 0))
lcd_backlight(1);
lcd.light_tempo = FLASH_LIGHT_TEMPO;
} else if (lcd.light_tempo > 0) {
lcd.light_tempo--;
if (lcd.light_tempo == 0 &&
((lcd.flags & LCD_FLAG_L) == 0))
lcd_backlight(0);
}
}
mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME); mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME);
} }
...@@ -2265,6 +2280,10 @@ static void panel_detach(struct parport *port) ...@@ -2265,6 +2280,10 @@ static void panel_detach(struct parport *port)
if (lcd.enabled) { if (lcd.enabled) {
panel_lcd_print("\x0cLCD driver unloaded.\x1b[Lc\x1b[Lb\x1b[L-"); panel_lcd_print("\x0cLCD driver unloaded.\x1b[Lc\x1b[Lb\x1b[L-");
misc_deregister(&lcd_dev); misc_deregister(&lcd_dev);
if (lcd.pins.bl != PIN_NONE) {
cancel_delayed_work_sync(&lcd.bl_work);
__lcd_backlight(0);
}
lcd.initialized = false; lcd.initialized = false;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment