cec.c 37 KB

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