hdmi_tx.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479
  1. /*
  2. * Amlogic M1
  3. * frame buffer driver-----------HDMI_TX
  4. * Copyright (C) 2010 Amlogic, Inc.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the named License,
  9. * or any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. */
  17. #define HDMI_DEBUG() printk("HDMI DEBUG: %s [%d]", __FUNCTION__, __LINE__)
  18. #ifndef AVOS
  19. #include <linux/version.h>
  20. #include <linux/module.h>
  21. #include <linux/types.h>
  22. #include <linux/kernel.h>
  23. #include <linux/kthread.h>
  24. #include <linux/delay.h>
  25. #include <linux/interrupt.h>
  26. #include <linux/fs.h>
  27. #include <linux/init.h>
  28. #include <linux/device.h>
  29. #include <linux/mm.h>
  30. #include <linux/major.h>
  31. #include <linux/platform_device.h>
  32. #include <linux/mutex.h>
  33. #include <linux/cdev.h>
  34. #include <linux/proc_fs.h>
  35. #include <asm/uaccess.h>
  36. #include <mach/am_regs.h>
  37. #include <linux/osd/osd_dev.h>
  38. #include <linux/switch.h>
  39. #else
  40. #include "includes.h"
  41. #include "os_internal.h"
  42. #include "os_cpu.h"
  43. #include "prf.h"
  44. #include "ioapi.h"
  45. #include <chipsupport/chipsupport.h>
  46. #include <os/extend/interrupt.h>
  47. #include <Drivers/include/peripheral_reg.h>
  48. #include <Drivers/include/isa_reg.h>
  49. #include <Drivers/include/mpeg_reg.h>
  50. #include <interrupt.h>
  51. #include "displaydev.h"
  52. #include "policy.h"
  53. typedef struct{
  54. char name[32];
  55. }vinfo_t;
  56. vinfo_t lvideo_info;
  57. #endif
  58. #include "hdmi_info_global.h"
  59. #include "hdmi_tx_cec.h"
  60. #include "hdmi_tx_module.h"
  61. #ifndef AVOS
  62. #define DEVICE_NAME "amhdmitx"
  63. #define HDMI_TX_COUNT 32
  64. #define HDMI_TX_POOL_NUM 6
  65. #define HDMI_TX_RESOURCE_NUM 4
  66. #ifdef DEBUG
  67. #define pr_dbg(fmt, args...) printk(KERN_DEBUG "amhdmitx: " fmt, ## args)
  68. #else
  69. #define pr_dbg(fmt, args...)
  70. #endif
  71. #define pr_error(fmt, args...) printk(KERN_ERR "amhdmitx: " fmt, ## args)
  72. static dev_t hdmitx_id;
  73. static struct class *hdmitx_class;
  74. static struct device *hdmitx_dev;
  75. #endif
  76. static hdmitx_dev_t hdmitx_device;
  77. static struct switch_dev sdev = { // android ics switch device
  78. .name = "hdmi",
  79. };
  80. //static HDMI_TX_INFO_t hdmi_info;
  81. #define INIT_FLAG_VDACOFF 0x1
  82. /* unplug powerdown */
  83. #define INIT_FLAG_POWERDOWN 0x2
  84. // HDMI CEC Function Flag
  85. #define INIT_FLAG_CEC_FUNC 0x4
  86. #define INIT_FLAG_NOT_LOAD 0x80
  87. #define HDMI_SINK_NO_EDID // For sink no edid case. If HDMI CTS, undef HDMI_SINK_NO_EDID
  88. #ifdef AVOS
  89. static unsigned char init_flag=INIT_FLAG_POWERDOWN;
  90. static unsigned char init_powermode=0x80;
  91. #else
  92. static unsigned char init_flag=0;
  93. static unsigned char init_powermode=0;
  94. #endif
  95. #undef DISABLE_AUDIO
  96. unsigned char hdmi_audio_off_flag = 0; //if set to 1, then HDMI will output no audio
  97. //In KTV case, HDMI output Picture only, and Audio is driven by other sources.
  98. static int hpdmode = 1; /*
  99. 0, do not unmux hpd when off or unplug ;
  100. 1, unmux hpd when unplug;
  101. 2, unmux hpd when unplug or off;
  102. */
  103. static int force_vout_index = 0;
  104. static int hdmi_prbs_mode = 0xffff; /* 0xffff=disable; 0=PRBS 11; 1=PRBS 15; 2=PRBS 7; 3=PRBS 31*/
  105. static int hdmi_480p_force_clk = 0; /* 200, 225, 250, 270 */
  106. #ifdef HDMI_SINK_NO_EDID
  107. static int force_output_mode = 0; // if 1, then output force without edid if 0, the with edid
  108. #endif
  109. static int hdmi_output_on = 1;
  110. static int hdmi_authenticated = -1;
  111. static int auth_output_auto_off = 0;
  112. /*****************************
  113. * hdmitx attr management :
  114. * enable
  115. * mode
  116. * reg
  117. ******************************/
  118. static void set_test_mode(void)
  119. {
  120. #ifdef ENABLE_TEST_MODE
  121. //when it is used as test source (PRBS and 20,22.5,25MHz)
  122. if((hdmi_480p_force_clk)&&
  123. ((hdmitx_device.cur_VIC==HDMI_480p60)||
  124. (hdmitx_device.cur_VIC==HDMI_480p60_16x9)||
  125. (hdmitx_device.cur_VIC==HDMI_480i60)||
  126. (hdmitx_device.cur_VIC==HDMI_480i60_16x9)||
  127. (hdmitx_device.cur_VIC==HDMI_576p50)||
  128. (hdmitx_device.cur_VIC==HDMI_576p50_16x9)||
  129. (hdmitx_device.cur_VIC==HDMI_576i50)||
  130. (hdmitx_device.cur_VIC==HDMI_576i50_16x9))
  131. ){
  132. if(hdmitx_device.HWOp.Cntl){
  133. hdmitx_device.HWOp.Cntl(&hdmitx_device, HDMITX_FORCE_480P_CLK, hdmi_480p_force_clk);
  134. }
  135. }
  136. if(hdmi_prbs_mode != 0xffff){
  137. if(hdmitx_device.HWOp.Cntl){
  138. hdmitx_device.HWOp.Cntl(&hdmitx_device, HDMITX_HWCMD_TURN_ON_PRBS, hdmi_prbs_mode);
  139. }
  140. }
  141. #endif
  142. }
  143. int get_cur_vout_index(void)
  144. /*
  145. return value: 1, vout; 2, vout2;
  146. */
  147. {
  148. int vout_index = 1;
  149. #ifdef CONFIG_AM_TV_OUTPUT2
  150. const vinfo_t *info;
  151. if(force_vout_index){
  152. vout_index = force_vout_index;
  153. }
  154. else{
  155. //VPU_VIU_VENC_MUX_CTRL
  156. // [ 3: 2] cntl_viu2_sel_venc. Select which one of the encI/P/T that VIU2 connects to:
  157. // 0=No connection, 1=ENCI, 2=ENCP, 3=ENCT.
  158. // [ 1: 0] cntl_viu1_sel_venc. Select which one of the encI/P/T that VIU1 connects to:
  159. // 0=No connection, 1=ENCI, 2=ENCP, 3=ENCT.
  160. int viu2_sel = (READ_MPEG_REG(VPU_VIU_VENC_MUX_CTRL)>>2)&0x3;
  161. int viu1_sel = READ_MPEG_REG(VPU_VIU_VENC_MUX_CTRL)&0x3;
  162. if(((viu2_sel==1)||(viu2_sel==2))&&
  163. (viu1_sel!=1)&&(viu1_sel!=2)){
  164. vout_index = 2;
  165. }
  166. }
  167. #endif
  168. return vout_index;
  169. }
  170. vinfo_t * hdmi_get_current_vinfo(void)
  171. {
  172. const vinfo_t *info;
  173. #ifdef CONFIG_AM_TV_OUTPUT2
  174. if(get_cur_vout_index() == 2){
  175. info = get_current_vinfo2();
  176. if(info == NULL){ //add to fix problem when dual display is not enabled in UI
  177. info = get_current_vinfo();
  178. }
  179. }
  180. else{
  181. info = get_current_vinfo();
  182. }
  183. #else
  184. info = get_current_vinfo();
  185. #endif
  186. return info;
  187. }
  188. static int set_disp_mode(const char *mode)
  189. {
  190. int ret=-1;
  191. HDMI_Video_Codes_t vic;
  192. #ifndef HDMI_SINK_NO_EDID
  193. vic = hdmitx_edid_get_VIC(&hdmitx_device, mode, 1);
  194. #else
  195. if(force_output_mode){
  196. vic = hdmitx_get_VIC(&hdmitx_device, mode);
  197. }
  198. else{
  199. vic = hdmitx_edid_get_VIC(&hdmitx_device, mode, 1);
  200. }
  201. #endif
  202. if(vic != HDMI_Unkown){
  203. hdmitx_device.mux_hpd_if_pin_high_flag = 1;
  204. if(hdmitx_device.vic_count == 0){
  205. if(hdmitx_device.unplug_powerdown){
  206. return 0;
  207. }
  208. }
  209. }
  210. hdmitx_device.cur_VIC = HDMI_Unkown;
  211. ret = hdmitx_set_display(&hdmitx_device, vic);
  212. if(ret>=0){
  213. hdmitx_device.cur_VIC = vic;
  214. hdmitx_device.audio_param_update_flag = 1;
  215. hdmi_authenticated = -1;
  216. hdmitx_device.auth_process_timer = AUTH_PROCESS_TIME;
  217. set_test_mode();
  218. }
  219. if(hdmitx_device.cur_VIC == HDMI_Unkown){
  220. if(hpdmode == 2){
  221. hdmitx_edid_clear(&hdmitx_device); /* edid will be read again when hpd is muxed and it is high */
  222. hdmitx_device.mux_hpd_if_pin_high_flag = 0;
  223. }
  224. if(hdmitx_device.HWOp.Cntl){
  225. hdmitx_device.HWOp.Cntl(&hdmitx_device, HDMITX_HWCMD_TURNOFF_HDMIHW, (hpdmode==2)?1:0);
  226. }
  227. }
  228. return ret;
  229. }
  230. static int set_disp_mode_auto(void)
  231. {
  232. int ret=-1;
  233. #ifndef AVOS
  234. const vinfo_t *info = hdmi_get_current_vinfo();
  235. #else
  236. vinfo_t* info=&lvideo_info;
  237. #endif
  238. HDMI_Video_Codes_t vic; //Prevent warning
  239. //msleep(500);
  240. #ifndef HDMI_SINK_NO_EDID
  241. vic = hdmitx_edid_get_VIC(&hdmitx_device, info->name, (hdmitx_device.disp_switch_config==DISP_SWITCH_FORCE)?1:0);
  242. #else
  243. if(force_output_mode){
  244. vic = hdmitx_get_VIC(&hdmitx_device, info->name);
  245. }
  246. else{
  247. vic = hdmitx_edid_get_VIC(&hdmitx_device, info->name, (hdmitx_device.disp_switch_config==DISP_SWITCH_FORCE)?1:0);
  248. }
  249. #endif
  250. vic = hdmitx_edid_get_VIC(&hdmitx_device, info->name, (hdmitx_device.disp_switch_config==DISP_SWITCH_FORCE)?1:0);
  251. hdmitx_device.cur_VIC = HDMI_Unkown;
  252. ret = hdmitx_set_display(&hdmitx_device, vic); //if vic is HDMI_Unkown, hdmitx_set_display will disable HDMI
  253. if(ret>=0){
  254. hdmitx_device.cur_VIC = vic;
  255. hdmitx_device.audio_param_update_flag = 1;
  256. hdmi_authenticated = -1;
  257. hdmitx_device.auth_process_timer = AUTH_PROCESS_TIME;
  258. set_test_mode();
  259. }
  260. if(hdmitx_device.cur_VIC == HDMI_Unkown){
  261. if(hpdmode==2){
  262. hdmitx_edid_clear(&hdmitx_device); /* edid will be read again when hpd is muxed and it is high */
  263. hdmitx_device.mux_hpd_if_pin_high_flag = 0;
  264. }
  265. if(hdmitx_device.HWOp.Cntl){
  266. hdmitx_device.HWOp.Cntl(&hdmitx_device, HDMITX_HWCMD_TURNOFF_HDMIHW, (hpdmode==2)?1:0);
  267. }
  268. }
  269. return ret;
  270. }
  271. static unsigned char is_dispmode_valid_for_hdmi(void)
  272. {
  273. HDMI_Video_Codes_t vic;
  274. #ifndef AVOS
  275. const vinfo_t *info = hdmi_get_current_vinfo();
  276. #else
  277. vinfo_t* info=&lvideo_info;
  278. #endif
  279. #ifndef HDMI_SINK_NO_EDID
  280. vic = hdmitx_edid_get_VIC(&hdmitx_device, info->name, (hdmitx_device.disp_switch_config==DISP_SWITCH_FORCE)?1:0);
  281. #else
  282. if(force_output_mode){
  283. vic = hdmitx_get_VIC(&hdmitx_device, info->name);
  284. }
  285. else{
  286. vic = hdmitx_edid_get_VIC(&hdmitx_device, info->name, (hdmitx_device.disp_switch_config==DISP_SWITCH_FORCE)?1:0);
  287. }
  288. #endif
  289. return (vic != HDMI_Unkown);
  290. }
  291. #ifndef AVOS
  292. /*disp_mode attr*/
  293. static ssize_t show_disp_mode(struct device * dev, struct device_attribute *attr, char * buf)
  294. {
  295. int pos=0;
  296. pos+=snprintf(buf+pos, PAGE_SIZE, "VIC:%d\r\n", hdmitx_device.cur_VIC);
  297. return pos;
  298. }
  299. static ssize_t store_disp_mode(struct device * dev, struct device_attribute *attr, const char * buf, size_t count)
  300. {
  301. set_disp_mode(buf);
  302. return 16;
  303. }
  304. /*cec attr*/
  305. static ssize_t show_cec(struct device * dev, struct device_attribute *attr, char * buf)
  306. {
  307. ssize_t t = cec_usrcmd_get_global_info(buf);
  308. return t;
  309. }
  310. static ssize_t store_cec(struct device * dev, struct device_attribute *attr, const char * buf, size_t count)
  311. {
  312. cec_usrcmd_set_dispatch(buf, count);
  313. return count;
  314. }
  315. /*aud_mode attr*/
  316. static ssize_t show_aud_mode(struct device * dev, struct device_attribute *attr, char * buf)
  317. {
  318. return 0;
  319. }
  320. static ssize_t store_aud_mode(struct device * dev, struct device_attribute *attr, const char * buf, size_t count)
  321. {
  322. //set_disp_mode(buf);
  323. Hdmi_tx_audio_para_t* audio_param = &(hdmitx_device.cur_audio_param);
  324. if(strncmp(buf, "32k", 3)==0){
  325. audio_param->sample_rate = FS_32K;
  326. }
  327. else if(strncmp(buf, "44.1k", 5)==0){
  328. audio_param->sample_rate = FS_44K1;
  329. }
  330. else if(strncmp(buf, "48k", 3)==0){
  331. audio_param->sample_rate = FS_48K;
  332. }
  333. else{
  334. hdmitx_device.force_audio_flag = 0;
  335. return count;
  336. }
  337. audio_param->type = CT_PCM;
  338. audio_param->channel_num = CC_2CH;
  339. audio_param->sample_size = SS_16BITS;
  340. hdmitx_device.audio_param_update_flag = 1;
  341. hdmitx_device.force_audio_flag = 1;
  342. return count;
  343. }
  344. /*edid attr*/
  345. static ssize_t show_edid(struct device *dev, struct device_attribute *attr, char *buf)
  346. {
  347. return hdmitx_edid_dump(&hdmitx_device, buf, PAGE_SIZE);
  348. }
  349. static ssize_t store_edid(struct device * dev, struct device_attribute *attr, const char * buf, size_t count)
  350. {
  351. if(buf[0]=='d'){
  352. int ii,jj;
  353. int block_idx;
  354. block_idx=simple_strtoul(buf+1,NULL,16);
  355. if(block_idx<EDID_MAX_BLOCK){
  356. for(ii=0;ii<8;ii++){
  357. for(jj=0;jj<16;jj++){
  358. printk("%02x ",hdmitx_device.EDID_buf[block_idx*128+ii*16+jj]);
  359. }
  360. printk("\n");
  361. }
  362. printk("\n");
  363. }
  364. }
  365. return 16;
  366. }
  367. /*config attr*/
  368. static ssize_t show_config(struct device * dev, struct device_attribute *attr, char * buf)
  369. {
  370. int pos=0;
  371. pos += snprintf(buf+pos, PAGE_SIZE, "disp switch (force or edid): %s\r\n", (hdmitx_device.disp_switch_config==DISP_SWITCH_FORCE)?"force":"edid");
  372. return pos;
  373. }
  374. static ssize_t store_config(struct device * dev, struct device_attribute *attr, const char * buf, size_t count)
  375. {
  376. if(strncmp(buf, "force", 5)==0){
  377. hdmitx_device.disp_switch_config=DISP_SWITCH_FORCE;
  378. }
  379. else if(strncmp(buf, "edid", 4)==0){
  380. hdmitx_device.disp_switch_config=DISP_SWITCH_EDID;
  381. }
  382. else if(strncmp(buf, "vdacoff", 7)==0){
  383. if(hdmitx_device.HWOp.Cntl){
  384. hdmitx_device.HWOp.Cntl(&hdmitx_device, HDMITX_HWCMD_VDAC_OFF, 0);
  385. }
  386. }
  387. else if(strncmp(buf, "powermode", 9)==0){
  388. int tmp;
  389. tmp = simple_strtoul(buf+9,NULL,10);
  390. if(hdmitx_device.HWOp.Cntl){
  391. hdmitx_device.HWOp.Cntl(&hdmitx_device, HDMITX_HWCMD_POWERMODE_SWITCH, tmp);
  392. printk("hdmi: set powermode %d\n", tmp);
  393. }
  394. }
  395. else if(strncmp(buf, "unplug_powerdown", 16) == 0){
  396. if(buf[16] == '0'){
  397. hdmitx_device.unplug_powerdown = 0;
  398. }
  399. else{
  400. hdmitx_device.unplug_powerdown = 1;
  401. }
  402. }
  403. else if(strncmp(buf, "3d", 2)==0){
  404. if(strncmp(buf+2, "tb", 2)==0){
  405. hdmi_set_3d(&hdmitx_device, 6, 0);
  406. }
  407. else if(strncmp(buf+2, "lr", 2)==0){
  408. int sub_sample_mode=0;
  409. if(buf[2])
  410. sub_sample_mode = simple_strtoul(buf+2,NULL,10);
  411. hdmi_set_3d(&hdmitx_device, 8, sub_sample_mode); //side by side
  412. }
  413. else if(strncmp(buf+2, "off", 3)==0){
  414. hdmi_set_3d(&hdmitx_device, 0xf, 0);
  415. }
  416. }
  417. return 16;
  418. }
  419. static ssize_t store_dbg(struct device * dev, struct device_attribute *attr, const char * buf, size_t count)
  420. {
  421. hdmitx_device.HWOp.DebugFun(&hdmitx_device, buf);
  422. return 16;
  423. }
  424. /**/
  425. static ssize_t show_disp_cap(struct device * dev, struct device_attribute *attr, char * buf)
  426. {
  427. int i,pos=0;
  428. char* disp_mode_t[]={"480i","480p","576i","576p","720p","1080i","1080p","720p50hz","1080i50hz","1080p50hz",NULL};
  429. char* native_disp_mode = hdmitx_edid_get_native_VIC(&hdmitx_device);
  430. HDMI_Video_Codes_t vic;
  431. #ifdef HDMI_SINK_NO_EDID
  432. if(force_output_mode){
  433. pos += snprintf(buf+pos, PAGE_SIZE,"null edid\n");
  434. }
  435. else{
  436. #endif
  437. for(i=0; disp_mode_t[i]; i++){
  438. vic = hdmitx_edid_get_VIC(&hdmitx_device, disp_mode_t[i], 0);
  439. if( vic != HDMI_Unkown){
  440. pos += snprintf(buf+pos, PAGE_SIZE,"%s",disp_mode_t[i]);
  441. if(native_disp_mode&&(strcmp(native_disp_mode, disp_mode_t[i])==0)){
  442. pos += snprintf(buf+pos, PAGE_SIZE,"*\n");
  443. }
  444. else{
  445. pos += snprintf(buf+pos, PAGE_SIZE,"\n");
  446. }
  447. }
  448. }
  449. #ifdef HDMI_SINK_NO_EDID
  450. }
  451. #endif
  452. return pos;
  453. }
  454. static ssize_t show_hpd_state(struct device * dev, struct device_attribute *attr, char * buf)
  455. {
  456. int i,pos=0;
  457. pos += snprintf(buf+pos, PAGE_SIZE,"%d", hdmitx_device.hpd_state);
  458. return pos;
  459. }
  460. static unsigned char* hdmi_log_buf=NULL;
  461. static unsigned int hdmi_log_wr_pos=0;
  462. static unsigned int hdmi_log_rd_pos=0;
  463. static unsigned int hdmi_log_buf_size=0;
  464. static DEFINE_SPINLOCK(hdmi_print_lock);
  465. #define PRINT_TEMP_BUF_SIZE 512
  466. int hdmi_print_buf(char* buf, int len)
  467. {
  468. unsigned long flags;
  469. int pos;
  470. int hdmi_log_rd_pos_;
  471. if(hdmi_log_buf_size==0)
  472. return 0;
  473. spin_lock_irqsave(&hdmi_print_lock, flags);
  474. hdmi_log_rd_pos_=hdmi_log_rd_pos;
  475. if(hdmi_log_wr_pos>=hdmi_log_rd_pos)
  476. hdmi_log_rd_pos_+=hdmi_log_buf_size;
  477. for(pos=0;pos<len && hdmi_log_wr_pos<(hdmi_log_rd_pos_-1);pos++,hdmi_log_wr_pos++){
  478. if(hdmi_log_wr_pos>=hdmi_log_buf_size)
  479. hdmi_log_buf[hdmi_log_wr_pos-hdmi_log_buf_size]=buf[pos];
  480. else
  481. hdmi_log_buf[hdmi_log_wr_pos]=buf[pos];
  482. }
  483. if(hdmi_log_wr_pos>=hdmi_log_buf_size)
  484. hdmi_log_wr_pos-=hdmi_log_buf_size;
  485. spin_unlock_irqrestore(&hdmi_print_lock, flags);
  486. return pos;
  487. }
  488. int hdmi_print(int printk_flag, const char *fmt, ...)
  489. {
  490. va_list args;
  491. int avail = PRINT_TEMP_BUF_SIZE;
  492. char buf[PRINT_TEMP_BUF_SIZE];
  493. int pos,len=0;
  494. if(printk_flag){
  495. va_start(args, fmt);
  496. vprintk(fmt, args);
  497. va_end(args);
  498. }
  499. if(hdmi_log_buf_size==0)
  500. return 0;
  501. va_start(args, fmt);
  502. len += vsnprintf(buf+len, avail-len, fmt, args);
  503. va_end(args);
  504. if ((avail-len) <= 0) {
  505. buf[PRINT_TEMP_BUF_SIZE - 1] = '\0';
  506. }
  507. pos = hdmi_print_buf(buf, len);
  508. //printk("hdmi_print:%d %d\n", hdmi_log_wr_pos, hdmi_log_rd_pos);
  509. return pos;
  510. }
  511. static ssize_t show_log(struct device * dev, struct device_attribute *attr, char * buf)
  512. {
  513. unsigned long flags;
  514. int read_size=0;
  515. if(hdmi_log_buf_size==0)
  516. return 0;
  517. //printk("show_log:%d %d\n", hdmi_log_wr_pos, hdmi_log_rd_pos);
  518. spin_lock_irqsave(&hdmi_print_lock, flags);
  519. if(hdmi_log_rd_pos<hdmi_log_wr_pos){
  520. read_size = hdmi_log_wr_pos-hdmi_log_rd_pos;
  521. }
  522. else if(hdmi_log_rd_pos>hdmi_log_wr_pos){
  523. read_size = hdmi_log_buf_size-hdmi_log_rd_pos;
  524. }
  525. if(read_size>PAGE_SIZE)
  526. read_size=PAGE_SIZE;
  527. if(read_size>0)
  528. memcpy(buf, hdmi_log_buf+hdmi_log_rd_pos, read_size);
  529. hdmi_log_rd_pos += read_size;
  530. if(hdmi_log_rd_pos>=hdmi_log_buf_size)
  531. hdmi_log_rd_pos = 0;
  532. spin_unlock_irqrestore(&hdmi_print_lock, flags);
  533. return read_size;
  534. }
  535. static ssize_t store_log(struct device * dev, struct device_attribute *attr, const char * buf, size_t count)
  536. {
  537. int tmp;
  538. unsigned long flags;
  539. if(strncmp(buf, "bufsize", 7)==0){
  540. tmp = simple_strtoul(buf+7,NULL,10);
  541. spin_lock_irqsave(&hdmi_print_lock, flags);
  542. if(tmp==0){
  543. if(hdmi_log_buf){
  544. kfree(hdmi_log_buf);
  545. hdmi_log_buf=NULL;
  546. hdmi_log_buf_size=0;
  547. hdmi_log_rd_pos=0;
  548. hdmi_log_wr_pos=0;
  549. }
  550. }
  551. if((tmp>=1024)&&(hdmi_log_buf==NULL)){
  552. hdmi_log_buf_size=0;
  553. hdmi_log_rd_pos=0;
  554. hdmi_log_wr_pos=0;
  555. hdmi_log_buf=kmalloc(tmp, GFP_KERNEL);
  556. if(hdmi_log_buf){
  557. hdmi_log_buf_size=tmp;
  558. hdmitx_device.HWOp.DebugFun(&hdmitx_device, "v");
  559. }
  560. }
  561. spin_unlock_irqrestore(&hdmi_print_lock, flags);
  562. //printk("hdmi_store:set bufsize tmp %d %d\n",tmp, hdmi_log_buf_size);
  563. }
  564. else{
  565. hdmi_print(0, "%s", buf);
  566. }
  567. return 16;
  568. }
  569. static DEVICE_ATTR(disp_mode, S_IWUSR | S_IRUGO, show_disp_mode, store_disp_mode);
  570. static DEVICE_ATTR(aud_mode, S_IWUSR | S_IRUGO, show_aud_mode, store_aud_mode);
  571. static DEVICE_ATTR(edid, S_IWUSR | S_IRUGO, show_edid, store_edid);
  572. static DEVICE_ATTR(config, S_IWUSR | S_IRUGO, show_config, store_config);
  573. static DEVICE_ATTR(debug, S_IWUSR | S_IRUGO, NULL, store_dbg);
  574. static DEVICE_ATTR(disp_cap, S_IWUSR | S_IRUGO, show_disp_cap, NULL);
  575. static DEVICE_ATTR(hpd_state, S_IWUSR | S_IRUGO, show_hpd_state, NULL);
  576. static DEVICE_ATTR(log, S_IWUSR | S_IRUGO, show_log, store_log);
  577. static DEVICE_ATTR(cec, S_IWUSR | S_IRUGO, show_cec, store_cec);
  578. /*****************************
  579. * hdmitx display client interface
  580. *
  581. ******************************/
  582. static int hdmitx_notify_callback_v(struct notifier_block *block, unsigned long cmd , void *para)
  583. {
  584. if(get_cur_vout_index()!=1)
  585. return 0;
  586. if (cmd != VOUT_EVENT_MODE_CHANGE)
  587. return 0;
  588. if(hdmitx_device.vic_count == 0){
  589. if(is_dispmode_valid_for_hdmi()){
  590. hdmitx_device.mux_hpd_if_pin_high_flag = 1;
  591. if(hdmitx_device.unplug_powerdown){
  592. return 0;
  593. }
  594. }
  595. }
  596. set_disp_mode_auto();
  597. return 0;
  598. }
  599. #ifdef CONFIG_AM_TV_OUTPUT2
  600. static int hdmitx_notify_callback_v2(struct notifier_block *block, unsigned long cmd , void *para)
  601. {
  602. if(get_cur_vout_index()!=2)
  603. return 0;
  604. if (cmd != VOUT_EVENT_MODE_CHANGE)
  605. return 0;
  606. if(hdmitx_device.vic_count == 0){
  607. if(is_dispmode_valid_for_hdmi()){
  608. hdmitx_device.mux_hpd_if_pin_high_flag = 1;
  609. if(hdmitx_device.unplug_powerdown){
  610. return 0;
  611. }
  612. }
  613. }
  614. set_disp_mode_auto();
  615. return 0;
  616. }
  617. #endif
  618. static struct notifier_block hdmitx_notifier_nb_v = {
  619. .notifier_call = hdmitx_notify_callback_v,
  620. };
  621. #ifdef CONFIG_AM_TV_OUTPUT2
  622. static struct notifier_block hdmitx_notifier_nb_v2 = {
  623. .notifier_call = hdmitx_notify_callback_v2,
  624. };
  625. #endif
  626. #ifndef DISABLE_AUDIO
  627. #define AOUT_EVENT_PREPARE 0x1
  628. #define AOUT_EVENT_RAWDATA_AC_3 0x2
  629. #define AOUT_EVENT_RAWDATA_DTS 0x3
  630. extern int aout_register_client(struct notifier_block * ) ;
  631. extern int aout_unregister_client(struct notifier_block * ) ;
  632. #include <linux/soundcard.h>
  633. #include <sound/core.h>
  634. #include <sound/pcm.h>
  635. #include <sound/initval.h>
  636. #include <sound/control.h>
  637. static int hdmitx_notify_callback_a(struct notifier_block *block, unsigned long cmd , void *para)
  638. {
  639. struct snd_pcm_substream *substream =(struct snd_pcm_substream*)para;
  640. Hdmi_tx_audio_para_t* audio_param = &(hdmitx_device.cur_audio_param);
  641. switch (cmd){
  642. case AOUT_EVENT_PREPARE:
  643. audio_param->type = CT_PCM;
  644. audio_param->channel_num = CC_2CH;
  645. audio_param->sample_size = SS_16BITS;
  646. switch (substream->runtime->rate) {
  647. case 192000:
  648. audio_param->sample_rate = FS_192K;
  649. break;
  650. case 176400:
  651. audio_param->sample_rate = FS_176K4;
  652. break;
  653. case 96000:
  654. audio_param->sample_rate = FS_96K;
  655. break;
  656. case 88200:
  657. audio_param->sample_rate = FS_88K2;
  658. break;
  659. case 48000:
  660. audio_param->sample_rate = FS_48K;
  661. break;
  662. case 44100:
  663. audio_param->sample_rate = FS_44K1;
  664. break;
  665. case 32000:
  666. audio_param->sample_rate = FS_32K;
  667. break;
  668. default:
  669. break;
  670. }
  671. hdmi_print(1, "HDMI: aout notify rate %d\n", substream->runtime->rate);
  672. hdmi_print(1, "HDMI: aout notify format PCM\n");
  673. hdmitx_device.audio_param_update_flag = 1;
  674. return 0;
  675. case AOUT_EVENT_RAWDATA_AC_3:
  676. audio_param->type = CT_AC_3;
  677. audio_param->channel_num = CC_2CH;
  678. audio_param->sample_size = SS_16BITS;
  679. hdmi_print(1, "HDMI: aout notify format AC-3\n");
  680. hdmitx_device.audio_param_update_flag = 1;
  681. return 0;
  682. case AOUT_EVENT_RAWDATA_DTS:
  683. audio_param->type = CT_DTS;
  684. audio_param->channel_num = CC_2CH;
  685. audio_param->sample_size = SS_16BITS;
  686. hdmi_print(1, "HDMI: aout notify format DTS\n");
  687. hdmitx_device.audio_param_update_flag = 1;
  688. return 0;
  689. default:
  690. return -1;
  691. }
  692. }
  693. static struct notifier_block hdmitx_notifier_nb_a = {
  694. .notifier_call = hdmitx_notify_callback_a,
  695. };
  696. #endif
  697. #else
  698. /* AVOS */
  699. typedef void(*set_tv_enc_post_fun_t)(char* mode);
  700. extern set_tv_enc_post_fun_t tv_tv_enc_post_fun;
  701. Hdmi_tx_video_para_t *hdmi_get_video_param(HDMI_Video_Codes_t VideoCode);
  702. void hdmi_tvenc_set(Hdmi_tx_video_para_t *param);
  703. void hdmi_tv_enc_post_func(char* mode)
  704. {
  705. strcpy(lvideo_info.name, mode);
  706. if(hdmitx_device.vic_count == 0){
  707. if(is_dispmode_valid_for_hdmi()){
  708. hdmitx_device.mux_hpd_if_pin_high_flag = 1;
  709. if(hdmitx_device.unplug_powerdown){
  710. return;
  711. }
  712. }
  713. }
  714. set_disp_mode_auto();
  715. }
  716. int hdmi_audio_post_func(int type, int channel, int sample_size, int rate)
  717. {
  718. Hdmi_tx_audio_para_t* audio_param = &(hdmitx_device.cur_audio_param);
  719. audio_param->type = CT_PCM;
  720. audio_param->channel_num = CC_2CH;
  721. audio_param->sample_size = SS_16BITS;
  722. switch (rate) {
  723. case 192000:
  724. audio_param->sample_rate = FS_192K;
  725. break;
  726. case 176400:
  727. audio_param->sample_rate = FS_176K4;
  728. break;
  729. case 96000:
  730. audio_param->sample_rate = FS_96K;
  731. break;
  732. case 88200:
  733. audio_param->sample_rate = FS_88K2;
  734. break;
  735. case 48000:
  736. audio_param->sample_rate = FS_48K;
  737. break;
  738. case 44100:
  739. audio_param->sample_rate = FS_44K1;
  740. break;
  741. case 32000:
  742. audio_param->sample_rate = FS_32K;
  743. break;
  744. default:
  745. break;
  746. }
  747. hdmitx_device.audio_param_update_flag = 1;
  748. hdmi_print(1, "HDMI: aout notify rate %d\n", rate);
  749. return 0;
  750. }
  751. #endif
  752. /******************************
  753. * hdmitx kernel task
  754. *******************************/
  755. #ifndef AVOS
  756. static int
  757. #else
  758. static void
  759. #endif
  760. hdmi_task_handle(void *data)
  761. {
  762. extern void hdmitx_edid_ram_buffer_clear(hdmitx_dev_t*);
  763. hdmitx_dev_t* hdmitx_device = (hdmitx_dev_t*)data;
  764. hdmitx_init_parameters(&hdmitx_device->hdmi_info);
  765. HDMITX_M1B_Init(hdmitx_device);
  766. //When init hdmi, clear the hdmitx module edid ram and edid buffer.
  767. hdmitx_edid_ram_buffer_clear(hdmitx_device);
  768. hdmitx_device->HWOp.SetupIRQ(hdmitx_device);
  769. if(hdmitx_device->HWOp.Cntl){
  770. if(init_flag&INIT_FLAG_VDACOFF){
  771. hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_HWCMD_VDAC_OFF, 0);
  772. }
  773. if(init_powermode&0x80){
  774. hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_HWCMD_POWERMODE_SWITCH, init_powermode&0x1f);
  775. }
  776. }
  777. if(init_flag&INIT_FLAG_POWERDOWN){
  778. hdmitx_device->HWOp.SetDispMode(NULL); //power down
  779. hdmitx_device->unplug_powerdown=1;
  780. if(hdmitx_device->HWOp.Cntl){
  781. hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_HWCMD_TURNOFF_HDMIHW, (hpdmode!=0)?1:0);
  782. }
  783. }
  784. else{
  785. if(hdmitx_device->HWOp.Cntl){
  786. hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_HWCMD_MUX_HPD, 0);
  787. }
  788. }
  789. HDMI_DEBUG();
  790. while (hdmitx_device->hpd_event != 0xff)
  791. {
  792. if((hdmitx_device->vic_count == 0)&&(hdmitx_device->mux_hpd_if_pin_high_flag)){
  793. if(hdmitx_device->HWOp.Cntl){
  794. hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_HWCMD_MUX_HPD_IF_PIN_HIGH, 0);
  795. }
  796. }
  797. if((!hdmi_audio_off_flag)&&(hdmitx_device->audio_param_update_flag)&&
  798. ((hdmitx_device->cur_VIC != HDMI_Unkown)||(hdmitx_device->force_audio_flag))){
  799. hdmitx_set_audio(hdmitx_device, &(hdmitx_device->cur_audio_param));
  800. hdmitx_device->audio_param_update_flag = 0;
  801. hdmi_print(1, "HDMI: set audio param\n");
  802. }
  803. if (hdmitx_device->hpd_event == 1)
  804. {
  805. #ifdef HDMI_SINK_NO_EDID
  806. msleep(500);
  807. #endif
  808. if(hdmitx_device->HWOp.GetEDIDData(hdmitx_device)){
  809. hdmi_print(1,"HDMI: EDID Ready\n");
  810. hdmitx_edid_clear(hdmitx_device);
  811. hdmitx_edid_parse(hdmitx_device);
  812. cec_node_init(hdmitx_device);
  813. #ifdef HDMI_SINK_NO_EDID
  814. force_output_mode = 0;
  815. #endif
  816. set_disp_mode_auto();
  817. switch_set_state(&sdev, 1);
  818. hdmitx_device->hpd_event = 0;
  819. }
  820. #ifdef HDMI_SINK_NO_EDID
  821. else{
  822. hdmi_print(1,"HDMI: EDID Bad\n");
  823. force_output_mode = 1;
  824. set_disp_mode_auto();
  825. switch_set_state(&sdev, 1);
  826. hdmitx_device->hpd_event = 0;
  827. }
  828. #endif
  829. hdmitx_device->hpd_state = 1;
  830. }
  831. else if(hdmitx_device->hpd_event == 2)
  832. {
  833. //When unplug hdmi, clear the hdmitx module edid ram and edid buffer.
  834. hdmitx_edid_ram_buffer_clear(hdmitx_device);
  835. hdmitx_edid_clear(hdmitx_device);
  836. cec_node_uninit(hdmitx_device);
  837. if(hdmitx_device->unplug_powerdown){
  838. hdmitx_set_display(hdmitx_device, HDMI_Unkown);
  839. if(hdmitx_device->HWOp.Cntl){
  840. hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_HWCMD_TURNOFF_HDMIHW, (hpdmode!=0)?1:0);
  841. }
  842. }
  843. hdmitx_device->cur_VIC = HDMI_Unkown;
  844. hdmi_authenticated = -1;
  845. switch_set_state(&sdev, 0);
  846. hdmitx_device->hpd_event = 0;
  847. hdmitx_device->hpd_state = 0;
  848. }
  849. else{
  850. }
  851. /* authentication process */
  852. #ifdef CONFIG_AML_HDMI_TX_HDCP
  853. if(hdmitx_device->cur_VIC != HDMI_Unkown){
  854. if(hdmitx_device->auth_process_timer>0){
  855. hdmitx_device->auth_process_timer--;
  856. }
  857. else{
  858. hdmi_authenticated = hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_GET_AUTHENTICATE_STATE, NULL);
  859. if(auth_output_auto_off){
  860. if(hdmi_authenticated){
  861. hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_OUTPUT_ENABLE, 1);
  862. }
  863. else{
  864. hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_OUTPUT_ENABLE, 0);
  865. }
  866. }
  867. else{
  868. hdmitx_device->HWOp.Cntl(hdmitx_device, HDMITX_OUTPUT_ENABLE, hdmi_output_on);
  869. }
  870. }
  871. }
  872. #endif
  873. /**/
  874. HDMI_PROCESS_DELAY;
  875. }
  876. #ifndef AVOS
  877. return 0;
  878. #endif
  879. }
  880. #ifdef AVOS
  881. #define PRINT_TEMP_BUF_SIZE 256
  882. int hdmi_print_buf(char* buf, int len)
  883. {
  884. if(AVOS_Print_Flag&DBGHLP_LOG_HDMI){
  885. AVOS_printf("%s", buf);
  886. }
  887. return 0;
  888. }
  889. int hdmi_print(int printk_flag, const char *fmt, ...)
  890. {
  891. va_list args;
  892. int avail = PRINT_TEMP_BUF_SIZE;
  893. char buf[PRINT_TEMP_BUF_SIZE];
  894. int pos,len=0;
  895. /*
  896. if(printk_flag){
  897. va_start(args, fmt);
  898. vprintk(fmt, args);
  899. va_end(args);
  900. }
  901. if(hdmi_log_buf_size==0)
  902. return 0;
  903. */
  904. va_start(args, fmt);
  905. len += vsnprintf(buf+len, avail-len, fmt, args);
  906. va_end(args);
  907. if ((avail-len) <= 0) {
  908. buf[PRINT_TEMP_BUF_SIZE - 1] = '\0';
  909. }
  910. if(printk_flag){
  911. AVOS_printf("%s", buf);
  912. }
  913. else{
  914. pos = hdmi_print_buf(buf, len);
  915. }
  916. //printk("hdmi_print:%d %d\n", hdmi_log_wr_pos, hdmi_log_rd_pos);
  917. return pos;
  918. }
  919. #define HDMI_OP_STK_SIZE (512)
  920. #define HDMI_OP_STK_SIZE_IN_BYTE (HDMI_OP_STK_SIZE * 4)
  921. #define HDMI_OP_TASK_PRI (20) //(19)
  922. #define DRIVER_NAME "/dev/hdmi"
  923. avfs_device_driver hdmi_init(avfs_device_major_number major, avfs_device_minor_number minor, void *arg)
  924. {
  925. avfs_status_code status;
  926. status = avfs_io_register_name(
  927. DRIVER_NAME,
  928. major,
  929. (avfs_device_minor_number) 0
  930. );
  931. HDMI_DEBUG();
  932. memset(&hdmitx_device, 0, sizeof(hdmitx_dev_t));
  933. strcpy(lvideo_info.name, "");
  934. hdmitx_device.vic_count=0;
  935. if((init_flag&INIT_FLAG_POWERDOWN)&&(hpdmode==2)){
  936. hdmitx_device.mux_hpd_if_pin_high_flag=0;
  937. }
  938. else{
  939. hdmitx_device.mux_hpd_if_pin_high_flag=1;
  940. }
  941. hdmitx_device.audio_param_update_flag=0;
  942. tv_tv_enc_post_fun = hdmi_tv_enc_post_func;
  943. hdmitx_device.taskstack = (OS_STK*) AVMem_malloc(HDMI_OP_STK_SIZE_IN_BYTE);
  944. AVTaskCreate(hdmi_task_handle, (void *)(&hdmitx_device), &hdmitx_device.taskstack[HDMI_OP_STK_SIZE - 1], HDMI_OP_TASK_PRI, &hdmitx_device.task_id);
  945. #if OS_TASK_STACKCHK_EN > 0
  946. AVTaskSetStackSize(hdmitx_device.task_id, HDMI_OP_STK_SIZE * sizeof(OS_STK));
  947. #endif
  948. return AVFS_SUCCESSFUL;
  949. }
  950. avfs_device_driver hdmi_open(avfs_device_major_number major, avfs_device_minor_number minor, void *arg)
  951. {
  952. return AVFS_SUCCESSFUL;
  953. }
  954. avfs_device_driver hdmi_close(avfs_device_major_number major, avfs_device_minor_number minor, void *arg)
  955. {
  956. return AVFS_SUCCESSFUL;
  957. }
  958. avfs_device_driver hdmi_read(avfs_device_major_number major, avfs_device_minor_number minor, void *arg)
  959. {
  960. return AVFS_SUCCESSFUL;
  961. }
  962. avfs_device_driver hdmi_write(avfs_device_major_number major, avfs_device_minor_number minor, void *arg)
  963. {
  964. return AVFS_SUCCESSFUL;
  965. }
  966. avfs_device_driver hdmi_ioctl(avfs_device_major_number major, avfs_device_minor_number minor, void *arg)
  967. {
  968. return AVFS_NOT_IMPLEMENTED;
  969. }
  970. #else
  971. /* Linux */
  972. /*****************************
  973. * hdmitx driver file_operations
  974. *
  975. ******************************/
  976. static int amhdmitx_open(struct inode *node, struct file *file)
  977. {
  978. hdmitx_dev_t *hdmitx_in_devp;
  979. /* Get the per-device structure that contains this cdev */
  980. hdmitx_in_devp = container_of(node->i_cdev, hdmitx_dev_t, cdev);
  981. file->private_data = hdmitx_in_devp;
  982. return 0;
  983. }
  984. static int amhdmitx_release(struct inode *node, struct file *file)
  985. {
  986. //hdmitx_dev_t *hdmitx_in_devp = file->private_data;
  987. /* Reset file pointer */
  988. /* Release some other fields */
  989. /* ... */
  990. return 0;
  991. }
  992. static int amhdmitx_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long args)
  993. {
  994. int r = 0;
  995. switch (cmd) {
  996. default:
  997. break;
  998. }
  999. return r;
  1000. }
  1001. const static struct file_operations amhdmitx_fops = {
  1002. .owner = THIS_MODULE,
  1003. .open = amhdmitx_open,
  1004. .release = amhdmitx_release,
  1005. // .ioctl = amhdmitx_ioctl,
  1006. };
  1007. static int amhdmitx_probe(struct platform_device *pdev)
  1008. {
  1009. int r;
  1010. HDMI_DEBUG();
  1011. pr_dbg("amhdmitx_probe\n");
  1012. r = alloc_chrdev_region(&hdmitx_id, 0, HDMI_TX_COUNT, DEVICE_NAME);
  1013. if (r < 0) {
  1014. pr_error("Can't register major for amhdmitx device\n");
  1015. return r;
  1016. }
  1017. hdmitx_class = class_create(THIS_MODULE, DEVICE_NAME);
  1018. if (IS_ERR(hdmitx_class))
  1019. {
  1020. unregister_chrdev_region(hdmitx_id, HDMI_TX_COUNT);
  1021. return -1;
  1022. //return PTR_ERR(aoe_class);
  1023. }
  1024. hdmitx_device.unplug_powerdown=0;
  1025. hdmitx_device.vic_count=0;
  1026. hdmitx_device.auth_process_timer=0;
  1027. hdmitx_device.force_audio_flag=0;
  1028. if(init_flag&INIT_FLAG_CEC_FUNC){
  1029. hdmitx_device.cec_func_flag = 1;
  1030. }
  1031. else{
  1032. hdmitx_device.cec_func_flag = 0;
  1033. }
  1034. if((init_flag&INIT_FLAG_POWERDOWN)&&(hpdmode==2)){
  1035. hdmitx_device.mux_hpd_if_pin_high_flag=0;
  1036. }
  1037. else{
  1038. hdmitx_device.mux_hpd_if_pin_high_flag=1;
  1039. }
  1040. hdmitx_device.audio_param_update_flag=0;
  1041. cdev_init(&(hdmitx_device.cdev), &amhdmitx_fops);
  1042. hdmitx_device.cdev.owner = THIS_MODULE;
  1043. cdev_add(&(hdmitx_device.cdev), hdmitx_id, HDMI_TX_COUNT);
  1044. //hdmitx_dev = device_create(hdmitx_class, NULL, hdmitx_id, "amhdmitx%d", 0);
  1045. hdmitx_dev = device_create(hdmitx_class, NULL, hdmitx_id, NULL, "amhdmitx%d", 0); //kernel>=2.6.27
  1046. device_create_file(hdmitx_dev, &dev_attr_disp_mode);
  1047. device_create_file(hdmitx_dev, &dev_attr_aud_mode);
  1048. device_create_file(hdmitx_dev, &dev_attr_edid);
  1049. device_create_file(hdmitx_dev, &dev_attr_config);
  1050. device_create_file(hdmitx_dev, &dev_attr_debug);
  1051. device_create_file(hdmitx_dev, &dev_attr_disp_cap);
  1052. device_create_file(hdmitx_dev, &dev_attr_hpd_state);
  1053. device_create_file(hdmitx_dev, &dev_attr_log);
  1054. device_create_file(hdmitx_dev, &dev_attr_cec);
  1055. if (hdmitx_dev == NULL) {
  1056. pr_error("device_create create error\n");
  1057. class_destroy(hdmitx_class);
  1058. r = -EEXIST;
  1059. return r;
  1060. }
  1061. vout_register_client(&hdmitx_notifier_nb_v);
  1062. #ifdef CONFIG_AM_TV_OUTPUT2
  1063. vout2_register_client(&hdmitx_notifier_nb_v2);
  1064. #endif
  1065. #ifndef DISABLE_AUDIO
  1066. aout_register_client(&hdmitx_notifier_nb_a);
  1067. #endif
  1068. hdmitx_device.task = kthread_run(hdmi_task_handle, &hdmitx_device, "kthread_hdmi");
  1069. switch_dev_register(&sdev);
  1070. if (r < 0){
  1071. printk(KERN_ERR "hdmitx: register switch dev failed\n");
  1072. return r;
  1073. }
  1074. return r;
  1075. }
  1076. static int amhdmitx_remove(struct platform_device *pdev)
  1077. {
  1078. switch_dev_unregister(&sdev);
  1079. if(hdmitx_device.HWOp.UnInit){
  1080. hdmitx_device.HWOp.UnInit(&hdmitx_device);
  1081. }
  1082. hdmitx_device.hpd_event = 0xff;
  1083. kthread_stop(hdmitx_device.task);
  1084. vout_unregister_client(&hdmitx_notifier_nb_v);
  1085. #ifdef CONFIG_AM_TV_OUTPUT2
  1086. vout2_unregister_client(&hdmitx_notifier_nb_v2);
  1087. #endif
  1088. #ifndef DISABLE_AUDIO
  1089. aout_unregister_client(&hdmitx_notifier_nb_a);
  1090. #endif
  1091. /* Remove the cdev */
  1092. device_remove_file(hdmitx_dev, &dev_attr_disp_mode);
  1093. device_remove_file(hdmitx_dev, &dev_attr_aud_mode);
  1094. device_remove_file(hdmitx_dev, &dev_attr_edid);
  1095. device_remove_file(hdmitx_dev, &dev_attr_config);
  1096. device_remove_file(hdmitx_dev, &dev_attr_debug);
  1097. device_remove_file(hdmitx_dev, &dev_attr_disp_cap);
  1098. device_remove_file(hdmitx_dev, &dev_attr_hpd_state);
  1099. device_remove_file(hdmitx_dev, &dev_attr_log);
  1100. device_remove_file(hdmitx_dev, &dev_attr_cec);
  1101. cdev_del(&hdmitx_device.cdev);
  1102. device_destroy(hdmitx_class, hdmitx_id);
  1103. class_destroy(hdmitx_class);
  1104. unregister_chrdev_region(hdmitx_id, HDMI_TX_COUNT);
  1105. return 0;
  1106. }
  1107. #ifdef CONFIG_PM
  1108. static int amhdmitx_suspend(struct platform_device *pdev,pm_message_t state)
  1109. {
  1110. pr_info("amhdmitx: hdmirx_suspend\n");
  1111. return 0;
  1112. }
  1113. static int amhdmitx_resume(struct platform_device *pdev)
  1114. {
  1115. pr_info("amhdmitx: resume module\n");
  1116. return 0;
  1117. }
  1118. #endif
  1119. static struct platform_driver amhdmitx_driver = {
  1120. .probe = amhdmitx_probe,
  1121. .remove = amhdmitx_remove,
  1122. #ifdef CONFIG_PM
  1123. .suspend = amhdmitx_suspend,
  1124. .resume = amhdmitx_resume,
  1125. #endif
  1126. .driver = {
  1127. .name = DEVICE_NAME,
  1128. .owner = THIS_MODULE,
  1129. }
  1130. };
  1131. static struct platform_device* amhdmi_tx_device = NULL;
  1132. static int __init amhdmitx_init(void)
  1133. {
  1134. HDMI_DEBUG();
  1135. if(init_flag&INIT_FLAG_NOT_LOAD)
  1136. return 0;
  1137. pr_dbg("amhdmitx_init\n");
  1138. if(hdmi_log_buf_size>0){
  1139. hdmi_log_buf=kmalloc(hdmi_log_buf_size, GFP_KERNEL);
  1140. if(hdmi_log_buf==NULL){
  1141. hdmi_log_buf_size=0;
  1142. }
  1143. }
  1144. amhdmi_tx_device = platform_device_alloc(DEVICE_NAME,0);
  1145. if (!amhdmi_tx_device) {
  1146. pr_error("failed to alloc amhdmi_tx_device\n");
  1147. return -ENOMEM;
  1148. }
  1149. if(platform_device_add(amhdmi_tx_device)){
  1150. platform_device_put(amhdmi_tx_device);
  1151. pr_error("failed to add amhdmi_tx_device\n");
  1152. return -ENODEV;
  1153. }
  1154. if (platform_driver_register(&amhdmitx_driver)) {
  1155. pr_error("failed to register amhdmitx module\n");
  1156. platform_device_del(amhdmi_tx_device);
  1157. platform_device_put(amhdmi_tx_device);
  1158. return -ENODEV;
  1159. }
  1160. return 0;
  1161. }
  1162. static void __exit amhdmitx_exit(void)
  1163. {
  1164. pr_dbg("amhdmitx_exit\n");
  1165. platform_driver_unregister(&amhdmitx_driver);
  1166. platform_device_unregister(amhdmi_tx_device);
  1167. amhdmi_tx_device = NULL;
  1168. return ;
  1169. }
  1170. module_init(amhdmitx_init);
  1171. //arch_initcall(amhdmitx_init);
  1172. module_exit(amhdmitx_exit);
  1173. MODULE_DESCRIPTION("AMLOGIC HDMI TX driver");
  1174. MODULE_LICENSE("GPL");
  1175. MODULE_VERSION("1.0.0");
  1176. static char* next_token_ex(char* seperator, char *buf, unsigned size, unsigned offset, unsigned *token_len, unsigned *token_offset)
  1177. { /* besides characters defined in seperator, '\"' are used as seperator; and any characters in '\"' will not act as seperator */
  1178. char *pToken = NULL;
  1179. char last_seperator = 0;
  1180. char trans_char_flag = 0;
  1181. if(buf){
  1182. for (;offset<size;offset++){
  1183. int ii=0;
  1184. char ch;
  1185. if (buf[offset] == '\\'){
  1186. trans_char_flag = 1;
  1187. continue;
  1188. }
  1189. while(((ch=seperator[ii++])!=buf[offset])&&(ch)){
  1190. }
  1191. if (ch){
  1192. if (!pToken){
  1193. continue;
  1194. }
  1195. else {
  1196. if (last_seperator != '"'){
  1197. *token_len = (unsigned)(buf + offset - pToken);
  1198. *token_offset = offset;
  1199. return pToken;
  1200. }
  1201. }
  1202. }
  1203. else if (!pToken)
  1204. {
  1205. if (trans_char_flag&&(buf[offset] == '"'))
  1206. last_seperator = buf[offset];
  1207. pToken = &buf[offset];
  1208. }
  1209. else if ((trans_char_flag&&(buf[offset] == '"'))&&(last_seperator == '"')){
  1210. *token_len = (unsigned)(buf + offset - pToken - 2);
  1211. *token_offset = offset + 1;
  1212. return pToken + 1;
  1213. }
  1214. trans_char_flag = 0;
  1215. }
  1216. if (pToken) {
  1217. *token_len = (unsigned)(buf + offset - pToken);
  1218. *token_offset = offset;
  1219. }
  1220. }
  1221. return pToken;
  1222. }
  1223. static int __init hdmitx_boot_para_setup(char *s)
  1224. {
  1225. char separator[]={' ',',',';',0x0};
  1226. char *token;
  1227. unsigned token_len, token_offset, offset=0;
  1228. int size=strlen(s);
  1229. HDMI_DEBUG();
  1230. do{
  1231. token=next_token_ex(separator, s, size, offset, &token_len, &token_offset);
  1232. if(token){
  1233. if((token_len==3) && (strncmp(token, "off", token_len)==0)){
  1234. init_flag|=INIT_FLAG_NOT_LOAD;
  1235. }
  1236. else if((token_len==7) && (strncmp(token, "vdacoff", token_len)==0)){
  1237. init_flag|=INIT_FLAG_VDACOFF;
  1238. }
  1239. else if((token_len==16) && (strncmp(token, "unplug_powerdown", token_len)==0)){
  1240. init_flag|=INIT_FLAG_POWERDOWN;
  1241. }
  1242. else if(strncmp(token, "pllmode1", 8)==0){
  1243. /* use external xtal as source of hdmi pll */
  1244. hdmi_pll_mode = 1;
  1245. }
  1246. else if((token_len==7)&& (strncmp(token, "hpdmode", token_len)==0)){
  1247. hpdmode = simple_strtoul(token+7,NULL,10);
  1248. }
  1249. else if((token_len==3)&&(strncmp(token, "rgb", 3)==0)){
  1250. hdmitx_output_rgb();
  1251. }
  1252. else if(strncmp(token, "audpara", 7)==0){
  1253. int tmp;
  1254. tmp = simple_strtoul(token+7,NULL,10);
  1255. hdmi_set_audio_para(tmp);
  1256. printk("hdmi: set hdmi aud_para %d\n", tmp);
  1257. }
  1258. else if(strncmp(token, "bufsize", 7)==0){
  1259. int tmp;
  1260. tmp = simple_strtoul(token+7,NULL,10);
  1261. if(tmp>=1024){
  1262. hdmi_log_buf_size=0;
  1263. hdmi_log_rd_pos=0;
  1264. hdmi_log_wr_pos=0;
  1265. hdmi_log_buf_size=tmp;
  1266. printk("hdmi: set log buffer size %d\n", tmp);
  1267. }
  1268. }
  1269. else if(strncmp(token, "powermode", 9)==0){
  1270. int tmp;
  1271. tmp = simple_strtoul(token+9,NULL,10);
  1272. init_powermode=tmp|0x80;
  1273. printk("hdmi: set init powermode %d\n", tmp);
  1274. }
  1275. else if(strncmp(token, "audiooff", 8)==0){
  1276. hdmi_audio_off_flag = 1;
  1277. printk("hdmi: set no audio output\n");
  1278. }
  1279. else if(strncmp(token, "prbs", 4)==0){
  1280. hdmi_prbs_mode = simple_strtoul(token+4,NULL,16);
  1281. printk("hdmi, set prbs mode as %x always\n", hdmi_prbs_mode);
  1282. }
  1283. else if(strncmp(token, "480p_clk", 8)==0){
  1284. hdmi_480p_force_clk = simple_strtoul(token+8,NULL,10);
  1285. printk("hdmi, set 480p mode clock as %dMHz always\n", hdmi_480p_force_clk);
  1286. }
  1287. else if(strncmp(token, "true", 4)==0){
  1288. init_flag |= INIT_FLAG_CEC_FUNC;
  1289. printk("hdmi: enable cec function\n");
  1290. }
  1291. }
  1292. offset=token_offset;
  1293. }while(token);
  1294. return 0;
  1295. }
  1296. __setup("hdmitx=",hdmitx_boot_para_setup);
  1297. MODULE_PARM_DESC(force_vout_index, "\n force_vout_index\n");
  1298. module_param(force_vout_index, uint, 0664);
  1299. MODULE_PARM_DESC(hdmi_480p_force_clk, "\n hdmi_480p_force_clk \n");
  1300. module_param(hdmi_480p_force_clk, int, 0664);
  1301. MODULE_PARM_DESC(hdmi_prbs_mode, "\n hdmi_prbs_mode \n");
  1302. module_param(hdmi_prbs_mode, int, 0664);
  1303. MODULE_PARM_DESC(hdmi_authenticated, "\n hdmi_authenticated \n");
  1304. module_param(hdmi_authenticated, int, 0664);
  1305. MODULE_PARM_DESC(hdmi_output_on, "\n hdmi_output_on \n");
  1306. module_param(hdmi_output_on, int, 0664);
  1307. MODULE_PARM_DESC(auth_output_auto_off, "\n auth_output_auto_off \n");
  1308. module_param(auth_output_auto_off, int, 0664);
  1309. #endif