Advertisement
mpthompson

WonderMedia video post processor (VPP) driver

Sep 26th, 2012
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.62 KB | None | 0 0
  1. /*++
  2. * linux/drivers/video/wmt/parse-edid.c
  3. * WonderMedia video post processor (VPP) driver
  4. *
  5. * Copyright c 2010 WonderMedia Technologies, Inc.
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. * WonderMedia Technologies, Inc.
  21. * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
  22. --*/
  23.  
  24. /*
  25. * ChangeLog
  26. *
  27. * 2010-08-05 Sam Shen
  28. * * Add License declaration and ChangeLog
  29. */
  30.  
  31. #define PARSE_EDID_C
  32. // #define DEBUG
  33.  
  34. #include "vpp-osif.h"
  35. #include "edid.h"
  36.  
  37. const unsigned char edid_v1_header[] = {
  38. 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
  39.  
  40. const unsigned char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
  41.  
  42. #define COMBINE_HI_8LO( hi, lo ) \
  43. ( (((unsigned)hi) << 8) | (unsigned)lo )
  44.  
  45. #define COMBINE_HI_4LO( hi, lo ) \
  46. ( (((unsigned)hi) << 4) | (unsigned)lo )
  47.  
  48. #define UPPER_NIBBLE( x ) \
  49. (((128|64|32|16) & (x)) >> 4)
  50.  
  51. #define LOWER_NIBBLE( x ) \
  52. ((1|2|4|8) & (x))
  53.  
  54. #define MONITOR_NAME 0xfc
  55. #define MONITOR_LIMITS 0xfd
  56. #define UNKNOWN_DESCRIPTOR -1
  57. #define DETAILED_TIMING_BLOCK -2
  58.  
  59. edid_timing_t edid_establish_timing[] = {
  60. { 800, 600, 60 }, { 800, 600, 56 }, { 640, 480, 75 }, { 640, 480, 72 }, { 640, 480, 67 }, { 640, 480, 60 },
  61. { 720, 400, 88 }, { 720, 400, 70 }, { 1280, 1024, 75 }, { 1024, 768, 75 }, { 1024, 768, 70 }, { 1024, 768, 60 },
  62. { 1024, 768, 87 }, { 832, 624, 75 }, { 800, 600, 75 }, { 800, 600, 72 }, { 1152, 870, 75 }
  63. };
  64. edid_info_t edid_info;
  65.  
  66. static int block_type( unsigned char * block )
  67. {
  68. if ( !memcmp( edid_v1_descriptor_flag, block, 2 ) ) {
  69. // DBGMSG("# Block type: 2:%x 3:%x\n", block[2], block[3]);
  70.  
  71. /* descriptor */
  72. if ( block[ 2 ] != 0 )
  73. return UNKNOWN_DESCRIPTOR;
  74. return block[ 3 ];
  75. }
  76. /* detailed timing block */
  77. return DETAILED_TIMING_BLOCK;
  78. } /* End of block_type() */
  79.  
  80. static char * get_vendor_sign( unsigned char * block, char *sign)
  81. {
  82. // static char sign[4];
  83. unsigned short h;
  84.  
  85. /*
  86. 08h WORD big-endian manufacturer ID (see #00136)
  87. bits 14-10: first letter (01h='A', 02h='B', etc.)
  88. bits 9-5: second letter
  89. bits 4-0: third letter
  90. */
  91. h = COMBINE_HI_8LO(block[0], block[1]);
  92. sign[0] = ((h>>10) & 0x1f) + 'A' - 1;
  93. sign[1] = ((h>>5) & 0x1f) + 'A' - 1;
  94. sign[2] = (h & 0x1f) + 'A' - 1;
  95. sign[3] = 0;
  96.  
  97. return sign;
  98. } /* End of get_vendor_sign() */
  99.  
  100. static char * get_monitor_name( unsigned char * block )
  101. {
  102. #define DESCRIPTOR_DATA 5
  103.  
  104. unsigned char *ptr = block + DESCRIPTOR_DATA;
  105. static char name[ 13 ];
  106. unsigned i;
  107.  
  108.  
  109. for( i = 0; i < 13; i++, ptr++ ) {
  110. if ( *ptr == 0xa ) {
  111. name[ i ] = 0;
  112. return name;
  113. }
  114. name[ i ] = *ptr;
  115. }
  116. return name;
  117. } /* End of get_monitor_name() */
  118.  
  119. static int parse_timing_description( unsigned char* dtd )
  120. {
  121. #define PIXEL_CLOCK_LO (unsigned)dtd[ 0 ]
  122. #define PIXEL_CLOCK_HI (unsigned)dtd[ 1 ]
  123. #define PIXEL_CLOCK (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000)
  124. #define H_ACTIVE_LO (unsigned)dtd[ 2 ]
  125. #define H_BLANKING_LO (unsigned)dtd[ 3 ]
  126. #define H_ACTIVE_HI UPPER_NIBBLE( (unsigned)dtd[ 4 ] )
  127. #define H_ACTIVE COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
  128. #define H_BLANKING_HI LOWER_NIBBLE( (unsigned)dtd[ 4 ] )
  129. #define H_BLANKING COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
  130. #define V_ACTIVE_LO (unsigned)dtd[ 5 ]
  131. #define V_BLANKING_LO (unsigned)dtd[ 6 ]
  132. #define V_ACTIVE_HI UPPER_NIBBLE( (unsigned)dtd[ 7 ] )
  133. #define V_ACTIVE COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
  134. #define V_BLANKING_HI LOWER_NIBBLE( (unsigned)dtd[ 7 ] )
  135. #define V_BLANKING COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
  136. #define H_SYNC_OFFSET_LO (unsigned)dtd[ 8 ]
  137. #define H_SYNC_WIDTH_LO (unsigned)dtd[ 9 ]
  138. #define V_SYNC_OFFSET_LO UPPER_NIBBLE( (unsigned)dtd[ 10 ] )
  139. #define V_SYNC_WIDTH_LO LOWER_NIBBLE( (unsigned)dtd[ 10 ] )
  140. #define V_SYNC_WIDTH_HI ((unsigned)dtd[ 11 ] & (1|2))
  141. #define V_SYNC_OFFSET_HI (((unsigned)dtd[ 11 ] & (4|8)) >> 2)
  142. #define H_SYNC_WIDTH_HI (((unsigned)dtd[ 11 ] & (16|32)) >> 4)
  143. #define H_SYNC_OFFSET_HI (((unsigned)dtd[ 11 ] & (64|128)) >> 6)
  144. #define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
  145. #define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
  146. #define H_SYNC_WIDTH COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
  147. #define H_SYNC_OFFSET COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
  148. #define H_SIZE_LO (unsigned)dtd[ 12 ]
  149. #define V_SIZE_LO (unsigned)dtd[ 13 ]
  150. #define H_SIZE_HI UPPER_NIBBLE( (unsigned)dtd[ 14 ] )
  151. #define V_SIZE_HI LOWER_NIBBLE( (unsigned)dtd[ 14 ] )
  152. #define H_SIZE COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
  153. #define V_SIZE COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
  154. #define H_BORDER (unsigned)dtd[ 15 ]
  155. #define V_BORDER (unsigned)dtd[ 16 ]
  156. #define FLAGS (unsigned)dtd[ 17 ]
  157. #define INTERLACED (FLAGS&128)
  158. #define SYNC_TYPE (FLAGS&3<<3) /* bits 4,3 */
  159. #define SYNC_SEPARATE (3<<3)
  160. #define HSYNC_POSITIVE (FLAGS & 4)
  161. #define VSYNC_POSITIVE (FLAGS & 2)
  162.  
  163. int htotal, vtotal;
  164.  
  165. htotal = H_ACTIVE + H_BLANKING;
  166. vtotal = V_ACTIVE + V_BLANKING;
  167.  
  168. DBGMSG( "\tMode \"%dx%d\"", H_ACTIVE, V_ACTIVE );
  169. DPRINT("\n");
  170. DBGMSG( "# vfreq %dHz, hfreq %dkHz\n",
  171. PIXEL_CLOCK/(vtotal*htotal),
  172. PIXEL_CLOCK/(htotal*1000));
  173. DBGMSG( "\tDotClock\t%d\n", PIXEL_CLOCK/1000000 );
  174. DBGMSG( "\tHTimings\t%u %u %u %u\n", H_ACTIVE,
  175. H_ACTIVE+H_SYNC_OFFSET,
  176. H_ACTIVE+H_SYNC_OFFSET+H_SYNC_WIDTH,
  177. htotal );
  178.  
  179. DBGMSG( "\tVTimings\t%u %u %u %u\n", V_ACTIVE,
  180. V_ACTIVE+V_SYNC_OFFSET,
  181. V_ACTIVE+V_SYNC_OFFSET+V_SYNC_WIDTH,
  182. vtotal );
  183.  
  184. if ( INTERLACED || (SYNC_TYPE == SYNC_SEPARATE)) {
  185. DBGMSG( "Flags\t%s\"%sHSync\" \"%sVSync\"\n",
  186. INTERLACED ? "\"Interlace\" ": "",
  187. HSYNC_POSITIVE ? "+": "-",
  188. VSYNC_POSITIVE ? "+": "-");
  189. }
  190.  
  191. DBGMSG( "EndMode\n" );
  192.  
  193. {
  194. int i;
  195. for(i=0;i<4;i++){
  196. if( edid_info.detail_timing[i].resx == 0 ){
  197. edid_info.detail_timing[i].resx = H_ACTIVE;
  198. edid_info.detail_timing[i].resy = V_ACTIVE;
  199. edid_info.detail_timing[i].freq = PIXEL_CLOCK/(vtotal*htotal);
  200. }
  201. }
  202. }
  203. return 0;
  204. } /* End of parse_timing_description() */
  205.  
  206. static int parse_dpms_capabilities(unsigned char flags)
  207. {
  208. #define DPMS_ACTIVE_OFF (1 << 5)
  209. #define DPMS_SUSPEND (1 << 6)
  210. #define DPMS_STANDBY (1 << 7)
  211.  
  212. DBGMSG("# DPMS capabilities: Active off:%s Suspend:%s Standby:%s\n\n",
  213. (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
  214. (flags & DPMS_SUSPEND) ? "yes" : "no",
  215. (flags & DPMS_STANDBY) ? "yes" : "no");
  216. return 0;
  217. } /* End of parse_dpms_capabilities() */
  218.  
  219. static int parse_monitor_limits( unsigned char * block )
  220. {
  221. #define V_MIN_RATE block[ 5 ]
  222. #define V_MAX_RATE block[ 6 ]
  223. #define H_MIN_RATE block[ 7 ]
  224. #define H_MAX_RATE block[ 8 ]
  225. #define MAX_PIXEL_CLOCK (((int)block[ 9 ]) * 10)
  226. #define GTF_SUPPORT block[10]
  227.  
  228. DBGMSG( "\tHorizontal Frequency: %u-%u Hz\n", H_MIN_RATE, H_MAX_RATE );
  229. DBGMSG( "\tVertical Frequency: %u-%u kHz\n", V_MIN_RATE, V_MAX_RATE );
  230. if ( MAX_PIXEL_CLOCK == 10*0xff )
  231. DBGMSG( "\t# Max dot clock not given\n" );
  232. else {
  233. DBGMSG( "\t# Max dot clock (video bandwidth) %u MHz\n", (int)MAX_PIXEL_CLOCK );
  234. edid_info.pixel_clock_limit = MAX_PIXEL_CLOCK;
  235. }
  236.  
  237. if ( GTF_SUPPORT ) {
  238. DBGMSG( "\t# EDID version 3 GTF given: contact author\n" );
  239. }
  240. return 0;
  241. } /* End of parse_monitor_limits() */
  242.  
  243. static int get_established_timing( unsigned char * edid )
  244. {
  245. unsigned char time_1, time_2;
  246.  
  247. time_1 = edid[ESTABLISHED_TIMING_I];
  248. time_2 = edid[ESTABLISHED_TIMING_II];
  249. edid_info.establish_timing = time_1 + (time_2 << 8);
  250.  
  251. /*--------------------------------------------------------------------------
  252. 35: ESTABLISHED TIMING I
  253. bit 7-0: 720��400@70 Hz, 720��400@88 Hz, 640��480@60 Hz, 640��480@67 Hz,
  254. 640��480@72 Hz, 640��480@75 Hz, 800��600@56 Hz, 800��600@60 Hz
  255. --------------------------------------------------------------------------*/
  256. DBGMSG("Established Timimgs I: 0x%x\n", time_1);
  257. if( time_1 & 0x80 )
  258. DBGMSG(" \t%- dx%d@%dHz\n", 720, 400, 70);
  259. if( time_1 & 0x40 )
  260. DBGMSG(" \t%- dx%d@%dHz\n", 720, 400, 88);
  261. if( time_1 & 0x20 )
  262. DBGMSG(" \t%- dx%d@%dHz\n", 640, 480, 60);
  263. if( time_1 & 0x10 )
  264. DBGMSG(" \t%- dx%d@%dHz\n", 640, 480, 67);
  265. if( time_1 & 0x08 )
  266. DBGMSG(" \t%- dx%d@%dHz\n", 640, 480, 72);
  267. if( time_1 & 0x04 )
  268. DBGMSG(" \t%- dx%d@%dHz\n", 640, 480, 75);
  269. if( time_1 & 0x02 )
  270. DBGMSG(" \t%- dx%d@%dHz\n", 800, 600, 56);
  271. if( time_1 & 0x01 )
  272. DBGMSG(" \t%- dx%d@%dHz\n", 800, 600, 60);
  273.  
  274. /*--------------------------------------------------------------------------
  275. 36: ESTABLISHED TIMING II
  276. bit 7-0: 800��600@72 Hz, 800��600@75 Hz, 832��624@75 Hz, 1024��768@87 Hz (Interlaced),
  277. 1024��768@60 Hz, 1024��768@70 Hz, 1024��768@75 Hz, 1280��1024@75 Hz
  278. --------------------------------------------------------------------------*/
  279. DBGMSG("Established Timimgs II: 0x%x\n", time_2);
  280. if( time_2 & 0x80 )
  281. DBGMSG(" \t%- dx%d@%dHz\n", 800, 600, 72);
  282. if( time_2 & 0x40 )
  283. DBGMSG(" \t%- dx%d@%dHz\n", 800, 600, 75);
  284. if( time_2 & 0x20 )
  285. DBGMSG(" \t%- dx%d@%dHz\n", 832, 624, 75);
  286. if( time_2 & 0x10 )
  287. DBGMSG(" \t%- dx%d@%dHz (Interlace)\n", 1024, 768, 87);
  288. if( time_2 & 0x08 )
  289. DBGMSG(" \t%- dx%d@%dHz\n", 1024, 768, 60);
  290. if( time_2 & 0x04 )
  291. DBGMSG(" \t%- dx%d@%dHz\n", 1024, 768, 70);
  292. if( time_2 & 0x02 )
  293. DBGMSG(" \t%- dx%d@%dHz\n", 1024, 768, 75);
  294. if( time_2 & 0x01 )
  295. DBGMSG(" \t%- dx%d@%dHz\n", 1280, 1024, 75);
  296.  
  297. return 0;
  298. } /* End of get_established_timing() */
  299.  
  300. static int get_standard_timing( unsigned char * edid )
  301. {
  302. unsigned char *ptr = edid +STANDARD_TIMING_IDENTIFICATION_START;
  303. int h_res, v_res, v_freq;
  304. int byte_1, byte_2, aspect, i;
  305.  
  306. /*--------------------------------------------------------------------------
  307. First byte
  308. Horizontal resolution. Multiply by 8, then add 248 for actual value.
  309. Second byte
  310. bit 7-6: Aspect ratio. Actual vertical resolution depends on horizontal
  311. resolution.
  312. 00=16:10, 01=4:3, 10=5:4, 11=16:9 (00=1:1 prior to v1.3)
  313. bit 5-0: Vertical frequency. Add 60 to get actual value.
  314. --------------------------------------------------------------------------*/
  315. DBGMSG("Standard Timing Identification \n");
  316. for(i=0; i< STANDARD_TIMING_IDENTIFICATION_SIZE/2; i++ ) {
  317. byte_1 = *ptr++;
  318. byte_2 = *ptr++;
  319. if( (byte_1 == 0x01) && (byte_2 == 0x01) )
  320. break;
  321. h_res = (byte_1 * 8) + 248;
  322. aspect = byte_2 & 0xC0;
  323. switch(aspect) {
  324. default:
  325. case 0x00:
  326. v_res = h_res * 10/16;
  327. break;
  328. case 0x40:
  329. v_res = h_res * 3/4;
  330. break;
  331. case 0x80:
  332. v_res = h_res * 4/5;
  333. break;
  334. case 0xC0:
  335. v_res = h_res * 9/16;
  336. break;
  337. }
  338. v_freq = (byte_2 & 0x1F) + 60;
  339. DBGMSG("Standard Timing: \t%dx%d@%dHz\n", h_res, v_res, v_freq);
  340. edid_info.standard_timing[i].resx = h_res;
  341. edid_info.standard_timing[i].resy = v_res;
  342. edid_info.standard_timing[i].freq = v_freq;
  343. }
  344. return 0;
  345. } /* End of get_standard_timing() */
  346.  
  347. void edid_dump(unsigned char *edid)
  348. {
  349. int i;
  350.  
  351. DPRINT("===================== EDID BlOCK =====================");
  352. for(i=0;i<128;i++){
  353. if( (i%16)==0 ) DPRINT("\n");
  354. DPRINT("%02x ",edid[i]);
  355. }
  356. DPRINT("\n");
  357. DPRINT("======================================================\n");
  358. }
  359.  
  360. int edid_parse_v1( unsigned char * edid )
  361. {
  362. unsigned char * block;
  363. unsigned char checksum = 0;
  364. char *monitor_name = 0;
  365. char monitor_alt_name[100];
  366. char vendor_sign[4];
  367. int i, ret = 0;
  368.  
  369. memset(&edid_info,0,sizeof(edid_info_t));
  370. for( i = 0; i < EDID_LENGTH; i++ )
  371. checksum += edid[ i ];
  372.  
  373. if ( checksum != 0 ) {
  374. DPRINT("*E* EDID checksum failed - data is corrupt\n" );
  375. ret = -1;
  376. goto parse_end;
  377. }
  378.  
  379. if ( memcmp( edid+EDID_HEADER, edid_v1_header, EDID_HEADER_END+1 ) ) {
  380. DBGMSG("*E* first bytes don't match EDID version 1 header\n");
  381. ret = -1;
  382. goto parse_end;
  383. }
  384.  
  385. edid_dump(edid);
  386.  
  387. DPRINT("[EDID] EDID version: %d.%d\n", (int)edid[EDID_STRUCT_VERSION],(int)edid[EDID_STRUCT_REVISION] );
  388.  
  389. get_vendor_sign( edid + ID_MANUFACTURER_NAME,(char *) &vendor_sign );
  390.  
  391. /*--------------------------------------------------------------------------
  392. Parse Monitor name
  393. --------------------------------------------------------------------------*/
  394. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  395. for( i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++,
  396. block += DETAILED_TIMING_DESCRIPTION_SIZE ) {
  397. if ( block_type( block ) == MONITOR_NAME ) {
  398. monitor_name = get_monitor_name( block );
  399. break;
  400. }
  401. }
  402.  
  403. if (!monitor_name) {
  404. /* Stupid djgpp hasn't snDBGMSG so we have to hack something together */
  405. if(strlen(vendor_sign) + 10 > sizeof(monitor_alt_name))
  406. vendor_sign[3] = 0;
  407.  
  408. sprintf(monitor_alt_name, "%s:%02x%02x",
  409. vendor_sign, edid[ID_MODEL], edid[ID_MODEL+1]) ;
  410. monitor_name = monitor_alt_name;
  411. }
  412.  
  413. DBGMSG( "Identifier \"%s\"\n", monitor_name );
  414. DBGMSG( "VendorName \"%s\"\n", vendor_sign );
  415. DBGMSG( "ModelName \"%s\"\n", monitor_name );
  416.  
  417. parse_dpms_capabilities(edid[DPMS_FLAGS]);
  418.  
  419. /*--------------------------------------------------------------------------
  420. Parse ESTABLISHED TIMING I and II
  421. --------------------------------------------------------------------------*/
  422. get_established_timing( edid );
  423.  
  424. /*--------------------------------------------------------------------------
  425. Parse STANDARD TIMING IDENTIFICATION
  426. --------------------------------------------------------------------------*/
  427. get_standard_timing( edid );
  428.  
  429. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  430. for( i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++,
  431. block += DETAILED_TIMING_DESCRIPTION_SIZE ) {
  432. if ( block_type( block ) == MONITOR_LIMITS )
  433. parse_monitor_limits( block );
  434. }
  435.  
  436. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  437. for( i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++,
  438. block += DETAILED_TIMING_DESCRIPTION_SIZE ) {
  439. if ( block_type( block ) == DETAILED_TIMING_BLOCK )
  440. parse_timing_description( block );
  441. }
  442. parse_end:
  443. return ret;
  444. }
  445.  
  446. int edid_parse_CEA(unsigned char *edid)
  447. {
  448. unsigned char *block;
  449. unsigned char checksum = 0;
  450. int i,len;
  451. unsigned int pixclk, hpixel, hporch, vpixel, vporch, fps;
  452.  
  453. if((edid[0]!=0x2) || (edid[1]!=0x3)){
  454. return -1;
  455. }
  456.  
  457. for( i = 0; i < EDID_LENGTH; i++ )
  458. checksum += edid[ i ];
  459.  
  460. if ( checksum != 0 ) {
  461. DPRINT("*E* CEA EDID checksum failed - data is corrupt\n" );
  462. return -1;
  463. }
  464.  
  465. edid_dump(edid);
  466.  
  467. DPRINT("[EDID] CEA EDID Version %d.%d\n",edid[0],edid[1]);
  468.  
  469. edid_info.option = (edid[3] & 0xF0) | EDID_OPT_VALID;
  470. DBGMSG("\t %s support 422\n", (edid[3] & 0x10)? "":"no" );
  471. DBGMSG("\t %s support 444\n", (edid[3] & 0x20)? "":"no" );
  472. DBGMSG("\t %s support audio\n", (edid[3] & 0x40)? "":"no" );
  473. DBGMSG("\t %s support underscan\n", (edid[3] & 0x80)? "":"no" );
  474.  
  475. block = edid + 4;
  476. do {
  477. len = block[0] & 0x1F;
  478. switch(((block[0] & 0xE0)>>5)){
  479. case 1: // Audio Data Block
  480. DBGMSG("Audio Data Block\n");
  481. DBGMSG("\t Max channel %d\n", (block[1] & 0x7)+1 );
  482. DBGMSG("\t %s support 32 KHz\n", (block[2] & 0x1)? "":"no" );
  483. DBGMSG("\t %s support 44 KHz\n", (block[2] & 0x2)? "":"no" );
  484. DBGMSG("\t %s support 48 KHz\n", (block[2] & 0x4)? "":"no" );
  485. DBGMSG("\t %s support 88 KHz\n", (block[2] & 0x8)? "":"no" );
  486. DBGMSG("\t %s support 96 KHz\n", (block[2] & 0x10)? "":"no" );
  487. DBGMSG("\t %s support 176 KHz\n", (block[2] & 0x20)? "":"no" );
  488. DBGMSG("\t %s support 192 KHz\n", (block[2] & 0x40)? "":"no" );
  489. DBGMSG("\t %s support 16 bit\n", (block[3] & 0x1)? "":"no" );
  490. DBGMSG("\t %s support 20 bit\n", (block[3] & 0x2)? "":"no" );
  491. DBGMSG("\t %s support 24 bit\n", (block[3] & 0x4)? "":"no" );
  492. break;
  493. case 2: // Video Data Block
  494. DBGMSG("Video Data Block\n");
  495. for(i=0;i<len;i++){
  496. DBGMSG("\t support VIC %d\n",block[1+i]);
  497. edid_info.cea_vic[i] = (block[1+i] & 0x7F);
  498. }
  499. break;
  500. case 3: // Vendor Spec Data Block
  501. DBGMSG("Vendor Spec Data Block\n");
  502. if( (block[1]==0x03) && (block[2]==0x0C) && (block[3]==0x0)){ // IEEE Registration Identifier 0x000C03
  503. edid_info.option |= EDID_OPT_HDMI;
  504. DBGMSG("\t support HDMI\n");
  505. }
  506. break;
  507. case 4: // Speaker Allocation Data Block
  508. DBGMSG("Speaker Allocation Data Block\n");
  509. break;
  510. case 5: // VESA DTC Data Block
  511. DBGMSG("VESA DTC Data Block\n");
  512. break;
  513. case 7: // Use Extended Tag
  514. DBGMSG("Use Extended Tag\n");
  515. break;
  516. case 0: // Reserved
  517. default:
  518. len = 0;
  519. break;
  520. }
  521. block += (1+len);
  522. } while(len);
  523.  
  524. block = edid + edid[2];
  525. for(i=0; i<6; i++, block += 18 ){
  526. pixclk = ((block[1]<<8)+block[0])*10000;
  527. if( pixclk == 0 ) break;
  528. hpixel = ((block[4]&0xF0)<<4)+block[2];
  529. hporch = ((block[4]&0x0F)<<8)+block[3];
  530. vpixel = ((block[7]&0xF0)<<4)+block[5];
  531. vporch = ((block[7]&0x0F)<<8)+block[6];
  532. fps = pixclk / ((hpixel+hporch)*(vpixel+vporch));
  533. if( block[17] & 0x80 ) vpixel *= 2;
  534. if( fps == 59 ) fps = 60;
  535. DBGMSG("Support %dx%d%s@%d,clk %d\n",hpixel,vpixel,(block[17]&0x80)?"I":"P",fps,pixclk);
  536. edid_info.cea_timing[i].resx = hpixel;
  537. edid_info.cea_timing[i].resy = vpixel;
  538. edid_info.cea_timing[i].freq = fps;
  539. }
  540. return 0;
  541. }
  542.  
  543. int edid_parse(unsigned char *edid)
  544. {
  545. int ext_cnt = 0;
  546.  
  547. if( edid == 0 )
  548. return 0;
  549.  
  550. if( edid_parse_v1(edid) == 0 ){
  551. ext_cnt = edid[0x7E];
  552. }
  553.  
  554. while( ext_cnt ){
  555. edid += 128;
  556. ext_cnt--;
  557. if( edid_parse_CEA(edid) == 0 ){
  558. continue;
  559. }
  560.  
  561. DPRINT("*W* not support EDID\n");
  562. edid_dump(edid);
  563. }
  564. return 0;
  565. }
  566.  
  567. int edid_find_support(unsigned int resx,unsigned int resy,int freq)
  568. {
  569. int ret;
  570. int i;
  571.  
  572. ret = 0;
  573. if( edid_info.establish_timing == 0 ){
  574. goto find_end;
  575. }
  576.  
  577. // find established timing
  578. for(i=0;i<17;i++){
  579. if( edid_info.establish_timing & (0x1 << i) ){
  580. if( (resx == edid_establish_timing[i].resx) && (resy == edid_establish_timing[i].resy) ){
  581. if( freq == edid_establish_timing[i].freq ){
  582. ret = 1;
  583. goto find_end;
  584. }
  585. }
  586. }
  587. }
  588.  
  589. // find standard timing
  590. for(i=0;i<8;i++){
  591. if( edid_info.standard_timing[i].resx == 0 )
  592. continue;
  593. if( (resx == edid_info.standard_timing[i].resx) && (resy == edid_info.standard_timing[i].resy) ){
  594. if( freq == edid_info.standard_timing[i].freq ){
  595. ret = 1;
  596. goto find_end;
  597. }
  598. }
  599. }
  600.  
  601. // find detail timing
  602. for(i=0;i<4;i++){
  603. if( edid_info.detail_timing[i].resx == 0 )
  604. continue;
  605. if( (resx == edid_info.detail_timing[i].resx) && (resy == edid_info.detail_timing[i].resy) ){
  606. if( freq == edid_info.detail_timing[i].freq ){
  607. ret = 1;
  608. goto find_end;
  609. }
  610. }
  611. }
  612.  
  613. // find cea timing
  614. for(i=0;i<6;i++){
  615. if( edid_info.cea_timing[i].resx == 0 )
  616. continue;
  617. if( (resx == edid_info.cea_timing[i].resx) && (resy == edid_info.cea_timing[i].resy) ){
  618. if( freq == edid_info.cea_timing[i].freq ){
  619. ret = 1;
  620. goto find_end;
  621. }
  622. }
  623. }
  624. find_end:
  625. printk("[EDID] %s support %dx%d@%d\n",(ret)? "":"No",resx,resy,freq);
  626. return ret;
  627. }
  628.  
  629. int edid_find_support_vic(char vic)
  630. {
  631. int i;
  632.  
  633. if( vic == 0 )
  634. return 0;
  635.  
  636. for(i=0;i<16;i++){
  637. if( edid_info.cea_vic[i] == vic )
  638. break;
  639. if( edid_info.cea_vic[i] == 0 )
  640. return 0;
  641. }
  642. printk("[EDID] support vic %d\n",vic);
  643. return 1;
  644. }
  645.  
  646. int edid_parse_option(unsigned char *edid)
  647. {
  648. int option = 0;
  649. unsigned char *block;
  650. unsigned char checksum = 0;
  651. int i,len;
  652. int ext_cnt;
  653.  
  654. if( edid == 0 ){
  655. DBGMSG("*E* buf pointer invalid\n");
  656. return 0;
  657. }
  658.  
  659. for( i = 0; i < EDID_LENGTH; i++ )
  660. checksum += edid[ i ];
  661. if ( checksum != 0 ) {
  662. DPRINT("*E* EDID checksum failed - data is corrupt\n" );
  663. }
  664.  
  665. if ( memcmp( edid+EDID_HEADER, edid_v1_header, EDID_HEADER_END+1 ) ) {
  666. DBGMSG("*E* first bytes don't match EDID version 1 header\n");
  667. edid_dump(edid);
  668. return 0;
  669. }
  670. ext_cnt = edid[0x7E];
  671. if( ext_cnt > 1 ){
  672. DPRINT("*W* edid ext cnt %d\n",ext_cnt);
  673. ext_cnt = 1;
  674. }
  675.  
  676. while( ext_cnt ){
  677. edid += 128;
  678. ext_cnt--;
  679.  
  680. if((edid[0]!=0x2) || (edid[1]!=0x3)){
  681. continue;
  682. }
  683.  
  684. for( i = 0; i < EDID_LENGTH; i++ )
  685. checksum += edid[ i ];
  686.  
  687. if ( checksum != 0 ) {
  688. DBGMSG("*E* CEA EDID checksum failed - data is corrupt\n" );
  689. // continue;
  690. }
  691.  
  692. option = (edid[3] & 0xF0) | EDID_OPT_VALID;
  693. DBGMSG("\t %s support 422\n", (edid[3] & 0x10)? "":"no" );
  694. DBGMSG("\t %s support 444\n", (edid[3] & 0x20)? "":"no" );
  695. DBGMSG("\t %s support audio\n", (edid[3] & 0x40)? "":"no" );
  696. DBGMSG("\t %s support underscan\n", (edid[3] & 0x80)? "":"no" );
  697.  
  698. block = edid + 4;
  699. do {
  700. len = block[0] & 0x1F;
  701. switch(((block[0] & 0xE0)>>5)){
  702. case 1: // Audio Data Block
  703. DBGMSG("Audio Data Block\n");
  704. DBGMSG("\t Max channel %d\n", (edid[1] & 0x7)+1 );
  705. DBGMSG("\t %s support 32 KHz\n", (edid[2] & 0x1)? "":"no" );
  706. DBGMSG("\t %s support 44 KHz\n", (edid[2] & 0x2)? "":"no" );
  707. DBGMSG("\t %s support 48 KHz\n", (edid[2] & 0x4)? "":"no" );
  708. DBGMSG("\t %s support 88 KHz\n", (edid[2] & 0x8)? "":"no" );
  709. DBGMSG("\t %s support 96 KHz\n", (edid[2] & 0x10)? "":"no" );
  710. DBGMSG("\t %s support 176 KHz\n", (edid[2] & 0x20)? "":"no" );
  711. DBGMSG("\t %s support 192 KHz\n", (edid[2] & 0x40)? "":"no" );
  712. DBGMSG("\t %s support 16 bit\n", (edid[3] & 0x1)? "":"no" );
  713. DBGMSG("\t %s support 20 bit\n", (edid[3] & 0x2)? "":"no" );
  714. DBGMSG("\t %s support 24 bit\n", (edid[3] & 0x4)? "":"no" );
  715. break;
  716. case 2: // Video Data Block
  717. DBGMSG("Video Data Block\n");
  718. break;
  719. case 3: // Vendor Spec Data Block
  720. DBGMSG("Vendor Spec Data Block\n");
  721. if( (block[1]==0x03) && (block[2]==0x0C) && (block[3]==0x0)){ // IEEE Registration Identifier 0x000C03
  722. option |= EDID_OPT_HDMI;
  723. DBGMSG("\t support HDMI\n");
  724. }
  725. break;
  726. case 4: // Speaker Allocation Data Block
  727. DBGMSG("Speaker Allocation Data Block\n");
  728. break;
  729. case 5: // VESA DTC Data Block
  730. DBGMSG("VESA DTC Data Block\n");
  731. break;
  732. case 7: // Use Extended Tag
  733. DBGMSG("Use Extended Tag\n");
  734. break;
  735. case 0: // Reserved
  736. default:
  737. len = 0;
  738. break;
  739. }
  740. block += (1+len);
  741. } while(len);
  742. }
  743. return option;
  744. }
  745.  
  746. int edid_check_block(char *edid)
  747. {
  748. unsigned char checksum = 0;
  749. int i;
  750.  
  751. if( edid == 0 ){
  752. DBGMSG("*E* buf pointer invalid\n");
  753. return 1;
  754. }
  755.  
  756. for( i = 0; i < EDID_LENGTH; i++ )
  757. checksum += edid[ i ];
  758. if ( checksum != 0 ) {
  759. DPRINT("*E* EDID checksum failed - data is corrupt\n" );
  760. return 1;
  761. }
  762. return 0;
  763. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement