1 /* 2 Copyright (c) 2003, Thomas Kurschel 3 4 5 Part of DDC driver 6 7 Main DDC communication 8 */ 9 10 #include <OS.h> 11 #include <KernelExport.h> 12 #include <stdlib.h> 13 #include "ddc_int.h" 14 #include "ddc.h" 15 16 #include "i2c.h" 17 18 // number of retries to read ddc data 19 #define READ_RETRIES 4 20 21 // verify checksum of ddc data 22 // (some monitors have a broken checksum - bad luck for them) 23 static status_t verify_checksum( const uint8 *data, size_t len ) 24 { 25 int i; 26 uint8 sum = 0; 27 uint8 all_or = 0; 28 29 for( i = 0; i < len; ++i, ++data ) { 30 sum += *data; 31 all_or |= *data; 32 } 33 34 if( all_or == 0 ) { 35 SHOW_ERROR0( 2, "DDC information contains zeros only" ); 36 return B_ERROR; 37 } 38 39 if( sum != 0 ) { 40 SHOW_ERROR0( 2, "Checksum error of DDC information" ); 41 return B_IO_ERROR; 42 } 43 44 return B_OK; 45 } 46 47 // read ddc2 data from monitor 48 static status_t ddc2_read( const i2c_bus *bus, int start, uint8 *buffer, size_t len ) 49 { 50 uint8 write_buffer[2]; 51 i2c_timing timing; 52 int i; 53 status_t res; 54 55 write_buffer[0] = start & 0xff; 56 write_buffer[1] = (start >> 8) & 0xff; 57 58 i2c_get100k_timing( &timing ); 59 60 timing.start_timeout = 550; 61 timing.byte_timeout = 2200; 62 timing.bit_timeout = 40; 63 timing.ack_start_timeout = 40; 64 timing.ack_timeout = 40; 65 66 for( i = 0; i < READ_RETRIES; ++i ) { 67 res = i2c_send_receive( bus, &timing, 68 0xa0, write_buffer, start < 0x100 ? 1 : 2, 69 buffer, len ); 70 // don't verify checksum - it's often broken 71 if( res == B_OK /*&& verify_checksum( buffer, len ) == B_OK*/ ) 72 break; 73 74 res = B_ERROR; 75 } 76 77 return res; 78 } 79 80 81 // reading VDIF has not been tested. 82 // it seems that almost noone supports VDIF which makes testing hard, 83 // but what's the point anyway? 84 #if 0 85 static status_t ddc2_read_vdif( const i2c_bus *bus, int start, 86 void **vdif, size_t *vdif_len ) 87 { 88 status_t res; 89 uint8 *data, *cur_data; 90 int i; 91 uint8 buffer[64]; 92 93 *vdif = NULL; 94 *vdif_len = 0; 95 96 res = ddc2_read( bus, start, buffer, 64 ); 97 SHOW_INFO( 2, "%x", buffer[0] ); 98 if( res != B_OK || buffer[0] == 0 ) 99 return B_OK; 100 101 // each block is 63 bytes plus 1 checksum long 102 // we strip the checksum but store data directly into 103 // buffer, so we need an extra byte for checksum of the last block 104 data = malloc( buffer[0] * 63 + 1 ); 105 if( data == NULL ) 106 return B_NO_MEMORY; 107 108 cur_data = data; 109 for( i = 0; i < buffer[0]; ++i ) { 110 ddc2_read( bus, start + i * 64, cur_data, 64 ); 111 // strip checksum byte 112 cur_data += 63; 113 } 114 115 *vdif_len = buffer[0] * 63; 116 *vdif = data; 117 return B_OK; 118 } 119 #endif 120 121 // read EDID and VDIF from monitor via ddc2 122 status_t ddc2_read_edid1( const i2c_bus *bus, edid1_info *edid, 123 void **vdif, size_t *vdif_len ) 124 { 125 status_t res; 126 edid1_raw raw; 127 128 res = ddc2_read( bus, 0, (uint8 *)&raw, sizeof( raw )); 129 if( res != B_OK ) 130 return res; 131 132 edid_decode( edid, &raw ); 133 134 *vdif = NULL; 135 *vdif_len = 0; 136 137 // skip vdif as long as it's not tested 138 #if 0 139 res = ddc2_read_vdif( bus, sizeof( raw ) * (edid->num_sections + 1), 140 vdif, vdif_len ); 141 if( res != B_OK ) 142 return res; 143 #endif 144 145 return B_OK; 146 } 147