27b48d975SAxel Dörfler * Copyright 2003, Thomas Kurschel. All Rights Reserved.
37b48d975SAxel Dörfler * Distributed under the terms of the MIT License.
47b48d975SAxel Dörfler */
6c54a6536SAxel Dörfler/*!	DDC communication */
87b48d975SAxel Dörfler
9409f1731Sshadow#include "ddc_int.h"
102a37e4c1Sshadow#include "ddc.h"
11409f1731Sshadow#include "i2c.h"
137b48d975SAxel Dörfler#include <KernelExport.h>
147b48d975SAxel Dörfler#include <OS.h>
157b48d975SAxel Dörfler
167b48d975SAxel Dörfler#include <stdlib.h>
177b48d975SAxel Dörfler
187b48d975SAxel Dörfler
19c54a6536SAxel Dörfler#define READ_RETRIES 4		// number of retries to read ddc data
21c54a6536SAxel Dörfler#define TRACE_DDC
22c54a6536SAxel Dörfler#ifdef TRACE_DDC
23c54a6536SAxel Dörflerextern void _sPrintf(const char* format, ...);
24c54a6536SAxel Dörfler#	define TRACE(x...) _sPrintf("DDC: " x)
25c54a6536SAxel Dörfler#else
26c54a6536SAxel Dörfler#	define TRACE(x...) ;
27c54a6536SAxel Dörfler#endif
28c54a6536SAxel Dörfler
29c54a6536SAxel Dörfler
30c54a6536SAxel Dörfler//! Verify checksum of DDC data.
317b48d975SAxel Dörflerstatic status_t
327b48d975SAxel Dörflerverify_checksum(const uint8 *data, size_t len)
347b48d975SAxel Dörfler	uint32 index;
35409f1731Sshadow	uint8 sum = 0;
36c54a6536SAxel Dörfler	uint8 allOr = 0;
37c54a6536SAxel Dörfler
387b48d975SAxel Dörfler	for (index = 0; index < len; ++index, ++data) {
39409f1731Sshadow		sum += *data;
40c54a6536SAxel Dörfler		allOr |= *data;
41409f1731Sshadow	}
42c54a6536SAxel Dörfler
43c54a6536SAxel Dörfler	if (allOr == 0) {
4439bc159eSAlexander von Gluck IV		TRACE("%s: DDC information contains zeros only\n", __func__);
45409f1731Sshadow		return B_ERROR;
46409f1731Sshadow	}
47c54a6536SAxel Dörfler
487b48d975SAxel Dörfler	if (sum != 0) {
4939bc159eSAlexander von Gluck IV		TRACE("%s: Checksum error in DDC information\n", __func__);
50409f1731Sshadow		return B_IO_ERROR;
51409f1731Sshadow	}
52c54a6536SAxel Dörfler
53409f1731Sshadow	return B_OK;
557b48d975SAxel Dörfler
577b48d975SAxel Dörfler//!	Read ddc2 data from monitor
587b48d975SAxel Dörflerstatic status_t
5993a1ccabSAxel Dörflerddc2_read(const i2c_bus *bus, int start, uint8 *buffer, size_t length)
6193a1ccabSAxel Dörfler	status_t status = B_OK;
6293a1ccabSAxel Dörfler	uint8 writeBuffer[2];
63409f1731Sshadow	int i;
6539bc159eSAlexander von Gluck IV	writeBuffer[0] = start & 0xff;
6693a1ccabSAxel Dörfler	writeBuffer[1] = (start >> 8) & 0xff;
677b48d975SAxel Dörfler
687b48d975SAxel Dörfler	for (i = 0; i < READ_RETRIES; ++i) {
6993a1ccabSAxel Dörfler		status = i2c_send_receive(bus, 0xa0, writeBuffer,
7093a1ccabSAxel Dörfler			start < 0x100 ? 1 : 2, buffer, length);
717b48d975SAxel Dörfler
72c54a6536SAxel Dörfler		if (status != B_OK)
7339bc159eSAlexander von Gluck IV			TRACE("%s: DDC information read failure\n", __func__);
74c54a6536SAxel Dörfler
75c54a6536SAxel Dörfler		if (status == B_OK) {
76c54a6536SAxel Dörfler			status = verify_checksum(buffer, length);
77c54a6536SAxel Dörfler			if (status == B_OK)
78c54a6536SAxel Dörfler				break;
79c54a6536SAxel Dörfler
8039bc159eSAlexander von Gluck IV			dprintf("%s: DDC checksum incorrect!\n", __func__);
81c54a6536SAxel Dörfler		}
82409f1731Sshadow	}
837b48d975SAxel Dörfler
8493a1ccabSAxel Dörfler	return status;
887b48d975SAxel Dörfler/*!
8939bc159eSAlexander von Gluck IV	Reading VDIF has not been tested.
907b48d975SAxel Dörfler	it seems that almost noone supports VDIF which makes testing hard,
917b48d975SAxel Dörfler	but what's the point anyway?
927b48d975SAxel Dörfler*/
93409f1731Sshadow#if 0
947b48d975SAxel Dörflerstatic status_t
9539bc159eSAlexander von Gluck IVddc2_read_vdif(const i2c_bus *bus, int start,
967b48d975SAxel Dörfler	void **vdif, size_t *vdif_len)
98409f1731Sshadow	status_t res;
99409f1731Sshadow	uint8 *data, *cur_data;
100409f1731Sshadow	int i;
101409f1731Sshadow	uint8 buffer[64];
10239bc159eSAlexander von Gluck IV
103409f1731Sshadow	*vdif = NULL;
104409f1731Sshadow	*vdif_len = 0;
10539bc159eSAlexander von Gluck IV
1067b48d975SAxel Dörfler	res = ddc2_read(bus, start, buffer, 64);
1077b48d975SAxel Dörfler	SHOW_INFO(2, "%x", buffer[0]);
1087b48d975SAxel Dörfler	if (res != B_OK || buffer[0] == 0)
109409f1731Sshadow		return B_OK;
1107b48d975SAxel Dörfler
111409f1731Sshadow	// each block is 63 bytes plus 1 checksum long
112409f1731Sshadow	// we strip the checksum but store data directly into
113409f1731Sshadow	// buffer, so we need an extra byte for checksum of the last block
1147b48d975SAxel Dörfler	data = malloc(buffer[0] * 63 + 1);
1157b48d975SAxel Dörfler	if (data == NULL)
116409f1731Sshadow		return B_NO_MEMORY;
1177b48d975SAxel Dörfler
118409f1731Sshadow	cur_data = data;
1197b48d975SAxel Dörfler	for (i = 0; i < buffer[0]; ++i) {
1207b48d975SAxel Dörfler		ddc2_read(bus, start + i * 64, cur_data, 64);
121409f1731Sshadow		// strip checksum byte
122409f1731Sshadow		cur_data += 63;
123409f1731Sshadow	}
125409f1731Sshadow	*vdif_len = buffer[0] * 63;
126409f1731Sshadow	*vdif = data;
127409f1731Sshadow	return B_OK;
1317b48d975SAxel Dörfler
132c54a6536SAxel Dörfler//	#pragma mark -
133c54a6536SAxel Dörfler
134c54a6536SAxel Dörfler
13593a1ccabSAxel Dörflervoid
13693a1ccabSAxel Dörflerddc2_init_timing(i2c_bus *bus)
13793a1ccabSAxel Dörfler{
13893a1ccabSAxel Dörfler	i2c_get100k_timing(&bus->timing);
13993a1ccabSAxel Dörfler
14093a1ccabSAxel Dörfler	// VESA standard
14193a1ccabSAxel Dörfler	bus->timing.start_timeout = 550;
14293a1ccabSAxel Dörfler	bus->timing.byte_timeout = 2200;
14393a1ccabSAxel Dörfler	bus->timing.bit_timeout = 40;
14493a1ccabSAxel Dörfler	bus->timing.ack_start_timeout = 40;
14593a1ccabSAxel Dörfler	bus->timing.ack_timeout = 40;
14693a1ccabSAxel Dörfler}
14793a1ccabSAxel Dörfler
14893a1ccabSAxel Dörfler
1497b48d975SAxel Dörfler//! Read EDID and VDIF from monitor via ddc2
1507b48d975SAxel Dörflerstatus_t
15139bc159eSAlexander von Gluck IVddc2_read_edid1(const i2c_bus *bus, edid1_info *edid,
15293a1ccabSAxel Dörfler	void **vdif, size_t *vdifLength)
154409f1731Sshadow	edid1_raw raw;
15593a1ccabSAxel Dörfler	status_t status = ddc2_read(bus, 0, (uint8 *)&raw, sizeof(raw));
15693a1ccabSAxel Dörfler	if (status != B_OK)
15793a1ccabSAxel Dörfler		return status;
1587b48d975SAxel Dörfler
159c54a6536SAxel Dörfler	if (raw.version.version != 1 || raw.version.revision > 4) {
16039bc159eSAlexander von Gluck IV		TRACE("%s: EDID version or revision out of range\n", __func__);
161c54a6536SAxel Dörfler		return B_ERROR;
162c54a6536SAxel Dörfler	}
163c54a6536SAxel Dörfler
1647b48d975SAxel Dörfler	edid_decode(edid, &raw);
1657b48d975SAxel Dörfler
166fd7e4cc3SAxel Dörfler	if (vdif != NULL)
167fd7e4cc3SAxel Dörfler		*vdif = NULL;
168fd7e4cc3SAxel Dörfler	if (vdifLength != NULL)
169fd7e4cc3SAxel Dörfler		*vdifLength = 0;
171409f1731Sshadow	// skip vdif as long as it's not tested
172409f1731Sshadow#if 0
17393a1ccabSAxel Dörfler	status = ddc2_read_vdif(bus, sizeof(raw) * (edid->num_sections + 1),
174fd7e4cc3SAxel Dörfler		vdif, vdifLength);
17593a1ccabSAxel Dörfler	if (status != B_OK)
17693a1ccabSAxel Dörfler		return status;
17893a1ccabSAxel Dörfler
179409f1731Sshadow	return B_OK;