hdmirx_cec.c 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410
  1. #include <linux/version.h>
  2. #include <linux/module.h>
  3. #include <linux/types.h>
  4. #include <linux/kernel.h>
  5. #include <linux/kthread.h>
  6. #include <linux/delay.h>
  7. #include <linux/interrupt.h>
  8. #include <linux/fs.h>
  9. #include <linux/init.h>
  10. #include <linux/device.h>
  11. #include <linux/mm.h>
  12. #include <linux/major.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/mutex.h>
  15. #include <linux/cdev.h>
  16. #include <linux/module.h>
  17. #include <linux/kernel.h>
  18. #include <linux/slab.h>
  19. #include <linux/list.h>
  20. #include <linux/spinlock.h>
  21. #include <asm/uaccess.h>
  22. #include <asm/delay.h>
  23. #include <mach/am_regs.h>
  24. #include <mach/power_gate.h>
  25. #include <linux/tvin/tvin.h>
  26. #include <mach/gpio.h>
  27. #include "hdmirx.h"
  28. #include "hdmi_regs.h"
  29. #include "hdmirx_cec.h"
  30. #define _RX_CEC_DBG_ON_
  31. #ifdef _RX_CEC_DBG_ON_
  32. #define hdmirx_cec_dbg_print hdmirx_print
  33. #else
  34. #define hdmirx_cec_dbg_print
  35. #endif
  36. #define _RX_DATA_BUF_SIZE_ 6
  37. /* global variables */
  38. static unsigned char gbl_msg[MAX_MSG];
  39. static cec_global_info_t cec_global_info;
  40. static struct semaphore tv_cec_sema;
  41. static DEFINE_SPINLOCK(p_tx_list_lock);
  42. static DEFINE_SPINLOCK(cec_tx_lock);
  43. static unsigned long cec_tx_list_flags;
  44. static unsigned long cec_tx_flags;
  45. static unsigned int tx_msg_cnt = 0;
  46. static struct list_head cec_tx_msg_phead = LIST_HEAD_INIT(cec_tx_msg_phead);
  47. static tv_cec_pending_e cec_pending_flag = TV_CEC_PENDING_OFF;
  48. static tv_cec_polling_state_e cec_polling_state = TV_CEC_POLLING_OFF;
  49. unsigned int menu_lang_array[] = {(((unsigned int)'c')<<16)|(((unsigned int)'h')<<8)|((unsigned int)'i'),
  50. (((unsigned int)'e')<<16)|(((unsigned int)'n')<<8)|((unsigned int)'g'),
  51. (((unsigned int)'j')<<16)|(((unsigned int)'p')<<8)|((unsigned int)'n'),
  52. (((unsigned int)'k')<<16)|(((unsigned int)'o')<<8)|((unsigned int)'r'),
  53. (((unsigned int)'f')<<16)|(((unsigned int)'r')<<8)|((unsigned int)'a'),
  54. (((unsigned int)'g')<<16)|(((unsigned int)'e')<<8)|((unsigned int)'r')
  55. };
  56. static unsigned char * default_osd_name[16] = {
  57. "tv",
  58. "recording 1",
  59. "recording 2",
  60. "tuner 1",
  61. "playback 1",
  62. "audio system",
  63. "tuner 2",
  64. "tuner 3",
  65. "playback 2",
  66. "recording 3",
  67. "tunre 4",
  68. "playback 3",
  69. "reserved 1",
  70. "reserved 2",
  71. "free use",
  72. "unregistered"
  73. };
  74. static struct {
  75. cec_rx_message_t cec_rx_message[_RX_DATA_BUF_SIZE_];
  76. unsigned char rx_write_pos;
  77. unsigned char rx_read_pos;
  78. unsigned char rx_buf_size;
  79. } cec_rx_msg_buf;
  80. static unsigned char * osd_name_uninit = "\0\0\0\0\0\0\0\0";
  81. static irqreturn_t cec_handler(int irq, void *dev_instance);
  82. static unsigned int hdmi_rd_reg(unsigned long addr);
  83. static void hdmi_wr_reg(unsigned long addr, unsigned long data);
  84. void cec_test_function(unsigned char* arg, unsigned char arg_cnt)
  85. {
  86. int i;
  87. char buf[1024];
  88. printk("arg_cnt = %d\n", arg_cnt);
  89. for (i=0; i<arg_cnt; i++)
  90. printk("arg[%x]:%d, ", i, arg[i]);
  91. printk("\n");
  92. switch (arg[0]) {
  93. case 0:
  94. cec_usrcmd_parse_all_dev_online();
  95. break;
  96. case 1:
  97. cec_usrcmd_get_cec_version(arg[1]);
  98. break;
  99. case 2:
  100. cec_usrcmd_get_audio_status(arg[1]);
  101. break;
  102. case 3:
  103. cec_usrcmd_get_deck_status(arg[1]);
  104. break;
  105. case 4:
  106. cec_usrcmd_get_device_power_status(arg[1]);
  107. break;
  108. case 5:
  109. cec_usrcmd_get_device_vendor_id(arg[1]);
  110. break;
  111. case 6:
  112. cec_usrcmd_get_osd_name(arg[1]);
  113. break;
  114. case 7:
  115. cec_usrcmd_get_physical_address(arg[1]);
  116. break;
  117. case 8:
  118. cec_usrcmd_get_system_audio_mode_status(arg[1]);
  119. break;
  120. case 9:
  121. cec_usrcmd_get_tuner_device_status(arg[1]);
  122. break;
  123. case 10:
  124. cec_usrcmd_set_deck_cnt_mode(arg[1], arg[2]);
  125. break;
  126. case 11:
  127. cec_usrcmd_set_standby(arg[1]);
  128. break;
  129. case 12:
  130. cec_usrcmd_set_imageview_on(arg[1]);
  131. break;
  132. case 13:
  133. cec_usrcmd_set_play_mode(arg[1], arg[2]);
  134. break;
  135. case 14:
  136. cec_usrcmd_get_menu_state(arg[1]);
  137. break;
  138. case 15:
  139. cec_usrcmd_set_menu_state(arg[1], arg[2]);
  140. break;
  141. case 16:
  142. cec_usrcmd_get_global_info(buf);
  143. break;
  144. case 17:
  145. cec_usrcmd_get_menu_language(arg[1]);
  146. break;
  147. case 18:
  148. cec_usrcmd_set_menu_language(arg[1], arg[2]);
  149. break;
  150. case 19:
  151. cec_usrcmd_get_active_source();
  152. break;
  153. case 20:
  154. cec_usrcmd_set_active_source(arg[1]);
  155. break;
  156. case 21:
  157. cec_usrcmd_set_deactive_source(arg[1]);
  158. break;
  159. case 22:
  160. cec_usrcmd_set_stream_path(arg[1]);
  161. break;
  162. default:
  163. break;
  164. }
  165. }
  166. /* cec low level code */
  167. static unsigned int hdmi_rd_reg(unsigned long addr)
  168. {
  169. unsigned long data;
  170. WRITE_APB_REG(HDMI_ADDR_PORT, addr);
  171. WRITE_APB_REG(HDMI_ADDR_PORT, addr);
  172. data = READ_APB_REG(HDMI_DATA_PORT);
  173. return (data);
  174. }
  175. static void hdmi_wr_reg(unsigned long addr, unsigned long data)
  176. {
  177. unsigned long rd_data;
  178. WRITE_APB_REG(HDMI_ADDR_PORT, addr);
  179. WRITE_APB_REG(HDMI_ADDR_PORT, addr);
  180. WRITE_APB_REG(HDMI_DATA_PORT, data);
  181. rd_data = hdmi_rd_reg (addr);
  182. if (rd_data != data) {
  183. //while(1){};
  184. }
  185. }
  186. static unsigned int cec_get_ms_tick(void)
  187. {
  188. unsigned int ret = 0;
  189. struct timeval cec_tick;
  190. do_gettimeofday(&cec_tick);
  191. ret = cec_tick.tv_sec * 1000 + cec_tick.tv_usec / 1000;
  192. return ret;
  193. }
  194. static unsigned int cec_get_ms_tick_interval(unsigned int last_tick)
  195. {
  196. unsigned int ret = 0;
  197. unsigned int tick = 0;
  198. struct timeval cec_tick;
  199. do_gettimeofday(&cec_tick);
  200. tick = cec_tick.tv_sec * 1000 + cec_tick.tv_usec / 1000;
  201. if (last_tick < tick) ret = tick - last_tick;
  202. else ret = ((unsigned int)(-1) - last_tick) + tick;
  203. return ret;
  204. }
  205. #define TX_TIME_OUT_CNT 300
  206. int cec_ll_tx(unsigned char *msg, unsigned char len, unsigned char *stat_header)
  207. {
  208. int i;
  209. int ret;
  210. int tick = 0;
  211. int cnt = 0;
  212. spin_lock_irqsave(&cec_tx_lock, cec_tx_flags);
  213. for (i = 0; i < len; i++) {
  214. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_MSG_0_HEADER + i, msg[i]);
  215. }
  216. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_MSG_LENGTH, len-1);
  217. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_MSG_CMD, TX_REQ_CURRENT);
  218. if (stat_header == NULL) {
  219. tick = cec_get_ms_tick();
  220. while (hdmi_rd_reg(CEC0_BASE_ADDR+CEC_TX_MSG_STATUS) == TX_BUSY) {
  221. msleep(50);
  222. cnt = cec_get_ms_tick_interval(tick);
  223. if (cnt >= TX_TIME_OUT_CNT)
  224. break;
  225. }
  226. } else if (*stat_header == 1) { // ping
  227. tick = cec_get_ms_tick();
  228. while (hdmi_rd_reg(CEC0_BASE_ADDR+CEC_TX_MSG_STATUS) == TX_BUSY) {
  229. msleep(50);
  230. cnt = cec_get_ms_tick_interval(tick);
  231. if (cnt >= (TX_TIME_OUT_CNT / 2))
  232. break;
  233. }
  234. }
  235. ret = hdmi_rd_reg(CEC0_BASE_ADDR+CEC_TX_MSG_STATUS);
  236. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_MSG_CMD, TX_NO_OP);
  237. //if (cnt >= TX_TIME_OUT_CNT)
  238. // hdmirx_cec_dbg_print("tx time out: cnt = %x\n", cnt);
  239. spin_unlock_irqrestore(&cec_tx_lock, cec_tx_flags);
  240. return ret;
  241. }
  242. #define RX_TIME_OUT_CNT 0x10
  243. int cec_ll_rx( unsigned char *msg, unsigned char *len)
  244. {
  245. unsigned char rx_status = hdmi_rd_reg(CEC0_BASE_ADDR+CEC_RX_MSG_STATUS);
  246. int i;
  247. int tick = 0;
  248. int cnt = 0;
  249. unsigned char data;
  250. int rx_msg_length = hdmi_rd_reg(CEC0_BASE_ADDR + CEC_RX_MSG_LENGTH) + 1;
  251. for (i = 0; i < rx_msg_length; i++) {
  252. data = hdmi_rd_reg(CEC0_BASE_ADDR + CEC_RX_MSG_0_HEADER +i);
  253. *msg = data;
  254. msg++;
  255. //hdmirx_cec_dbg_print("cec rx message %x = %x\n", i, data);
  256. }
  257. *len = rx_msg_length;
  258. hdmi_wr_reg(CEC0_BASE_ADDR + CEC_RX_MSG_CMD, RX_ACK_CURRENT);
  259. tick = cec_get_ms_tick();
  260. while (hdmi_rd_reg(CEC0_BASE_ADDR+CEC_RX_MSG_STATUS) == RX_BUSY) {
  261. cnt = cec_get_ms_tick_interval(tick);
  262. if (cnt++ >= RX_TIME_OUT_CNT)
  263. break;
  264. }
  265. hdmi_wr_reg(CEC0_BASE_ADDR + CEC_RX_MSG_CMD, RX_NO_OP);
  266. //if (cnt >= RX_TIME_OUT_CNT)
  267. // hdmirx_cec_dbg_print("rx time out cnt = %x\n", cnt);
  268. return rx_status;
  269. }
  270. void cec_isr_post_process(void)
  271. {
  272. /* isr post process */
  273. while(cec_rx_msg_buf.rx_read_pos != cec_rx_msg_buf.rx_write_pos) {
  274. cec_handle_message(&(cec_rx_msg_buf.cec_rx_message[cec_rx_msg_buf.rx_read_pos]));
  275. if (cec_rx_msg_buf.rx_read_pos == cec_rx_msg_buf.rx_buf_size - 1) {
  276. cec_rx_msg_buf.rx_read_pos = 0;
  277. } else {
  278. cec_rx_msg_buf.rx_read_pos++;
  279. }
  280. }
  281. //printk("[TV CEC RX]: rx_read_pos %x, rx_write_pos %x\n", cec_rx_msg_buf.rx_read_pos, cec_rx_msg_buf.rx_write_pos);
  282. }
  283. void cec_usr_cmd_post_process(void)
  284. {
  285. cec_tx_message_list_t *p, *ptmp;
  286. /* usr command post process */
  287. spin_lock_irqsave(&p_tx_list_lock, cec_tx_list_flags);
  288. list_for_each_entry_safe(p, ptmp, &cec_tx_msg_phead, list) {
  289. cec_ll_tx(p->msg, p->length, NULL);
  290. unregister_cec_tx_msg(p);
  291. }
  292. spin_unlock_irqrestore(&p_tx_list_lock, cec_tx_list_flags);
  293. //printk("[TV CEC TX]: tx_msg_cnt = %x\n", tx_msg_cnt);
  294. }
  295. void cec_timer_post_process(void)
  296. {
  297. /* timer post process*/
  298. if (cec_polling_state == TV_CEC_POLLING_ON) {
  299. cec_tv_polling_online_dev();
  300. cec_polling_state = TV_CEC_POLLING_OFF;
  301. }
  302. }
  303. static int tv_cec_task_handle(void *data)
  304. {
  305. while (1) {
  306. down_interruptible(&tv_cec_sema);
  307. cec_isr_post_process();
  308. cec_usr_cmd_post_process();
  309. cec_timer_post_process();
  310. }
  311. return 0;
  312. }
  313. /* cec low level code end */
  314. /* cec middle level code */
  315. void tv_cec_timer_func(unsigned long arg)
  316. {
  317. struct timer_list *timer = (struct timer_list *)arg;
  318. timer->expires = jiffies + TV_CEC_INTERVAL;
  319. if (cec_pending_flag == TV_CEC_PENDING_OFF) {
  320. cec_polling_state = TV_CEC_POLLING_ON;
  321. }
  322. add_timer(timer);
  323. up(&tv_cec_sema);
  324. }
  325. void register_cec_rx_msg(unsigned char *msg, unsigned char len )
  326. {
  327. memset((void*)(&(cec_rx_msg_buf.cec_rx_message[cec_rx_msg_buf.rx_write_pos])), 0, sizeof(cec_rx_message_t));
  328. memcpy(cec_rx_msg_buf.cec_rx_message[cec_rx_msg_buf.rx_write_pos].content.buffer, msg, len);
  329. cec_rx_msg_buf.cec_rx_message[cec_rx_msg_buf.rx_write_pos].operand_num = len >= 2 ? len - 2 : 0;
  330. cec_rx_msg_buf.cec_rx_message[cec_rx_msg_buf.rx_write_pos].msg_length = len;
  331. if (cec_rx_msg_buf.rx_write_pos == cec_rx_msg_buf.rx_buf_size - 1) {
  332. cec_rx_msg_buf.rx_write_pos = 0;
  333. } else {
  334. cec_rx_msg_buf.rx_write_pos++;
  335. }
  336. up(&tv_cec_sema);
  337. }
  338. void register_cec_tx_msg(unsigned char *msg, unsigned char len )
  339. {
  340. cec_tx_message_list_t* cec_usr_message_list = kmalloc(sizeof(cec_tx_message_list_t), GFP_ATOMIC);
  341. if (cec_usr_message_list != NULL) {
  342. memset(cec_usr_message_list, 0, sizeof(cec_tx_message_list_t));
  343. memcpy(cec_usr_message_list->msg, msg, len);
  344. cec_usr_message_list->length = len;
  345. spin_lock_irqsave(&p_tx_list_lock, cec_tx_list_flags);
  346. list_add_tail(&cec_usr_message_list->list, &cec_tx_msg_phead);
  347. spin_unlock_irqrestore(&p_tx_list_lock, cec_tx_list_flags);
  348. tx_msg_cnt++;
  349. up(&tv_cec_sema);
  350. }
  351. }
  352. void unregister_cec_tx_msg(cec_tx_message_list_t* cec_tx_message_list)
  353. {
  354. if (cec_tx_message_list != NULL) {
  355. list_del(&cec_tx_message_list->list);
  356. kfree(cec_tx_message_list);
  357. cec_tx_message_list = NULL;
  358. if (tx_msg_cnt > 0) tx_msg_cnt--;
  359. }
  360. }
  361. static void cec_recover_reset(void)
  362. {
  363. WRITE_APB_REG(HDMI_CTRL_PORT, READ_APB_REG(HDMI_CTRL_PORT)|(1<<16));
  364. hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_CTRL0, 0xC);
  365. mdelay(10);
  366. hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_CTRL0, 0x0);
  367. WRITE_APB_REG(HDMI_CTRL_PORT, READ_APB_REG(HDMI_CTRL_PORT)&(~(1<<16)));
  368. #ifdef _SUPPORT_CEC_TV_MASTER_
  369. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x00 );
  370. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0xF9 );
  371. #else
  372. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x07 );
  373. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0x52 );
  374. #endif
  375. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_LOGICAL_ADDR0, (0x1 << 4) | CEC0_LOG_ADDR);
  376. }
  377. static unsigned char check_cec_msg_valid(cec_rx_message_t* pcec_message)
  378. {
  379. unsigned char rt = 0;
  380. unsigned char opcode;
  381. unsigned char opernum;
  382. if (!pcec_message)
  383. return rt;
  384. opcode = pcec_message->content.msg.opcode;
  385. opernum = pcec_message->operand_num;
  386. switch (opcode) {
  387. case CEC_OC_VENDOR_REMOTE_BUTTON_UP:
  388. case CEC_OC_STANDBY:
  389. if ( opernum == 0) rt = 1;
  390. break;
  391. case CEC_OC_SET_SYSTEM_AUDIO_MODE:
  392. if ( opernum == 1) rt = 1;
  393. break;
  394. case CEC_OC_VENDOR_COMMAND_WITH_ID:
  395. if ((opernum > 3)&&(opernum < 15)) rt = 1;
  396. break;
  397. case CEC_OC_VENDOR_REMOTE_BUTTON_DOWN:
  398. if (opernum < 15) rt = 1;
  399. break;
  400. case CEC_OC_RECORD_OFF:
  401. case CEC_OC_RECORD_TV_SCREEN:
  402. case CEC_OC_TUNER_STEP_DECREMENT:
  403. case CEC_OC_TUNER_STEP_INCREMENT:
  404. case CEC_OC_GIVE_AUDIO_STATUS:
  405. case CEC_OC_GIVE_SYSTEM_AUDIO_MODE_STATUS:
  406. case CEC_OC_USER_CONTROL_RELEASED:
  407. case CEC_OC_GIVE_OSD_NAME:
  408. case CEC_OC_GIVE_PHYSICAL_ADDRESS:
  409. case CEC_OC_GET_CEC_VERSION:
  410. case CEC_OC_GET_MENU_LANGUAGE:
  411. case CEC_OC_GIVE_DEVICE_VENDOR_ID:
  412. case CEC_OC_GIVE_DEVICE_POWER_STATUS:
  413. case CEC_OC_TEXT_VIEW_ON:
  414. case CEC_OC_IMAGE_VIEW_ON:
  415. case CEC_OC_ABORT_MESSAGE:
  416. if (opernum == 0) rt = 1;
  417. break;
  418. case CEC_OC_RECORD_STATUS:
  419. case CEC_OC_DECK_CONTROL:
  420. case CEC_OC_DECK_STATUS:
  421. case CEC_OC_GIVE_DECK_STATUS:
  422. case CEC_OC_GIVE_TUNER_DEVICE_STATUS:
  423. case CEC_OC_PLAY:
  424. case CEC_OC_MENU_REQUEST:
  425. case CEC_OC_MENU_STATUS:
  426. case CEC_OC_REPORT_AUDIO_STATUS:
  427. case CEC_OC_TIMER_CLEARED_STATUS:
  428. case CEC_OC_SYSTEM_AUDIO_MODE_STATUS:
  429. case CEC_OC_USER_CONTROL_PRESSED:
  430. case CEC_OC_CEC_VERSION:
  431. case CEC_OC_REPORT_POWER_STATUS:
  432. case CEC_OC_SET_AUDIO_RATE:
  433. if (opernum == 1) rt = 1;
  434. break;
  435. case CEC_OC_INACTIVE_SOURCE:
  436. case CEC_OC_SYSTEM_AUDIO_MODE_REQUEST:
  437. case CEC_OC_FEATURE_ABORT:
  438. if (opernum == 2) rt = 1;
  439. break;
  440. case CEC_OC_SELECT_ANALOGUE_SERVICE:
  441. if (opernum == 4) rt = 1;
  442. break;
  443. case CEC_OC_SELECT_DIGITAL_SERVICE:
  444. if (opernum == 7) rt = 1;
  445. break;
  446. case CEC_OC_SET_ANALOGUE_TIMER:
  447. case CEC_OC_CLEAR_ANALOGUE_TIMER:
  448. if (opernum == 11) rt = 1;
  449. break;
  450. case CEC_OC_CLEAR_DIGITAL_TIMER:
  451. case CEC_OC_SET_DIGITAL_TIMER:
  452. if (opernum == 14) rt = 1;
  453. break;
  454. case CEC_OC_TIMER_STATUS:
  455. if ((opernum == 1 || opernum == 3)) rt = 1;
  456. break;
  457. case CEC_OC_TUNER_DEVICE_STATUS:
  458. if ((opernum == 5 || opernum == 8)) rt = 1;
  459. break;
  460. case CEC_OC_RECORD_ON:
  461. if (opernum > 0 && opernum < 9) rt = 1;
  462. break;
  463. case CEC_OC_CLEAR_EXTERNAL_TIMER:
  464. case CEC_OC_SET_EXTERNAL_TIMER:
  465. if ((opernum == 9 || opernum == 10)) rt = 1;
  466. break;
  467. case CEC_OC_SET_TIMER_PROGRAM_TITLE:
  468. case CEC_OC_SET_OSD_NAME:
  469. if (opernum > 0 && opernum < 15) rt = 1;
  470. break;
  471. case CEC_OC_SET_OSD_STRING:
  472. if (opernum > 1 && opernum < 15) rt = 1;
  473. break;
  474. case CEC_OC_VENDOR_COMMAND:
  475. if (opernum < 15) rt = 1;
  476. break;
  477. case CEC_OC_REQUEST_ACTIVE_SOURCE:
  478. if (opernum == 0) rt = 1;
  479. break;
  480. case CEC_OC_REPORT_PHYSICAL_ADDRESS:
  481. case CEC_OC_SET_MENU_LANGUAGE:
  482. case CEC_OC_DEVICE_VENDOR_ID:
  483. if (opernum == 3) rt = 1;
  484. break;
  485. case CEC_OC_ROUTING_CHANGE:
  486. if (opernum == 4) rt = 1;
  487. break;
  488. case CEC_OC_ACTIVE_SOURCE:
  489. case CEC_OC_ROUTING_INFORMATION:
  490. case CEC_OC_SET_STREAM_PATH:
  491. if (opernum == 2) rt = 1;
  492. break;
  493. default:
  494. rt = 1;
  495. break;
  496. }
  497. if (rt == 0)
  498. hdmirx_cec_dbg_print("opcode and opernum not match: %x, %x\n", opcode, opernum);
  499. rt = 1; // temporal
  500. return rt;
  501. }
  502. static irqreturn_t cec_handler(int irq, void *dev_instance)
  503. {
  504. unsigned int data;
  505. if (cec_pending_flag == TV_CEC_PENDING_ON) {
  506. WRITE_MPEG_REG(A9_0_IRQ_IN1_INTR_STAT_CLR, 1 << 23); // Clear the interrupt
  507. return;
  508. }
  509. data = hdmi_rd_reg(CEC0_BASE_ADDR+CEC_RX_MSG_STATUS);
  510. if (data) {
  511. //hdmirx_cec_dbg_print("CEC Irq Rx Status %x\n", data);
  512. if ((data & 0x3) == RX_DONE) {
  513. data = hdmi_rd_reg(CEC0_BASE_ADDR + CEC_RX_NUM_MSG);
  514. if (data == 1) {
  515. unsigned char rx_msg[MAX_MSG], rx_len;
  516. cec_ll_rx(rx_msg, &rx_len);
  517. register_cec_rx_msg(rx_msg, rx_len);
  518. } else {
  519. hdmi_wr_reg(CEC0_BASE_ADDR + CEC_RX_CLEAR_BUF, 0x01);
  520. hdmi_wr_reg(CEC0_BASE_ADDR + CEC_RX_MSG_CMD, RX_NO_OP);
  521. cec_recover_reset();
  522. hdmirx_cec_dbg_print("Error: CEC1->CEC0 transmit data fail, rx_num_msg = %x !", data);
  523. }
  524. } else {
  525. hdmirx_cec_dbg_print("Error: CEC1->CEC0 transmit data fail, msg_status = %x!", data);
  526. hdmi_wr_reg(CEC0_BASE_ADDR + CEC_RX_CLEAR_BUF, 0x01);
  527. hdmi_wr_reg(CEC0_BASE_ADDR + CEC_RX_MSG_CMD, RX_NO_OP);
  528. cec_recover_reset();
  529. }
  530. }
  531. data = hdmi_rd_reg(CEC0_BASE_ADDR+CEC_TX_MSG_STATUS);
  532. if (data) {
  533. //hdmirx_cec_dbg_print("CEC Irq Tx Status %x\n", data);
  534. }
  535. WRITE_MPEG_REG(A9_0_IRQ_IN1_INTR_STAT_CLR, 1 << 23); // Clear the interrupt
  536. return IRQ_HANDLED;
  537. }
  538. static unsigned short cec_log_addr_to_dev_type(unsigned char log_addr)
  539. {
  540. unsigned short us = CEC_UNREGISTERED_DEVICE_TYPE;
  541. if ((1 << log_addr) & CEC_DISPLAY_DEVICE) {
  542. us = CEC_DISPLAY_DEVICE_TYPE;
  543. } else if ((1 << log_addr) & CEC_RECORDING_DEVICE) {
  544. us = CEC_RECORDING_DEVICE_TYPE;
  545. } else if ((1 << log_addr) & CEC_PLAYBACK_DEVICE) {
  546. us = CEC_PLAYBACK_DEVICE_TYPE;
  547. } else if ((1 << log_addr) & CEC_TUNER_DEVICE) {
  548. us = CEC_TUNER_DEVICE_TYPE;
  549. } else if ((1 << log_addr) & CEC_AUDIO_SYSTEM_DEVICE) {
  550. us = CEC_AUDIO_SYSTEM_DEVICE_TYPE;
  551. }
  552. return us;
  553. }
  554. static cec_hdmi_port_e cec_find_hdmi_port(unsigned char log_addr)
  555. {
  556. cec_hdmi_port_e rt = CEC_HDMI_PORT_UKNOWN;
  557. if ((cec_global_info.dev_mask & (1 << log_addr)) &&
  558. (cec_global_info.cec_node_info[log_addr].phy_addr != 0) &&
  559. (cec_global_info.cec_node_info[log_addr].hdmi_port == CEC_HDMI_PORT_UKNOWN)) {
  560. if ((cec_global_info.cec_node_info[log_addr].phy_addr & 0xF000) == 0x1000) {
  561. cec_global_info.cec_node_info[log_addr].hdmi_port = CEC_HDMI_PORT_1;
  562. } else if ((cec_global_info.cec_node_info[log_addr].phy_addr & 0xF000) == 0x2000) {
  563. cec_global_info.cec_node_info[log_addr].hdmi_port = CEC_HDMI_PORT_2;
  564. } else if ((cec_global_info.cec_node_info[log_addr].phy_addr & 0xF000) == 0x3000) {
  565. cec_global_info.cec_node_info[log_addr].hdmi_port = CEC_HDMI_PORT_3;
  566. }
  567. }
  568. rt = cec_global_info.cec_node_info[log_addr].hdmi_port;
  569. return rt;
  570. }
  571. // -------------- command from cec devices ---------------------
  572. void cec_tv_polling_online_dev(void)
  573. {
  574. int log_addr = 0;
  575. int r;
  576. unsigned short dev_mask_tmp = 0;
  577. unsigned char msg[1];
  578. unsigned char ping = 1;
  579. for (log_addr = 1; log_addr < CEC_UNREGISTERED_ADDR; log_addr++) {
  580. msg[0] = log_addr;
  581. r = cec_ll_tx(msg, 1, &ping);
  582. if (r != TX_DONE) {
  583. dev_mask_tmp &= ~(1 << log_addr);
  584. memset(&(cec_global_info.cec_node_info[log_addr]), 0, sizeof(cec_node_info_t));
  585. }
  586. if (r == TX_DONE) {
  587. dev_mask_tmp |= 1 << log_addr;
  588. cec_global_info.cec_node_info[log_addr].log_addr = log_addr;
  589. cec_global_info.cec_node_info[log_addr].dev_type = cec_log_addr_to_dev_type(log_addr);
  590. cec_find_hdmi_port(log_addr);
  591. }
  592. }
  593. if (cec_global_info.dev_mask != dev_mask_tmp) {
  594. cec_global_info.dev_mask = dev_mask_tmp;
  595. }
  596. //hdmirx_cec_dbg_print("cec log device exist: %x\n", dev_mask_tmp);
  597. }
  598. void cec_report_phy_addr(cec_rx_message_t* pcec_message)
  599. {
  600. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  601. cec_global_info.dev_mask |= 1 << log_addr;
  602. cec_global_info.cec_node_info[log_addr].dev_type = cec_log_addr_to_dev_type(log_addr);
  603. cec_global_info.cec_node_info[log_addr].real_info_mask |= INFO_MASK_DEVICE_TYPE;
  604. memcpy(cec_global_info.cec_node_info[log_addr].osd_name_def, default_osd_name[log_addr], 16);
  605. if ((cec_global_info.cec_node_info[log_addr].real_info_mask & INFO_MASK_OSD_NAME) == 0) {
  606. memcpy(cec_global_info.cec_node_info[log_addr].osd_name, osd_name_uninit, 16);
  607. }
  608. cec_global_info.cec_node_info[log_addr].log_addr = log_addr;
  609. cec_global_info.cec_node_info[log_addr].real_info_mask |= INFO_MASK_LOGIC_ADDRESS;
  610. cec_global_info.cec_node_info[log_addr].phy_addr = (pcec_message->content.msg.operands[0] << 8) | pcec_message->content.msg.operands[1];
  611. cec_global_info.cec_node_info[log_addr].real_info_mask |= INFO_MASK_PHYSICAL_ADDRESS;
  612. hdmirx_cec_dbg_print("cec_report_phy_addr: %s\n", cec_global_info.cec_node_info[log_addr].osd_name_def);
  613. }
  614. void cec_report_power_status(cec_rx_message_t* pcec_message)
  615. {
  616. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  617. if (cec_global_info.dev_mask & (1 << log_addr)) {
  618. cec_global_info.cec_node_info[log_addr].power_status = pcec_message->content.msg.operands[0];
  619. cec_global_info.cec_node_info[log_addr].real_info_mask |= INFO_MASK_POWER_STATUS;
  620. hdmirx_cec_dbg_print("cec_report_power_status: %x\n", cec_global_info.cec_node_info[log_addr].power_status);
  621. }
  622. }
  623. void cec_feature_abort(cec_rx_message_t* pcec_message)
  624. {
  625. hdmirx_cec_dbg_print("cec_feature_abort: opcode %x\n", pcec_message->content.msg.opcode);
  626. }
  627. void cec_report_version(cec_rx_message_t* pcec_message)
  628. {
  629. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  630. if (cec_global_info.dev_mask & (1 << log_addr)) {
  631. cec_global_info.cec_node_info[log_addr].cec_version = pcec_message->content.msg.operands[0];
  632. cec_global_info.cec_node_info[log_addr].real_info_mask |= INFO_MASK_CEC_VERSION;
  633. hdmirx_cec_dbg_print("cec_report_version: %x\n", cec_global_info.cec_node_info[log_addr].cec_version);
  634. }
  635. }
  636. void cec_active_source(cec_rx_message_t* pcec_message)
  637. {
  638. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  639. if (cec_global_info.dev_mask & (1 << log_addr)) {
  640. cec_global_info.active_log_dev = log_addr;
  641. hdmirx_cec_dbg_print("cec_active_source: %x\n", log_addr);
  642. }
  643. }
  644. void cec_deactive_source(cec_rx_message_t* pcec_message)
  645. {
  646. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  647. if (cec_global_info.dev_mask & (1 << log_addr)) {
  648. if (cec_global_info.active_log_dev == log_addr) {
  649. cec_global_info.active_log_dev = 0;
  650. }
  651. hdmirx_cec_dbg_print("cec_deactive_source: %x\n", log_addr);
  652. }
  653. }
  654. void cec_get_version(cec_rx_message_t* pcec_message)
  655. {
  656. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  657. if (cec_global_info.dev_mask & (1 << log_addr)) {
  658. unsigned char msg[3];
  659. msg[0] = log_addr;
  660. msg[1] = CEC_OC_CEC_VERSION;
  661. msg[2] = CEC_VERSION_13A;
  662. cec_ll_tx(msg, 3, NULL);
  663. }
  664. }
  665. void cec_give_deck_status(cec_rx_message_t* pcec_message)
  666. {
  667. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  668. if (cec_global_info.dev_mask & (1 << log_addr)) {
  669. }
  670. }
  671. void cec_menu_status(cec_rx_message_t* pcec_message)
  672. {
  673. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  674. if (cec_global_info.dev_mask & (1 << log_addr)) {
  675. cec_global_info.cec_node_info[log_addr].menu_state = pcec_message->content.msg.operands[0];
  676. cec_global_info.cec_node_info[log_addr].real_info_mask |= INFO_MASK_MENU_STATE;
  677. hdmirx_cec_dbg_print("cec_menu_status: %x\n", cec_global_info.cec_node_info[log_addr].menu_state);
  678. }
  679. }
  680. void cec_deck_status(cec_rx_message_t* pcec_message)
  681. {
  682. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  683. if (cec_global_info.dev_mask & (1 << log_addr)) {
  684. cec_global_info.cec_node_info[log_addr].specific_info.playback.deck_info = pcec_message->content.msg.operands[0];
  685. cec_global_info.cec_node_info[log_addr].real_info_mask |= INFO_MASK_DECK_INfO;
  686. hdmirx_cec_dbg_print("cec_deck_status: %x\n", cec_global_info.cec_node_info[log_addr].specific_info.playback.deck_info);
  687. }
  688. }
  689. void cec_device_vendor_id(cec_rx_message_t* pcec_message)
  690. {
  691. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  692. if (cec_global_info.dev_mask & (1 << log_addr)) {
  693. int i, tmp = 0;
  694. for (i = 0; i < pcec_message->operand_num; i++) {
  695. tmp |= (pcec_message->content.msg.operands[i] << ((pcec_message->operand_num - i - 1)*8));
  696. }
  697. cec_global_info.cec_node_info[log_addr].vendor_id.vendor_id= tmp;
  698. cec_global_info.cec_node_info[log_addr].vendor_id.vendor_id_byte_num = pcec_message->operand_num;
  699. cec_global_info.cec_node_info[log_addr].real_info_mask |= INFO_MASK_VENDOR_ID;
  700. hdmirx_cec_dbg_print("cec_device_vendor_id: %x\n", cec_global_info.cec_node_info[log_addr].vendor_id);
  701. }
  702. }
  703. void cec_set_osd_name(cec_rx_message_t* pcec_message)
  704. {
  705. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  706. if (cec_global_info.dev_mask & (1 << log_addr)) {
  707. memcpy(cec_global_info.cec_node_info[log_addr].osd_name, pcec_message->content.msg.operands, 14);
  708. cec_global_info.cec_node_info[log_addr].real_info_mask |= INFO_MASK_OSD_NAME;
  709. hdmirx_cec_dbg_print("cec_set_osd_name: %s\n", cec_global_info.cec_node_info[log_addr].osd_name);
  710. }
  711. }
  712. void cec_vendor_cmd_with_id(cec_rx_message_t* pcec_message)
  713. {
  714. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  715. if (cec_global_info.dev_mask & (1 << log_addr)) {
  716. if (cec_global_info.cec_node_info[log_addr].vendor_id.vendor_id_byte_num != 0) {
  717. int i = cec_global_info.cec_node_info[log_addr].vendor_id.vendor_id_byte_num;
  718. int tmp = 0;
  719. for ( ; i < pcec_message->operand_num; i++) {
  720. tmp |= (pcec_message->content.msg.operands[i] << ((cec_global_info.cec_node_info[log_addr].vendor_id.vendor_id_byte_num - i - 1)*8));
  721. }
  722. hdmirx_cec_dbg_print("cec_vendor_cmd_with_id: %x, %x\n", cec_global_info.cec_node_info[log_addr].vendor_id.vendor_id, tmp);
  723. }
  724. }
  725. }
  726. void cec_set_menu_language(cec_rx_message_t* pcec_message)
  727. {
  728. unsigned char log_addr = pcec_message->content.msg.header >> 4;
  729. if (cec_global_info.dev_mask & (1 << log_addr)) {
  730. if (pcec_message->operand_num == 3) {
  731. int i;
  732. unsigned int tmp = ((pcec_message->content.msg.operands[0] << 16) |
  733. (pcec_message->content.msg.operands[1] << 8) |
  734. (pcec_message->content.msg.operands[2]));
  735. hdmirx_cec_dbg_print("%c, %c, %c\n", pcec_message->content.msg.operands[0],
  736. pcec_message->content.msg.operands[1],
  737. pcec_message->content.msg.operands[2]);
  738. for (i = 0; i < (sizeof(menu_lang_array)/sizeof(menu_lang_array[0])); i++) {
  739. if (menu_lang_array[i] == tmp)
  740. break;
  741. }
  742. cec_global_info.cec_node_info[log_addr].menu_lang = i;
  743. cec_global_info.cec_node_info[log_addr].real_info_mask |= INFO_MASK_MENU_LANGUAGE;
  744. hdmirx_cec_dbg_print("cec_set_menu_language: %x\n", cec_global_info.cec_node_info[log_addr].menu_lang);
  745. }
  746. }
  747. }
  748. void cec_handle_message(cec_rx_message_t* pcec_message)
  749. {
  750. unsigned char brdcst, opcode;
  751. unsigned char initiator, follower;
  752. unsigned char operand_num;
  753. unsigned char msg_length;
  754. /* parse message */
  755. if ((!pcec_message) || (check_cec_msg_valid(pcec_message) == 0)) return;
  756. initiator = pcec_message->content.msg.header >> 4;
  757. follower = pcec_message->content.msg.header & 0x0f;
  758. opcode = pcec_message->content.msg.opcode;
  759. operand_num = pcec_message->operand_num;
  760. brdcst = (follower == 0x0f);
  761. msg_length = pcec_message->msg_length;
  762. /* process messages from tv polling and cec devices */
  763. switch (opcode) {
  764. case CEC_OC_ACTIVE_SOURCE:
  765. cec_active_source(pcec_message);
  766. break;
  767. case CEC_OC_INACTIVE_SOURCE:
  768. cec_deactive_source(pcec_message);
  769. break;
  770. case CEC_OC_CEC_VERSION:
  771. cec_report_version(pcec_message);
  772. break;
  773. case CEC_OC_DECK_STATUS:
  774. cec_deck_status(pcec_message);
  775. break;
  776. case CEC_OC_DEVICE_VENDOR_ID:
  777. cec_device_vendor_id(pcec_message);
  778. break;
  779. case CEC_OC_FEATURE_ABORT:
  780. cec_feature_abort(pcec_message);
  781. break;
  782. case CEC_OC_GET_CEC_VERSION:
  783. cec_get_version(pcec_message);
  784. break;
  785. case CEC_OC_GIVE_DECK_STATUS:
  786. cec_give_deck_status(pcec_message);
  787. break;
  788. case CEC_OC_MENU_STATUS:
  789. cec_menu_status(pcec_message);
  790. break;
  791. case CEC_OC_REPORT_PHYSICAL_ADDRESS:
  792. cec_report_phy_addr(pcec_message);
  793. break;
  794. case CEC_OC_REPORT_POWER_STATUS:
  795. cec_report_power_status(pcec_message);
  796. break;
  797. case CEC_OC_SET_OSD_NAME:
  798. cec_set_osd_name(pcec_message);
  799. break;
  800. case CEC_OC_VENDOR_COMMAND_WITH_ID:
  801. cec_vendor_cmd_with_id(pcec_message);
  802. break;
  803. case CEC_OC_SET_MENU_LANGUAGE:
  804. cec_set_menu_language(pcec_message);
  805. break;
  806. case CEC_OC_VENDOR_REMOTE_BUTTON_DOWN:
  807. case CEC_OC_VENDOR_REMOTE_BUTTON_UP:
  808. case CEC_OC_CLEAR_ANALOGUE_TIMER:
  809. case CEC_OC_CLEAR_DIGITAL_TIMER:
  810. case CEC_OC_CLEAR_EXTERNAL_TIMER:
  811. case CEC_OC_DECK_CONTROL:
  812. case CEC_OC_GIVE_DEVICE_POWER_STATUS:
  813. case CEC_OC_GIVE_DEVICE_VENDOR_ID:
  814. case CEC_OC_GIVE_OSD_NAME:
  815. case CEC_OC_GIVE_PHYSICAL_ADDRESS:
  816. case CEC_OC_GIVE_SYSTEM_AUDIO_MODE_STATUS:
  817. case CEC_OC_GIVE_TUNER_DEVICE_STATUS:
  818. case CEC_OC_IMAGE_VIEW_ON:
  819. case CEC_OC_MENU_REQUEST:
  820. case CEC_OC_SET_OSD_STRING:
  821. case CEC_OC_SET_STREAM_PATH:
  822. case CEC_OC_SET_SYSTEM_AUDIO_MODE:
  823. case CEC_OC_SET_TIMER_PROGRAM_TITLE:
  824. case CEC_OC_STANDBY:
  825. case CEC_OC_SYSTEM_AUDIO_MODE_REQUEST:
  826. case CEC_OC_SYSTEM_AUDIO_MODE_STATUS:
  827. case CEC_OC_TEXT_VIEW_ON:
  828. case CEC_OC_TIMER_CLEARED_STATUS:
  829. case CEC_OC_TIMER_STATUS:
  830. case CEC_OC_TUNER_DEVICE_STATUS:
  831. case CEC_OC_TUNER_STEP_DECREMENT:
  832. case CEC_OC_TUNER_STEP_INCREMENT:
  833. case CEC_OC_USER_CONTROL_PRESSED:
  834. case CEC_OC_USER_CONTROL_RELEASED:
  835. case CEC_OC_VENDOR_COMMAND:
  836. case CEC_OC_REQUEST_ACTIVE_SOURCE:
  837. case CEC_OC_ROUTING_CHANGE:
  838. case CEC_OC_ROUTING_INFORMATION:
  839. case CEC_OC_SELECT_ANALOGUE_SERVICE:
  840. case CEC_OC_SELECT_DIGITAL_SERVICE:
  841. case CEC_OC_SET_ANALOGUE_TIMER :
  842. case CEC_OC_SET_AUDIO_RATE:
  843. case CEC_OC_SET_DIGITAL_TIMER:
  844. case CEC_OC_SET_EXTERNAL_TIMER:
  845. case CEC_OC_PLAY:
  846. case CEC_OC_RECORD_OFF:
  847. case CEC_OC_RECORD_ON:
  848. case CEC_OC_RECORD_STATUS:
  849. case CEC_OC_RECORD_TV_SCREEN:
  850. case CEC_OC_REPORT_AUDIO_STATUS:
  851. case CEC_OC_GET_MENU_LANGUAGE:
  852. case CEC_OC_GIVE_AUDIO_STATUS:
  853. case CEC_OC_ABORT_MESSAGE:
  854. printk("\n=========================\n");
  855. printk("Get not support cec command: %x\n", opcode);
  856. printk("\n=========================\n");
  857. break;
  858. default:
  859. break;
  860. }
  861. }
  862. // --------------- cec command from user application --------------------
  863. void cec_usrcmd_parse_all_dev_online(void)
  864. {
  865. int i;
  866. unsigned short tmp_mask;
  867. hdmirx_cec_dbg_print("cec online: ###############################################\n");
  868. hdmirx_cec_dbg_print("active_log_dev %x\n", cec_global_info.active_log_dev);
  869. for (i = 0; i < MAX_NUM_OF_DEV; i++) {
  870. tmp_mask = 1 << i;
  871. if (tmp_mask & cec_global_info.dev_mask) {
  872. hdmirx_cec_dbg_print("cec online: -------------------------------------------\n");
  873. hdmirx_cec_dbg_print("hdmi_port: %x\n", cec_global_info.cec_node_info[i].hdmi_port);
  874. hdmirx_cec_dbg_print("dev_type: %x\n", cec_global_info.cec_node_info[i].dev_type);
  875. hdmirx_cec_dbg_print("power_status: %x\n", cec_global_info.cec_node_info[i].power_status);
  876. hdmirx_cec_dbg_print("cec_version: %x\n", cec_global_info.cec_node_info[i].cec_version);
  877. hdmirx_cec_dbg_print("vendor_id: %x\n", cec_global_info.cec_node_info[i].vendor_id.vendor_id);
  878. hdmirx_cec_dbg_print("phy_addr: %x\n", cec_global_info.cec_node_info[i].phy_addr);
  879. hdmirx_cec_dbg_print("log_addr: %x\n", cec_global_info.cec_node_info[i].log_addr);
  880. hdmirx_cec_dbg_print("osd_name: %s\n", cec_global_info.cec_node_info[i].osd_name);
  881. hdmirx_cec_dbg_print("osd_name_def: %s\n", cec_global_info.cec_node_info[i].osd_name_def);
  882. hdmirx_cec_dbg_print("menu_state: %x\n", cec_global_info.cec_node_info[i].menu_state);
  883. if (cec_global_info.cec_node_info[i].dev_type == CEC_PLAYBACK_DEVICE_TYPE) {
  884. hdmirx_cec_dbg_print("deck_cnt_mode: %x\n", cec_global_info.cec_node_info[i].specific_info.playback.deck_cnt_mode);
  885. hdmirx_cec_dbg_print("deck_info: %x\n", cec_global_info.cec_node_info[i].specific_info.playback.deck_info);
  886. hdmirx_cec_dbg_print("play_mode: %x\n", cec_global_info.cec_node_info[i].specific_info.playback.play_mode);
  887. }
  888. }
  889. }
  890. hdmirx_cec_dbg_print("##############################################################\n");
  891. }
  892. void cec_usrcmd_get_cec_version(unsigned char log_addr)
  893. {
  894. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_CEC_VERSION);
  895. register_cec_tx_msg(gbl_msg, 2);
  896. }
  897. void cec_usrcmd_get_audio_status(unsigned char log_addr)
  898. {
  899. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_GIVE_AUDIO_STATUS);
  900. register_cec_tx_msg(gbl_msg, 2);
  901. }
  902. void cec_usrcmd_get_deck_status(unsigned char log_addr)
  903. {
  904. MSG_P1(cec_global_info.tv_log_addr, log_addr, CEC_OC_GIVE_DECK_STATUS, STATUS_REQ_ON);
  905. register_cec_tx_msg(gbl_msg, 3);
  906. }
  907. void cec_usrcmd_set_deck_cnt_mode(unsigned char log_addr, deck_cnt_mode_e deck_cnt_mode)
  908. {
  909. MSG_P1(cec_global_info.tv_log_addr, log_addr, CEC_OC_DECK_CONTROL, deck_cnt_mode);
  910. register_cec_tx_msg(gbl_msg, 3);
  911. }
  912. void cec_usrcmd_get_device_power_status(unsigned char log_addr)
  913. {
  914. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_GIVE_DEVICE_POWER_STATUS);
  915. register_cec_tx_msg(gbl_msg, 2);
  916. }
  917. void cec_usrcmd_get_device_vendor_id(unsigned char log_addr)
  918. {
  919. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_GIVE_DEVICE_VENDOR_ID);
  920. register_cec_tx_msg(gbl_msg, 2);
  921. }
  922. void cec_usrcmd_get_osd_name(unsigned char log_addr)
  923. {
  924. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_GIVE_OSD_NAME);
  925. register_cec_tx_msg(gbl_msg, 2);
  926. }
  927. void cec_usrcmd_get_physical_address(unsigned char log_addr)
  928. {
  929. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_GIVE_PHYSICAL_ADDRESS);
  930. register_cec_tx_msg(gbl_msg, 2);
  931. }
  932. void cec_usrcmd_get_system_audio_mode_status(unsigned char log_addr)
  933. {
  934. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_GIVE_SYSTEM_AUDIO_MODE_STATUS);
  935. register_cec_tx_msg(gbl_msg, 2);
  936. }
  937. void cec_usrcmd_set_standby(unsigned char log_addr)
  938. {
  939. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_STANDBY);
  940. register_cec_tx_msg(gbl_msg, 2);
  941. }
  942. void cec_usrcmd_set_imageview_on(unsigned char log_addr)
  943. {
  944. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_IMAGE_VIEW_ON);
  945. register_cec_tx_msg(gbl_msg, 2);
  946. }
  947. void cec_usrcmd_get_tuner_device_status(unsigned char log_addr)
  948. {
  949. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_GIVE_TUNER_DEVICE_STATUS);
  950. register_cec_tx_msg(gbl_msg, 2);
  951. }
  952. void cec_usrcmd_set_play_mode(unsigned char log_addr, play_mode_e play_mode)
  953. {
  954. MSG_P1(cec_global_info.tv_log_addr, log_addr, CEC_OC_PLAY, play_mode);
  955. register_cec_tx_msg(gbl_msg, 3);
  956. }
  957. void cec_usrcmd_get_menu_state(unsigned char log_addr)
  958. {
  959. MSG_P1(cec_global_info.tv_log_addr, log_addr, CEC_OC_MENU_REQUEST, MENU_REQ_QUERY);
  960. register_cec_tx_msg(gbl_msg, 3);
  961. }
  962. void cec_usrcmd_set_menu_state(unsigned char log_addr, menu_req_type_e menu_req_type)
  963. {
  964. MSG_P1(cec_global_info.tv_log_addr, log_addr, CEC_OC_MENU_REQUEST, menu_req_type);
  965. register_cec_tx_msg(gbl_msg, 3);
  966. }
  967. void cec_usrcmd_get_menu_language(unsigned char log_addr)
  968. {
  969. MSG_P0(cec_global_info.tv_log_addr, log_addr, CEC_OC_GET_MENU_LANGUAGE);
  970. register_cec_tx_msg(gbl_msg, 2);
  971. }
  972. void cec_usrcmd_set_menu_language(unsigned char log_addr, cec_menu_lang_e menu_lang)
  973. {
  974. MSG_P3(cec_global_info.tv_log_addr, log_addr, CEC_OC_SET_MENU_LANGUAGE, (menu_lang_array[menu_lang]>>16)&0xFF,
  975. (menu_lang_array[menu_lang]>>8)&0xFF,
  976. (menu_lang_array[menu_lang])&0xFF);
  977. register_cec_tx_msg(gbl_msg, 5);
  978. }
  979. void cec_usrcmd_get_active_source(void)
  980. {
  981. MSG_P0(cec_global_info.tv_log_addr, 0xF, CEC_OC_REQUEST_ACTIVE_SOURCE);
  982. register_cec_tx_msg(gbl_msg, 2);
  983. }
  984. void cec_usrcmd_set_active_source(unsigned char log_addr)
  985. {
  986. MSG_P2(cec_global_info.tv_log_addr, log_addr, CEC_OC_ACTIVE_SOURCE,
  987. (unsigned char)(cec_global_info.cec_node_info[log_addr].phy_addr >> 8),
  988. (unsigned char)(cec_global_info.cec_node_info[log_addr].phy_addr & 0xFF));
  989. register_cec_tx_msg(gbl_msg, 4);
  990. }
  991. void cec_usrcmd_set_deactive_source(unsigned char log_addr)
  992. {
  993. MSG_P2(cec_global_info.tv_log_addr, log_addr, CEC_OC_INACTIVE_SOURCE,
  994. (unsigned char)(cec_global_info.cec_node_info[log_addr].phy_addr >> 8),
  995. (unsigned char)(cec_global_info.cec_node_info[log_addr].phy_addr & 0xFF));
  996. register_cec_tx_msg(gbl_msg, 4);
  997. }
  998. void cec_usrcmd_clear_node_dev_real_info_mask(unsigned char log_addr, cec_info_mask mask)
  999. {
  1000. cec_global_info.cec_node_info[log_addr].real_info_mask &= ~mask;
  1001. }
  1002. void cec_usrcmd_set_stream_path(unsigned char log_addr)
  1003. {
  1004. MSG_P2(cec_global_info.tv_log_addr, log_addr, CEC_OC_SET_STREAM_PATH,
  1005. (unsigned char)(cec_global_info.cec_node_info[log_addr].phy_addr >> 8),
  1006. (unsigned char)(cec_global_info.cec_node_info[log_addr].phy_addr & 0xFF));
  1007. register_cec_tx_msg(gbl_msg, 4);
  1008. }
  1009. /* cec middle level code end */
  1010. /* cec high level code */
  1011. static struct timer_list tv_cec_timer;
  1012. static unsigned char dev = 0;
  1013. static unsigned char cec_init_flag = 0;
  1014. static unsigned char cec_mutex_flag = 0;
  1015. void cec_init(void)
  1016. {
  1017. // cec Clock
  1018. #ifdef _SUPPORT_CEC_TV_MASTER_
  1019. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x00 );
  1020. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0xF9 );
  1021. #else
  1022. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x07 );
  1023. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0x52 );
  1024. #endif
  1025. hdmi_wr_reg(CEC0_BASE_ADDR+CEC_LOGICAL_ADDR0, (0x1 << 4) | CEC0_LOG_ADDR);
  1026. if (cec_init_flag == 1) return;
  1027. cec_rx_msg_buf.rx_write_pos = 0;
  1028. cec_rx_msg_buf.rx_read_pos = 0;
  1029. cec_rx_msg_buf.rx_buf_size = sizeof(cec_rx_msg_buf.cec_rx_message)/sizeof(cec_rx_msg_buf.cec_rx_message[0]);
  1030. memset(cec_rx_msg_buf.cec_rx_message, 0, sizeof(cec_rx_msg_buf.cec_rx_message));
  1031. memset(&cec_global_info, 0, sizeof(cec_global_info_t));
  1032. if (cec_mutex_flag == 0) {
  1033. init_MUTEX(&tv_cec_sema);
  1034. cec_mutex_flag = 1;
  1035. }
  1036. kthread_run(tv_cec_task_handle, &dev, "kthread_cec");
  1037. request_irq(INT_HDMI_CEC, &cec_handler,
  1038. IRQF_SHARED, "amhdmirx",
  1039. (void *)"amhdmirx");
  1040. WRITE_MPEG_REG(A9_0_IRQ_IN1_INTR_STAT_CLR, READ_MPEG_REG(A9_0_IRQ_IN1_INTR_STAT_CLR) | (1 << 23)); // Clear the interrupt
  1041. WRITE_MPEG_REG(A9_0_IRQ_IN1_INTR_MASK, READ_MPEG_REG(A9_0_IRQ_IN1_INTR_MASK) | (1 << 23)); // Enable the hdmi cec interrupt
  1042. init_timer(&tv_cec_timer);
  1043. tv_cec_timer.data = (ulong) & tv_cec_timer;
  1044. tv_cec_timer.function = tv_cec_timer_func;
  1045. tv_cec_timer.expires = jiffies + TV_CEC_INTERVAL;
  1046. add_timer(&tv_cec_timer);
  1047. cec_init_flag = 1;
  1048. return;
  1049. }
  1050. void cec_uninit(void)
  1051. {
  1052. if (cec_init_flag == 1) {
  1053. WRITE_MPEG_REG(A9_0_IRQ_IN1_INTR_MASK, READ_MPEG_REG(A9_0_IRQ_IN1_INTR_MASK) & ~(1 << 23)); // Disable the hdmi cec interrupt
  1054. free_irq(INT_HDMI_CEC, (void *)"amhdmirx");
  1055. del_timer_sync(&tv_cec_timer);
  1056. cec_init_flag = 0;
  1057. }
  1058. }
  1059. void cec_set_pending(tv_cec_pending_e on_off)
  1060. {
  1061. cec_pending_flag = on_off;
  1062. }
  1063. size_t cec_usrcmd_get_global_info(char * buf)
  1064. {
  1065. int i = 0;
  1066. int dev_num = 0;
  1067. cec_node_info_t * buf_node_addr = (cec_node_info_t *)(buf + (unsigned int)(((cec_global_info_to_usr_t*)0)->cec_node_info_online));
  1068. for (i = 0; i < MAX_NUM_OF_DEV; i++) {
  1069. if (cec_global_info.dev_mask & (1 << i)) {
  1070. memcpy(&(buf_node_addr[dev_num]), &(cec_global_info.cec_node_info[i]), sizeof(cec_node_info_t));
  1071. dev_num++;
  1072. }
  1073. }
  1074. buf[0] = dev_num;
  1075. buf[1] = cec_global_info.active_log_dev;
  1076. #if 0
  1077. printk("\n");
  1078. printk("%x\n",(unsigned int)(((cec_global_info_to_usr_t*)0)->cec_node_info_online));
  1079. printk("%x\n", ((cec_global_info_to_usr_t*)buf)->dev_number);
  1080. printk("%x\n", ((cec_global_info_to_usr_t*)buf)->active_log_dev);
  1081. printk("%x\n", ((cec_global_info_to_usr_t*)buf)->cec_node_info_online[0].hdmi_port);
  1082. for (i=0; i < (sizeof(cec_node_info_t) * dev_num) + 2; i++) {
  1083. printk("%x,",buf[i]);
  1084. }
  1085. printk("\n");
  1086. #endif
  1087. return (sizeof(cec_node_info_t) * dev_num) + (unsigned int)(((cec_global_info_to_usr_t*)0)->cec_node_info_online);
  1088. }
  1089. void cec_usrcmd_set_dispatch(const char * buf, size_t count)
  1090. {
  1091. int i;
  1092. usr_cmd_type_e usr_cmd_type = 0;
  1093. int param1 = 0;
  1094. int param2 = 0;
  1095. int param3 = 0;
  1096. int param4 = 0;
  1097. int param5 = 0;
  1098. hdmirx_cec_dbg_print("cec_usrcmd_set_dispatch: \n");
  1099. for (i = 0; i < count; i++) {
  1100. hdmirx_cec_dbg_print("%x,", buf[i]);
  1101. }
  1102. hdmirx_cec_dbg_print("\n");
  1103. if (count < 2) return;
  1104. usr_cmd_type = buf[0];
  1105. if (count == 2) {
  1106. param1 = buf[1];
  1107. } else if (count == 3) {
  1108. param1 = buf[1];
  1109. param2 = buf[2];
  1110. } else if (count == 4) {
  1111. param1 = buf[1];
  1112. param2 = buf[2];
  1113. param3 = buf[3];
  1114. } else if (count == 5) {
  1115. param1 = buf[1];
  1116. param2 = buf[2];
  1117. param3 = buf[3];
  1118. param4 = buf[4];
  1119. } else if (count == 6) {
  1120. param1 = buf[1];
  1121. param2 = buf[2];
  1122. param3 = buf[3];
  1123. param4 = buf[4];
  1124. param5 = buf[5];
  1125. }
  1126. switch (usr_cmd_type) {
  1127. case GET_CEC_VERSION:
  1128. cec_usrcmd_get_cec_version(param1);
  1129. break;
  1130. case GET_DEV_POWER_STATUS:
  1131. cec_usrcmd_get_device_power_status(param1);
  1132. break;
  1133. case GET_DEV_VENDOR_ID:
  1134. cec_usrcmd_get_device_vendor_id(param1);
  1135. break;
  1136. case GET_OSD_NAME:
  1137. cec_usrcmd_get_osd_name(param1);
  1138. break;
  1139. case GET_PHYSICAL_ADDR:
  1140. cec_usrcmd_get_physical_address(param1);
  1141. break;
  1142. case SET_STANDBY:
  1143. cec_usrcmd_set_standby(param1);
  1144. break;
  1145. case SET_IMAGEVIEW_ON:
  1146. cec_usrcmd_set_standby(param1);
  1147. break;
  1148. case GIVE_DECK_STATUS:
  1149. cec_usrcmd_get_deck_status(param1);
  1150. break;
  1151. case SET_DECK_CONTROL_MODE:
  1152. cec_usrcmd_set_deck_cnt_mode(param1, param2);
  1153. break;
  1154. case SET_PLAY_MODE:
  1155. cec_usrcmd_set_play_mode(param1, param2);
  1156. break;
  1157. case GET_SYSTEM_AUDIO_MODE:
  1158. cec_usrcmd_get_system_audio_mode_status(param1);
  1159. break;
  1160. case GET_TUNER_DEV_STATUS:
  1161. cec_usrcmd_get_tuner_device_status(param1);
  1162. break;
  1163. case GET_AUDIO_STATUS:
  1164. cec_usrcmd_get_audio_status(param1);
  1165. break;
  1166. case GET_OSD_STRING:
  1167. break;
  1168. case GET_MENU_STATE:
  1169. cec_usrcmd_get_menu_state(param1);
  1170. break;
  1171. case SET_MENU_STATE:
  1172. cec_usrcmd_set_menu_state(param1, param2);
  1173. break;
  1174. case SET_MENU_LANGAGE:
  1175. cec_usrcmd_set_menu_language(param1, param2);
  1176. break;
  1177. case GET_MENU_LANGUAGE:
  1178. cec_usrcmd_get_menu_language(param1);
  1179. break;
  1180. case GET_ACTIVE_SOURCE:
  1181. cec_usrcmd_get_active_source();
  1182. break;
  1183. case SET_ACTIVE_SOURCE:
  1184. cec_usrcmd_set_active_source(param1);
  1185. break;
  1186. case SET_DEACTIVE_SOURCE:
  1187. cec_usrcmd_set_deactive_source(param1);
  1188. break;
  1189. case CLR_NODE_DEV_REAL_INFO_MASK:
  1190. cec_usrcmd_clear_node_dev_real_info_mask(param1, (((cec_info_mask)param2) << 24) |
  1191. (((cec_info_mask)param3) << 16) |
  1192. (((cec_info_mask)param4) << 8) |
  1193. ((cec_info_mask)param5));
  1194. break;
  1195. case SET_STREAM_PATH:
  1196. cec_usrcmd_set_stream_path(param1);
  1197. break;
  1198. default:
  1199. break;
  1200. }
  1201. }
  1202. /* cec high level code end */