1/*
2	Haiku S3 Virge driver adapted from the X.org Virge and Savage driver.
3
4	Copyright (C) 1994-2000 The XFree86 Project, Inc.  All Rights Reserved.
5
6	Copyright 2007-2008 Haiku, Inc.  All rights reserved.
7	Distributed under the terms of the MIT license.
8
9	Authors:
10	Gerald Zajac 2007-2008
11*/
12
13#include "accel.h"
14#include "virge.h"
15
16#include <string.h>
17#include <ddc.h>
18#include <edid.h>
19
20
21
22static status_t
23GetI2CSignals_Alt(void* cookie, int* _clock, int* data)
24{
25	uint32 index = (uint32)(addr_t)cookie;
26	uint8 value = ReadCrtcReg(index);
27
28	*_clock = (value & 0x4) != 0;
29	*data = (value & 0x8) != 0;
30	return B_OK;
31}
32
33
34static status_t
35SetI2CSignals_Alt(void* cookie, int _clock, int data)
36{
37	uint32 index = (uint32)(addr_t)cookie;
38	uint8 value = 0x10;
39
40	if (_clock)
41		value |= 0x1;
42	if (data)
43		value |= 0x2;
44
45	WriteCrtcReg(index, value);
46	return B_OK;
47}
48
49
50
51static status_t
52GetI2CSignals(void* cookie, int* _clock, int* data)
53{
54	(void)cookie;		// avoid compiler warning for unused arg
55
56	uint8 reg = ReadReg8(DDC_REG);
57
58	*_clock = (reg & 0x4) != 0;
59	*data = (reg & 0x8) != 0;
60	return B_OK;
61}
62
63
64static status_t
65SetI2CSignals(void* cookie, int _clock, int data)
66{
67	(void)cookie;		// avoid compiler warning for unused arg
68
69	uint8 reg = 0x10;
70
71	if (_clock)
72		reg |= 0x1;
73	if (data)
74		reg |= 0x2;
75
76	WriteReg8(DDC_REG, reg);
77	return B_OK;
78}
79
80
81
82bool
83Virge_GetEdidInfo(edid1_info& edidInfo)
84{
85	// Get the EDID info and return true if successful.
86
87	SharedInfo& si = *gInfo.sharedInfo;
88
89	bool bResult = false;
90
91	if (si.chipType == S3_TRIO_3D_2X) {
92		uint32 DDCPort = 0xAA;
93
94		i2c_bus bus;
95		bus.cookie = (void*)(addr_t)DDCPort;
96		bus.set_signals = &SetI2CSignals_Alt;
97		bus.get_signals = &GetI2CSignals_Alt;
98		ddc2_init_timing(&bus);
99
100		uint8 tmp = ReadCrtcReg(DDCPort);
101		WriteCrtcReg(DDCPort, tmp | 0x13);
102
103		bResult = (ddc2_read_edid1(&bus, &edidInfo, NULL, NULL) == B_OK);
104
105		WriteCrtcReg(DDCPort, tmp);
106	} else {
107		i2c_bus bus;
108		bus.cookie = (void*)DDC_REG;
109		bus.set_signals = &SetI2CSignals;
110		bus.get_signals = &GetI2CSignals;
111		ddc2_init_timing(&bus);
112
113		uint8 tmp = ReadReg8(DDC_REG);
114		WriteReg8(DDC_REG, tmp | 0x13);
115
116		bResult = (ddc2_read_edid1(&bus, &edidInfo, NULL, NULL) == B_OK);
117
118		WriteReg8(DDC_REG, tmp);
119	}
120
121	return bResult;
122}
123