cec.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209
  1. #include "drv_types.h"
  2. #include <linux/module.h>
  3. #include <linux/init.h>
  4. #include <linux/device.h>
  5. #include <linux/signal.h>
  6. #include <linux/kernel.h>
  7. #include <linux/sched.h>
  8. #include <linux/fs.h>
  9. #include <linux/cdev.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/mm.h>
  12. #include <linux/vmalloc.h> // drv_vmalloc() drv_vfree()
  13. #include <linux/version.h>
  14. #include <drv_devices.h>
  15. #include <drv_cec_internal.h>
  16. #include <drv_cec_external.h>
  17. #include "cec.h"
  18. #include "sysreg.h"
  19. #include "hdmi_cfg.h"
  20. #include "hdmi.h"
  21. #include "hdmi_hw.h"
  22. #include "hdmi_mapping.h"
  23. #include "hdmi_hpd.h"
  24. #include "hdmi_dbg.h"
  25. #include "debounce.h"
  26. #include "hdmi_processing.h"
  27. #include "hdmi_time.h"
  28. #include "drv_gpio.h"
  29. #define CDEV_CEC_MAJOR CEC_DEV_MAJOR
  30. #define CECSTATE_ADDR 0xbe0f0510
  31. static INT32 cecd_pid = -1;
  32. static struct work_struct wq_cec_signal;
  33. static pCEC_MSG_t pMsg = NULL;
  34. #ifdef HDMI_DDC5V_WORKAROUND
  35. static DEBOUNCE PortA_5V_debounce;
  36. static DEBOUNCE PortB_5V_debounce;
  37. static DEBOUNCE PortC_5V_debounce;
  38. static DRV_5V_LEVEL_e ePortA_SW_5V = DRV_5V_LEVEL_LOW, ePortB_SW_5V = DRV_5V_LEVEL_LOW, ePortC_SW_5V = DRV_5V_LEVEL_LOW;
  39. #else
  40. static DEBOUNCE Src_5V_debounce;
  41. #endif
  42. //for ARC 5V GPIO
  43. GPIOPin_t geGpio5V_Pin = GPIO_NOT_USE;
  44. HDMI_PORT_T geARCPort = HDMI_PORT_NULL;
  45. extern BOOL MHL_CABLE_IN;
  46. static BOOL MHL_CABLE_A_STATUS = false;
  47. static BOOL MHL_CABLE_B_STATUS = false;
  48. static DEBOUNCE ArcGpio_5V_debounce;
  49. static UINT8 BootUpLog = 0x0;
  50. static struct work_struct wq_SetHPD_A_TOGGLE;
  51. static struct work_struct wq_SetHPD_B_TOGGLE;
  52. static struct work_struct wq_SetHPD_C_TOGGLE;
  53. void SetHPD_A_TOGGLE(void)
  54. {
  55. hdmi_apply_hpd(DRV_HDMI_PORT_A, DRV_HPD_LEVEL_LOW);
  56. /* Wait HDMI_HPD_L2H_DELAY ms for hot plug pulse width */
  57. HDMI_DelayMs(HDMI_HPD_L2H_DELAY);
  58. hdmi_apply_hpd(DRV_HDMI_PORT_A, DRV_HPD_LEVEL_HIGH);
  59. }
  60. void SetHPD_B_TOGGLE(void)
  61. {
  62. hdmi_apply_hpd(DRV_HDMI_PORT_B, DRV_HPD_LEVEL_LOW);
  63. /* Wait HDMI_HPD_L2H_DELAY ms for hot plug pulse width */
  64. HDMI_DelayMs(HDMI_HPD_L2H_DELAY);
  65. hdmi_apply_hpd(DRV_HDMI_PORT_B, DRV_HPD_LEVEL_HIGH);
  66. }
  67. void SetHPD_C_TOGGLE(void)
  68. {
  69. hdmi_apply_hpd(DRV_HDMI_PORT_C, DRV_HPD_LEVEL_LOW);
  70. /* Wait HDMI_HPD_L2H_DELAY ms for hot plug pulse width */
  71. HDMI_DelayMs(HDMI_HPD_L2H_DELAY);
  72. hdmi_apply_hpd(DRV_HDMI_PORT_C, DRV_HPD_LEVEL_HIGH);
  73. }
  74. #ifdef INIT_BY_KMF
  75. static void TxFIFO_handler(pCEC_MSG_t pm);
  76. static INT32 QueryLink(UINT32 pAddr)
  77. {
  78. return (pAddr & 0xf000) >> 12;
  79. }
  80. static UINT32 query_physical_address(UINT8 logAddr)
  81. {
  82. UINT32 paddr = 0;
  83. INT32 timeout = 20, count;
  84. UINT8 cec_interrupt_flag = false;
  85. pFRAME_t m = &(pMsg->txMsg);
  86. m->block_num = 2;
  87. m->src = 0x0;
  88. m->dst = logAddr;
  89. m->opcode = 0x83;
  90. TxFIFO_handler(pMsg);
  91. HDMI_DelayMs(55);
  92. for (; timeout > 0; timeout--)
  93. {
  94. if (m->status == CEC_STATUS_TXNOACK)
  95. {
  96. cecdbg("CEC_STATUS_TXNOACK\n");
  97. return 0;
  98. }
  99. if (m->status == CEC_STATUS_TXEOMDONE)
  100. {
  101. cecdbg("CEC_STATUS_TXEOMDONE\n");
  102. break;
  103. }
  104. HDMI_DelayMs(25);
  105. }
  106. timeout = 30;
  107. for(;;)
  108. {
  109. HDMI_DelayMs(100);
  110. //cecdbg("HDMI_RegisterRead(CEC_rxData_EOM) = %d, (pMsg->bMsg = %d) , (timeout = %d) , (pMsg->bMessageDone = %d)",HDMI_RegisterRead(CEC_rxData_EOM), (pMsg->bMsg) , (timeout) , (pMsg->bMessageDone));
  111. if(pMsg->bMessageDone == true)
  112. {
  113. break;
  114. }
  115. if((timeout--) <= 0)
  116. {
  117. break;
  118. }
  119. }
  120. cecdbg("timeout = %d\n",timeout);
  121. for(timeout = 0;timeout<20 && (cec_interrupt_flag == false);timeout++)
  122. {
  123. pFRAME_t f;
  124. INT32 i = pMsg->Rp;
  125. count = pMsg->Wp;
  126. for (; i != count ; i = (i + 1) % FRAMEMAX)
  127. {
  128. f = &pMsg->rxMsg[i];
  129. if (f->opcode == 0x84 && f->src == logAddr && f->block_num == 5)
  130. {
  131. cec_interrupt_flag = true;
  132. paddr = ((f->param[0] << 8) | f->param[1]);
  133. break;
  134. }
  135. }
  136. HDMI_DelayMs(50);
  137. }
  138. return paddr;
  139. }
  140. /* return hdmi link no to umf: 1-hdmi1, 2-hdmi2 */
  141. INT32 CEC_Query(UINT8 logAddr)
  142. {
  143. INT32 ret;
  144. BootUpLog = logAddr;
  145. ret = QueryLink(query_physical_address(logAddr));
  146. cecdbg("%s: logAddr 0x%x in hdmi %d\n", __FUNCTION__, logAddr, ret);
  147. return ret;
  148. }
  149. #endif
  150. #ifdef HDMI_DDC5V_WORKAROUND
  151. static void Check_PortA_5V_change(void *data)
  152. {
  153. BOOL fIs_5V_Changed = FALSE;
  154. //DRV_5V_LEVEL_e ePortA_5V_Level = *((DRV_5V_LEVEL_e*)data);
  155. DRV_5V_LEVEL_e ePortA_5V_Level = (DRV_5V_LEVEL_e)data;
  156. //UINT8 fInRange = HDMI_RegisterRead(HDMIRX_IN_RANGE);
  157. if(ePortA_5V_Level == DRV_5V_LEVEL_HIGH)
  158. {
  159. if(ePortA_SW_5V == DRV_5V_LEVEL_LOW)
  160. {
  161. cecdbg("A in\n");
  162. fIs_5V_Changed = TRUE;
  163. ePortA_SW_5V = DRV_5V_LEVEL_HIGH;
  164. //if(hdmi_get_cur_port() == HDMI_PORT_A)
  165. // hdmi_set_termination(DRV_HDMI_PORT_A, DRV_HPD_LEVEL_HIGH);
  166. #ifdef CONFIG_CHANGE_HOT_PLUG_ACTION
  167. #ifndef CONFIG_SUPPORT_CEC_TV
  168. if(hdmi_get_cur_port() == HDMI_PORT_A)
  169. #endif
  170. #endif
  171. hdmi_apply_hpd(DRV_HDMI_PORT_A, DRV_HPD_LEVEL_HIGH);
  172. }
  173. //turn on SW 5V prevent HDMI auto reset when DDC 5V low
  174. if(hdmi_get_cur_port() == HDMI_PORT_A)
  175. sysset_HDMI_SW5V(HDMI_PORT_A, TRUE);
  176. }
  177. else if(ePortA_5V_Level == DRV_5V_LEVEL_LOW && ePortA_SW_5V == DRV_5V_LEVEL_HIGH)
  178. {
  179. if((hdmi_get_cur_port() == HDMI_PORT_A) && (hdmi_flag_check(HAS_ACTIVE_DATA)))
  180. {
  181. return;
  182. }
  183. else
  184. {
  185. cecdbg("A out\n");
  186. fIs_5V_Changed = TRUE;
  187. ePortA_SW_5V = DRV_5V_LEVEL_LOW;
  188. hdmi_apply_hpd(DRV_HDMI_PORT_A, DRV_HPD_LEVEL_LOW);
  189. //hdmi_set_termination(DRV_HDMI_PORT_A, DRV_HPD_LEVEL_LOW);
  190. }
  191. }
  192. if( fIs_5V_Changed == TRUE)
  193. {
  194. hdmi_hpd_update();
  195. if((hdmi_get_cur_port() == HDMI_PORT_A) &&(ePortA_SW_5V ==DRV_5V_LEVEL_HIGH))
  196. {
  197. schedule_work(&wq_SetHPD_A_TOGGLE);
  198. }
  199. }
  200. }
  201. static void Check_PortB_5V_change(void *data)
  202. {
  203. BOOL fIs_5V_Changed = FALSE;
  204. //DRV_5V_LEVEL_e ePortB_5V_Level = *((DRV_5V_LEVEL_e*)data);
  205. DRV_5V_LEVEL_e ePortB_5V_Level = (DRV_5V_LEVEL_e)data;
  206. //UINT8 fInRange = HDMI_RegisterRead(HDMIRX_IN_RANGE);
  207. if(ePortB_5V_Level == DRV_5V_LEVEL_HIGH)
  208. {
  209. if(ePortB_SW_5V == DRV_5V_LEVEL_LOW)
  210. {
  211. cecdbg("B in\n");
  212. fIs_5V_Changed = TRUE;
  213. ePortB_SW_5V = DRV_5V_LEVEL_HIGH;
  214. //if(hdmi_get_cur_port() == HDMI_PORT_B)
  215. // hdmi_set_termination(DRV_HDMI_PORT_B, DRV_HPD_LEVEL_HIGH);
  216. #ifdef CONFIG_CHANGE_HOT_PLUG_ACTION
  217. #ifndef CONFIG_SUPPORT_CEC_TV
  218. if(hdmi_get_cur_port() == HDMI_PORT_B)
  219. #endif
  220. #endif
  221. hdmi_apply_hpd(DRV_HDMI_PORT_B, DRV_HPD_LEVEL_HIGH);
  222. }
  223. //turn on SW 5V prevent HDMI auto reset when DDC 5V low
  224. if(hdmi_get_cur_port() == HDMI_PORT_B)
  225. sysset_HDMI_SW5V(HDMI_PORT_B, TRUE);
  226. }
  227. else if(ePortB_5V_Level == DRV_5V_LEVEL_LOW && ePortB_SW_5V == DRV_5V_LEVEL_HIGH)
  228. {
  229. if((hdmi_get_cur_port() == HDMI_PORT_B) && (hdmi_flag_check(HAS_ACTIVE_DATA)))
  230. {
  231. return;
  232. }
  233. else
  234. {
  235. cecdbg("B out\n");
  236. fIs_5V_Changed = TRUE;
  237. ePortB_SW_5V = DRV_5V_LEVEL_LOW;
  238. hdmi_apply_hpd(DRV_HDMI_PORT_B, DRV_HPD_LEVEL_LOW);
  239. //hdmi_set_termination(DRV_HDMI_PORT_B, DRV_HPD_LEVEL_LOW);
  240. }
  241. }
  242. if( fIs_5V_Changed == TRUE)
  243. {
  244. hdmi_hpd_update();
  245. if((hdmi_get_cur_port() == HDMI_PORT_B) &&(ePortB_SW_5V ==DRV_5V_LEVEL_HIGH))
  246. {
  247. schedule_work(&wq_SetHPD_B_TOGGLE);
  248. }
  249. }
  250. }
  251. static void Check_PortC_5V_change(void *data)
  252. {
  253. BOOL fIs_5V_Changed = FALSE;
  254. //DRV_5V_LEVEL_e ePortC_5V_Level = *((DRV_5V_LEVEL_e*)data);
  255. DRV_5V_LEVEL_e ePortC_5V_Level = (DRV_5V_LEVEL_e)data;
  256. //UINT8 fInRange = HDMI_RegisterRead(HDMIRX_IN_RANGE);
  257. if(ePortC_5V_Level == DRV_5V_LEVEL_HIGH)
  258. {
  259. if(ePortC_SW_5V == DRV_5V_LEVEL_LOW)
  260. {
  261. cecdbg("C in\n");
  262. fIs_5V_Changed = TRUE;
  263. ePortC_SW_5V = DRV_5V_LEVEL_HIGH;
  264. //if(hdmi_get_cur_port() == HDMI_PORT_C)
  265. // hdmi_set_termination(DRV_HDMI_PORT_C, DRV_HPD_LEVEL_HIGH);
  266. #ifdef CONFIG_CHANGE_HOT_PLUG_ACTION
  267. #ifndef CONFIG_SUPPORT_CEC_TV
  268. if(hdmi_get_cur_port() == HDMI_PORT_C)
  269. #endif
  270. #endif
  271. hdmi_apply_hpd(DRV_HDMI_PORT_C, DRV_HPD_LEVEL_HIGH);
  272. }
  273. //turn on SW 5V prevent HDMI auto reset when DDC 5V low
  274. if(hdmi_get_cur_port() == HDMI_PORT_C)
  275. sysset_HDMI_SW5V(HDMI_PORT_C, TRUE);
  276. }
  277. else if(ePortC_5V_Level == DRV_5V_LEVEL_LOW && ePortC_SW_5V == DRV_5V_LEVEL_HIGH)
  278. {
  279. if((hdmi_get_cur_port() == HDMI_PORT_C) && (hdmi_flag_check(HAS_ACTIVE_DATA)))
  280. {
  281. return;
  282. }
  283. else
  284. {
  285. cecdbg("C out\n");
  286. fIs_5V_Changed = TRUE;
  287. ePortC_SW_5V = DRV_5V_LEVEL_LOW;
  288. hdmi_apply_hpd(DRV_HDMI_PORT_C, DRV_HPD_LEVEL_LOW);
  289. //hdmi_set_termination(DRV_HDMI_PORT_C, DRV_HPD_LEVEL_LOW);
  290. }
  291. }
  292. if( fIs_5V_Changed == TRUE)
  293. {
  294. hdmi_hpd_update();
  295. if((hdmi_get_cur_port() == HDMI_PORT_C) &&(ePortC_SW_5V ==DRV_5V_LEVEL_HIGH))
  296. {
  297. schedule_work(&wq_SetHPD_C_TOGGLE);
  298. }
  299. }
  300. }
  301. DRV_5V_LEVEL_e CEC_Get_SW5V(HDMI_PORT_T ePort)
  302. {
  303. DRV_5V_LEVEL_e eLevel;
  304. switch(ePort)
  305. {
  306. case HDMI_PORT_A:
  307. eLevel = ePortA_SW_5V;
  308. break;
  309. case HDMI_PORT_B:
  310. eLevel = ePortB_SW_5V;
  311. break;
  312. case HDMI_PORT_C:
  313. eLevel = ePortC_SW_5V;
  314. break;
  315. default:
  316. eLevel = DRV_5V_LEVEL_LOW;
  317. break;
  318. }
  319. return eLevel;
  320. }
  321. #else
  322. static void CheckSrc5V_change(void *dummy)
  323. {
  324. hdmi_hpd_update();
  325. }
  326. #endif
  327. static void CEC_parser_wq(void *dummy)
  328. {
  329. struct task_struct *p;
  330. p = find_task_by_vpid(cecd_pid);
  331. if (p)
  332. {
  333. send_sig_info(CEC_SIG, (void*)1, p);
  334. }
  335. }
  336. static void CEC_parser(void)
  337. {
  338. schedule_work(&wq_cec_signal);
  339. }
  340. static void RxFIFO_handler(pCEC_MSG_t pm)
  341. {
  342. if (!pm->rxFifo_cnt)
  343. {
  344. return;
  345. }
  346. HDMI_RegisterWrite(CEC_Rx_FIFO_POP, 0);
  347. pm->rxFifo_cnt--;
  348. if (HDMI_RegisterRead(CEC_rxData_sbit))
  349. {
  350. pm->rxBlock_ptr = 0;
  351. pm->rxMsg[pm->Wp].block_num = 0;
  352. pm->bMsg = true;
  353. }
  354. if (pm->bMsg)
  355. {
  356. pm->rxMsg[pm->Wp].block[pm->rxBlock_ptr] = HDMI_RegisterRead(CEC_rxData);
  357. //hdmidbg("\trxMsg[%d].block[%d]=0x%02x\tA%dE%d\n",pm->Wp,pm->rxBlock_ptr,HDMI_RegisterRead(CEC_rxData), HDMI_RegisterRead(CEC_rxData_ACK), HDMI_RegisterRead(CEC_rxData_EOM));
  358. if (pm->rxBlock_ptr < 17)
  359. {
  360. pm->rxBlock_ptr++;
  361. }
  362. }
  363. if (HDMI_RegisterRead(CEC_rxData_EOM) && pm->bMsg)
  364. {
  365. #ifdef CONFIG_SUPPORT_DEBUG_MESSAGE
  366. INT32 c,n;
  367. INT8 str[40];
  368. #endif
  369. pm->rxMsg[pm->Wp].block_num = pm->rxBlock_ptr;
  370. pm->rxBlock_ptr = 0;
  371. pm->rxFifo_cnt = 0;
  372. pm->bMsg = false;
  373. #ifdef CONFIG_SUPPORT_DEBUG_MESSAGE
  374. //print recieved CEC message
  375. for(c=0,n=0;c<pm->rxMsg[pm->Wp].block_num;c++)
  376. {
  377. if (n >= 0)
  378. {
  379. n += sprintf(&str[n], "%02x%s", pm->rxMsg[pm->Wp].block[c], c != (pm->rxMsg[pm->Wp].block_num - 1) ? "" : "\n");
  380. }
  381. }
  382. cecdbg("Msg recv %s",str);
  383. #endif
  384. pm->Wp = (pm->Wp + 1) % FRAMEMAX;
  385. if (pm->Wp == pm->Rp)
  386. {
  387. pm->bOverwrite = true;
  388. }
  389. pm->bMessageDone = true;
  390. CEC_parser();
  391. }
  392. HDMI_RegisterWrite(CEC_Rx_FIFO_POP, 1);
  393. }
  394. static void TxFIFO_handler(pCEC_MSG_t pm)
  395. {
  396. pFRAME_t ptxMsg = &(pm->txMsg);
  397. INT32 i = 0;
  398. #ifdef CONFIG_SUPPORT_DEBUG_MESSAGE
  399. INT32 c,n;
  400. INT8 str[40];
  401. #endif
  402. if (ptxMsg->status == CEC_STATUS_TXSENDING)
  403. {
  404. return;
  405. }
  406. if (ptxMsg->block_num <= 0)
  407. {
  408. return;
  409. }
  410. ptxMsg->status = CEC_STATUS_TXSENDING;
  411. HDMI_RegisterWrite(CEC_HEADER_follower, ptxMsg->block[0] & 0xf);
  412. HDMI_RegisterWrite(CEC_HEADER_initiator, ptxMsg->block[0] >> 4);
  413. for (i = 1; i < ptxMsg->block_num; i++)
  414. {
  415. HDMI_RegisterWrite(CEC_DataBlock00 + (i - 1), ptxMsg->block[i]);
  416. }
  417. #ifdef CONFIG_SUPPORT_DEBUG_MESSAGE
  418. //print send CEC message
  419. for(c=0,n=0;c<ptxMsg->block_num;c++)
  420. {
  421. if (n >= 0)
  422. {
  423. n += sprintf(&str[n], "%02x%s", ptxMsg->block[c], c != (ptxMsg->block_num - 1) ? "" : "\n");
  424. }
  425. }
  426. cecdbg("Msg sent: %s",str);
  427. #endif
  428. if (ptxMsg->block_num > 1)
  429. {
  430. HDMI_RegisterWrite(CEC_Header_EOM, 0);
  431. HDMI_RegisterWrite(CEC_Block_XX_EOM, ptxMsg->block_num - 2);
  432. HDMI_RegisterWrite(CEC_R_retry_th, 3);
  433. }
  434. else
  435. {
  436. HDMI_RegisterWrite(CEC_Header_EOM, 1);
  437. HDMI_RegisterWrite(CEC_Block_XX_EOM, 0);
  438. HDMI_RegisterWrite(CEC_R_retry_th, 1);
  439. }
  440. HDMI_RegisterWrite(CEC_TransmissionStart, 0);
  441. HDMI_RegisterWrite(CEC_TransmissionStart, 1);
  442. }
  443. #ifdef CONFIG_DEBUG_DRV_CEC_WRITE_EN
  444. static UINT8 char2Hex(INT8 ch)
  445. {
  446. if (ch >= '0' && ch <= '9')
  447. {
  448. return ch - '0';
  449. }
  450. else if (ch >= 'a' && ch <= 'f')
  451. {
  452. return ch - 'a' + 10;
  453. }
  454. else if (ch >= 'A' && ch <= 'F')
  455. {
  456. return ch - 'A' + 10;
  457. }
  458. return 0x0;
  459. }
  460. static void msg_parser(const INT8 *str)
  461. {
  462. UINT8 ch = '\0';
  463. UINT32 i = 0;
  464. while (*str != ' ' && *str != '\0' && *(str + 1) != '\0')
  465. {
  466. ch = char2Hex(*str) * 16 + char2Hex(*(str + 1));
  467. str = str + 2;
  468. pMsg->txMsg.block[i] = ch;
  469. i++;
  470. if (i >= 17)
  471. {
  472. break;
  473. }
  474. }
  475. pMsg->txMsg.block_num = i;
  476. }
  477. #endif
  478. static void BootUpPatch(void)
  479. {
  480. cecdbg("%s:\n", __FUNCTION__);
  481. /* Patch: Change source to related hdmi source */
  482. if (BootUpLog)
  483. {
  484. UINT32 addr;
  485. FRAME_t m;
  486. pMsg->bMessageDone = false;
  487. addr = query_physical_address(BootUpLog);
  488. m.block[0] = 0xf | ((BootUpLog & 0xf) << 4);
  489. m.block[1] = 0x82; // Active Source
  490. m.block[2] = ((addr >> 8) & 0xff);
  491. m.block[3] = ((addr) & 0xff);
  492. m.block_num = 4;
  493. if (pMsg->bOverwrite)
  494. {
  495. cecdbg("Msg overwrite\n");
  496. pMsg->Rp++;
  497. }
  498. memcpy(&pMsg->rxMsg[pMsg->Wp], &m, sizeof(FRAME_t));
  499. pMsg->txMsg.status = CEC_STATUS_TXEOMDONE;
  500. pMsg->txMsg.block_num = 0;
  501. pMsg->Wp = (pMsg->Wp + 1) % FRAMEMAX;
  502. if (pMsg->Wp == pMsg->Rp)
  503. {
  504. cecdbg("Msg Full\n");
  505. pMsg->bOverwrite = true;
  506. }
  507. pMsg->bMessageDone = true;
  508. cecdbg("Patch: Send <Active Source> log 0x%01x addr 0x%04x\n", BootUpLog, addr);
  509. BootUpLog = 0;
  510. }
  511. }
  512. #ifdef CONFIG_DEBUG_DRV_CEC_WRITE_EN
  513. INT32 CEC_write(struct file *file, const INT8 __user * buf, size_t size, loff_t * ppos)
  514. {
  515. switch (buf[0])
  516. {
  517. case 'm':
  518. case 'M':
  519. msg_parser(buf + 1);
  520. TxFIFO_handler(pMsg);
  521. break;
  522. case 't':
  523. case 'T':
  524. msg_parser(buf + 1);
  525. memcpy(&pMsg->rxMsg[pMsg->Wp], &pMsg->txMsg, sizeof(FRAME_t));
  526. pMsg->txMsg.status = CEC_STATUS_TXEOMDONE;
  527. pMsg->txMsg.block_num = 0;
  528. pMsg->Wp = (pMsg->Wp + 1) % FRAMEMAX;
  529. if (pMsg->Wp == pMsg->Rp)
  530. {
  531. pMsg->bOverwrite = true;
  532. }
  533. pMsg->bMessageDone = true;
  534. CEC_parser();
  535. break;
  536. default:
  537. break;
  538. }
  539. return size;
  540. }
  541. #endif
  542. void DRV_CEC_Transmit_ARC(UINT8 ucEnable, UINT8 hw_port, INT8 sw_port)
  543. {
  544. sysset_cec_arc(ucEnable ? true : false);
  545. }
  546. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,8)
  547. long CEC_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  548. #else
  549. ssize_t CEC_ioctl(struct inode *inode, struct file *filp, UINT32 cmd, ULONG arg)
  550. #endif
  551. {
  552. BOOL bDebugLog = bCECDBG;
  553. UINT32 uiPhyAddr;
  554. UINT8 hw_port, ucEnable = 0;
  555. INT8 sw_port;
  556. switch (cmd)
  557. {
  558. case CEC_CECEnable:
  559. cecdbg("IOC CECEnable:%ld\n",arg);
  560. if (arg==0)
  561. {
  562. ucEnable = 0;
  563. cecdbg("Set ARC OFF\n");
  564. DRV_CEC_Transmit_ARC(ucEnable , hw_port, sw_port);
  565. }
  566. break;
  567. case CEC_REGISTER:
  568. cecdbg("IOC REGISTER:PID%d\n", cecd_pid);
  569. /* Patch: boot up by cec, resend active source to cecd */
  570. BootUpPatch();
  571. /* Report hpd status again when cecd is started. */
  572. hdmi_report_cur_hpd();
  573. /* Assign cecd pid for driver. Put this at the last one. */
  574. cecd_pid = arg;
  575. break;
  576. case CEC_DEBUGLOG:
  577. copy_to_user((void*)arg, (void*)&bDebugLog, sizeof(BOOL));
  578. cecdbg("IOC DEBUGLOG:%d\n", bCECDBG);
  579. break;
  580. case CEC_SENDMSG:
  581. cecdbg("IOC SENDMSG\n");
  582. TxFIFO_handler(pMsg);
  583. break;
  584. case CEC_DEBUG://For AP debug only.
  585. memcpy(&pMsg->rxMsg[pMsg->Wp], &pMsg->txMsg, sizeof(FRAME_t));
  586. pMsg->txMsg.status = CEC_STATUS_TXEOMDONE;
  587. pMsg->txMsg.block_num = 0;
  588. pMsg->Wp = (pMsg->Wp + 1) % FRAMEMAX;
  589. if (pMsg->Wp == pMsg->Rp)
  590. {
  591. pMsg->bOverwrite = true;
  592. }
  593. pMsg->bMessageDone = true;
  594. CEC_parser();
  595. break;
  596. case CEC_ReportARCInitiation:
  597. uiPhyAddr = arg;
  598. cecdbg("IOC ReportARCInitiationn:0x%x\n", uiPhyAddr);
  599. hw_port = (UINT8) hdmi_hw_port(((uiPhyAddr >> 12) & 0x0f) - 1);
  600. sw_port = hdmi_sw_port(((uiPhyAddr >> 12) & 0x0f) - 1); //switch port
  601. ucEnable = 1;
  602. DRV_CEC_Transmit_ARC(ucEnable, hw_port, sw_port);
  603. break;
  604. case CEC_ReportARCTermination:
  605. uiPhyAddr = arg;
  606. cecdbg("IOC ReportARCTermination:0x%x\n", uiPhyAddr);
  607. hw_port = (UINT8) hdmi_hw_port(((uiPhyAddr >> 12) & 0x0f) - 1);
  608. sw_port = hdmi_sw_port(((uiPhyAddr >> 12) & 0x0f) - 1); //switch port
  609. ucEnable = 0;
  610. DRV_CEC_Transmit_ARC(ucEnable, hw_port, sw_port);
  611. break;
  612. case CEC_ARC_PORT_HPD_TOGGLE:
  613. printk("IOC CEC_ARC_PORT_HPD_TOGGLE:%ld\n",arg);
  614. if (arg==1)
  615. {
  616. printk("CEC_ARC_PORT_HPD_TOGGLE\n");
  617. hdmi_apply_hpd((1 << geARCPort), DRV_HPD_LEVEL_LOW);
  618. HDMI_DelayMs(HDMI_HPD_L2H_DELAY);
  619. hdmi_apply_hpd((1 << geARCPort), DRV_HPD_LEVEL_HIGH);
  620. }
  621. break;
  622. }
  623. return 0;
  624. }
  625. INT32 CEC_mmap(struct file *filp, struct vm_area_struct *vma)
  626. {
  627. if (vma->vm_end - vma->vm_start > 4096)
  628. {
  629. return -ENOMEM;
  630. }
  631. if (remap_pfn_range(vma, vma->vm_start, vmalloc_to_pfn(pMsg), vma->vm_end - vma->vm_start, vma->vm_page_prot))
  632. {
  633. return -EAGAIN;
  634. }
  635. return 0;
  636. }
  637. irqreturn_t CEC_ISR(INT32 irq, void* dev_id)
  638. {
  639. //static DRV_5V_LEVEL_e ePortA_5V_Level = DRV_5V_LEVEL_LOW, ePortB_5V_Level = DRV_5V_LEVEL_LOW, ePortC_5V_Level = DRV_5V_LEVEL_LOW;
  640. //volatile CEC_REG0000_t *tCEC_INT = (CEC_REG0000_t *)0xbe1e0000;
  641. CEC_REG0000_t tCEC_INT;
  642. CEC_REG0000_t dCEC_INT_tmp;
  643. tCEC_INT.dCECReg0000_0003 = HDMI_RegisterRead(CEC_0000_DW_0000);
  644. dCEC_INT_tmp.dCECReg0000_0003 = tCEC_INT.dCECReg0000_0003 & 0xF00017FF; //mask interrupt bit
  645. if(geARCPort != HDMI_PORT_A)
  646. {
  647. if (tCEC_INT.ists_ddc5v_0_rise)
  648. {
  649. cecdbg("INT A 5V in\n");
  650. dCEC_INT_tmp.ists_ddc5v_0_rise = 1; //for clear
  651. //ePortA_5V_Level = DRV_5V_LEVEL_HIGH;
  652. if(((true != MHL_CABLE_IN) && (MHL_CABLE_A_STATUS == false)) || (true == MHL_CABLE_B_STATUS))
  653. {
  654. #ifdef HDMI_DDC5V_WORKAROUND
  655. debounce_notice(&PortA_5V_debounce, (void *)DRV_5V_LEVEL_HIGH, 0);
  656. #else
  657. debounce_notice(&Src_5V_debounce, NULL, 30);
  658. #endif
  659. }
  660. else
  661. {
  662. MHL_CABLE_A_STATUS = true;
  663. }
  664. }
  665. if (tCEC_INT.ists_ddc5v_0_fall)
  666. {
  667. cecdbg("INT A 5V out\n");
  668. dCEC_INT_tmp.ists_ddc5v_0_fall = 1; //for clear
  669. //ePortA_5V_Level = DRV_5V_LEVEL_LOW;
  670. if(true != MHL_CABLE_A_STATUS)
  671. {
  672. #ifdef HDMI_DDC5V_WORKAROUND
  673. debounce_notice(&PortA_5V_debounce, (void *)DRV_5V_LEVEL_LOW, 500);
  674. #else
  675. debounce_notice(&Src_5V_debounce, NULL, 30);
  676. #endif
  677. }
  678. else
  679. {
  680. MHL_CABLE_A_STATUS = false;
  681. }
  682. }
  683. }
  684. if(geARCPort != HDMI_PORT_B)
  685. {
  686. if (tCEC_INT.ists_ddc5v_1_rise)
  687. {
  688. cecdbg("INT B 5V in\n");
  689. dCEC_INT_tmp.ists_ddc5v_1_rise = 1; //for clear
  690. //ePortB_5V_Level = DRV_5V_LEVEL_HIGH;
  691. if(((true != MHL_CABLE_IN) && (MHL_CABLE_B_STATUS == false)) || (true == MHL_CABLE_A_STATUS))
  692. {
  693. #ifdef HDMI_DDC5V_WORKAROUND
  694. debounce_notice(&PortB_5V_debounce, (void *)DRV_5V_LEVEL_HIGH, 0);
  695. #else
  696. debounce_notice(&Src_5V_debounce, NULL, 30);
  697. #endif
  698. }
  699. else
  700. {
  701. MHL_CABLE_B_STATUS = true;
  702. }
  703. }
  704. if (tCEC_INT.ists_ddc5v_1_fall)
  705. {
  706. cecdbg("INT B 5V out\n");
  707. dCEC_INT_tmp.ists_ddc5v_1_fall = 1; //for clear
  708. //ePortB_5V_Level = DRV_5V_LEVEL_LOW;
  709. if(true != MHL_CABLE_B_STATUS)
  710. {
  711. #ifdef HDMI_DDC5V_WORKAROUND
  712. debounce_notice(&PortB_5V_debounce, (void *)DRV_5V_LEVEL_LOW, 500);
  713. #else
  714. debounce_notice(&Src_5V_debounce, NULL, 30);
  715. #endif
  716. }
  717. else
  718. {
  719. MHL_CABLE_B_STATUS = false;
  720. }
  721. }
  722. }
  723. if(geARCPort != HDMI_PORT_C)
  724. {
  725. if (tCEC_INT.R_INTR_Status_rx_ddc5v_2_rise)
  726. {
  727. cecdbg("INT C 5V in\n");
  728. dCEC_INT_tmp.R_INTR_Status_rx_ddc5v_2_rise = 1; //for clear
  729. //ePortC_5V_Level = DRV_5V_LEVEL_HIGH;
  730. #ifdef HDMI_DDC5V_WORKAROUND
  731. debounce_notice(&PortC_5V_debounce, (void *)DRV_5V_LEVEL_HIGH, 0);
  732. #else
  733. debounce_notice(&Src_5V_debounce, NULL, 30);
  734. #endif
  735. }
  736. if (tCEC_INT.R_INTR_Status_rx_ddc5v_2_fall)
  737. {
  738. cecdbg("INT C 5V out\n");
  739. dCEC_INT_tmp.R_INTR_Status_rx_ddc5v_2_fall = 1; //for clear
  740. //ePortC_5V_Level = DRV_5V_LEVEL_LOW;
  741. #ifdef HDMI_DDC5V_WORKAROUND
  742. debounce_notice(&PortC_5V_debounce, (void *)DRV_5V_LEVEL_LOW, 500);
  743. #else
  744. debounce_notice(&Src_5V_debounce, NULL, 30);
  745. #endif
  746. }
  747. }
  748. if (tCEC_INT.ists_tx_noarbit)
  749. {
  750. cecdbg("tx_noarbit\n");
  751. dCEC_INT_tmp.ists_tx_noarbit = 1; //for clear
  752. pMsg->txMsg.status = CEC_STATUS_TXNOARBIT;
  753. pMsg->txMsg.block_num = 0;
  754. }
  755. else if (tCEC_INT.ists_tx_noack)
  756. {
  757. cecdbg("x_noack\n");
  758. dCEC_INT_tmp.ists_tx_noack = 1; //for clear
  759. pMsg->txMsg.status = CEC_STATUS_TXNOACK;
  760. pMsg->txMsg.block_num = 0;
  761. }
  762. else if (tCEC_INT.ists_tx_eom_done)
  763. {
  764. pFRAME_t ptxMsg = &(pMsg->txMsg);
  765. cecdbg("tx_eom_done\n");
  766. dCEC_INT_tmp.ists_tx_eom_done = 1; //for clear
  767. ptxMsg->status = CEC_STATUS_TXEOMDONE;
  768. ptxMsg->block_num = 0;
  769. }
  770. else if (tCEC_INT.ists_rfifo_ready)
  771. {
  772. cecdbg("rfifo_ready\n");
  773. dCEC_INT_tmp.ists_rfifo_ready = 1; //for clear
  774. pMsg->rxFifo_cnt = HDMI_RegisterRead(CEC_R_rfifo_th) + 1;
  775. RxFIFO_handler(pMsg);
  776. }
  777. else if (tCEC_INT.ists_rx_pop_done)
  778. {
  779. cecdbg("rx_pop_done\n");
  780. dCEC_INT_tmp.ists_rx_pop_done = 1; //for clear
  781. RxFIFO_handler(pMsg);
  782. }
  783. else if (tCEC_INT.ists_rx_discon)
  784. {
  785. cecdbg("rx_discon\n");
  786. dCEC_INT_tmp.ists_rx_discon = 1; //for clear
  787. }
  788. else if (tCEC_INT.ists_rx_eom)
  789. {
  790. cecdbg("rx_eom\n");
  791. dCEC_INT_tmp.ists_rx_eom = 1; //for clear
  792. pMsg->rxFifo_cnt = HDMI_RegisterRead(CEC_R_rfifo_th);
  793. RxFIFO_handler(pMsg);
  794. }
  795. HDMI_RegisterWrite(CEC_0000_DW_0000, dCEC_INT_tmp.dCECReg0000_0003); //clear interrupt status
  796. return IRQ_HANDLED;
  797. }
  798. static void CheckArcGpio5V_change(void *dummy)
  799. {
  800. UINT32 Delay_ms;
  801. DRV_5V_LEVEL_e eGpio5VLevel = (GPIOTryRead(geGpio5V_Pin) == 1?DRV_5V_LEVEL_HIGH:DRV_5V_LEVEL_LOW);
  802. cecdbg("%s Gpio5VLevel=%d\n", __FUNCTION__, eGpio5VLevel);
  803. if(eGpio5VLevel == DRV_5V_LEVEL_HIGH)
  804. {
  805. EnableGPIOInterrupt(geGpio5V_Pin, 0x0); // 00 low_level trigger, 01 high_level trigger, 10 falling edge, 11 rising edge
  806. }
  807. else
  808. {
  809. EnableGPIOInterrupt(geGpio5V_Pin, 0x1); // 00 low_level trigger, 01 high_level trigger, 10 falling edge, 11 rising edge
  810. }
  811. if((eGpio5VLevel == DRV_5V_LEVEL_LOW) && (hdmi_flag_check(HAS_ACTIVE_DATA)))
  812. {
  813. Delay_ms = 2000;
  814. }
  815. else
  816. {
  817. Delay_ms = 0;
  818. }
  819. #ifdef HDMI_DDC5V_WORKAROUND
  820. if(geARCPort == HDMI_PORT_A)
  821. {
  822. debounce_notice(&PortA_5V_debounce, (void *)eGpio5VLevel, Delay_ms);
  823. }
  824. else if(geARCPort == HDMI_PORT_B)
  825. {
  826. debounce_notice(&PortB_5V_debounce, (void *)eGpio5VLevel, Delay_ms);
  827. }
  828. else if(geARCPort == HDMI_PORT_C)
  829. {
  830. debounce_notice(&PortC_5V_debounce, (void *)eGpio5VLevel, Delay_ms);
  831. }
  832. #else
  833. debounce_notice(&Src_5V_debounce, NULL, 0);
  834. #endif
  835. }
  836. void DRV_GPIO5V_ISR_Callback(void)
  837. {
  838. DisableGPIOInterrupt(geGpio5V_Pin); //disable interrupt when interrupt happend
  839. cecdbg("%s\n", __FUNCTION__);
  840. debounce_notice(&ArcGpio_5V_debounce, (void *)NULL, 250); //debounce GPIO 5V value for 250ms and enable interrupt
  841. }
  842. char check_mhl_det(void)
  843. {
  844. int i;
  845. for( i=0 ; i<5 ; i++ )
  846. {
  847. if(GPIOGetValueByPinFunc(GPIO_PIN_MHL_CD_SENSE_DETECT)==1)
  848. {
  849. cecdbg("in MHL mode ignore set hpd %d \n",i);
  850. return 1;
  851. }
  852. }
  853. return 0;
  854. }
  855. void DRV_Set_GPIO5V_ARCPort(GPIOPin_t eGpio5V_Pin, HDMI_PORT_T eARCPort)
  856. {
  857. UINT8 bIntrEn = 0;
  858. geGpio5V_Pin = eGpio5V_Pin;
  859. geARCPort = eARCPort;
  860. cecdbg("%s GPIO:%d ARCPort:%d\n", __FUNCTION__, geGpio5V_Pin, geARCPort);
  861. //setup DDC 5V interrupt
  862. bIntrEn = (geARCPort == HDMI_PORT_A)?0:
  863. (hdmi_get_channel_at_hw_port(HDMI_PORT_A) == HDMI_SRC_NULL)?0:1;
  864. HDMI_RegisterWrite(CEC_ien_ddc5v_0_rise, bIntrEn);
  865. HDMI_RegisterWrite(CEC_ien_ddc5v_0_fall, bIntrEn);
  866. sysset_DDC_PortA_Det5V_En(bIntrEn);
  867. bIntrEn = (geARCPort == HDMI_PORT_B)?0:
  868. (hdmi_get_channel_at_hw_port(HDMI_PORT_B) == HDMI_SRC_NULL)?0:1;
  869. HDMI_RegisterWrite(CEC_ien_ddc5v_1_rise, bIntrEn);
  870. HDMI_RegisterWrite(CEC_ien_ddc5v_1_fall, bIntrEn);
  871. sysset_DDC_PortB_Det5V_En(bIntrEn);
  872. bIntrEn = (geARCPort == HDMI_PORT_C)?0:
  873. (hdmi_get_channel_at_hw_port(HDMI_PORT_C) == HDMI_SRC_NULL)?0:1;
  874. HDMI_RegisterWrite(CEC_R_INTR_en_rx_ddc5v_2_rise, bIntrEn);
  875. HDMI_RegisterWrite(CEC_R_INTR_en_rx_ddc5v_2_fall, bIntrEn);
  876. sysset_DDC_PortC_Det5V_En(bIntrEn);
  877. if(geGpio5V_Pin != GPIO_NOT_USE && geARCPort != HDMI_PORT_NULL)
  878. {
  879. RegGPIOCallBackFun(geGpio5V_Pin, DRV_GPIO5V_ISR_Callback);
  880. //dabounce GPIO 5V value for 250ms and enable interrupt
  881. debounce_notice(&ArcGpio_5V_debounce, (void *)NULL, 250);
  882. }
  883. #ifdef CONFIG_HDMI_SUPPORT_MHL
  884. #if CONFIG_HDMI_MHL_PORT == 0
  885. if(check_mhl_det()== 0)
  886. #endif
  887. #endif
  888. {
  889. #ifdef CONFIG_HDMI_GPIO_DETECT_PORT_A
  890. #else
  891. sysset_HDMI_SW5V(HDMI_PORT_A,false);
  892. #endif
  893. }
  894. #ifdef CONFIG_HDMI_SUPPORT_MHL
  895. #if CONFIG_HDMI_MHL_PORT == 1
  896. if(check_mhl_det()== 0)
  897. #endif
  898. #endif
  899. {
  900. #ifdef CONFIG_HDMI_GPIO_DETECT_PORT_B
  901. #else
  902. sysset_HDMI_SW5V(HDMI_PORT_B,false);
  903. #endif
  904. }
  905. {
  906. #ifdef CONFIG_HDMI_GPIO_DETECT_PORT_C
  907. #else
  908. sysset_HDMI_SW5V(HDMI_PORT_C,false);
  909. #endif
  910. }
  911. }
  912. HDMI_PORT_T DRV_Get_GPIO5V_ARCPort(void)
  913. {
  914. return geARCPort;
  915. }
  916. #define IRQ_CEC 34
  917. static void CEC_dispatch(struct pt_regs *regs)
  918. {
  919. do_IRQ(IRQ_CEC);
  920. }
  921. static struct file_operations CEC_fops =
  922. {
  923. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,8))
  924. .unlocked_ioctl = CEC_ioctl,
  925. #else
  926. .ioctl = CEC_ioctl,
  927. #endif
  928. #ifdef CONFIG_DEBUG_DRV_CEC_WRITE_EN
  929. .write = CEC_write,
  930. #endif
  931. .mmap = CEC_mmap,
  932. .owner = THIS_MODULE,
  933. };
  934. #define RXFIFO_TH 2
  935. #define CECDRV_DEVNAME "/dev/cec" /* Driver Device Name */
  936. static INT32 cec_devno;
  937. static struct cdev cec_cdev;
  938. INT32 DRV_CEC_Init(void)
  939. {
  940. INT32 status;
  941. UINT8 *pCECstate = (UINT8*)CECSTATE_ADDR;
  942. cecdbg("%s\n", __FUNCTION__);
  943. pMsg = (pCEC_MSG_t)drv_vmalloc(sizeof(CEC_MSG_t), MODULEID_CEC);
  944. memset(pMsg, 0x0, sizeof(CEC_MSG_t));
  945. sysset_hdmi_hpd_detection();
  946. HDMI_RegisterWrite(CEC_ien_ddc5v_0_rise, 0);
  947. HDMI_RegisterWrite(CEC_ien_ddc5v_0_fall, 0);
  948. HDMI_RegisterWrite(CEC_ien_ddc5v_1_rise, 0);
  949. HDMI_RegisterWrite(CEC_ien_ddc5v_1_fall, 0);
  950. HDMI_RegisterWrite(CEC_R_INTR_en_rx_ddc5v_2_rise, 0);
  951. HDMI_RegisterWrite(CEC_R_INTR_en_rx_ddc5v_2_fall, 0);
  952. if(HDMI_RegisterRead(CEC_ists_ddc5v_0_rise) == 1){cecdbg("CEC_ists_ddc5v_0_rise clr");HDMI_RegisterWrite(CEC_ists_ddc5v_0_rise,0);}
  953. if(HDMI_RegisterRead(CEC_ists_ddc5v_0_fall) == 1){cecdbg("CEC_ists_ddc5v_0_fall clr");HDMI_RegisterWrite(CEC_ists_ddc5v_0_fall,0);}
  954. if(HDMI_RegisterRead(CEC_ists_ddc5v_1_rise) == 1){cecdbg("CEC_ists_ddc5v_1_rise clr");HDMI_RegisterWrite(CEC_ists_ddc5v_1_rise,0);}
  955. if(HDMI_RegisterRead(CEC_ists_ddc5v_1_fall) == 1){cecdbg("CEC_ists_ddc5v_1_fall clr");HDMI_RegisterWrite(CEC_ists_ddc5v_1_fall,0);}
  956. if(HDMI_RegisterRead(CEC_R_INTR_Status_rx_ddc5v_2_rise) == 1){cecdbg("CEC_R_INTR_Status_rx_ddc5v_2_rise clr");HDMI_RegisterWrite(CEC_R_INTR_Status_rx_ddc5v_2_rise,0);}
  957. if(HDMI_RegisterRead(CEC_R_INTR_Status_rx_ddc5v_2_fall) == 1){cecdbg("CEC_R_INTR_Status_rx_ddc5v_2_fall clr");HDMI_RegisterWrite(CEC_R_INTR_Status_rx_ddc5v_2_fall,0);}
  958. if (!pMsg)
  959. {
  960. cecdbg("%s: Can not allocate memory\n", __FUNCTION__);
  961. return -ENOMEM;
  962. }
  963. if (*pCECstate)
  964. {
  965. cecdbg("onetouch play");
  966. hdmi_apply_hpd(DRV_HDMI_PORT_ALL , DRV_HPD_LEVEL_LOW);
  967. HDMI_DelayMs(HDMI_HPD_L2H_DELAY);
  968. hdmi_apply_hpd_by5V(DRV_HDMI_PORT_ALL);
  969. }
  970. INIT_WORK(&wq_cec_signal, (work_func_t) CEC_parser_wq);
  971. #ifdef HDMI_DDC5V_WORKAROUND
  972. debounce_init(&PortA_5V_debounce, Check_PortA_5V_change);
  973. debounce_init(&PortB_5V_debounce, Check_PortB_5V_change);
  974. debounce_init(&PortC_5V_debounce, Check_PortC_5V_change);
  975. #else
  976. debounce_init(&Src_5V_debounce, CheckSrc5V_change);
  977. #endif
  978. debounce_init(&ArcGpio_5V_debounce, CheckArcGpio5V_change);
  979. INIT_WORK(&wq_SetHPD_A_TOGGLE, (work_func_t) SetHPD_A_TOGGLE);
  980. INIT_WORK(&wq_SetHPD_B_TOGGLE, (work_func_t) SetHPD_B_TOGGLE);
  981. INIT_WORK(&wq_SetHPD_C_TOGGLE, (work_func_t) SetHPD_C_TOGGLE);
  982. set_vi_handler(IRQ_CEC, (vi_handler_t) CEC_dispatch);
  983. status = request_irq(IRQ_CEC, &CEC_ISR, IRQF_DISABLED, "cec", NULL);
  984. if (status)
  985. {
  986. return -EIO;
  987. }
  988. cec_devno = MKDEV(CDEV_CEC_MAJOR, 0);
  989. status = register_chrdev_region(cec_devno, 0, CECDRV_DEVNAME);
  990. if (status)
  991. {
  992. return -EIO;
  993. }
  994. cdev_init(&cec_cdev, &CEC_fops);
  995. cec_cdev.owner = THIS_MODULE;
  996. cec_cdev.ops = &CEC_fops;
  997. if (cdev_add(&cec_cdev, cec_devno, 1))
  998. {
  999. return -EIO;
  1000. }
  1001. sysset_hdmi_hpd_detection();
  1002. HDMI_RegisterWrite(CEC_R_cec_en, 0); //Disable CEC
  1003. HDMI_RegisterWrite(CEC_R_cec_en, 1); //Enable CEC
  1004. HDMI_RegisterWrite(CEC_R_rfifo_th, RXFIFO_TH);
  1005. HDMI_RegisterWrite(CEC_ien_tx_noarbit, 1);
  1006. HDMI_RegisterWrite(CEC_ien_tx_noack, 1);
  1007. HDMI_RegisterWrite(CEC_ien_tx_eom_done, 1);
  1008. HDMI_RegisterWrite(CEC_ien_rfifo_ready, 1);
  1009. HDMI_RegisterWrite(CEC_ien_rx_pop_done, 1);
  1010. HDMI_RegisterWrite(CEC_ien_rx_discon, 1);
  1011. HDMI_RegisterWrite(CEC_ien_rx_eom, 1);
  1012. //HDMI_RegisterWrite(CEC_timer_retryframe_period, 0xca);
  1013. //HDMI_RegisterWrite(CEC_timer_newframe_preiod, 0x12);
  1014. //HDMI_RegisterWrite(CEC_timer_conframe_period, 0x1d);
  1015. HDMI_RegisterWrite(CEC_timer_bit_tran_period, 0x37);
  1016. HDMI_RegisterWrite(CEC_timer_conframe_period, 0x1E);
  1017. HDMI_RegisterWrite(CEC_timer_dbit_end_max_period, 0x55);
  1018. HDMI_RegisterWrite(CEC_timer_dbit_end_min_peiord, 0x12);
  1019. HDMI_RegisterWrite(CEC_timer_dbit_high_min_period, 0x1F);
  1020. HDMI_RegisterWrite(CEC_timer_dbit_low_min_period, 0x21);
  1021. HDMI_RegisterWrite(CEC_timer_newframe_preiod, 0x12);
  1022. HDMI_RegisterWrite(CEC_timer_retryframe_period, 0xCF);
  1023. HDMI_RegisterWrite(CEC_timer_rx_dbit_end_max_period, 0x5A);
  1024. HDMI_RegisterWrite(CEC_timer_rx_dbit_end_min_period, 0x5A);
  1025. HDMI_RegisterWrite(CEC_timer_rx_dbit_latch_period, 0x6B);
  1026. HDMI_RegisterWrite(CEC_timer_sbit_end_min_period, 0x16);
  1027. HDMI_RegisterWrite(CEC_timer_sbit_tran_min_period, 0x3A);
  1028. HDMI_RegisterWrite(CEC_timer_tx_dbit_end_period, 0x2C);
  1029. HDMI_RegisterWrite(CEC_timer_tx_dbit_high_period, 0x1D);
  1030. HDMI_RegisterWrite(CEC_timer_tx_dbit_low_period, 0x2C);
  1031. HDMI_RegisterWrite(CEC_timer_tx_sbit_end_period, 0x2B);
  1032. HDMI_RegisterWrite(CEC_timer_tx_sbit_tran_period, 0x3D);
  1033. //enable 5V interrupt move to DRV_Set_GPIO5V_ARCPort
  1034. //HDMI_RegisterWrite(CEC_ien_ddc5v_0_rise, 1);
  1035. //HDMI_RegisterWrite(CEC_ien_ddc5v_0_fall, 1);
  1036. //HDMI_RegisterWrite(CEC_ien_ddc5v_1_rise, 1);
  1037. //HDMI_RegisterWrite(CEC_ien_ddc5v_1_fall, 1);
  1038. //HDMI_RegisterWrite(CEC_R_INTR_en_rx_ddc5v_2_rise, 1);
  1039. //HDMI_RegisterWrite(CEC_R_INTR_en_rx_ddc5v_2_fall, 1);
  1040. HDMI_RegisterWrite(CEC_R_hpd_man, 1); /* enable */
  1041. pMsg->txMsg.status = CEC_STATUS_TXEOMDONE;
  1042. pMsg->txMsg.block_num = 0;
  1043. pMsg->Wp = 0;
  1044. pMsg->Rp = 0;
  1045. pMsg->bMessageDone = false;
  1046. return 0;
  1047. }
  1048. void DRV_CEC_Exit(void)
  1049. {
  1050. //Disable all interrupts.
  1051. HDMI_RegisterWrite(CEC_0008_DW_0008, HDMI_RegisterRead(CEC_0008_DW_0008) & 0xfffff000);
  1052. HDMI_RegisterWrite(CEC_0020_DW_0020, HDMI_RegisterRead(CEC_0020_DW_0020) & 0xf0ffffff);
  1053. HDMI_RegisterWrite(CEC_R_cec_en, 0);//Disable CEC
  1054. free_irq(IRQ_CEC, NULL);
  1055. cdev_del(&cec_cdev);
  1056. unregister_chrdev_region(cec_devno, 0);
  1057. #ifdef HDMI_DDC5V_WORKAROUND
  1058. debounce_exit(&PortA_5V_debounce);
  1059. debounce_exit(&PortB_5V_debounce);
  1060. debounce_exit(&PortC_5V_debounce);
  1061. #else
  1062. debounce_exit(&Src_5V_debounce);
  1063. #endif
  1064. if (pMsg)
  1065. {
  1066. vfree(pMsg);
  1067. }
  1068. }