xref: /haiku/src/add-ons/accelerants/common/ddc.c (revision ed6250c95736c0b55da79d6e9dd01369532260c0)
1 /*
2  * Copyright 2003, Thomas Kurschel. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 /*!
7 	DDC communication
8 */
9 
10 
11 #include "ddc_int.h"
12 #include "ddc.h"
13 #include "i2c.h"
14 
15 #include <KernelExport.h>
16 #include <OS.h>
17 
18 #include <stdlib.h>
19 
20 
21 #define READ_RETRIES 4
22 	// number of retries to read ddc data
23 
24 #if 0
25 /*!	Verify checksum of ddc data
26 	(some monitors have a broken checksum - bad luck for them)
27 */
28 static status_t
29 verify_checksum(const uint8 *data, size_t len)
30 {
31 	uint32 index;
32 	uint8 sum = 0;
33 	uint8 all_or = 0;
34 
35 	for (index = 0; index < len; ++index, ++data) {
36 		sum += *data;
37 		all_or |= *data;
38 	}
39 
40 	if (all_or == 0) {
41 		SHOW_ERROR0(2, "DDC information contains zeros only");
42 		return B_ERROR;
43 	}
44 
45 	if (sum != 0) {
46 		SHOW_ERROR0(2, "Checksum error of DDC information");
47 		return B_IO_ERROR;
48 	}
49 
50 	return B_OK;
51 }
52 #endif
53 
54 
55 //!	Read ddc2 data from monitor
56 static status_t
57 ddc2_read(const i2c_bus *bus, int start, uint8 *buffer, size_t length)
58 {
59 	status_t status = B_OK;
60 	uint8 writeBuffer[2];
61 	int i;
62 
63 	writeBuffer[0] = start & 0xff;
64 	writeBuffer[1] = (start >> 8) & 0xff;
65 
66 	for (i = 0; i < READ_RETRIES; ++i) {
67 		status = i2c_send_receive(bus, 0xa0, writeBuffer,
68 			start < 0x100 ? 1 : 2, buffer, length);
69 		// don't verify checksum - it's often broken
70 		if (status == B_OK /*&& verify_checksum( buffer, len ) == B_OK*/)
71 			break;
72 
73 		status = B_ERROR;
74 	}
75 
76 	return status;
77 }
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 */
85 #if 0
86 static status_t
87 ddc2_read_vdif(const i2c_bus *bus, int start,
88 	void **vdif, size_t *vdif_len)
89 {
90 	status_t res;
91 	uint8 *data, *cur_data;
92 	int i;
93 	uint8 buffer[64];
94 
95 	*vdif = NULL;
96 	*vdif_len = 0;
97 
98 	res = ddc2_read(bus, start, buffer, 64);
99 	SHOW_INFO(2, "%x", buffer[0]);
100 	if (res != B_OK || buffer[0] == 0)
101 		return B_OK;
102 
103 	// each block is 63 bytes plus 1 checksum long
104 	// we strip the checksum but store data directly into
105 	// buffer, so we need an extra byte for checksum of the last block
106 	data = malloc(buffer[0] * 63 + 1);
107 	if (data == NULL)
108 		return B_NO_MEMORY;
109 
110 	cur_data = data;
111 	for (i = 0; i < buffer[0]; ++i) {
112 		ddc2_read(bus, start + i * 64, cur_data, 64);
113 		// strip checksum byte
114 		cur_data += 63;
115 	}
116 
117 	*vdif_len = buffer[0] * 63;
118 	*vdif = data;
119 	return B_OK;
120 }
121 #endif
122 
123 
124 void
125 ddc2_init_timing(i2c_bus *bus)
126 {
127 	i2c_get100k_timing(&bus->timing);
128 
129 	// VESA standard
130 	bus->timing.start_timeout = 550;
131 	bus->timing.byte_timeout = 2200;
132 	bus->timing.bit_timeout = 40;
133 	bus->timing.ack_start_timeout = 40;
134 	bus->timing.ack_timeout = 40;
135 }
136 
137 
138 //! Read EDID and VDIF from monitor via ddc2
139 status_t
140 ddc2_read_edid1(const i2c_bus *bus, edid1_info *edid,
141 	void **vdif, size_t *vdifLength)
142 {
143 	edid1_raw raw;
144 	status_t status = ddc2_read(bus, 0, (uint8 *)&raw, sizeof(raw));
145 	if (status != B_OK)
146 		return status;
147 
148 	edid_decode(edid, &raw);
149 
150 	if (vdif != NULL)
151 		*vdif = NULL;
152 	if (vdifLength != NULL)
153 		*vdifLength = 0;
154 
155 	// skip vdif as long as it's not tested
156 #if 0
157 	status = ddc2_read_vdif(bus, sizeof(raw) * (edid->num_sections + 1),
158 		vdif, vdifLength);
159 	if (status != B_OK)
160 		return status;
161 #endif
162 
163 	return B_OK;
164 }
165