xref: /haiku/src/add-ons/accelerants/common/ddc.c (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
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