PageRenderTime 64ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/u-boot-2014.07/drivers/video_sunxi/sunxi_v3/hdmi/aw/hdmi_edid.c

https://gitlab.com/pine64-android/brandy
C | 379 lines | 280 code | 56 blank | 43 comment | 117 complexity | 9d578ad07eae30efe5837af3f2c83f55 MD5 | raw file
  1. #include "hdmi_core.h"
  2. static __s32 is_hdmi;
  3. static __s32 is_yuv;
  4. __u32 rgb_only = 0;
  5. __u8 EDID_Buf[1024];
  6. __u8 Device_Support_VIC[512];
  7. void DDC_Init(void)
  8. {
  9. }
  10. /*
  11. void send_ini_sequence()
  12. {
  13. int i,j;
  14. set_wbit(HDMI_BASE + 0x524,BIT3);
  15. for(i=0;i<9;i++)
  16. {
  17. for(j=0;j<200;j++); //for simulation, delete it
  18. clr_wbit(HDMI_BASE + 0x524,BIT2);
  19. for(j=0;j<200;j++); //for simulation, delete it
  20. set_wbit(HDMI_BASE + 0x524,BIT2);
  21. }
  22. clr_wbit(HDMI_BASE + 0x524,BIT3);
  23. clr_wbit(HDMI_BASE + 0x524,BIT1);
  24. return;
  25. }*/
  26. __s32 DDC_Read(char cmd,char pointer,char offset,int nbyte,char * pbuf)
  27. {
  28. __inf("DDC_Read\n");
  29. bsp_hdmi_ddc_read(cmd,pointer,offset,128,pbuf);
  30. return 0;
  31. }
  32. static void GetEDIDData(__u8 block,__u8 *buf)
  33. {
  34. __u8 i;
  35. char * pbuf = (char *)(buf + 128*block);
  36. __u8 offset = (block&0x01)? 128:0;
  37. DDC_Read(Explicit_Offset_Address_E_DDC_Read,block>>1,offset,128,pbuf);
  38. ////////////////////////////////////////////////////////////////////////////
  39. __inf("Sink : EDID bank %d:\n",block);
  40. __inf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
  41. __inf(" ===============================================================================================\n");
  42. for (i = 0; i < 8; i++) {
  43. __inf(" %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
  44. pbuf[i*16 + 0 ],pbuf[i*16 + 1 ],pbuf[i*16 + 2 ],pbuf[i*16 + 3 ],
  45. pbuf[i*16 + 4 ],pbuf[i*16 + 5 ],pbuf[i*16 + 6 ],pbuf[i*16 + 7 ],
  46. pbuf[i*16 + 8 ],pbuf[i*16 + 9 ],pbuf[i*16 + 10],pbuf[i*16 + 11],
  47. pbuf[i*16 + 12],pbuf[i*16 + 13],pbuf[i*16 + 14],pbuf[i*16 + 15]
  48. );
  49. }
  50. __inf(" ===============================================================================================\n");
  51. return;
  52. }
  53. /////////////////////////////////////////////////////////////////////
  54. // ParseEDID()
  55. // Check EDID check sum and EDID 1.3 extended segment.
  56. /////////////////////////////////////////////////////////////////////
  57. static __s32 EDID_CheckSum(__u8 block,__u8 *buf)
  58. {
  59. __s32 i = 0, CheckSum = 0;
  60. __u8 *pbuf = buf + 128*block;
  61. for( i = 0, CheckSum = 0 ; i < 128 ; i++ ) {
  62. CheckSum += pbuf[i] ;
  63. CheckSum &= 0xFF ;
  64. }
  65. if( CheckSum != 0 ) {
  66. __inf("EDID block %d checksum error\n",block);
  67. return -1 ;
  68. }
  69. return 0;
  70. }
  71. static __s32 EDID_Header_Check(__u8 *pbuf)
  72. {
  73. if( pbuf[0] != 0x00 ||
  74. pbuf[1] != 0xFF ||
  75. pbuf[2] != 0xFF ||
  76. pbuf[3] != 0xFF ||
  77. pbuf[4] != 0xFF ||
  78. pbuf[5] != 0xFF ||
  79. pbuf[6] != 0xFF ||
  80. pbuf[7] != 0x00)
  81. {
  82. __inf("EDID block0 header error\n");
  83. return -1 ;
  84. }
  85. return 0;
  86. }
  87. static __s32 EDID_Version_Check(__u8 *pbuf)
  88. {
  89. __inf("EDID version: %d.%d ",pbuf[0x12],pbuf[0x13]) ;
  90. if( (pbuf[0x12]!= 0x01) || (pbuf[0x13]!=0x03)) {
  91. __inf("Unsupport EDID format,EDID parsing exit\n");
  92. return -1;
  93. }
  94. return 0;
  95. }
  96. static __s32 Parse_DTD_Block(__u8 *pbuf)
  97. {
  98. __u32 pclk,sizex,Hblanking,sizey,Vblanking,/*Hsync_offset,Hsync_plus,
  99. Vsync_offset,Vsync_plus,H_image_size,V_image_size,H_Border,
  100. V_Border,*/pixels_total,frame_rate;
  101. pclk = ( (__u32)pbuf[1] << 8) + pbuf[0];
  102. sizex = (((__u32)pbuf[4] << 4) & 0x0f00) + pbuf[2];
  103. Hblanking = (((__u32)pbuf[4] << 8) & 0x0f00) + pbuf[3];
  104. sizey = (((__u32)pbuf[7] << 4) & 0x0f00) + pbuf[5];
  105. Vblanking = (((__u32)pbuf[7] << 8) & 0x0f00) + pbuf[6];
  106. // Hsync_offset= (((__u32)pbuf[11] << 2) & 0x0300) + pbuf[8];
  107. // Hsync_plus = (((__u32)pbuf[11] << 4) & 0x0300) + pbuf[9];
  108. // Vsync_offset= (((__u32)pbuf[11] << 2) & 0x0030) + (pbuf[10] >> 4);
  109. // Vsync_plus = (((__u32)pbuf[11] << 4) & 0x0030) + (pbuf[8] & 0x0f);
  110. // H_image_size= (((__u32)pbuf[14] << 4) & 0x0f00) + pbuf[12];
  111. // V_image_size= (((__u32)pbuf[14] << 8) & 0x0f00) + pbuf[13];
  112. // H_Border = pbuf[15];
  113. // V_Border = pbuf[16];
  114. pixels_total = (sizex + Hblanking) * (sizey + Vblanking);
  115. if( (pbuf[0] == 0) && (pbuf[1] == 0) && (pbuf[2] == 0)) {
  116. return 0;
  117. }
  118. if(pixels_total == 0) {
  119. return 0;
  120. } else {
  121. frame_rate = (pclk * 10000) /pixels_total;
  122. }
  123. if ((frame_rate == 59) || (frame_rate == 60)) {
  124. if ((sizex== 720) && (sizey == 240)) {
  125. Device_Support_VIC[HDMI1440_480I] = 1;
  126. }
  127. if ((sizex== 720) && (sizey == 480)) {
  128. //Device_Support_VIC[HDMI480P] = 1;
  129. }
  130. if ((sizex== 1280) && (sizey == 720)) {
  131. Device_Support_VIC[HDMI720P_60] = 1;
  132. }
  133. if ((sizex== 1920) && (sizey == 540)) {
  134. Device_Support_VIC[HDMI1080I_60] = 1;
  135. }
  136. if ((sizex== 1920) && (sizey == 1080)) {
  137. Device_Support_VIC[HDMI1080P_60] = 1;
  138. }
  139. }
  140. else if ((frame_rate == 49) || (frame_rate == 50)) {
  141. if ((sizex== 720) && (sizey == 288)) {
  142. Device_Support_VIC[HDMI1440_576I] = 1;
  143. }
  144. if ((sizex== 720) && (sizey == 576)) {
  145. Device_Support_VIC[HDMI576P] = 1;
  146. }
  147. if ((sizex== 1280) && (sizey == 720)) {
  148. Device_Support_VIC[HDMI720P_50] = 1;
  149. }
  150. if ((sizex== 1920) && (sizey == 540)) {
  151. Device_Support_VIC[HDMI1080I_50] = 1;
  152. }
  153. if ((sizex== 1920) && (sizey == 1080)) {
  154. Device_Support_VIC[HDMI1080P_50] = 1;
  155. }
  156. }
  157. else if ((frame_rate == 23) || (frame_rate == 24)) {
  158. if ((sizex== 1920) && (sizey == 1080)) {
  159. Device_Support_VIC[HDMI1080P_24] = 1;
  160. }
  161. }
  162. __inf("PCLK=%d\tXsize=%d\tYsize=%d\tFrame_rate=%d\n",
  163. pclk*10000,sizex,sizey,frame_rate);
  164. return 0;
  165. }
  166. static __s32 Parse_VideoData_Block(__u8 *pbuf,__u8 size)
  167. {
  168. int i=0;
  169. while(i<size) {
  170. Device_Support_VIC[pbuf[i] &0x7f] = 1;
  171. if(pbuf[i] &0x80) {
  172. __inf("Parse_VideoData_Block: VIC %d(native) support\n", pbuf[i]&0x7f);
  173. }
  174. else {
  175. __inf("Parse_VideoData_Block: VIC %d support\n", pbuf[i]);
  176. }
  177. i++;
  178. }
  179. return 0;
  180. }
  181. static __s32 Parse_AudioData_Block(__u8 *pbuf,__u8 size)
  182. {
  183. __u8 sum = 0;
  184. while(sum < size) {
  185. if( (pbuf[sum]&0xf8) == 0x08) {
  186. __inf("Parse_AudioData_Block: max channel=%d\n",(pbuf[sum]&0x7)+1);
  187. __inf("Parse_AudioData_Block: SampleRate code=%x\n",pbuf[sum+1]);
  188. __inf("Parse_AudioData_Block: WordLen code=%x\n",pbuf[sum+2]);
  189. }
  190. sum += 3;
  191. }
  192. return 0;
  193. }
  194. static __s32 Parse_HDMI_VSDB(__u8 * pbuf,__u8 size)
  195. {
  196. __u8 index = 8;
  197. /* check if it's HDMI VSDB */
  198. if((pbuf[0] ==0x03) && (pbuf[1] ==0x0c) && (pbuf[2] ==0x00)) {
  199. is_hdmi = 1;
  200. __inf("Find HDMI Vendor Specific DataBlock\n");
  201. } else {
  202. return 0;
  203. }
  204. if(size <=8)
  205. return 0;
  206. if((pbuf[7]&0x20) == 0 )
  207. return 0;
  208. if((pbuf[7]&0x40) == 0x40 )
  209. index = index +2;
  210. if((pbuf[7]&0x80) == 0x80 )
  211. index = index +2;
  212. /* mandatary format support */
  213. if(pbuf[index]&0x80) {
  214. Device_Support_VIC[HDMI1080P_24_3D_FP] = 1;
  215. Device_Support_VIC[HDMI720P_50_3D_FP] = 1;
  216. Device_Support_VIC[HDMI720P_60_3D_FP] = 1;
  217. __inf("3D_present\n");
  218. } else {
  219. return 0;
  220. }
  221. if( ((pbuf[index]&0x60) ==1) || ((pbuf[index]&0x60) ==2) )
  222. __inf("3D_multi_present\n");
  223. index += (pbuf[index+1]&0xe0) + 2;
  224. if(index > (size+1) )
  225. return 0;
  226. __inf("3D_multi_present byte(%2.2x,%2.2x)\n",pbuf[index],pbuf[index+1]);
  227. return 0;
  228. }
  229. __s32 ParseEDID(void)
  230. {
  231. //collect the EDID ucdata of segment 0
  232. __u8 BlockCount ;
  233. __u32 i,offset ;
  234. __inf("ParseEDID\n");
  235. memset(Device_Support_VIC,0,sizeof(Device_Support_VIC));
  236. memset(EDID_Buf,0,sizeof(EDID_Buf));
  237. is_hdmi = 0;
  238. is_yuv = 0;
  239. DDC_Init();
  240. GetEDIDData(0, EDID_Buf);
  241. if( EDID_CheckSum(0, EDID_Buf) != 0)
  242. return 0;
  243. if( EDID_Header_Check(EDID_Buf)!= 0)
  244. return 0;
  245. if( EDID_Version_Check(EDID_Buf)!= 0)
  246. return 0;
  247. Parse_DTD_Block(EDID_Buf + 0x36);
  248. Parse_DTD_Block(EDID_Buf + 0x48);
  249. BlockCount = EDID_Buf[0x7E];
  250. if( BlockCount > 0 ) {
  251. if ( BlockCount > 4 )
  252. BlockCount = 4 ;
  253. for( i = 1 ; i <= BlockCount ; i++ ) {
  254. GetEDIDData(i, EDID_Buf) ;
  255. if( EDID_CheckSum(i, EDID_Buf)!= 0)
  256. return 0;
  257. if((EDID_Buf[0x80*i+0]==2)/*&&(EDID_Buf[0x80*i+1]==1)*/)
  258. {
  259. if( (EDID_Buf[0x80*i+1]>=1)) {
  260. if(EDID_Buf[0x80*i+3]&0x20)
  261. {
  262. is_yuv = 1;
  263. __inf("device support YCbCr44 output\n");
  264. if(rgb_only == 1) {
  265. __inf("rgb only test!\n");
  266. is_yuv = 0;
  267. }
  268. }
  269. }
  270. offset = EDID_Buf[0x80*i+2];
  271. /* deal with reserved data block */
  272. if(offset > 4) {
  273. __u8 bsum = 4;
  274. while(bsum < offset)
  275. {
  276. __u8 tag = EDID_Buf[0x80*i+bsum]>>5;
  277. __u8 len = EDID_Buf[0x80*i+bsum]&0x1f;
  278. if( (len >0) && ((bsum + len + 1) > offset) ) {
  279. __inf("len or bsum size error\n");
  280. return 0;
  281. } else {
  282. if( tag == 1) {
  283. /* ADB */
  284. Parse_AudioData_Block(EDID_Buf+0x80*i+bsum+1,len);
  285. } else if( tag == 2) {
  286. /* VDB */
  287. Parse_VideoData_Block(EDID_Buf+0x80*i+bsum+1,len);
  288. } else if( tag == 3) {
  289. /* vendor specific */
  290. Parse_HDMI_VSDB(EDID_Buf+0x80*i+bsum+1,len);
  291. }
  292. }
  293. bsum += (len +1);
  294. }
  295. } else {
  296. __inf("no data in reserved block%d\n",i);
  297. }
  298. /* deal with 18-byte timing block */
  299. if(offset >= 4) {
  300. while(offset < (0x80-18)) {
  301. Parse_DTD_Block(EDID_Buf + 0x80*i + offset);
  302. offset += 18;
  303. }
  304. } else {
  305. __inf("no datail timing in block%d\n",i);
  306. }
  307. }
  308. }
  309. }
  310. return 0 ;
  311. }
  312. __u32 GetIsHdmi(void)
  313. {
  314. return is_hdmi;
  315. }
  316. __u32 GetIsYUV(void)
  317. {
  318. return is_yuv;
  319. }