Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * Front panel driver for Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Copyright (C) 2016-2017 Glider bvba
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * This code drives an LCD module (/dev/lcd), and a keypad (/dev/keypad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * connected to a parallel printer port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * The LCD module may either be an HD44780-like 8-bit parallel LCD, or a 1-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  * serial module compatible with Samsung's KS0074. The pins may be connected in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * any combination, everything is programmable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  * The keypad consists in a matrix of push buttons connecting input pins to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  * data output pins or to the ground. The combinations have to be hard-coded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  * in the driver, though several profiles exist and adding new ones is easy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  * Several profiles are provided for commonly found LCD+keypad modules on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  * market, such as those found in Nexcom's appliances.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  * FIXME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)  *      - the initialization/deinitialization process is very dirty and should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23)  *        be rewritten. It may even be buggy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25)  * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)  *	- document 24 keys keyboard (3 rows of 8 cols, 32 diodes + 2 inputs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)  *      - make the LCD a part of a virtual screen of Vx*Vy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)  *	- make the inputs list smp-safe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29)  *      - change the keyboard to a double mapping : signals -> key_id -> values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30)  *        so that applications can change values without knowing signals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #include <linux/parport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #include "charlcd.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define LCD_MAXBYTES		256	/* max burst write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define KEYPAD_BUFFER		64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) /* poll the keyboard this every second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #define INPUT_POLL_TIME		(HZ / 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) /* a key starts to repeat after this times INPUT_POLL_TIME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #define KEYPAD_REP_START	(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) /* a key repeats this times INPUT_POLL_TIME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #define KEYPAD_REP_DELAY	(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) /* converts an r_str() input to an active high, bits string : 000BAOSE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) #define PNL_PINPUT(a)		((((unsigned char)(a)) ^ 0x7F) >> 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) #define PNL_PBUSY		0x80	/* inverted input, active low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) #define PNL_PACK		0x40	/* direct input, active low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) #define PNL_POUTPA		0x20	/* direct input, active high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) #define PNL_PSELECD		0x10	/* direct input, active high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) #define PNL_PERRORP		0x08	/* direct input, active low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #define PNL_PBIDIR		0x20	/* bi-directional ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) /* high to read data in or-ed with data out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #define PNL_PINTEN		0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #define PNL_PSELECP		0x08	/* inverted output, active low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) #define PNL_PINITP		0x04	/* direct output, active low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #define PNL_PAUTOLF		0x02	/* inverted output, active low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) #define PNL_PSTROBE		0x01	/* inverted output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) #define PNL_PD0			0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) #define PNL_PD1			0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) #define PNL_PD2			0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) #define PNL_PD3			0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) #define PNL_PD4			0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) #define PNL_PD5			0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) #define PNL_PD6			0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) #define PNL_PD7			0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) #define PIN_NONE		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) #define PIN_STROBE		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) #define PIN_D0			2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) #define PIN_D1			3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) #define PIN_D2			4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) #define PIN_D3			5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) #define PIN_D4			6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) #define PIN_D5			7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) #define PIN_D6			8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) #define PIN_D7			9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) #define PIN_AUTOLF		14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) #define PIN_INITP		16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) #define PIN_SELECP		17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) #define PIN_NOT_SET		127
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) #define NOT_SET			-1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) /* macros to simplify use of the parallel port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) #define r_ctr(x)        (parport_read_control((x)->port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) #define r_dtr(x)        (parport_read_data((x)->port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) #define r_str(x)        (parport_read_status((x)->port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) #define w_ctr(x, y)     (parport_write_control((x)->port, (y)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) #define w_dtr(x, y)     (parport_write_data((x)->port, (y)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) /* this defines which bits are to be used and which ones to be ignored */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) /* logical or of the output bits involved in the scan matrix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) static __u8 scan_mask_o;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) /* logical or of the input bits involved in the scan matrix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) static __u8 scan_mask_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) enum input_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 	INPUT_TYPE_STD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	INPUT_TYPE_KBD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) enum input_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	INPUT_ST_LOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	INPUT_ST_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 	INPUT_ST_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	INPUT_ST_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) struct logical_input {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	__u64 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	__u64 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	enum input_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	enum input_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	__u8 rise_time, fall_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	__u8 rise_timer, fall_timer, high_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 		struct {	/* valid when type == INPUT_TYPE_STD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 			void (*press_fct)(int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 			void (*release_fct)(int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 			int press_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 			int release_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 		} std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 		struct {	/* valid when type == INPUT_TYPE_KBD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 			char press_str[sizeof(void *) + sizeof(int)] __nonstring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 			char repeat_str[sizeof(void *) + sizeof(int)] __nonstring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 			char release_str[sizeof(void *) + sizeof(int)] __nonstring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 		} kbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	} u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) static LIST_HEAD(logical_inputs);	/* list of all defined logical inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) /* physical contacts history
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166)  * Physical contacts are a 45 bits string of 9 groups of 5 bits each.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167)  * The 8 lower groups correspond to output bits 0 to 7, and the 9th group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168)  * corresponds to the ground.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169)  * Within each group, bits are stored in the same order as read on the port :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170)  * BAPSE (busy=4, ack=3, paper empty=2, select=1, error=0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171)  * So, each __u64 is represented like this :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172)  * 0000000000000000000BAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173)  * <-----unused------><gnd><d07><d06><d05><d04><d03><d02><d01><d00>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) /* what has just been read from the I/O ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) static __u64 phys_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) /* previous phys_read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) static __u64 phys_read_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) /* stabilized phys_read (phys_read|phys_read_prev) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) static __u64 phys_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) /* previous phys_curr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) static __u64 phys_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) /* 0 means that at least one logical signal needs be computed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) static char inputs_stable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) /* these variables are specific to the keypad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) } keypad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) static char keypad_buffer[KEYPAD_BUFFER];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) static int keypad_buflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) static int keypad_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) static char keypressed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) static wait_queue_head_t keypad_read_wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) /* lcd-specific variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	bool initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	int charset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	int proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	/* TODO: use union here? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		int e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		int rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 		int rw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 		int cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 		int da;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 		int bl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	} pins;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	struct charlcd *charlcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) } lcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) /* Needed only for init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) static int selected_lcd_type = NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223)  * Bit masks to convert LCD signals to parallel port outputs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224)  * _d_ are values for data port, _c_ are for control port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225)  * [0] = signal OFF, [1] = signal ON, [2] = mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) #define BIT_CLR		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) #define BIT_SET		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) #define BIT_MSK		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) #define BIT_STATES	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232)  * one entry for each bit on the LCD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) #define LCD_BIT_E	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) #define LCD_BIT_RS	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) #define LCD_BIT_RW	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) #define LCD_BIT_BL	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) #define LCD_BIT_CL	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) #define LCD_BIT_DA	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) #define LCD_BITS	6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243)  * each bit can be either connected to a DATA or CTRL port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) #define LCD_PORT_C	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) #define LCD_PORT_D	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) #define LCD_PORTS	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252)  * LCD protocols
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) #define LCD_PROTO_PARALLEL      0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) #define LCD_PROTO_SERIAL        1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) #define LCD_PROTO_TI_DA8XX_LCD	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259)  * LCD character sets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) #define LCD_CHARSET_NORMAL      0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) #define LCD_CHARSET_KS0074      1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265)  * LCD types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) #define LCD_TYPE_NONE		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) #define LCD_TYPE_CUSTOM		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) #define LCD_TYPE_OLD		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) #define LCD_TYPE_KS0074		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) #define LCD_TYPE_HANTRONIX	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) #define LCD_TYPE_NEXCOM		5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275)  * keypad types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) #define KEYPAD_TYPE_NONE	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) #define KEYPAD_TYPE_OLD		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) #define KEYPAD_TYPE_NEW		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) #define KEYPAD_TYPE_NEXCOM	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283)  * panel profiles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) #define PANEL_PROFILE_CUSTOM	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) #define PANEL_PROFILE_OLD	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) #define PANEL_PROFILE_NEW	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) #define PANEL_PROFILE_HANTRONIX	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) #define PANEL_PROFILE_NEXCOM	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) #define PANEL_PROFILE_LARGE	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293)  * Construct custom config from the kernel's configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) #define DEFAULT_PARPORT         0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) #define DEFAULT_PROFILE         PANEL_PROFILE_LARGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) #define DEFAULT_KEYPAD_TYPE     KEYPAD_TYPE_OLD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) #define DEFAULT_LCD_TYPE        LCD_TYPE_OLD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) #define DEFAULT_LCD_HEIGHT      2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) #define DEFAULT_LCD_WIDTH       40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) #define DEFAULT_LCD_BWIDTH      40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) #define DEFAULT_LCD_HWIDTH      64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) #define DEFAULT_LCD_CHARSET     LCD_CHARSET_NORMAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) #define DEFAULT_LCD_PROTO       LCD_PROTO_PARALLEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) #define DEFAULT_LCD_PIN_E       PIN_AUTOLF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) #define DEFAULT_LCD_PIN_RS      PIN_SELECP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) #define DEFAULT_LCD_PIN_RW      PIN_INITP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) #define DEFAULT_LCD_PIN_SCL     PIN_STROBE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) #define DEFAULT_LCD_PIN_SDA     PIN_D0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) #define DEFAULT_LCD_PIN_BL      PIN_NOT_SET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) #ifdef CONFIG_PANEL_PARPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) #undef DEFAULT_PARPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) #define DEFAULT_PARPORT CONFIG_PANEL_PARPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) #ifdef CONFIG_PANEL_PROFILE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) #undef DEFAULT_PROFILE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) #define DEFAULT_PROFILE CONFIG_PANEL_PROFILE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) #if DEFAULT_PROFILE == 0	/* custom */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) #ifdef CONFIG_PANEL_KEYPAD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) #undef DEFAULT_KEYPAD_TYPE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) #define DEFAULT_KEYPAD_TYPE CONFIG_PANEL_KEYPAD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) #ifdef CONFIG_PANEL_LCD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) #undef DEFAULT_LCD_TYPE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) #define DEFAULT_LCD_TYPE CONFIG_PANEL_LCD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) #ifdef CONFIG_PANEL_LCD_HEIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) #undef DEFAULT_LCD_HEIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) #define DEFAULT_LCD_HEIGHT CONFIG_PANEL_LCD_HEIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) #ifdef CONFIG_PANEL_LCD_WIDTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) #undef DEFAULT_LCD_WIDTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) #define DEFAULT_LCD_WIDTH CONFIG_PANEL_LCD_WIDTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) #ifdef CONFIG_PANEL_LCD_BWIDTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) #undef DEFAULT_LCD_BWIDTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) #define DEFAULT_LCD_BWIDTH CONFIG_PANEL_LCD_BWIDTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) #ifdef CONFIG_PANEL_LCD_HWIDTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) #undef DEFAULT_LCD_HWIDTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) #define DEFAULT_LCD_HWIDTH CONFIG_PANEL_LCD_HWIDTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) #ifdef CONFIG_PANEL_LCD_CHARSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) #undef DEFAULT_LCD_CHARSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) #define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) #ifdef CONFIG_PANEL_LCD_PROTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) #undef DEFAULT_LCD_PROTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) #define DEFAULT_LCD_PROTO CONFIG_PANEL_LCD_PROTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) #ifdef CONFIG_PANEL_LCD_PIN_E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) #undef DEFAULT_LCD_PIN_E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) #define DEFAULT_LCD_PIN_E CONFIG_PANEL_LCD_PIN_E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) #ifdef CONFIG_PANEL_LCD_PIN_RS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) #undef DEFAULT_LCD_PIN_RS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) #define DEFAULT_LCD_PIN_RS CONFIG_PANEL_LCD_PIN_RS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) #ifdef CONFIG_PANEL_LCD_PIN_RW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) #undef DEFAULT_LCD_PIN_RW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) #define DEFAULT_LCD_PIN_RW CONFIG_PANEL_LCD_PIN_RW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) #ifdef CONFIG_PANEL_LCD_PIN_SCL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) #undef DEFAULT_LCD_PIN_SCL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) #define DEFAULT_LCD_PIN_SCL CONFIG_PANEL_LCD_PIN_SCL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) #ifdef CONFIG_PANEL_LCD_PIN_SDA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) #undef DEFAULT_LCD_PIN_SDA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) #define DEFAULT_LCD_PIN_SDA CONFIG_PANEL_LCD_PIN_SDA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) #ifdef CONFIG_PANEL_LCD_PIN_BL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) #undef DEFAULT_LCD_PIN_BL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) #define DEFAULT_LCD_PIN_BL CONFIG_PANEL_LCD_PIN_BL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) #endif /* DEFAULT_PROFILE == 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) /* global variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) /* Device single-open policy control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) static atomic_t keypad_available = ATOMIC_INIT(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) static struct pardevice *pprt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) static int keypad_initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) static DEFINE_SPINLOCK(pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) static struct timer_list scan_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) MODULE_DESCRIPTION("Generic parallel port LCD/Keypad driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) static int parport = DEFAULT_PARPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) module_param(parport, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) MODULE_PARM_DESC(parport, "Parallel port index (0=lpt1, 1=lpt2, ...)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) static int profile = DEFAULT_PROFILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) module_param(profile, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) MODULE_PARM_DESC(profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 		 "1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		 "4=16x2 nexcom; default=40x2, old kp");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) static int keypad_type = NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) module_param(keypad_type, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) MODULE_PARM_DESC(keypad_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 		 "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) static int lcd_type = NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) module_param(lcd_type, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) MODULE_PARM_DESC(lcd_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 		 "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) static int lcd_height = NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) module_param(lcd_height, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) MODULE_PARM_DESC(lcd_height, "Number of lines on the LCD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) static int lcd_width = NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) module_param(lcd_width, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) MODULE_PARM_DESC(lcd_width, "Number of columns on the LCD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) static int lcd_bwidth = NOT_SET;	/* internal buffer width (usually 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) module_param(lcd_bwidth, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) MODULE_PARM_DESC(lcd_bwidth, "Internal LCD line width (40)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) static int lcd_hwidth = NOT_SET;	/* hardware buffer width (usually 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) module_param(lcd_hwidth, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) MODULE_PARM_DESC(lcd_hwidth, "LCD line hardware address (64)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) static int lcd_charset = NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) module_param(lcd_charset, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) static int lcd_proto = NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) module_param(lcd_proto, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) MODULE_PARM_DESC(lcd_proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		 "LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456)  * These are the parallel port pins the LCD control signals are connected to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457)  * Set this to 0 if the signal is not used. Set it to its opposite value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458)  * (negative) if the signal is negated. -MAXINT is used to indicate that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459)  * pin has not been explicitly specified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461)  * WARNING! no check will be performed about collisions with keypad !
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) static int lcd_e_pin  = PIN_NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) module_param(lcd_e_pin, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) MODULE_PARM_DESC(lcd_e_pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		 "# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) static int lcd_rs_pin = PIN_NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) module_param(lcd_rs_pin, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) MODULE_PARM_DESC(lcd_rs_pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		 "# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) static int lcd_rw_pin = PIN_NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) module_param(lcd_rw_pin, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) MODULE_PARM_DESC(lcd_rw_pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		 "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) static int lcd_cl_pin = PIN_NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) module_param(lcd_cl_pin, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) MODULE_PARM_DESC(lcd_cl_pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 		 "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) static int lcd_da_pin = PIN_NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) module_param(lcd_da_pin, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) MODULE_PARM_DESC(lcd_da_pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		 "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) static int lcd_bl_pin = PIN_NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) module_param(lcd_bl_pin, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) MODULE_PARM_DESC(lcd_bl_pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		 "# of the // port pin connected to LCD backlight, with polarity (-17..17)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) /* Deprecated module parameters - consider not using them anymore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) static int lcd_enabled = NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) module_param(lcd_enabled, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) static int keypad_enabled = NOT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) module_param(keypad_enabled, int, 0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) /* for some LCD drivers (ks0074) we need a charset conversion table. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) static const unsigned char lcd_char_conv_ks0074[256] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	/*          0|8   1|9   2|A   3|B   4|C   5|D   6|E   7|F */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	/* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	/* 0x08 */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	/* 0x10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	/* 0x18 */ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	/* 0x20 */ 0x20, 0x21, 0x22, 0x23, 0xa2, 0x25, 0x26, 0x27,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	/* 0x28 */ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	/* 0x30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	/* 0x38 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	/* 0x40 */ 0xa0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	/* 0x48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	/* 0x50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	/* 0x58 */ 0x58, 0x59, 0x5a, 0xfa, 0xfb, 0xfc, 0x1d, 0xc4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	/* 0x60 */ 0x96, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	/* 0x68 */ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	/* 0x70 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	/* 0x78 */ 0x78, 0x79, 0x7a, 0xfd, 0xfe, 0xff, 0xce, 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	/* 0x80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	/* 0x88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	/* 0x90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	/* 0x98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	/* 0xA0 */ 0x20, 0x40, 0xb1, 0xa1, 0x24, 0xa3, 0xfe, 0x5f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	/* 0xA8 */ 0x22, 0xc8, 0x61, 0x14, 0x97, 0x2d, 0xad, 0x96,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	/* 0xB0 */ 0x80, 0x8c, 0x82, 0x83, 0x27, 0x8f, 0x86, 0xdd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	/* 0xB8 */ 0x2c, 0x81, 0x6f, 0x15, 0x8b, 0x8a, 0x84, 0x60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	/* 0xC0 */ 0xe2, 0xe2, 0xe2, 0x5b, 0x5b, 0xae, 0xbc, 0xa9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	/* 0xC8 */ 0xc5, 0xbf, 0xc6, 0xf1, 0xe3, 0xe3, 0xe3, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	/* 0xD0 */ 0x44, 0x5d, 0xa8, 0xe4, 0xec, 0xec, 0x5c, 0x78,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	/* 0xD8 */ 0xab, 0xa6, 0xe5, 0x5e, 0x5e, 0xe6, 0xaa, 0xbe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	/* 0xE0 */ 0x7f, 0xe7, 0xaf, 0x7b, 0x7b, 0xaf, 0xbd, 0xc8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	/* 0xE8 */ 0xa4, 0xa5, 0xc7, 0xf6, 0xa7, 0xe8, 0x69, 0x69,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	/* 0xF0 */ 0xed, 0x7d, 0xa8, 0xe4, 0xec, 0x5c, 0x5c, 0x25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	/* 0xF8 */ 0xac, 0xa6, 0xea, 0xef, 0x7e, 0xeb, 0xb2, 0x79,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) static const char old_keypad_profile[][4][9] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	{"S0", "Left\n", "Left\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	{"S1", "Down\n", "Down\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	{"S2", "Up\n", "Up\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	{"S3", "Right\n", "Right\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	{"S4", "Esc\n", "Esc\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	{"S5", "Ret\n", "Ret\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	{"", "", "", ""}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) /* signals, press, repeat, release */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) static const char new_keypad_profile[][4][9] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	{"S0", "Left\n", "Left\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	{"S1", "Down\n", "Down\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	{"S2", "Up\n", "Up\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	{"S3", "Right\n", "Right\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	{"S4s5", "", "Esc\n", "Esc\n"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	{"s4S5", "", "Ret\n", "Ret\n"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	{"S4S5", "Help\n", "", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	/* add new signals above this line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	{"", "", "", ""}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) /* signals, press, repeat, release */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) static const char nexcom_keypad_profile[][4][9] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	{"a-p-e-", "Down\n", "Down\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	{"a-p-E-", "Ret\n", "Ret\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	{"a-P-E-", "Esc\n", "Esc\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	{"a-P-e-", "Up\n", "Up\n", ""},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	/* add new signals above this line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	{"", "", "", ""}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) static const char (*keypad_profile)[4][9] = old_keypad_profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) static DECLARE_BITMAP(bits, LCD_BITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) static void lcd_get_bits(unsigned int port, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	unsigned int bit, state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 	for (bit = 0; bit < LCD_BITS; bit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 		state = test_bit(bit, bits) ? BIT_SET : BIT_CLR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		*val &= lcd_bits[port][bit][BIT_MSK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		*val |= lcd_bits[port][bit][state];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) /* sets data port bits according to current signals values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) static int set_data_bits(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	val = r_dtr(pprt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	lcd_get_bits(LCD_PORT_D, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	w_dtr(pprt, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) /* sets ctrl port bits according to current signals values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) static int set_ctrl_bits(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	val = r_ctr(pprt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	lcd_get_bits(LCD_PORT_C, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	w_ctr(pprt, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) /* sets ctrl & data port bits according to current signals values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) static void panel_set_bits(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	set_data_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	set_ctrl_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619)  * Converts a parallel port pin (from -25 to 25) to data and control ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620)  * masks, and data and control port bits. The signal will be considered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621)  * unconnected if it's on pin 0 or an invalid pin (<-25 or >25).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623)  * Result will be used this way :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624)  *   out(dport, in(dport) & d_val[2] | d_val[signal_state])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625)  *   out(cport, in(cport) & c_val[2] | c_val[signal_state])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	int d_bit, c_bit, inv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	d_val[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	c_val[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	d_val[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	c_val[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	d_val[2] = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	c_val[2] = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	if (pin == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	inv = (pin < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	if (inv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 		pin = -pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	d_bit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	c_bit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	switch (pin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	case PIN_STROBE:	/* strobe, inverted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 		c_bit = PNL_PSTROBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 		inv = !inv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	case PIN_D0...PIN_D7:	/* D0 - D7 = 2 - 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		d_bit = 1 << (pin - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	case PIN_AUTOLF:	/* autofeed, inverted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 		c_bit = PNL_PAUTOLF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		inv = !inv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	case PIN_INITP:		/* init, direct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		c_bit = PNL_PINITP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	case PIN_SELECP:	/* select_in, inverted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		c_bit = PNL_PSELECP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		inv = !inv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 	default:		/* unknown pin, ignore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	if (c_bit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 		c_val[2] &= ~c_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 		c_val[!inv] = c_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	} else if (d_bit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		d_val[2] &= ~d_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		d_val[!inv] = d_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681)  * send a serial byte to the LCD panel. The caller is responsible for locking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682)  * if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) static void lcd_send_serial(int byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	int bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	 * the data bit is set on D0, and the clock on STROBE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	 * LCD reads D0 on STROBE's rising edge.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	for (bit = 0; bit < 8; bit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		clear_bit(LCD_BIT_CL, bits);	/* CLK low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		panel_set_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		if (byte & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 			set_bit(LCD_BIT_DA, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 			clear_bit(LCD_BIT_DA, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		panel_set_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 		udelay(2);  /* maintain the data during 2 us before CLK up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		set_bit(LCD_BIT_CL, bits);	/* CLK high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		panel_set_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		udelay(1);  /* maintain the strobe during 1 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		byte >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) /* turn the backlight on or off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) static void lcd_backlight(struct charlcd *charlcd, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	if (lcd.pins.bl == PIN_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	/* The backlight is activated by setting the AUTOFEED line to +5V  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	spin_lock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 		set_bit(LCD_BIT_BL, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 		clear_bit(LCD_BIT_BL, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	panel_set_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) /* send a command to the LCD panel in serial mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) static void lcd_write_cmd_s(struct charlcd *charlcd, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	spin_lock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	lcd_send_serial(0x1F);	/* R/W=W, RS=0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	lcd_send_serial(cmd & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	lcd_send_serial((cmd >> 4) & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	udelay(40);		/* the shortest command takes at least 40 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) /* send data to the LCD panel in serial mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) static void lcd_write_data_s(struct charlcd *charlcd, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	spin_lock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	lcd_send_serial(0x5F);	/* R/W=W, RS=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	lcd_send_serial(data & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	lcd_send_serial((data >> 4) & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	udelay(40);		/* the shortest data takes at least 40 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) /* send a command to the LCD panel in 8 bits parallel mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) static void lcd_write_cmd_p8(struct charlcd *charlcd, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	spin_lock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	/* present the data to the data port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	w_dtr(pprt, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	udelay(20);	/* maintain the data during 20 us before the strobe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	set_bit(LCD_BIT_E, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	clear_bit(LCD_BIT_RS, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	clear_bit(LCD_BIT_RW, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	set_ctrl_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	udelay(40);	/* maintain the strobe during 40 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	clear_bit(LCD_BIT_E, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	set_ctrl_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	udelay(120);	/* the shortest command takes at least 120 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) /* send data to the LCD panel in 8 bits parallel mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) static void lcd_write_data_p8(struct charlcd *charlcd, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	spin_lock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	/* present the data to the data port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	w_dtr(pprt, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	udelay(20);	/* maintain the data during 20 us before the strobe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	set_bit(LCD_BIT_E, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	set_bit(LCD_BIT_RS, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	clear_bit(LCD_BIT_RW, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	set_ctrl_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	udelay(40);	/* maintain the strobe during 40 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	clear_bit(LCD_BIT_E, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	set_ctrl_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	udelay(45);	/* the shortest data takes at least 45 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) /* send a command to the TI LCD panel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) static void lcd_write_cmd_tilcd(struct charlcd *charlcd, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	spin_lock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	/* present the data to the control port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	w_ctr(pprt, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	udelay(60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) /* send data to the TI LCD panel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) static void lcd_write_data_tilcd(struct charlcd *charlcd, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	spin_lock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	/* present the data to the data port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	w_dtr(pprt, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	udelay(60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) /* fills the display with spaces and resets X/Y */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) static void lcd_clear_fast_s(struct charlcd *charlcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	int pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	spin_lock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	for (pos = 0; pos < charlcd->height * charlcd->hwidth; pos++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 		lcd_send_serial(0x5F);	/* R/W=W, RS=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 		lcd_send_serial(' ' & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		lcd_send_serial((' ' >> 4) & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 		/* the shortest data takes at least 40 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 		udelay(40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) /* fills the display with spaces and resets X/Y */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) static void lcd_clear_fast_p8(struct charlcd *charlcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	int pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	spin_lock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	for (pos = 0; pos < charlcd->height * charlcd->hwidth; pos++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 		/* present the data to the data port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 		w_dtr(pprt, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		/* maintain the data during 20 us before the strobe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 		udelay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 		set_bit(LCD_BIT_E, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		set_bit(LCD_BIT_RS, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 		clear_bit(LCD_BIT_RW, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		set_ctrl_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 		/* maintain the strobe during 40 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 		udelay(40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		clear_bit(LCD_BIT_E, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		set_ctrl_bits();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 		/* the shortest data takes at least 45 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 		udelay(45);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) /* fills the display with spaces and resets X/Y */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) static void lcd_clear_fast_tilcd(struct charlcd *charlcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	int pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	spin_lock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	for (pos = 0; pos < charlcd->height * charlcd->hwidth; pos++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 		/* present the data to the data port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 		w_dtr(pprt, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 		udelay(60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) static const struct charlcd_ops charlcd_serial_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 	.write_cmd	= lcd_write_cmd_s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	.write_data	= lcd_write_data_s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 	.clear_fast	= lcd_clear_fast_s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	.backlight	= lcd_backlight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) static const struct charlcd_ops charlcd_parallel_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	.write_cmd	= lcd_write_cmd_p8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	.write_data	= lcd_write_data_p8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	.clear_fast	= lcd_clear_fast_p8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	.backlight	= lcd_backlight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) static const struct charlcd_ops charlcd_tilcd_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	.write_cmd	= lcd_write_cmd_tilcd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	.write_data	= lcd_write_data_tilcd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 	.clear_fast	= lcd_clear_fast_tilcd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	.backlight	= lcd_backlight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) /* initialize the LCD driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) static void lcd_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	struct charlcd *charlcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	charlcd = charlcd_alloc(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	if (!charlcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	 * Init lcd struct with load-time values to preserve exact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 	 * current functionality (at least for now).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	charlcd->height = lcd_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	charlcd->width = lcd_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	charlcd->bwidth = lcd_bwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	charlcd->hwidth = lcd_hwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	switch (selected_lcd_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	case LCD_TYPE_OLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 		/* parallel mode, 8 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 		lcd.proto = LCD_PROTO_PARALLEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		lcd.charset = LCD_CHARSET_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		lcd.pins.e = PIN_STROBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 		lcd.pins.rs = PIN_AUTOLF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		charlcd->width = 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 		charlcd->bwidth = 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		charlcd->hwidth = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		charlcd->height = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	case LCD_TYPE_KS0074:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		/* serial mode, ks0074 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 		lcd.proto = LCD_PROTO_SERIAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 		lcd.charset = LCD_CHARSET_KS0074;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 		lcd.pins.bl = PIN_AUTOLF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 		lcd.pins.cl = PIN_STROBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 		lcd.pins.da = PIN_D0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		charlcd->width = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 		charlcd->bwidth = 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 		charlcd->hwidth = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		charlcd->height = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	case LCD_TYPE_NEXCOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		/* parallel mode, 8 bits, generic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 		lcd.proto = LCD_PROTO_PARALLEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 		lcd.charset = LCD_CHARSET_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 		lcd.pins.e = PIN_AUTOLF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 		lcd.pins.rs = PIN_SELECP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 		lcd.pins.rw = PIN_INITP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		charlcd->width = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		charlcd->bwidth = 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		charlcd->hwidth = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 		charlcd->height = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	case LCD_TYPE_CUSTOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 		/* customer-defined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 		lcd.proto = DEFAULT_LCD_PROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 		lcd.charset = DEFAULT_LCD_CHARSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		/* default geometry will be set later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	case LCD_TYPE_HANTRONIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		/* parallel mode, 8 bits, hantronix-like */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		lcd.proto = LCD_PROTO_PARALLEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 		lcd.charset = LCD_CHARSET_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		lcd.pins.e = PIN_STROBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		lcd.pins.rs = PIN_SELECP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 		charlcd->width = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		charlcd->bwidth = 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		charlcd->hwidth = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		charlcd->height = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	/* Overwrite with module params set on loading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	if (lcd_height != NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		charlcd->height = lcd_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	if (lcd_width != NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 		charlcd->width = lcd_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 	if (lcd_bwidth != NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		charlcd->bwidth = lcd_bwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	if (lcd_hwidth != NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 		charlcd->hwidth = lcd_hwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	if (lcd_charset != NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 		lcd.charset = lcd_charset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	if (lcd_proto != NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		lcd.proto = lcd_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	if (lcd_e_pin != PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		lcd.pins.e = lcd_e_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	if (lcd_rs_pin != PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 		lcd.pins.rs = lcd_rs_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	if (lcd_rw_pin != PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		lcd.pins.rw = lcd_rw_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	if (lcd_cl_pin != PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 		lcd.pins.cl = lcd_cl_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	if (lcd_da_pin != PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		lcd.pins.da = lcd_da_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	if (lcd_bl_pin != PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 		lcd.pins.bl = lcd_bl_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 	/* this is used to catch wrong and default values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	if (charlcd->width <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 		charlcd->width = DEFAULT_LCD_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	if (charlcd->bwidth <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 		charlcd->bwidth = DEFAULT_LCD_BWIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	if (charlcd->hwidth <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 		charlcd->hwidth = DEFAULT_LCD_HWIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	if (charlcd->height <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 		charlcd->height = DEFAULT_LCD_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	if (lcd.proto == LCD_PROTO_SERIAL) {	/* SERIAL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 		charlcd->ops = &charlcd_serial_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		if (lcd.pins.cl == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 			lcd.pins.cl = DEFAULT_LCD_PIN_SCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 		if (lcd.pins.da == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 			lcd.pins.da = DEFAULT_LCD_PIN_SDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	} else if (lcd.proto == LCD_PROTO_PARALLEL) {	/* PARALLEL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		charlcd->ops = &charlcd_parallel_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 		if (lcd.pins.e == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 			lcd.pins.e = DEFAULT_LCD_PIN_E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 		if (lcd.pins.rs == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 			lcd.pins.rs = DEFAULT_LCD_PIN_RS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		if (lcd.pins.rw == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 			lcd.pins.rw = DEFAULT_LCD_PIN_RW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		charlcd->ops = &charlcd_tilcd_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	if (lcd.pins.bl == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		lcd.pins.bl = DEFAULT_LCD_PIN_BL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	if (lcd.pins.e == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 		lcd.pins.e = PIN_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	if (lcd.pins.rs == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 		lcd.pins.rs = PIN_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	if (lcd.pins.rw == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		lcd.pins.rw = PIN_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	if (lcd.pins.bl == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 		lcd.pins.bl = PIN_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	if (lcd.pins.cl == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 		lcd.pins.cl = PIN_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	if (lcd.pins.da == PIN_NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 		lcd.pins.da = PIN_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	if (lcd.charset == NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 		lcd.charset = DEFAULT_LCD_CHARSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	if (lcd.charset == LCD_CHARSET_KS0074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 		charlcd->char_conv = lcd_char_conv_ks0074;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 		charlcd->char_conv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 		    lcd_bits[LCD_PORT_C][LCD_BIT_E]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	pin_to_bits(lcd.pins.rs, lcd_bits[LCD_PORT_D][LCD_BIT_RS],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 		    lcd_bits[LCD_PORT_C][LCD_BIT_RS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	pin_to_bits(lcd.pins.rw, lcd_bits[LCD_PORT_D][LCD_BIT_RW],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		    lcd_bits[LCD_PORT_C][LCD_BIT_RW]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	pin_to_bits(lcd.pins.bl, lcd_bits[LCD_PORT_D][LCD_BIT_BL],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 		    lcd_bits[LCD_PORT_C][LCD_BIT_BL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	pin_to_bits(lcd.pins.cl, lcd_bits[LCD_PORT_D][LCD_BIT_CL],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 		    lcd_bits[LCD_PORT_C][LCD_BIT_CL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	pin_to_bits(lcd.pins.da, lcd_bits[LCD_PORT_D][LCD_BIT_DA],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 		    lcd_bits[LCD_PORT_C][LCD_BIT_DA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	lcd.charlcd = charlcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	lcd.initialized = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)  * These are the file operation function for user access to /dev/keypad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) static ssize_t keypad_read(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 			   char __user *buf, size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 	unsigned i = *ppos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	char __user *tmp = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	if (keypad_buflen == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		if (file->f_flags & O_NONBLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 			return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 		if (wait_event_interruptible(keypad_read_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 					     keypad_buflen != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 			return -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	for (; count-- > 0 && (keypad_buflen > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 	     ++i, ++tmp, --keypad_buflen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 		put_user(keypad_buffer[keypad_start], tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 		keypad_start = (keypad_start + 1) % KEYPAD_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	*ppos = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 	return tmp - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) static int keypad_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 	ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	if (!atomic_dec_and_test(&keypad_available))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		goto fail;	/* open only once at a time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 	ret = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 	if (file->f_mode & FMODE_WRITE)	/* device is read-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 	keypad_buflen = 0;	/* flush the buffer on opening */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)  fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	atomic_inc(&keypad_available);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) static int keypad_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	atomic_inc(&keypad_available);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) static const struct file_operations keypad_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 	.read    = keypad_read,		/* read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	.open    = keypad_open,		/* open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	.release = keypad_release,	/* close */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	.llseek  = default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static struct miscdevice keypad_dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	.minor	= KEYPAD_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	.name	= "keypad",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	.fops	= &keypad_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) static void keypad_send_key(const char *string, int max_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	/* send the key to the device only if a process is attached to it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	if (!atomic_read(&keypad_available)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 		while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 			keypad_buffer[(keypad_start + keypad_buflen++) %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 				      KEYPAD_BUFFER] = *string++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 		wake_up_interruptible(&keypad_read_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* this function scans all the bits involving at least one logical signal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)  * and puts the results in the bitfield "phys_read" (one bit per established
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)  * contact), and sets "phys_read_prev" to "phys_read".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)  * Note: to debounce input signals, we will only consider as switched a signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)  * which is stable across 2 measures. Signals which are different between two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)  * reads will be kept as they previously were in their logical form (phys_prev).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)  * A signal which has just switched will have a 1 in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)  * (phys_read ^ phys_read_prev).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) static void phys_scan_contacts(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	int bit, bitval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	char oldval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	char bitmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	char gndmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	phys_prev = phys_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	phys_read_prev = phys_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	phys_read = 0;		/* flush all signals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	/* keep track of old value, with all outputs disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	oldval = r_dtr(pprt) | scan_mask_o;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	/* activate all keyboard outputs (active low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	w_dtr(pprt, oldval & ~scan_mask_o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	/* will have a 1 for each bit set to gnd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 	bitmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	/* disable all matrix signals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 	w_dtr(pprt, oldval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	/* now that all outputs are cleared, the only active input bits are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	 * directly connected to the ground
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	/* 1 for each grounded input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 	/* grounded inputs are signals 40-44 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	phys_read |= (__u64)gndmask << 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 	if (bitmask != gndmask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 		 * since clearing the outputs changed some inputs, we know
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 		 * that some input signals are currently tied to some outputs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		 * So we'll scan them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 		for (bit = 0; bit < 8; bit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 			bitval = BIT(bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 			if (!(scan_mask_o & bitval))	/* skip unused bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 			w_dtr(pprt, oldval & ~bitval);	/* enable this output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 			bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 			phys_read |= (__u64)bitmask << (5 * bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 		w_dtr(pprt, oldval);	/* disable all outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	 * this is easy: use old bits when they are flapping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 	 * use new ones when stable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	phys_curr = (phys_prev & (phys_read ^ phys_read_prev)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 		    (phys_read & ~(phys_read ^ phys_read_prev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) static inline int input_state_high(struct logical_input *input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 	/* FIXME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	 * this is an invalid test. It tries to catch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	 * transitions from single-key to multiple-key, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	 * doesn't take into account the contacts polarity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	 * The only solution to the problem is to parse keys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	 * from the most complex to the simplest combinations,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	 * and mark them as 'caught' once a combination
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	 * matches, then unmatch it for all other ones.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	/* try to catch dangerous transitions cases :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	 * someone adds a bit, so this signal was a false
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	 * positive resulting from a transition. We should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	 * invalidate the signal immediately and not call the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	 * release function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	 * eg: 0 -(press A)-> A -(press B)-> AB : don't match A's release.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	if (((phys_prev & input->mask) == input->value) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	    ((phys_curr & input->mask) >  input->value)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 		input->state = INPUT_ST_LOW; /* invalidate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 	if ((phys_curr & input->mask) == input->value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 		if ((input->type == INPUT_TYPE_STD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 		    (input->high_timer == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 			input->high_timer++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 			if (input->u.std.press_fct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 				input->u.std.press_fct(input->u.std.press_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 		} else if (input->type == INPUT_TYPE_KBD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 			/* will turn on the light */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 			keypressed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 			if (input->high_timer == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 				char *press_str = input->u.kbd.press_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 				if (press_str[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 					int s = sizeof(input->u.kbd.press_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 					keypad_send_key(press_str, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 			if (input->u.kbd.repeat_str[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 				char *repeat_str = input->u.kbd.repeat_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 				if (input->high_timer >= KEYPAD_REP_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 					int s = sizeof(input->u.kbd.repeat_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 					input->high_timer -= KEYPAD_REP_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 					keypad_send_key(repeat_str, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 				/* we will need to come back here soon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 				inputs_stable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 			if (input->high_timer < 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 				input->high_timer++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 	/* else signal falling down. Let's fall through. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 	input->state = INPUT_ST_FALLING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 	input->fall_timer = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) static inline void input_state_falling(struct logical_input *input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 	/* FIXME !!! same comment as in input_state_high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	if (((phys_prev & input->mask) == input->value) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	    ((phys_curr & input->mask) >  input->value)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 		input->state = INPUT_ST_LOW;	/* invalidate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	if ((phys_curr & input->mask) == input->value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 		if (input->type == INPUT_TYPE_KBD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 			/* will turn on the light */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 			keypressed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 			if (input->u.kbd.repeat_str[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 				char *repeat_str = input->u.kbd.repeat_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 				if (input->high_timer >= KEYPAD_REP_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 					int s = sizeof(input->u.kbd.repeat_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 					input->high_timer -= KEYPAD_REP_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 					keypad_send_key(repeat_str, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 				/* we will need to come back here soon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 				inputs_stable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 			if (input->high_timer < 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 				input->high_timer++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 		input->state = INPUT_ST_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	} else if (input->fall_timer >= input->fall_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 		/* call release event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 		if (input->type == INPUT_TYPE_STD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 			void (*release_fct)(int) = input->u.std.release_fct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 			if (release_fct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 				release_fct(input->u.std.release_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 		} else if (input->type == INPUT_TYPE_KBD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 			char *release_str = input->u.kbd.release_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 			if (release_str[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 				int s = sizeof(input->u.kbd.release_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 				keypad_send_key(release_str, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 		input->state = INPUT_ST_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 		input->fall_timer++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 		inputs_stable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) static void panel_process_inputs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 	struct logical_input *input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 	keypressed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 	inputs_stable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 	list_for_each_entry(input, &logical_inputs, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 		switch (input->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 		case INPUT_ST_LOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 			if ((phys_curr & input->mask) != input->value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 			/* if all needed ones were already set previously,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 			 * this means that this logical signal has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 			 * activated by the releasing of another combined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 			 * signal, so we don't want to match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 			 * eg: AB -(release B)-> A -(release A)-> 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 			 *     don't match A.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 			if ((phys_prev & input->mask) == input->value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 			input->rise_timer = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 			input->state = INPUT_ST_RISING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 		case INPUT_ST_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 			if ((phys_curr & input->mask) != input->value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 				input->state = INPUT_ST_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 			if (input->rise_timer < input->rise_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 				inputs_stable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 				input->rise_timer++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 			input->high_timer = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 			input->state = INPUT_ST_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 		case INPUT_ST_HIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 			if (input_state_high(input))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 		case INPUT_ST_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 			input_state_falling(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) static void panel_scan_timer(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 	if (keypad.enabled && keypad_initialized) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 		if (spin_trylock_irq(&pprt_lock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 			phys_scan_contacts();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 			/* no need for the parport anymore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 			spin_unlock_irq(&pprt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		if (!inputs_stable || phys_curr != phys_prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 			panel_process_inputs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 	if (keypressed && lcd.enabled && lcd.initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 		charlcd_poke(lcd.charlcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 	mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) static void init_scan_timer(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 	if (scan_timer.function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 		return;		/* already started */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 	timer_setup(&scan_timer, panel_scan_timer, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 	scan_timer.expires = jiffies + INPUT_POLL_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 	add_timer(&scan_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) /* converts a name of the form "({BbAaPpSsEe}{01234567-})*" to a series of bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)  * if <omask> or <imask> are non-null, they will be or'ed with the bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)  * corresponding to out and in bits respectively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)  * returns 1 if ok, 0 if error (in which case, nothing is written).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 			  u8 *imask, u8 *omask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 	const char sigtab[] = "EeSsPpAaBb";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 	u8 im, om;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	__u64 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 	om = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 	im = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 	m = 0ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 	v = 0ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 	while (*name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 		int in, out, bit, neg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 		const char *idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		idx = strchr(sigtab, *name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 		if (!idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 			return 0;	/* input name not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 		in = idx - sigtab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 		neg = (in & 1);	/* odd (lower) names are negated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 		in >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 		im |= BIT(in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 		name++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 		if (*name >= '0' && *name <= '7') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 			out = *name - '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 			om |= BIT(out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 		} else if (*name == '-') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 			out = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 			return 0;	/* unknown bit name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 		bit = (out * 5) + in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 		m |= 1ULL << bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 		if (!neg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 			v |= 1ULL << bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 		name++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 	*mask = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 	*value = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 	if (imask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 		*imask |= im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 	if (omask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 		*omask |= om;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) /* tries to bind a key to the signal name <name>. The key will send the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)  * strings <press>, <repeat>, <release> for these respective events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)  * Returns the pointer to the new key if ok, NULL if the key could not be bound.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) static struct logical_input *panel_bind_key(const char *name, const char *press,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 					    const char *repeat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 					    const char *release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 	struct logical_input *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 	key = kzalloc(sizeof(*key), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 	if (!key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 	if (!input_name2mask(name, &key->mask, &key->value, &scan_mask_i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 			     &scan_mask_o)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) 		kfree(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 	key->type = INPUT_TYPE_KBD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 	key->state = INPUT_ST_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 	key->rise_time = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 	key->fall_time = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 	strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 	strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 	strncpy(key->u.kbd.release_str, release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 		sizeof(key->u.kbd.release_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 	list_add(&key->list, &logical_inputs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 	return key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) /* tries to bind a callback function to the signal name <name>. The function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512)  * <press_fct> will be called with the <press_data> arg when the signal is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)  * activated, and so on for <release_fct>/<release_data>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)  * Returns the pointer to the new signal if ok, NULL if the signal could not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)  * be bound.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) static struct logical_input *panel_bind_callback(char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 						 void (*press_fct)(int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 						 int press_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 						 void (*release_fct)(int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 						 int release_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 	struct logical_input *callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 	callback = kmalloc(sizeof(*callback), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 	if (!callback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 	memset(callback, 0, sizeof(struct logical_input));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 	if (!input_name2mask(name, &callback->mask, &callback->value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 			     &scan_mask_i, &scan_mask_o))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 	callback->type = INPUT_TYPE_STD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 	callback->state = INPUT_ST_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 	callback->rise_time = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 	callback->fall_time = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 	callback->u.std.press_fct = press_fct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 	callback->u.std.press_data = press_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 	callback->u.std.release_fct = release_fct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 	callback->u.std.release_data = release_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) 	list_add(&callback->list, &logical_inputs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) 	return callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) static void keypad_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) 	int keynum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 	init_waitqueue_head(&keypad_read_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 	keypad_buflen = 0;	/* flushes any eventual noisy keystroke */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 	/* Let's create all known keys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 	for (keynum = 0; keypad_profile[keynum][0][0]; keynum++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 		panel_bind_key(keypad_profile[keynum][0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) 			       keypad_profile[keynum][1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 			       keypad_profile[keynum][2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 			       keypad_profile[keynum][3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 	init_scan_timer();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) 	keypad_initialized = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) /**************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) /* device initialization                          */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) /**************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) static void panel_attach(struct parport *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) 	struct pardev_cb panel_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) 	if (port->number != parport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) 	if (pprt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 		pr_err("%s: port->number=%d parport=%d, already registered!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) 		       __func__, port->number, parport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) 	memset(&panel_cb, 0, sizeof(panel_cb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) 	panel_cb.private = &pprt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) 	/* panel_cb.flags = 0 should be PARPORT_DEV_EXCL? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) 	pprt = parport_register_dev_model(port, "panel", &panel_cb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) 	if (!pprt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 		pr_err("%s: port->number=%d parport=%d, parport_register_device() failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) 		       __func__, port->number, parport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 	if (parport_claim(pprt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) 		pr_err("could not claim access to parport%d. Aborting.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) 		       parport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 		goto err_unreg_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 	/* must init LCD first, just in case an IRQ from the keypad is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 	 * generated at keypad init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 	if (lcd.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) 		lcd_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) 		if (!lcd.charlcd || charlcd_register(lcd.charlcd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 			goto err_unreg_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 	if (keypad.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 		keypad_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 		if (misc_register(&keypad_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 			goto err_lcd_unreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) err_lcd_unreg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) 	if (scan_timer.function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 		del_timer_sync(&scan_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 	if (lcd.enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) 		charlcd_unregister(lcd.charlcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) err_unreg_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) 	charlcd_free(lcd.charlcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) 	lcd.charlcd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) 	parport_unregister_device(pprt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) 	pprt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) static void panel_detach(struct parport *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) 	if (port->number != parport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 	if (!pprt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 		pr_err("%s: port->number=%d parport=%d, nothing to unregister.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 		       __func__, port->number, parport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 	if (scan_timer.function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 		del_timer_sync(&scan_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 	if (keypad.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) 		misc_deregister(&keypad_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) 		keypad_initialized = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) 	if (lcd.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 		charlcd_unregister(lcd.charlcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) 		lcd.initialized = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) 		charlcd_free(lcd.charlcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) 		lcd.charlcd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) 	/* TODO: free all input signals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) 	parport_release(pprt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) 	parport_unregister_device(pprt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 	pprt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) static struct parport_driver panel_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 	.name = "panel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 	.match_port = panel_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 	.detach = panel_detach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 	.devmodel = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) /* init function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) static int __init panel_init_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) 	int selected_keypad_type = NOT_SET, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) 	/* take care of an eventual profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) 	switch (profile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 	case PANEL_PROFILE_CUSTOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 		/* custom profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 		selected_keypad_type = DEFAULT_KEYPAD_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) 		selected_lcd_type = DEFAULT_LCD_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) 	case PANEL_PROFILE_OLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) 		/* 8 bits, 2*16, old keypad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) 		selected_keypad_type = KEYPAD_TYPE_OLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) 		selected_lcd_type = LCD_TYPE_OLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) 		/* TODO: This two are a little hacky, sort it out later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) 		if (lcd_width == NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) 			lcd_width = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) 		if (lcd_hwidth == NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 			lcd_hwidth = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 	case PANEL_PROFILE_NEW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) 		/* serial, 2*16, new keypad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 		selected_keypad_type = KEYPAD_TYPE_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) 		selected_lcd_type = LCD_TYPE_KS0074;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) 	case PANEL_PROFILE_HANTRONIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 		/* 8 bits, 2*16 hantronix-like, no keypad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 		selected_keypad_type = KEYPAD_TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) 		selected_lcd_type = LCD_TYPE_HANTRONIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 	case PANEL_PROFILE_NEXCOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) 		/* generic 8 bits, 2*16, nexcom keypad, eg. Nexcom. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) 		selected_keypad_type = KEYPAD_TYPE_NEXCOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 		selected_lcd_type = LCD_TYPE_NEXCOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) 	case PANEL_PROFILE_LARGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) 		/* 8 bits, 2*40, old keypad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 		selected_keypad_type = KEYPAD_TYPE_OLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 		selected_lcd_type = LCD_TYPE_OLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 	 * Overwrite selection with module param values (both keypad and lcd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 	 * where the deprecated params have lower prio.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) 	if (keypad_enabled != NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) 		selected_keypad_type = keypad_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) 	if (keypad_type != NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) 		selected_keypad_type = keypad_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) 	keypad.enabled = (selected_keypad_type > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) 	if (lcd_enabled != NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) 		selected_lcd_type = lcd_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) 	if (lcd_type != NOT_SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) 		selected_lcd_type = lcd_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 	lcd.enabled = (selected_lcd_type > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) 	if (lcd.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 		 * Init lcd struct with load-time values to preserve exact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) 		 * current functionality (at least for now).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 		lcd.charset = lcd_charset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 		lcd.proto = lcd_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 		lcd.pins.e = lcd_e_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 		lcd.pins.rs = lcd_rs_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 		lcd.pins.rw = lcd_rw_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 		lcd.pins.cl = lcd_cl_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 		lcd.pins.da = lcd_da_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) 		lcd.pins.bl = lcd_bl_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) 	switch (selected_keypad_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) 	case KEYPAD_TYPE_OLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) 		keypad_profile = old_keypad_profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) 	case KEYPAD_TYPE_NEW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) 		keypad_profile = new_keypad_profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) 	case KEYPAD_TYPE_NEXCOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) 		keypad_profile = nexcom_keypad_profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) 		keypad_profile = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 	if (!lcd.enabled && !keypad.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 		/* no device enabled, let's exit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) 		pr_err("panel driver disabled.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 	err = parport_register_driver(&panel_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 	if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 		pr_err("could not register with parport. Aborting.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 	if (pprt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 		pr_info("panel driver registered on parport%d (io=0x%lx).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 			parport, pprt->port->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) 		pr_info("panel driver not yet registered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) static void __exit panel_cleanup_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) 	parport_unregister_driver(&panel_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) module_init(panel_init_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) module_exit(panel_cleanup_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) MODULE_AUTHOR("Willy Tarreau");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)  * Local variables:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)  *  c-indent-level: 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)  *  tab-width: 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)  * End:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795)  */