Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | /* [START]{ SMARTBOOK CUSTOM CODE. TODO: move to standalone file */ |
2 | /* Original MHL driver use tabstop=4, this policy is followed here. */ | |
3 | #ifdef CONFIG_MTK_SMARTBOOK_SUPPORT | |
4 | ||
5 | #include <linux/delay.h> | |
6 | #include <mach/mt_gpio.h> | |
7 | #include <cust_gpio_usage.h> | |
8 | #include <cust_eint.h> | |
9 | #include <linux/interrupt.h> | |
10 | #include <linux/input.h> | |
11 | #include <linux/time.h> | |
12 | #include <linux/device.h> | |
13 | #include <linux/miscdevice.h> | |
14 | #include <asm/uaccess.h> | |
15 | #include <linux/power_supply.h> | |
16 | #include <linux/kthread.h> | |
17 | #include <linux/wakelock.h> | |
18 | #include <linux/timex.h> | |
19 | #include <linux/proc_fs.h> | |
20 | #include <linux/module.h> | |
21 | #include <linux/seq_file.h> | |
22 | #include <linux/mutex.h> | |
23 | #include <linux/sched.h> | |
24 | ||
25 | #include "si_cra.h" | |
26 | #include "si_cra_cfg.h" | |
27 | #include "si_mhl_defs.h" | |
28 | #include "si_mhl_tx_api.h" | |
29 | #include "si_mhl_tx_base_drv_api.h" | |
30 | #include "si_8338_regs.h" | |
31 | #include "si_drv_mhl_tx.h" | |
32 | #include "si_platform.h" | |
33 | #include "linux/aee.h" | |
34 | #include "smartbook.h" | |
35 | ||
36 | ||
37 | ||
38 | ||
39 | extern int SiiHandshakeCommand(HandshakeType ComType); | |
40 | extern bool_t PutPriorityCBusTransactionWrapper(cbus_req_t *preq); | |
41 | extern bool_t PutPriorityCBusTransactionImpl(cbus_req_t *preq); | |
42 | ||
43 | #ifdef ENABLE_TX_DEBUG_PRINT | |
44 | #define PutPriorityCBusTransaction(req) PutPriorityCBusTransactionWrapper(req) | |
45 | #else | |
46 | #define PutPriorityCBusTransaction(req) PutPriorityCBusTransactionImpl(req) | |
47 | #endif | |
48 | ||
49 | static struct input_dev *smartbook_dev; | |
50 | ||
51 | /* HID Buffer */ | |
52 | static uint8_t hidbi; /* HID buffer index */ | |
53 | static uint8_t hidbt; /* HID buffer tail */ | |
54 | static uint8_t hidbuf[HID_BUF * HID_SIZE]; /* HID data ring buffer */ | |
55 | ||
56 | /* Mouse */ | |
57 | static __u32 mouse_btns[] = { BTN_LEFT, BTN_MIDDLE, BTN_RIGHT }; /* BTN_RIGHT */ | |
58 | ||
59 | int mouse_btn = 0; | |
60 | int HID_RES_X, HID_RES_Y = 0; | |
61 | ||
62 | /*#ifdef SMARTBOOK_CRYPTO | |
63 | // Crypto, deprecated | |
64 | unsigned char hid_mid[3] = {0xff,0xff,0xff}; | |
65 | unsigned char hid_cpc[3] = {0, 0, 0}; | |
66 | unsigned char mtkid[] = { 0x66, 0x19, 0x5a, 0x22, 0xba, 0x51 }; | |
67 | unsigned char methods[] = { 0xcc, 0xb2, 0xaa, 0x95, 0x8b }; | |
68 | #endif*/ | |
69 | ||
70 | /* Keyboard */ | |
71 | int kb_modifier = 0; | |
72 | int kb_codes[] = { 0, 0, 0, 0 }; | |
73 | ||
74 | const unsigned int kb_modmap[] = { | |
75 | KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_HOMEPAGE, | |
76 | KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA | |
77 | }; | |
78 | ||
79 | const unsigned int kb_map[KB_LEN] = { /* 10 keys per line. refer USB_HID_Usage_Table.pdf for this mapping */ | |
80 | 0, 0, 0, 0, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, | |
81 | KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, | |
82 | KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, | |
83 | KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, | |
84 | KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE, | |
85 | KEY_RIGHTBRACE, KEY_BACKSLASH, | |
86 | KEY_GRAVE, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT, KEY_SLASH, | |
87 | KEY_CAPSLOCK, KEY_F1, KEY_F2, | |
88 | KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, | |
89 | KEY_SYSRQ, KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE, KEY_END, | |
90 | KEY_PAGEDOWN, KEY_RIGHT, | |
91 | KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, | |
92 | KEY_KPPLUS, KEY_KPENTER, KEY_KP1, | |
93 | KEY_KP2, KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT, | |
94 | KEY_BACKSLASH, KEY_MENU, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15, KEY_F16, | |
95 | KEY_F17, KEY_F18, | |
96 | KEY_F19, KEY_F20, KEY_F21, KEY_F22, KEY_F23, KEY_F24, | |
97 | KEY_PLAYPAUSE /*can't find EXECUTE */ , KEY_HELP, KEY_MENU, KEY_SELECT, | |
98 | KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE, | |
99 | KEY_VOLUMEUP, KEY_VOLUMEDOWN, | |
100 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
101 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
102 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
103 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
104 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
105 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
106 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*19x */ | |
107 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20x */ | |
108 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*21x */ | |
109 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*22x */ | |
110 | 0, 0, KEY_BRIGHTNESSUP, KEY_BRIGHTNESSDOWN, KEY_FN_F1, KEY_FN_F2, KEY_FN_F3, KEY_FN_F4, | |
111 | KEY_FN_F5, KEY_FN_F6, | |
112 | KEY_FN_F7, KEY_FN_F8, KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_FN_F12, 0, 0, 0, 0, | |
113 | }; | |
114 | ||
115 | const unsigned char SourceID[ID_LEN] = | |
116 | { SMB_SOURCE_ID_0, SMB_SOURCE_ID_1, SMB_SOURCE_ID_2, SMB_SOURCE_ID_3, SMB_SOURCE_ID_4, | |
117 | SMB_SOURCE_ID_5 }; | |
118 | const unsigned char SinkID[ID_LEN] = | |
119 | { SMB_SINK_ID_0, SMB_SINK_ID_1, SMB_SINK_ID_2, SMB_SINK_ID_3, SMB_SINK_ID_4, SMB_SINK_ID_5 }; | |
120 | ||
121 | /* Misc. */ | |
122 | wait_queue_head_t smartbook_wq; | |
123 | struct wake_lock smartbook_suspend_lock; | |
124 | int sbk_isSuspend = 0; | |
125 | /* int deinit = 0; */ | |
126 | /* #ifdef SBK_FAKE_BATTERY */ | |
127 | /* int sbk_fake_battery = 0; */ | |
128 | /* #endif */ | |
129 | ||
130 | static DEFINE_MUTEX(smb_mutex); | |
131 | SinkType SinkStatus = NotConnect; | |
132 | ||
133 | #define PERF_MONITOR | |
134 | ||
135 | #ifdef PERF_MONITOR | |
136 | ||
137 | #define NUM_RECORD 5 | |
138 | /* Performance monitor facility */ | |
139 | int64_t GetTimeStamp(void) | |
140 | { | |
141 | struct timeval tv; | |
142 | do_gettimeofday(&tv); | |
143 | return (tv.tv_sec & 0xff) * 1000000 + tv.tv_usec; /*convert to microsecond */ | |
144 | } | |
145 | ||
146 | void RecordStamp(bool dump, char tag) | |
147 | { | |
148 | static int records; | |
149 | int i; | |
150 | static int stamp[NUM_RECORD]; | |
151 | static char name[NUM_RECORD]; | |
152 | ||
153 | stamp[records] = (int)GetTimeStamp(); | |
154 | name[records] = tag; | |
155 | records++; | |
156 | ||
157 | if (dump == true || records >= NUM_RECORD) { | |
158 | for (i = 0; i < records; i++) { | |
159 | smb_print("TimeStamp[%c]: %d\n", name[i], stamp[i]); | |
160 | stamp[i] = 0; | |
161 | name[i] = 0; | |
162 | } | |
163 | records = 0; | |
164 | } | |
165 | } | |
166 | ||
167 | #else | |
168 | void RecordStamp(bool dump, char tag) | |
169 | { | |
170 | ||
171 | } | |
172 | #endif | |
173 | ||
174 | static int smartbook_init(int flag) | |
175 | { | |
176 | int err, i; | |
177 | if (smartbook_dev == NULL) { | |
178 | HID_RES_X = simple_strtoul(CONFIG_LCM_WIDTH, NULL, 0); | |
179 | HID_RES_Y = simple_strtoul(CONFIG_LCM_HEIGHT, NULL, 0); | |
180 | smartbook_dev = input_allocate_device(); | |
181 | if (!smartbook_dev) { | |
182 | smb_print("smartbook_dev: Not enough memory\n"); | |
183 | return -ENOMEM; | |
184 | } | |
185 | smartbook_dev->name = "sbk-kpd"; | |
186 | smartbook_dev->id.bustype = BUS_HOST; | |
187 | smartbook_dev->id.vendor = 0x2454; | |
188 | smartbook_dev->id.product = 0x6589; | |
189 | smartbook_dev->id.version = 0x0001; | |
190 | set_bit(EV_KEY, smartbook_dev->evbit); /* for kpd and mouse */ | |
191 | /* set_bit(EV_ABS, smartbook_dev->evbit); */ | |
192 | set_bit(EV_REL, smartbook_dev->evbit); /* for mouse */ | |
193 | set_bit(REL_X, smartbook_dev->relbit); | |
194 | set_bit(REL_Y, smartbook_dev->relbit); | |
195 | set_bit(REL_WHEEL, smartbook_dev->relbit); | |
196 | set_bit(BTN_LEFT, smartbook_dev->keybit); | |
197 | set_bit(BTN_MIDDLE, smartbook_dev->keybit); | |
198 | set_bit(BTN_RIGHT, smartbook_dev->keybit); | |
199 | set_bit(KEY_BACK, smartbook_dev->keybit); | |
200 | set_bit(BTN_MOUSE, smartbook_dev->keybit); | |
201 | ||
202 | for (i = 0; i < KB_LEN; i++) | |
203 | set_bit(kb_map[i], smartbook_dev->keybit); | |
204 | for (i = 0; i < KB_MODLEN; i++) | |
205 | set_bit(kb_modmap[i], smartbook_dev->keybit); | |
206 | ||
207 | } | |
208 | ||
209 | if (flag != 0) { | |
210 | err = input_register_device(smartbook_dev); | |
211 | smb_print("plug-in into smartbook, register input_dev\n"); | |
212 | SinkStatus = MonitorTV; | |
213 | if (err) { | |
214 | smb_print("smartbook_dev: Failed to register device\n"); | |
215 | input_free_device(smartbook_dev); | |
216 | return err; | |
217 | } | |
218 | } else { | |
219 | /* deinit = 1; */ | |
220 | hidbi = 0; | |
221 | hidbt = 0; | |
222 | input_unregister_device(smartbook_dev); | |
223 | smb_print("plug-out from smartbook, unregister input_dev\n"); | |
224 | smartbook_dev = NULL; | |
225 | if (SinkStatus == SmartBook) { | |
226 | smb_print("call smartbook disconnection\n"); | |
227 | } | |
228 | SinkStatus = NotConnect; | |
229 | /* deinit = 0; */ | |
230 | /* remove battery status when MHL connection is break */ | |
231 | update_battery_2nd_info(POWER_SUPPLY_STATUS_NOT_CHARGING, 0, 0); | |
232 | smb_print("MHL connection break\n"); | |
233 | } | |
234 | return 0; | |
235 | } | |
236 | ||
237 | SinkType SMBGetSinkStatus(void) | |
238 | { | |
239 | return SinkStatus; | |
240 | } | |
241 | ||
242 | /*#ifdef SMARTBOOK_CRYPTO | |
243 | static void smartbook_crypt(unsigned char mid, unsigned char cpc) { | |
244 | unsigned char cps[6], enc; | |
245 | unsigned int i; | |
246 | for(i=0;i<6;i++) { | |
247 | enc = cpc; | |
248 | enc = enc & methods[mid]; | |
249 | enc = enc ^ (enc >> 4); | |
250 | enc = enc ^ (enc >> 2); | |
251 | enc = enc ^ (enc >> 1); | |
252 | cpc = ( cpc << 1 ) | (enc & 1); | |
253 | cps[i] = cpc; | |
254 | } | |
255 | for(i=hidbi+2;i<hidbi+8;i++) { | |
256 | hidbuf[i] = hidbuf[i] ^ cps[i-2]; | |
257 | } | |
258 | return 0; | |
259 | } | |
260 | #endif*/ | |
261 | ||
262 | /*void SiiSendCbusWriteBurst(unsigned char *bufp, int length){ | |
263 | int i; | |
264 | cbus_req_t req; | |
265 | req.command = MHL_WRITE_BURST; | |
266 | req.length = length; | |
267 | req.offsetData = SCRATCHPAD_OFFSET; // scratchpad offset (Don't modify it) | |
268 | req.payload_u.pdatabytes = bufp; | |
269 | //mutex_lock(&smb_mutex); | |
270 | //SiiMhlTxDrvSendCbusCommand(&req); | |
271 | PutNextCBusTransaction(&req); | |
272 | //mutex_unlock(&smb_mutex); | |
273 | }*/ | |
274 | ||
275 | int SiiHandshakeCommand(HandshakeType ComType) | |
276 | { | |
277 | int i; | |
278 | bool error = false; | |
279 | cbus_req_t req; | |
280 | HIDCommand *comm = (HIDCommand *) (req.payload_u.msgData); | |
281 | ||
282 | req.command = MHL_WRITE_BURST; | |
283 | req.length = WRITEBURST_MAX_LEN; | |
284 | req.offsetData = SCRATCHPAD_OFFSET; /* scratchpad offset (Don't modify it) */ | |
285 | ||
286 | comm->category = CA_MISC; | |
287 | comm->command = MISC_HANDSHAKE; | |
288 | ||
289 | switch (ComType) { | |
290 | case Init: | |
291 | for (i = 0; i < ID_LEN; i++) { | |
292 | comm->payload[i] = SourceID[i]; | |
293 | } | |
294 | smb_print("handshake Init\n"); | |
295 | break; | |
296 | case Ack: | |
297 | for (i = 0; i < ID_LEN; i++) { | |
298 | comm->payload[i] = 0x0; | |
299 | } | |
300 | break; | |
301 | default: | |
302 | error = true; | |
303 | break; | |
304 | } | |
305 | if (error == false) { | |
306 | /* PutPriorityCBusTransaction(&req); */ | |
307 | SiiMhlTxDrvSendCbusCommand(&req); | |
308 | } | |
309 | } | |
310 | ||
311 | int SiiSendScreenCommand(ScreenOffType ComType, unsigned int downCountSec) | |
312 | { | |
313 | ||
314 | bool error = false; | |
315 | cbus_req_t req; | |
316 | HIDCommand *comm = (HIDCommand *) (req.payload_u.msgData); | |
317 | ||
318 | req.command = MHL_WRITE_BURST; | |
319 | req.length = 4; | |
320 | req.offsetData = SCRATCHPAD_OFFSET; /* scratchpad offset (Don't modify it) */ | |
321 | ||
322 | comm->category = CA_PMU; | |
323 | comm->command = PMU_SCREEN; | |
324 | ||
325 | switch (ComType) { | |
326 | case ImmediateOff: | |
327 | comm->payload[0] = 0xC0; | |
328 | comm->payload[1] = 0x0; | |
329 | break; | |
330 | case DownCount: | |
331 | comm->payload[0] = 0x80 + ((downCountSec & 0x3f00) >> 8); | |
332 | comm->payload[1] = (downCountSec & 0xff); | |
333 | break; | |
334 | case CancelDownCount: | |
335 | comm->payload[0] = 0x0; | |
336 | comm->payload[1] = 0x0; | |
337 | break; | |
338 | default: | |
339 | error = true; | |
340 | break; | |
341 | } | |
342 | if (error == false) { | |
343 | /* PutPriorityCBusTransaction(&req); */ | |
344 | SiiMhlTxDrvSendCbusCommand(&req); | |
345 | } | |
346 | } | |
347 | ||
348 | int SiiLatencyCommand(void) | |
349 | { | |
350 | bool error = false; | |
351 | struct timeval tv; | |
352 | int64_t count; | |
353 | ||
354 | cbus_req_t req; | |
355 | HIDCommand *comm = (HIDCommand *) (req.payload_u.msgData); | |
356 | ||
357 | req.command = MHL_WRITE_BURST; | |
358 | req.length = 5; | |
359 | req.offsetData = SCRATCHPAD_OFFSET; /* scratchpad offset (Don't modify it) */ | |
360 | ||
361 | comm->category = CA_MISC; | |
362 | comm->command = MISC_LATENCY; | |
363 | ||
364 | do_gettimeofday(&tv); | |
365 | count = tv.tv_sec * 1000 + tv.tv_usec / 1000; /*convert to millisecond */ | |
366 | ||
367 | comm->payload[0] = 0x1; /* plug-in code ID, don't care on the sink side */ | |
368 | comm->payload[1] = (unsigned char)((count & 0xff00) >> 8); | |
369 | comm->payload[2] = (unsigned char)(count & 0xff); | |
370 | ||
371 | if (error == false) { | |
372 | /* PutPriorityCBusTransaction(&req); */ | |
373 | SiiMhlTxDrvSendCbusCommand(&req); | |
374 | } | |
375 | } | |
376 | ||
377 | static void smartbook_kb(void) | |
378 | { | |
379 | int i, j, k, kcode, kb_update[4] = { 0, 0, 0, 0 }; | |
380 | uint8_t *chidbuf = &(hidbuf[hidbi]); | |
381 | int mod_update = kb_modifier ^ chidbuf[2]; | |
382 | if (chidbuf[3] == 0x1 && chidbuf[4] == 0x1 && chidbuf[5] == 0x1) | |
383 | return; | |
384 | for (i = 0; i < 8; i++) { | |
385 | if (mod_update & (1 << i)) { | |
386 | input_report_key(smartbook_dev, kb_modmap[i], | |
387 | ((chidbuf[2] & (1 << i)) ? 1 : 0)); | |
388 | } | |
389 | } | |
390 | kb_modifier = chidbuf[2]; | |
391 | for (i = 3; i < 7; i++) { | |
392 | if (chidbuf[i] == 0) | |
393 | break; | |
394 | for (j = 0; j < 4; j++) | |
395 | if (kb_codes[j] == chidbuf[i]) | |
396 | break; | |
397 | if (j == 4) { | |
398 | /* smb_print("Press HID KeyCode: %d\n", (int)chidbuf[i]); */ | |
399 | kcode = kb_map[chidbuf[i] < KB_LEN ? chidbuf[i] : 0]; | |
400 | input_report_key(smartbook_dev, kcode, 1); | |
401 | smb_print("Press ScanCode: %d\n", kcode); | |
402 | /* for aee dump temp solution */ | |
403 | if (kcode == KEY_4 | |
404 | && ((chidbuf[2] & 0x5) == 0x5 || (chidbuf[2] & 0x50) == 0x50)) { | |
405 | aee_kernel_reminding("manual dump", | |
406 | "CTRL + ALT + 4 to trigger dump"); | |
407 | } | |
408 | } else | |
409 | kb_codes[j] = 0; | |
410 | } | |
411 | for (i = 0; i < 4; i++) | |
412 | if (kb_codes[i]) { | |
413 | kcode = kb_map[kb_codes[i]]; | |
414 | input_report_key(smartbook_dev, kcode, 0); | |
415 | } | |
416 | for (i = 0; i < 4; i++) | |
417 | kb_codes[i] = chidbuf[i + 3]; | |
418 | input_sync(smartbook_dev); | |
419 | } | |
420 | ||
421 | static void smartbook_mouse(void) | |
422 | { | |
423 | int x, y, z, i, tmp_btn; | |
424 | uint8_t *chidbuf = &(hidbuf[hidbi]); | |
425 | x = ((chidbuf[3] << 8) & 0xff00) + (chidbuf[4] & 0xff); | |
426 | y = ((chidbuf[5] << 8) & 0xff00) + (chidbuf[6] & 0xff); | |
427 | z = chidbuf[7]; | |
428 | tmp_btn = mouse_btn ^ chidbuf[2]; | |
429 | if (x >> 15) | |
430 | x = -(((~x) & 0xfff) + 1); | |
431 | if (y >> 15) | |
432 | y = -(((~y) & 0xfff) + 1); | |
433 | if (z >> 7) | |
434 | z = -(((~z) & 0x0ff) + 1); | |
435 | if (x < -100 || x > 100 || y < -100 || y > 100) | |
436 | return; | |
437 | mouse_btn = chidbuf[2]; | |
438 | x = x * 2; | |
439 | y = y * 2; | |
440 | ||
441 | for (i = 0; i < 3; i++) | |
442 | if (tmp_btn & (1 << i)) | |
443 | input_report_key(smartbook_dev, mouse_btns[i], chidbuf[2] & (1 << i)); | |
444 | input_report_rel(smartbook_dev, REL_X, x); | |
445 | input_report_rel(smartbook_dev, REL_Y, y); | |
446 | input_report_rel(smartbook_dev, REL_WHEEL, z); | |
447 | ||
448 | smb_print("Update Mouse: %d %d %d %d\n", x, y, z, mouse_btn); | |
449 | ||
450 | input_sync(smartbook_dev); | |
451 | } | |
452 | ||
453 | static void smartbook_battery(void) | |
454 | { | |
455 | uint8_t *chidbuf = &(hidbuf[hidbi]); | |
456 | int charge_status = ((chidbuf[2] & 0x80) ? 1 : 0); | |
457 | int sbk_power_level = chidbuf[2] & 0x7f; | |
458 | ||
459 | smb_print("sbk_power_level: %d\n", sbk_power_level); | |
460 | ||
461 | update_battery_2nd_info((sbk_power_level == 100 ? | |
462 | POWER_SUPPLY_STATUS_FULL : | |
463 | (charge_status ? | |
464 | POWER_SUPPLY_STATUS_CHARGING : | |
465 | POWER_SUPPLY_STATUS_NOT_CHARGING)), sbk_power_level, 1); | |
466 | /* SendCommand = true; */ | |
467 | } | |
468 | ||
469 | static void smartbook_handshake(void) | |
470 | { | |
471 | uint8_t *chidbuf = &(hidbuf[hidbi]); | |
472 | int i; | |
473 | /* skip category & command , total 2 bytes */ | |
474 | chidbuf += 2; | |
475 | /*for(i = 2; i < ID_LEN; i++){ | |
476 | if(chidbuf[i] != SinkID[i]){ | |
477 | smb_print("Compare ID Fail, i: %d, content: %d\n", i, chidbuf[i]); | |
478 | //SinkStatus = Unknown; | |
479 | return ; | |
480 | } | |
481 | } */ | |
482 | if (SinkStatus != SmartBook) { | |
483 | smb_print("Identify Sink is Smartbook!\n"); | |
484 | SinkStatus = SmartBook; | |
485 | SiiHandshakeCommand(Ack); | |
486 | } | |
487 | } | |
488 | ||
489 | static void smartbook_latency(void) | |
490 | { | |
491 | uint8_t *chidbuf = &(hidbuf[hidbi]); | |
492 | int timestamp = (chidbuf[3] << 8) + chidbuf[4]; | |
493 | ||
494 | smb_print("Latency: %d\n", timestamp); | |
495 | ||
496 | SiiLatencyCommand(); | |
497 | } | |
498 | ||
499 | /* Called in component/mhl_tx/si_mhl_tx.c, when plug / unplug MHL */ | |
500 | void SiiHidSuspend(int flag) | |
501 | { | |
502 | if (sbk_isSuspend == flag) | |
503 | return; | |
504 | mutex_lock(&smb_mutex); | |
505 | ||
506 | sbk_isSuspend = flag; | |
507 | smartbook_init(flag); | |
508 | ||
509 | mutex_unlock(&smb_mutex); | |
510 | wake_up_interruptible(&smartbook_wq); | |
511 | } | |
512 | ||
513 | /* Read data from Registers, write them to HID Buffer */ | |
514 | int SiiHidWrite(int key) | |
515 | { | |
516 | int cbusInt, i, startReg = 0; | |
517 | unsigned int hid_kid = 0; | |
518 | uint8_t *chidbuf = &(hidbuf[hidbt]); | |
519 | ||
520 | if (!smartbook_dev) | |
521 | return 0; | |
522 | if (unlikely(HID_RES_Y == 0)) | |
523 | smartbook_init(1); | |
524 | if (key == 0) | |
525 | SiiRegReadBlock(REG_CBUS_SCRATCHPAD_0 + 8, chidbuf, HID_SIZE); /* 8); */ | |
526 | hidbt = (hidbt + HID_SIZE) % (HID_SIZE * HID_BUF); | |
527 | /* hidbt = (hidbt + HID_SIZE) & 0x3ff; */ | |
528 | if (unlikely(hidbi == hidbt)) { | |
529 | smb_print("MHL Hid Ring buf Overflow. "); | |
530 | hidbi = (hidbt + HID_SIZE) % (HID_SIZE * HID_BUF); | |
531 | /* hidbi = (hidbt + HID_SIZE) & 0x3ff; */ | |
532 | } | |
533 | ||
534 | wake_up_interruptible(&smartbook_wq); | |
535 | } | |
536 | ||
537 | /* Read data from HID Buffer */ | |
538 | int SiiHidRead(void) | |
539 | { | |
540 | int cbusInt, i, startReg = 0; | |
541 | unsigned int hid_kid = 0; | |
542 | uint8_t *chidbuf = &(hidbuf[hidbi]); | |
543 | /*#ifdef SMARTBOOK_CRYPTO | |
544 | if(chidbuf[0]==2) { | |
545 | if(chidbuf[1]==2) hid_kid = 0; | |
546 | if(chidbuf[1]==3) hid_kid = 1; | |
547 | hid_mid[hid_kid] = chidbuf[2]>>4; | |
548 | hid_cpc[hid_kid] = chidbuf[3]; | |
549 | } | |
550 | if(chidbuf[0]==1 && chidbuf[1]==2) hid_kid = 0; | |
551 | if(chidbuf[0]==1 && chidbuf[1]==3) hid_kid = 1; | |
552 | #endif*/ | |
553 | ||
554 | if (chidbuf[0] == 1 && chidbuf[1] == 2) | |
555 | smartbook_mouse(); | |
556 | else if (chidbuf[0] == 1 && chidbuf[1] == 3) | |
557 | smartbook_kb(); | |
558 | else if (chidbuf[0] == 0x80 && chidbuf[1] == 3) | |
559 | smartbook_battery(); | |
560 | else if (chidbuf[0] == 0x2 && chidbuf[1] == 0xaa) | |
561 | smartbook_latency(); | |
562 | else if (chidbuf[0] == 0x2) | |
563 | smartbook_handshake(); | |
564 | hidbi = (hidbi + HID_SIZE) % (HID_SIZE * HID_BUF); | |
565 | ||
566 | } | |
567 | ||
568 | /* HID kthread offload ISR's tasks. ISR --> Kthread by HID Buffer */ | |
569 | int smartbook_kthread(void *data) | |
570 | { | |
571 | struct sched_param param; | |
572 | int i, retval; | |
573 | ||
574 | /* adjust priority */ | |
575 | param.sched_priority = RTPM_PRIO_SCRN_UPDATE; | |
576 | sched_setscheduler(current, SCHED_RR, ¶m); | |
577 | ||
578 | while (1) { | |
579 | if (hidbt == hidbi) { /* ring buffer empty */ | |
580 | set_current_state(TASK_INTERRUPTIBLE); | |
581 | retval = | |
582 | wait_event_interruptible_timeout(smartbook_wq, hidbt != hidbi, 60 * HZ); | |
583 | set_current_state(TASK_RUNNING); | |
584 | } | |
585 | mutex_lock(&smb_mutex); | |
586 | if (smartbook_dev && retval != 0 && hidbt != hidbi) | |
587 | SiiHidRead(); /* not timeout */ | |
588 | mutex_unlock(&smb_mutex); | |
589 | /*if(deinit) { | |
590 | input_unregister_device(smartbook_dev); | |
591 | smartbook_dev = NULL; | |
592 | if(SinkStatus == SmartBook){ | |
593 | smb_print("call smartbook disconnection\n"); | |
594 | smartbook_state_callback(SMART_BOOK_DISCONNECTED); | |
595 | } | |
596 | SinkStatus = NotConnect; | |
597 | deinit = 0; | |
598 | // remove battery status when MHL connection is break | |
599 | update_battery_2nd_info(POWER_SUPPLY_STATUS_NOT_CHARGING, 0, 0); | |
600 | smb_print("MHL connection break\n"); | |
601 | continue; | |
602 | } */ | |
603 | ||
604 | if (kthread_should_stop()) | |
605 | break; | |
606 | } | |
607 | } | |
608 | ||
609 | static int SMBSinkTypeRead(char *buf, char **start, off_t off, int count, int *eof, void *data) | |
610 | { | |
611 | int len = 0; | |
612 | char *p = buf; | |
613 | ||
614 | switch (SinkStatus) { | |
615 | case NotConnect: | |
616 | p += sprintf(p, "N\n"); | |
617 | break; | |
618 | case SmartBook: | |
619 | p += sprintf(p, "S\n"); | |
620 | break; | |
621 | case MonitorTV: | |
622 | p += sprintf(p, "M\n"); | |
623 | break; | |
624 | case Unknown: | |
625 | p += sprintf(p, "U\n"); | |
626 | break; | |
627 | default: | |
628 | p += sprintf(p, "error\n"); | |
629 | break; | |
630 | } | |
631 | ||
632 | len = p - buf; | |
633 | return len; | |
634 | } | |
635 | ||
636 | ||
637 | static int SMBScreenCommandRead(char *buf, char **start, off_t off, int count, int *eof, void *data) | |
638 | { | |
639 | /*int len = 0; | |
640 | char *p = buf; | |
641 | ||
642 | if (mt_gpufreq_debug) | |
643 | p += sprintf(p, "gpufreq debug enabled\n"); | |
644 | else | |
645 | p += sprintf(p, "gpufreq debug disabled\n"); | |
646 | ||
647 | len = p - buf; | |
648 | return len;*/ | |
649 | return 0; | |
650 | } | |
651 | ||
652 | ||
653 | static ssize_t SMBScreenCommandWrite(struct file *file, const char *buffer, size_t count, loff_t * off) | |
654 | { | |
655 | ||
656 | int comType = 0, countTime = 0; | |
657 | ||
658 | if (sscanf(buffer, "%d %d", &comType, &countTime) == 2 && smartbook_dev != NULL) | |
659 | { | |
660 | if(comType >= ImmediateOff && comType <= CancelDownCount){ | |
661 | SiiSendScreenCommand(comType, countTime); | |
662 | smb_print("SendScreenCommand: %d %d\n", comType, countTime); | |
663 | return count; | |
664 | } | |
665 | } | |
666 | else if (smartbook_dev == NULL){ | |
667 | smb_print("Smartbook is not connected! \n"); | |
668 | } | |
669 | else { | |
670 | smb_print("SendScreenCommand fail!\n"); | |
671 | } | |
672 | ||
673 | return -EINVAL; | |
674 | } | |
675 | ||
676 | static const struct file_operations screen_fops = { | |
677 | .owner = THIS_MODULE, | |
678 | .read = NULL, | |
679 | .write = SMBScreenCommandWrite, | |
680 | }; | |
681 | ||
682 | ||
683 | ||
684 | static int __init smb_init(void) | |
685 | { | |
686 | //struct proc_dir_entry *entry = NULL; | |
687 | struct proc_dir_entry *smb_dir = NULL; | |
688 | ||
689 | smb_dir = proc_mkdir("smb", NULL); | |
690 | if (!smb_dir) | |
691 | { | |
692 | smb_print("[%s]: mkdir /proc/smb failed\n", __FUNCTION__); | |
693 | } | |
694 | else | |
695 | { | |
696 | proc_create("ScreenComm", S_IRUGO | S_IWUSR | S_IWGRP, smb_dir, &screen_fops); | |
697 | } | |
698 | return 0; | |
699 | } | |
700 | ||
701 | late_initcall(smb_init); | |
702 | ||
703 | #endif | |
704 | /* [END]{ SMARTBOOK CUSTOM CODE. TODO: move to standalone file */ |