1*24c9d96dSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2fabdbf2fSBruno Prémont /***************************************************************************
3fabdbf2fSBruno Prémont * Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org> *
4fabdbf2fSBruno Prémont * *
5fabdbf2fSBruno Prémont * Based on Logitech G13 driver (v0.4) *
6fabdbf2fSBruno Prémont * Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu> *
7fabdbf2fSBruno Prémont * *
8fabdbf2fSBruno Prémont ***************************************************************************/
9fabdbf2fSBruno Prémont
10fabdbf2fSBruno Prémont #define PICOLCD_NAME "PicoLCD (graphic)"
11fabdbf2fSBruno Prémont
12fabdbf2fSBruno Prémont /* Report numbers */
13fabdbf2fSBruno Prémont #define REPORT_ERROR_CODE 0x10 /* LCD: IN[16] */
14fabdbf2fSBruno Prémont #define ERR_SUCCESS 0x00
15fabdbf2fSBruno Prémont #define ERR_PARAMETER_MISSING 0x01
16fabdbf2fSBruno Prémont #define ERR_DATA_MISSING 0x02
17fabdbf2fSBruno Prémont #define ERR_BLOCK_READ_ONLY 0x03
18fabdbf2fSBruno Prémont #define ERR_BLOCK_NOT_ERASABLE 0x04
19fabdbf2fSBruno Prémont #define ERR_BLOCK_TOO_BIG 0x05
20fabdbf2fSBruno Prémont #define ERR_SECTION_OVERFLOW 0x06
21fabdbf2fSBruno Prémont #define ERR_INVALID_CMD_LEN 0x07
22fabdbf2fSBruno Prémont #define ERR_INVALID_DATA_LEN 0x08
23fabdbf2fSBruno Prémont #define REPORT_KEY_STATE 0x11 /* LCD: IN[2] */
24fabdbf2fSBruno Prémont #define REPORT_IR_DATA 0x21 /* LCD: IN[63] */
25fabdbf2fSBruno Prémont #define REPORT_EE_DATA 0x32 /* LCD: IN[63] */
26fabdbf2fSBruno Prémont #define REPORT_MEMORY 0x41 /* LCD: IN[63] */
27fabdbf2fSBruno Prémont #define REPORT_LED_STATE 0x81 /* LCD: OUT[1] */
28fabdbf2fSBruno Prémont #define REPORT_BRIGHTNESS 0x91 /* LCD: OUT[1] */
29fabdbf2fSBruno Prémont #define REPORT_CONTRAST 0x92 /* LCD: OUT[1] */
30fabdbf2fSBruno Prémont #define REPORT_RESET 0x93 /* LCD: OUT[2] */
31fabdbf2fSBruno Prémont #define REPORT_LCD_CMD 0x94 /* LCD: OUT[63] */
32fabdbf2fSBruno Prémont #define REPORT_LCD_DATA 0x95 /* LCD: OUT[63] */
33fabdbf2fSBruno Prémont #define REPORT_LCD_CMD_DATA 0x96 /* LCD: OUT[63] */
34fabdbf2fSBruno Prémont #define REPORT_EE_READ 0xa3 /* LCD: OUT[63] */
35fabdbf2fSBruno Prémont #define REPORT_EE_WRITE 0xa4 /* LCD: OUT[63] */
36fabdbf2fSBruno Prémont #define REPORT_ERASE_MEMORY 0xb2 /* LCD: OUT[2] */
37fabdbf2fSBruno Prémont #define REPORT_READ_MEMORY 0xb3 /* LCD: OUT[3] */
38fabdbf2fSBruno Prémont #define REPORT_WRITE_MEMORY 0xb4 /* LCD: OUT[63] */
39fabdbf2fSBruno Prémont #define REPORT_SPLASH_RESTART 0xc1 /* LCD: OUT[1] */
40fabdbf2fSBruno Prémont #define REPORT_EXIT_KEYBOARD 0xef /* LCD: OUT[2] */
41fabdbf2fSBruno Prémont #define REPORT_VERSION 0xf1 /* LCD: IN[2],OUT[1] Bootloader: IN[2],OUT[1] */
42fabdbf2fSBruno Prémont #define REPORT_BL_ERASE_MEMORY 0xf2 /* Bootloader: IN[36],OUT[4] */
43fabdbf2fSBruno Prémont #define REPORT_BL_READ_MEMORY 0xf3 /* Bootloader: IN[36],OUT[4] */
44fabdbf2fSBruno Prémont #define REPORT_BL_WRITE_MEMORY 0xf4 /* Bootloader: IN[36],OUT[36] */
45fabdbf2fSBruno Prémont #define REPORT_DEVID 0xf5 /* LCD: IN[5], OUT[1] Bootloader: IN[5],OUT[1] */
46fabdbf2fSBruno Prémont #define REPORT_SPLASH_SIZE 0xf6 /* LCD: IN[4], OUT[1] */
47fabdbf2fSBruno Prémont #define REPORT_HOOK_VERSION 0xf7 /* LCD: IN[2], OUT[1] */
48fabdbf2fSBruno Prémont #define REPORT_EXIT_FLASHER 0xff /* Bootloader: OUT[2] */
49fabdbf2fSBruno Prémont
50fabdbf2fSBruno Prémont /* Description of in-progress IO operation, used for operations
51fabdbf2fSBruno Prémont * that trigger response from device */
52fabdbf2fSBruno Prémont struct picolcd_pending {
53fabdbf2fSBruno Prémont struct hid_report *out_report;
54fabdbf2fSBruno Prémont struct hid_report *in_report;
55fabdbf2fSBruno Prémont struct completion ready;
56fabdbf2fSBruno Prémont int raw_size;
57fabdbf2fSBruno Prémont u8 raw_data[64];
58fabdbf2fSBruno Prémont };
59fabdbf2fSBruno Prémont
60fabdbf2fSBruno Prémont
61fabdbf2fSBruno Prémont #define PICOLCD_KEYS 17
62fabdbf2fSBruno Prémont
63fabdbf2fSBruno Prémont /* Per device data structure */
64fabdbf2fSBruno Prémont struct picolcd_data {
65fabdbf2fSBruno Prémont struct hid_device *hdev;
66fabdbf2fSBruno Prémont #ifdef CONFIG_DEBUG_FS
67fabdbf2fSBruno Prémont struct dentry *debug_reset;
68fabdbf2fSBruno Prémont struct dentry *debug_eeprom;
69fabdbf2fSBruno Prémont struct dentry *debug_flash;
70fabdbf2fSBruno Prémont struct mutex mutex_flash;
71fabdbf2fSBruno Prémont int addr_sz;
72fabdbf2fSBruno Prémont #endif
73fabdbf2fSBruno Prémont u8 version[2];
74fabdbf2fSBruno Prémont unsigned short opmode_delay;
75fabdbf2fSBruno Prémont /* input stuff */
76fabdbf2fSBruno Prémont u8 pressed_keys[2];
77fabdbf2fSBruno Prémont struct input_dev *input_keys;
78ae08e324SBruno Prémont #ifdef CONFIG_HID_PICOLCD_CIR
79ae08e324SBruno Prémont struct rc_dev *rc_dev;
80ae08e324SBruno Prémont #endif
81fabdbf2fSBruno Prémont unsigned short keycode[PICOLCD_KEYS];
82fabdbf2fSBruno Prémont
83fabdbf2fSBruno Prémont #ifdef CONFIG_HID_PICOLCD_FB
84fabdbf2fSBruno Prémont /* Framebuffer stuff */
85fabdbf2fSBruno Prémont struct fb_info *fb_info;
86fabdbf2fSBruno Prémont #endif /* CONFIG_HID_PICOLCD_FB */
87fabdbf2fSBruno Prémont #ifdef CONFIG_HID_PICOLCD_LCD
88fabdbf2fSBruno Prémont struct lcd_device *lcd;
89fabdbf2fSBruno Prémont u8 lcd_contrast;
90fabdbf2fSBruno Prémont #endif /* CONFIG_HID_PICOLCD_LCD */
91fabdbf2fSBruno Prémont #ifdef CONFIG_HID_PICOLCD_BACKLIGHT
92fabdbf2fSBruno Prémont struct backlight_device *backlight;
93fabdbf2fSBruno Prémont u8 lcd_brightness;
94fabdbf2fSBruno Prémont u8 lcd_power;
95fabdbf2fSBruno Prémont #endif /* CONFIG_HID_PICOLCD_BACKLIGHT */
96fabdbf2fSBruno Prémont #ifdef CONFIG_HID_PICOLCD_LEDS
97fabdbf2fSBruno Prémont /* LED stuff */
98fabdbf2fSBruno Prémont u8 led_state;
99fabdbf2fSBruno Prémont struct led_classdev *led[8];
100fabdbf2fSBruno Prémont #endif /* CONFIG_HID_PICOLCD_LEDS */
101fabdbf2fSBruno Prémont
102fabdbf2fSBruno Prémont /* Housekeeping stuff */
103fabdbf2fSBruno Prémont spinlock_t lock;
104fabdbf2fSBruno Prémont struct mutex mutex;
105fabdbf2fSBruno Prémont struct picolcd_pending *pending;
106fabdbf2fSBruno Prémont int status;
107fabdbf2fSBruno Prémont #define PICOLCD_BOOTLOADER 1
108fabdbf2fSBruno Prémont #define PICOLCD_FAILED 2
109ae08e324SBruno Prémont #define PICOLCD_CIR_SHUN 4
110fabdbf2fSBruno Prémont };
111fabdbf2fSBruno Prémont
11216048709SBruno Prémont #ifdef CONFIG_HID_PICOLCD_FB
11316048709SBruno Prémont struct picolcd_fb_data {
11416048709SBruno Prémont /* Framebuffer stuff */
11516048709SBruno Prémont spinlock_t lock;
11616048709SBruno Prémont struct picolcd_data *picolcd;
11716048709SBruno Prémont u8 update_rate;
11816048709SBruno Prémont u8 bpp;
11916048709SBruno Prémont u8 force;
12016048709SBruno Prémont u8 ready;
12116048709SBruno Prémont u8 *vbitmap; /* local copy of what was sent to PicoLCD */
12216048709SBruno Prémont u8 *bitmap; /* framebuffer */
12316048709SBruno Prémont };
12416048709SBruno Prémont #endif /* CONFIG_HID_PICOLCD_FB */
125fabdbf2fSBruno Prémont
126fabdbf2fSBruno Prémont /* Find a given report */
127fabdbf2fSBruno Prémont #define picolcd_in_report(id, dev) picolcd_report(id, dev, HID_INPUT_REPORT)
128fabdbf2fSBruno Prémont #define picolcd_out_report(id, dev) picolcd_report(id, dev, HID_OUTPUT_REPORT)
129fabdbf2fSBruno Prémont
130fabdbf2fSBruno Prémont struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir);
131fabdbf2fSBruno Prémont
132fabdbf2fSBruno Prémont #ifdef CONFIG_DEBUG_FS
133fabdbf2fSBruno Prémont void picolcd_debug_out_report(struct picolcd_data *data,
134fabdbf2fSBruno Prémont struct hid_device *hdev, struct hid_report *report);
135d8814272SBenjamin Tissoires #define hid_hw_request(a, b, c) \
136fabdbf2fSBruno Prémont do { \
137fabdbf2fSBruno Prémont picolcd_debug_out_report(hid_get_drvdata(a), a, b); \
138d8814272SBenjamin Tissoires hid_hw_request(a, b, c); \
139fabdbf2fSBruno Prémont } while (0)
140fabdbf2fSBruno Prémont
141fabdbf2fSBruno Prémont void picolcd_debug_raw_event(struct picolcd_data *data,
142fabdbf2fSBruno Prémont struct hid_device *hdev, struct hid_report *report,
143fabdbf2fSBruno Prémont u8 *raw_data, int size);
144fabdbf2fSBruno Prémont
145fabdbf2fSBruno Prémont void picolcd_init_devfs(struct picolcd_data *data,
146fabdbf2fSBruno Prémont struct hid_report *eeprom_r, struct hid_report *eeprom_w,
147fabdbf2fSBruno Prémont struct hid_report *flash_r, struct hid_report *flash_w,
148fabdbf2fSBruno Prémont struct hid_report *reset);
149fabdbf2fSBruno Prémont
150fabdbf2fSBruno Prémont void picolcd_exit_devfs(struct picolcd_data *data);
151fabdbf2fSBruno Prémont #else
picolcd_debug_out_report(struct picolcd_data * data,struct hid_device * hdev,struct hid_report * report)152e9a7c79bSAxel Lin static inline void picolcd_debug_out_report(struct picolcd_data *data,
153e9a7c79bSAxel Lin struct hid_device *hdev, struct hid_report *report)
154e9a7c79bSAxel Lin {
155e9a7c79bSAxel Lin }
picolcd_debug_raw_event(struct picolcd_data * data,struct hid_device * hdev,struct hid_report * report,u8 * raw_data,int size)156fabdbf2fSBruno Prémont static inline void picolcd_debug_raw_event(struct picolcd_data *data,
157fabdbf2fSBruno Prémont struct hid_device *hdev, struct hid_report *report,
158fabdbf2fSBruno Prémont u8 *raw_data, int size)
159fabdbf2fSBruno Prémont {
160fabdbf2fSBruno Prémont }
picolcd_init_devfs(struct picolcd_data * data,struct hid_report * eeprom_r,struct hid_report * eeprom_w,struct hid_report * flash_r,struct hid_report * flash_w,struct hid_report * reset)161fabdbf2fSBruno Prémont static inline void picolcd_init_devfs(struct picolcd_data *data,
162fabdbf2fSBruno Prémont struct hid_report *eeprom_r, struct hid_report *eeprom_w,
163fabdbf2fSBruno Prémont struct hid_report *flash_r, struct hid_report *flash_w,
164fabdbf2fSBruno Prémont struct hid_report *reset)
165fabdbf2fSBruno Prémont {
166fabdbf2fSBruno Prémont }
picolcd_exit_devfs(struct picolcd_data * data)167fabdbf2fSBruno Prémont static inline void picolcd_exit_devfs(struct picolcd_data *data)
168fabdbf2fSBruno Prémont {
169fabdbf2fSBruno Prémont }
170fabdbf2fSBruno Prémont #endif /* CONFIG_DEBUG_FS */
171fabdbf2fSBruno Prémont
172fabdbf2fSBruno Prémont
173fabdbf2fSBruno Prémont #ifdef CONFIG_HID_PICOLCD_FB
174fabdbf2fSBruno Prémont int picolcd_fb_reset(struct picolcd_data *data, int clear);
175fabdbf2fSBruno Prémont
176fabdbf2fSBruno Prémont int picolcd_init_framebuffer(struct picolcd_data *data);
177fabdbf2fSBruno Prémont
178fabdbf2fSBruno Prémont void picolcd_exit_framebuffer(struct picolcd_data *data);
179fabdbf2fSBruno Prémont
180fabdbf2fSBruno Prémont void picolcd_fb_refresh(struct picolcd_data *data);
181fabdbf2fSBruno Prémont #define picolcd_fbinfo(d) ((d)->fb_info)
182fabdbf2fSBruno Prémont #else
picolcd_fb_reset(struct picolcd_data * data,int clear)183fabdbf2fSBruno Prémont static inline int picolcd_fb_reset(struct picolcd_data *data, int clear)
184fabdbf2fSBruno Prémont {
185fabdbf2fSBruno Prémont return 0;
186fabdbf2fSBruno Prémont }
picolcd_init_framebuffer(struct picolcd_data * data)187fabdbf2fSBruno Prémont static inline int picolcd_init_framebuffer(struct picolcd_data *data)
188fabdbf2fSBruno Prémont {
189fabdbf2fSBruno Prémont return 0;
190fabdbf2fSBruno Prémont }
picolcd_exit_framebuffer(struct picolcd_data * data)191fabdbf2fSBruno Prémont static inline void picolcd_exit_framebuffer(struct picolcd_data *data)
192fabdbf2fSBruno Prémont {
193fabdbf2fSBruno Prémont }
picolcd_fb_refresh(struct picolcd_data * data)194fabdbf2fSBruno Prémont static inline void picolcd_fb_refresh(struct picolcd_data *data)
195fabdbf2fSBruno Prémont {
196fabdbf2fSBruno Prémont }
197fabdbf2fSBruno Prémont #define picolcd_fbinfo(d) NULL
198fabdbf2fSBruno Prémont #endif /* CONFIG_HID_PICOLCD_FB */
199fabdbf2fSBruno Prémont
200fabdbf2fSBruno Prémont
201fabdbf2fSBruno Prémont #ifdef CONFIG_HID_PICOLCD_BACKLIGHT
202fabdbf2fSBruno Prémont int picolcd_init_backlight(struct picolcd_data *data,
203fabdbf2fSBruno Prémont struct hid_report *report);
204fabdbf2fSBruno Prémont
205fabdbf2fSBruno Prémont void picolcd_exit_backlight(struct picolcd_data *data);
206fabdbf2fSBruno Prémont
207fabdbf2fSBruno Prémont int picolcd_resume_backlight(struct picolcd_data *data);
208fabdbf2fSBruno Prémont
209fabdbf2fSBruno Prémont void picolcd_suspend_backlight(struct picolcd_data *data);
210fabdbf2fSBruno Prémont #else
picolcd_init_backlight(struct picolcd_data * data,struct hid_report * report)211fabdbf2fSBruno Prémont static inline int picolcd_init_backlight(struct picolcd_data *data,
212fabdbf2fSBruno Prémont struct hid_report *report)
213fabdbf2fSBruno Prémont {
214fabdbf2fSBruno Prémont return 0;
215fabdbf2fSBruno Prémont }
picolcd_exit_backlight(struct picolcd_data * data)216fabdbf2fSBruno Prémont static inline void picolcd_exit_backlight(struct picolcd_data *data)
217fabdbf2fSBruno Prémont {
218fabdbf2fSBruno Prémont }
picolcd_resume_backlight(struct picolcd_data * data)219fabdbf2fSBruno Prémont static inline int picolcd_resume_backlight(struct picolcd_data *data)
220fabdbf2fSBruno Prémont {
221fabdbf2fSBruno Prémont return 0;
222fabdbf2fSBruno Prémont }
picolcd_suspend_backlight(struct picolcd_data * data)223fabdbf2fSBruno Prémont static inline void picolcd_suspend_backlight(struct picolcd_data *data)
224fabdbf2fSBruno Prémont {
225fabdbf2fSBruno Prémont }
226fabdbf2fSBruno Prémont
227fabdbf2fSBruno Prémont #endif /* CONFIG_HID_PICOLCD_BACKLIGHT */
228fabdbf2fSBruno Prémont
229fabdbf2fSBruno Prémont
230fabdbf2fSBruno Prémont #ifdef CONFIG_HID_PICOLCD_LCD
231fabdbf2fSBruno Prémont int picolcd_init_lcd(struct picolcd_data *data,
232fabdbf2fSBruno Prémont struct hid_report *report);
233fabdbf2fSBruno Prémont
234fabdbf2fSBruno Prémont void picolcd_exit_lcd(struct picolcd_data *data);
235fabdbf2fSBruno Prémont
236fabdbf2fSBruno Prémont int picolcd_resume_lcd(struct picolcd_data *data);
237fabdbf2fSBruno Prémont #else
picolcd_init_lcd(struct picolcd_data * data,struct hid_report * report)238fabdbf2fSBruno Prémont static inline int picolcd_init_lcd(struct picolcd_data *data,
239fabdbf2fSBruno Prémont struct hid_report *report)
240fabdbf2fSBruno Prémont {
241fabdbf2fSBruno Prémont return 0;
242fabdbf2fSBruno Prémont }
picolcd_exit_lcd(struct picolcd_data * data)243fabdbf2fSBruno Prémont static inline void picolcd_exit_lcd(struct picolcd_data *data)
244fabdbf2fSBruno Prémont {
245fabdbf2fSBruno Prémont }
picolcd_resume_lcd(struct picolcd_data * data)246fabdbf2fSBruno Prémont static inline int picolcd_resume_lcd(struct picolcd_data *data)
247fabdbf2fSBruno Prémont {
248fabdbf2fSBruno Prémont return 0;
249fabdbf2fSBruno Prémont }
250fabdbf2fSBruno Prémont #endif /* CONFIG_HID_PICOLCD_LCD */
251fabdbf2fSBruno Prémont
252fabdbf2fSBruno Prémont
253fabdbf2fSBruno Prémont #ifdef CONFIG_HID_PICOLCD_LEDS
254fabdbf2fSBruno Prémont int picolcd_init_leds(struct picolcd_data *data,
255fabdbf2fSBruno Prémont struct hid_report *report);
256fabdbf2fSBruno Prémont
257fabdbf2fSBruno Prémont void picolcd_exit_leds(struct picolcd_data *data);
258fabdbf2fSBruno Prémont
259fabdbf2fSBruno Prémont void picolcd_leds_set(struct picolcd_data *data);
260fabdbf2fSBruno Prémont #else
picolcd_init_leds(struct picolcd_data * data,struct hid_report * report)261fabdbf2fSBruno Prémont static inline int picolcd_init_leds(struct picolcd_data *data,
262fabdbf2fSBruno Prémont struct hid_report *report)
263fabdbf2fSBruno Prémont {
264fabdbf2fSBruno Prémont return 0;
265fabdbf2fSBruno Prémont }
picolcd_exit_leds(struct picolcd_data * data)266fabdbf2fSBruno Prémont static inline void picolcd_exit_leds(struct picolcd_data *data)
267fabdbf2fSBruno Prémont {
268fabdbf2fSBruno Prémont }
picolcd_leds_set(struct picolcd_data * data)269fabdbf2fSBruno Prémont static inline void picolcd_leds_set(struct picolcd_data *data)
270fabdbf2fSBruno Prémont {
271fabdbf2fSBruno Prémont }
272fabdbf2fSBruno Prémont #endif /* CONFIG_HID_PICOLCD_LEDS */
273fabdbf2fSBruno Prémont
274fabdbf2fSBruno Prémont
275fabdbf2fSBruno Prémont #ifdef CONFIG_HID_PICOLCD_CIR
276fabdbf2fSBruno Prémont int picolcd_raw_cir(struct picolcd_data *data,
277fabdbf2fSBruno Prémont struct hid_report *report, u8 *raw_data, int size);
278fabdbf2fSBruno Prémont
279fabdbf2fSBruno Prémont int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report);
280fabdbf2fSBruno Prémont
281fabdbf2fSBruno Prémont void picolcd_exit_cir(struct picolcd_data *data);
282fabdbf2fSBruno Prémont #else
picolcd_raw_cir(struct picolcd_data * data,struct hid_report * report,u8 * raw_data,int size)283fabdbf2fSBruno Prémont static inline int picolcd_raw_cir(struct picolcd_data *data,
284fabdbf2fSBruno Prémont struct hid_report *report, u8 *raw_data, int size)
285fabdbf2fSBruno Prémont {
286fabdbf2fSBruno Prémont return 1;
287fabdbf2fSBruno Prémont }
picolcd_init_cir(struct picolcd_data * data,struct hid_report * report)288fabdbf2fSBruno Prémont static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report)
289fabdbf2fSBruno Prémont {
290fabdbf2fSBruno Prémont return 0;
291fabdbf2fSBruno Prémont }
picolcd_exit_cir(struct picolcd_data * data)292fabdbf2fSBruno Prémont static inline void picolcd_exit_cir(struct picolcd_data *data)
293fabdbf2fSBruno Prémont {
294fabdbf2fSBruno Prémont }
2954e55467eSPaul Bolle #endif /* CONFIG_HID_PICOLCD_CIR */
296fabdbf2fSBruno Prémont
297fabdbf2fSBruno Prémont int picolcd_reset(struct hid_device *hdev);
298fabdbf2fSBruno Prémont struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
299fabdbf2fSBruno Prémont int report_id, const u8 *raw_data, int size);
300