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