import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / hdmi / Sii8338 / smartbook.c
CommitLineData
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
39extern int SiiHandshakeCommand(HandshakeType ComType);
40extern bool_t PutPriorityCBusTransactionWrapper(cbus_req_t *preq);
41extern 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
49static struct input_dev *smartbook_dev;
50
51/* HID Buffer */
52static uint8_t hidbi; /* HID buffer index */
53static uint8_t hidbt; /* HID buffer tail */
54static uint8_t hidbuf[HID_BUF * HID_SIZE]; /* HID data ring buffer */
55
56/* Mouse */
57static __u32 mouse_btns[] = { BTN_LEFT, BTN_MIDDLE, BTN_RIGHT }; /* BTN_RIGHT */
58
59int mouse_btn = 0;
60int HID_RES_X, HID_RES_Y = 0;
61
62/*#ifdef SMARTBOOK_CRYPTO
63// Crypto, deprecated
64unsigned char hid_mid[3] = {0xff,0xff,0xff};
65unsigned char hid_cpc[3] = {0, 0, 0};
66unsigned char mtkid[] = { 0x66, 0x19, 0x5a, 0x22, 0xba, 0x51 };
67unsigned char methods[] = { 0xcc, 0xb2, 0xaa, 0x95, 0x8b };
68#endif*/
69
70/* Keyboard */
71int kb_modifier = 0;
72int kb_codes[] = { 0, 0, 0, 0 };
73
74const unsigned int kb_modmap[] = {
75 KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_HOMEPAGE,
76 KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA
77};
78
79const 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
115const 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,
117SMB_SOURCE_ID_5 };
118const 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. */
122wait_queue_head_t smartbook_wq;
123struct wake_lock smartbook_suspend_lock;
124int sbk_isSuspend = 0;
125/* int deinit = 0; */
126/* #ifdef SBK_FAKE_BATTERY */
127/* int sbk_fake_battery = 0; */
128/* #endif */
129
130static DEFINE_MUTEX(smb_mutex);
131SinkType SinkStatus = NotConnect;
132
133#define PERF_MONITOR
134
135#ifdef PERF_MONITOR
136
137#define NUM_RECORD 5
138/* Performance monitor facility */
139int64_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
146void 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
168void RecordStamp(bool dump, char tag)
169{
170
171}
172#endif
173
174static 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
237SinkType SMBGetSinkStatus(void)
238{
239 return SinkStatus;
240}
241
242/*#ifdef SMARTBOOK_CRYPTO
243static 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
275int 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
311int 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
348int 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
377static 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
421static 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
453static 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
469static 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
489static 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 */
500void 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 */
514int 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 */
538int 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 */
569int 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, &param);
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
609static 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
637static 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
653static 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
676static const struct file_operations screen_fops = {
677 .owner = THIS_MODULE,
678 .read = NULL,
679 .write = SMBScreenCommandWrite,
680};
681
682
683
684static 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
701late_initcall(smb_init);
702
703#endif
704/* [END]{ SMARTBOOK CUSTOM CODE. TODO: move to standalone file */