linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Geert Uytterhoeven <geert@linux-m68k.org>
To: Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Willy Tarreau <willy@haproxy.com>,
	Ksenija Stanojevic <ksenija.stanojevic@gmail.com>,
	Arnd Bergmann <arnd@arndb.de>
Cc: linux-kernel@vger.kernel.org, Geert Uytterhoeven <geert@linux-m68k.org>
Subject: [PATCH 08/13] misc: panel: Abstract temporary backlight handling
Date: Mon,  6 Feb 2017 15:38:10 +0100	[thread overview]
Message-ID: <1486391895-9554-9-git-send-email-geert@linux-m68k.org> (raw)
In-Reply-To: <1486391895-9554-1-git-send-email-geert@linux-m68k.org>

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: Geert Uytterhoeven <geert@linux-m68k.org>
---
 drivers/misc/panel.c | 101 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 60 insertions(+), 41 deletions(-)

diff --git a/drivers/misc/panel.c b/drivers/misc/panel.c
index 9c7b00951c22b1c2..ef2ece0f26afc6b5 100644
--- a/drivers/misc/panel.c
+++ b/drivers/misc/panel.c
@@ -56,6 +56,7 @@
 #include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
+#include <linux/workqueue.h>
 #include <generated/utsrelease.h>
 
 #include <linux/io.h>
@@ -75,8 +76,8 @@
 /* a key repeats this times INPUT_POLL_TIME */
 #define KEYPAD_REP_DELAY	(2)
 
-/* keep the light on this times INPUT_POLL_TIME for each flash */
-#define FLASH_LIGHT_TEMPO	(200)
+/* keep the light on this many seconds for each flash */
+#define FLASH_LIGHT_TEMPO	(4)
 
 /* converts an r_str() input to an active high, bits string : 000BAOSE */
 #define PNL_PINPUT(a)		((((unsigned char)(a)) ^ 0x7F) >> 3)
@@ -252,7 +253,10 @@ struct logical_input {
 	int hwidth;
 	int charset;
 	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? */
 	struct {
@@ -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 */
 static int set_data_bits(void)
 {
@@ -790,11 +792,8 @@ static void lcd_send_serial(int byte)
 }
 
 /* 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  */
 	spin_lock_irq(&pprt_lock);
 	if (on)
@@ -805,6 +804,44 @@ static void lcd_backlight(int on)
 	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 */
 static void lcd_write_cmd_s(int cmd)
 {
@@ -1099,13 +1136,8 @@ static inline int handle_lcd_special_code(void)
 		processed = 1;
 		break;
 	case '*':
-		/* flash back light using the keypad timer */
-		if (scan_timer.function) {
-			if (lcd.light_tempo == 0 &&
-			    ((lcd.flags & LCD_FLAG_L) == 0))
-				lcd_backlight(1);
-			lcd.light_tempo = FLASH_LIGHT_TEMPO;
-		}
+		/* flash back light */
+		lcd_poke();
 		processed = 1;
 		break;
 	case 'f':	/* Small Font */
@@ -1275,16 +1307,8 @@ static inline int handle_lcd_special_code(void)
 						      ? LCD_CMD_TWO_LINES
 								      : 0));
 		/* check whether L flag was changed */
-		else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L)) {
-			if (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);
-		}
+		else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L))
+			lcd_backlight(!!(lcd.flags & LCD_FLAG_L));
 	}
 
 	return processed;
@@ -1615,8 +1639,10 @@ static void lcd_init(void)
 	else
 		lcd_char_conv = NULL;
 
-	if (lcd.pins.bl != PIN_NONE)
-		init_scan_timer();
+	if (lcd.pins.bl != PIN_NONE) {
+		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],
 		    lcd_bits[LCD_PORT_C][LCD_BIT_E]);
@@ -1984,19 +2010,8 @@ static void panel_scan_timer(void)
 			panel_process_inputs();
 	}
 
-	if (lcd.enabled && lcd.initialized) {
-		if (keypressed) {
-			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);
-		}
-	}
+	if (keypressed && lcd.enabled && lcd.initialized)
+		lcd_poke();
 
 	mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME);
 }
@@ -2265,6 +2280,10 @@ static void panel_detach(struct parport *port)
 	if (lcd.enabled) {
 		panel_lcd_print("\x0cLCD driver unloaded.\x1b[Lc\x1b[Lb\x1b[L-");
 		misc_deregister(&lcd_dev);
+		if (lcd.pins.bl != PIN_NONE) {
+			cancel_delayed_work_sync(&lcd.bl_work);
+			__lcd_backlight(0);
+		}
 		lcd.initialized = false;
 	}
 
-- 
1.9.1

  parent reply	other threads:[~2017-02-06 14:39 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-06 14:38 [PATCH 00/13] Add HD44780 Character LCD support Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 01/13] misc: panel: Fix LCD_FLAG_F/LCD_FLAG_N exchange Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 02/13] misc: panel: Remove PANEL_VERSION Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 03/13] misc: panel: Remove unused LCD_FLAG_S and LCD_FLAG_ID Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 04/13] misc: panel: Remove reference to misc device support Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 05/13] misc: panel: Move all suboptions into a big if section Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 06/13] misc: panel: Remove always-true check from panel_detach() Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 07/13] misc: panel: Add lcd_home() helper Geert Uytterhoeven
2017-02-06 14:38 ` Geert Uytterhoeven [this message]
2017-02-06 14:38 ` [PATCH 09/13] auxdisplay: charlcd: Extract character LCD core from misc/panel Geert Uytterhoeven
2017-02-06 15:09   ` Arnd Bergmann
2017-02-06 15:18     ` Geert Uytterhoeven
2017-02-08 12:22   ` Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 10/13] auxdisplay: charlcd: Add support for 4-bit interfaces Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 11/13] auxdisplay: charlcd: Add support for displays with more than two lines Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 12/13] dt-bindings: auxdisplay: Add bindings for Hitachi HD44780 Geert Uytterhoeven
2017-02-09  1:11   ` Rob Herring
2017-02-09  8:51     ` Geert Uytterhoeven
2017-02-06 14:38 ` [PATCH 13/13] auxdisplay: Add HD44780 Character LCD support Geert Uytterhoeven
2017-02-07 11:23   ` Andy Shevchenko
2017-02-08 13:18     ` Geert Uytterhoeven
2017-02-08 13:38       ` Andy Shevchenko
2017-02-08 13:41         ` Geert Uytterhoeven
2017-02-08 16:27           ` Andy Shevchenko
2017-02-08 17:19             ` Geert Uytterhoeven
2017-02-06 15:09 ` [PATCH 00/13] " Willy TARREAU
2017-02-10 14:37 ` Greg Kroah-Hartman
2017-03-16 20:50 ` Linus Walleij
2017-03-17  7:40   ` Geert Uytterhoeven
2017-03-23 17:15 ` Willy TARREAU
2017-03-23 17:37   ` Willy TARREAU
2017-03-23 18:49     ` Geert Uytterhoeven
2017-03-23 19:03       ` Willy TARREAU
2017-03-23 20:29         ` Geert Uytterhoeven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1486391895-9554-9-git-send-email-geert@linux-m68k.org \
    --to=geert@linux-m68k.org \
    --cc=arnd@arndb.de \
    --cc=gregkh@linuxfoundation.org \
    --cc=ksenija.stanojevic@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miguel.ojeda.sandonis@gmail.com \
    --cc=willy@haproxy.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).