1 /*
2 * i2c interface for the G400 MAVEN under BeOS
3 *
4 * Provides I2CR,I2CW - functions to parallel DACW,DACR
5 * Bus should be run at max. 100kHz: see original Philips I2C specification
6 *
7 * Much help was provided by observing the Linux i2c code,
8 * so thanks go to: Gerd Knorr
9 *
10 * Other authors:
11 * Mark Watson 6/2000,
12 * Rudolf Cornelissen 12/2002-12/2003
13 */
14
15 #define MODULE_BIT 0x00004000
16
17 #include "std.h"
18
19 int i2c_set_lines(int clock, int data);
20 int i2c_get_data(void);
21 void i2c_start(void);
22 void i2c_stop(void);
23 void i2c_high(void);
24 void i2c_low(void);
25 int i2c_get_ack(void);
26 void i2c_send_ack(void);
27 int i2c_sendbyte(unsigned char data);
28 unsigned char i2c_readbyte(int ack_required);
29
30 /*which device on the bus is the MAVEN?*/
31 #define MAVEN_WRITE (0x1B<<1)
32 #define MAVEN_READ ((0x1B<<1)|1)
33
34 #define I2C_CLOCK 0x20
35 #define I2C_DATA 0x10
36
37 /* NV-TVO I2C for G200, G400 */
38 #define I2C_CLOCK 0x20
39 #define I2C_DATA 0x10
40 /* primary head DDC for Mystique(?), G100, G200, G400 */
41 #define DDC1_CLK 0x08
42 #define DDC1_DATA 0x02
43 /* primary head DDC for Millennium, Millennium II */
44 #define DDC1B_CLK 0x10
45 #define DDC1B_DATA 0x04
46 /* secondary head DDC for G400, G450 and G550 */
47 #define DDC2_CLK 0x04
48 #define DDC2_DATA 0x01
49
i2c_sec_tv_adapter()50 status_t i2c_sec_tv_adapter()
51 {
52 status_t result = B_ERROR;
53
54 /* The secondary DDC channel only exist on dualhead cards */
55 if (!si->ps.secondary_head) return result;
56
57 /* make sure the output lines will be active-low when enabled
58 * (they will be pulled 'passive-high' when disabled) */
59 // DXIW(GENIODATA,0x00);
60 /* send out B_STOP condition on secondary head DDC channel and use it to
61 * check for 'shortcut', indicating the Matrox VGA->TV adapter is connected */
62
63 /* make sure SDA is low */
64 // DXIW(GENIOCTRL, (DXIR(GENIOCTRL) | DDC2_DATA));
65 snooze(2);
66 /* make sure SCL should be high */
67 // DXIW(GENIOCTRL, (DXIR(GENIOCTRL) & ~DDC2_CLK));
68 snooze(2);
69 /* if SCL is low then the bus is blocked by a TV adapter */
70 // if (!(DXIR(GENIODATA) & DDC2_CLK)) result = B_OK;
71 snooze(5);
72 /* set SDA while SCL should be set (generates actual bus-stop condition) */
73 // DXIW(GENIOCTRL, (DXIR(GENIOCTRL) & ~DDC2_DATA));
74 snooze(5);
75
76 return result;
77 }
78
79 /*-----------------------------
80 *low level hardware access
81 */
82 #define I2C_DELAY 2
83 #define I2C_TIMEOUT 100
i2c_set_lines(int clock,int data)84 int i2c_set_lines(int clock,int data)
85 {
86 int count=0;
87 int program;
88 int required;
89
90 /*work out which bits to zero*/
91 program =
92 (clock ? 0 : I2C_CLOCK)|
93 (data ? 0 : I2C_DATA);
94
95 /*what value do I require on data lines*/
96 required =
97 (clock ? I2C_CLOCK : 0);
98
99 /*set the bits to zero*/
100 // DXIW(GENIOCTRL,program); /*drive these bits*/
101 // DXIW(GENIODATA,0x00); /*to zero*/
102
103 /*wait a bit*/
104 delay(I2C_DELAY);
105
106 /*loop until the clock is as required*/
107 // while ((DXIR(GENIODATA)&I2C_CLOCK)!=required)
108 {
109 delay(I2C_DELAY);
110 count++;
111 if (count>I2C_TIMEOUT)
112 {
113 // LOG(8,("I2C: Timeout on set lines - clock:%d data:%d actual:%x\n",clock,data,DXIR(GENIODATA)));
114 return -1;
115 }
116 }
117
118 return 0;
119 }
120
i2c_get_data()121 int i2c_get_data()
122 {
123 int data = 0;
124 int clock;
125 int count=0;
126
127 do
128 {
129 /*read the data and clock lines*/
130 // data = DXIR(GENIODATA);
131 clock = (data&I2C_CLOCK) ? 1 : 0;
132 data = (data&I2C_DATA) ? 1 : 0;
133
134 /*manage timeout*/
135 count++;
136 if (count>I2C_TIMEOUT)
137 {
138 return -1;
139 }
140
141 /*wait a bit, so not hammering bus*/
142 delay(I2C_DELAY);
143
144 }while (!clock); /*wait for high clock*/
145
146 return data;
147 }
148
149
150 /*-----------------------
151 *Standard I2C operations
152 */
i2c_start()153 void i2c_start()
154 {
155 int error=0;
156
157 error+= i2c_set_lines(0,1);
158 error+= i2c_set_lines(1,1);
159 error+= i2c_set_lines(1,0);
160 error+= i2c_set_lines(0,0);
161
162 if (error)
163 {
164 LOG(8,("I2C: start - %d\n",error));
165 }
166 }
167
i2c_stop()168 void i2c_stop()
169 {
170 int error=0;
171
172 error+= i2c_set_lines(0,0);
173 error+= i2c_set_lines(1,0);
174 error+= i2c_set_lines(1,1);
175 error+= i2c_set_lines(0,1);
176
177 if (error)
178 {
179 LOG(8,("I2C: stop - %d\n",error));
180 }
181 }
182
i2c_high()183 void i2c_high()
184 {
185 int error=0;
186
187 error+= i2c_set_lines(0,1);
188 error+= i2c_set_lines(1,1);
189 error+= i2c_set_lines(0,1);
190
191 if (error)
192 {
193 LOG(8,("I2C: high - %d\n",error));
194 }
195 }
196
i2c_low()197 void i2c_low()
198 {
199 int error=0;
200
201 error+= i2c_set_lines(0,0);
202 error+= i2c_set_lines(1,0);
203 error+= i2c_set_lines(0,0);
204
205 if (error)
206 {
207 LOG(8,("I2C: low - %d\n",error));
208 }
209 }
210
i2c_get_ack()211 int i2c_get_ack()
212 {
213 int error=0;
214 int ack;
215
216 error+= i2c_set_lines(0,1);
217 error+= i2c_set_lines(1,1);
218 ack = i2c_get_data();
219 error+= i2c_set_lines(0,1);
220
221 if (error)
222 {
223 LOG(8,("I2C: get_ack - %d value:%x\n",error,ack));
224 }
225
226 return ack;
227 }
228
i2c_send_ack()229 void i2c_send_ack()
230 {
231 int error=0;
232
233 error+= i2c_set_lines(0,0);
234 error+= i2c_set_lines(1,0);
235 error+= i2c_set_lines(0,0);
236
237 if (error)
238 {
239 LOG(8,("I2C: send_ack - %d\n",error));
240 }
241 }
242
243 /*------------------------------
244 *use above functions to send and receive bytes
245 */
246
i2c_sendbyte(unsigned char data)247 int i2c_sendbyte(unsigned char data)
248 {
249 int i;
250
251 for (i=7; i>=0; i--)
252 {
253 if (data&(1<<i))
254 {
255 i2c_high();
256 }
257 else
258 {
259 i2c_low();
260 }
261 }
262
263 return i2c_get_ack();
264 }
265
i2c_readbyte(int ack_required)266 unsigned char i2c_readbyte(int ack_required)
267 {
268 int i;
269 unsigned char data=0;
270
271 /*read data*/
272 i2c_set_lines(0,1);
273 for (i=7; i>=0; i--)
274 {
275 i2c_set_lines(1,1);
276 if (i2c_get_data()==1)
277 data |= (1<<i);
278 i2c_set_lines(0,1);
279 }
280
281 /*send acknowledge*/
282 if (ack_required) i2c_send_ack();
283
284 return data;
285 }
286
287 /*-------------------------------------------
288 *PUBLIC functions
289 */
i2c_maven_read(unsigned char address)290 int i2c_maven_read(unsigned char address)
291 {
292 int error=0;
293 int data;
294
295 i2c_start();
296 {
297 error+=i2c_sendbyte(MAVEN_READ);
298 error+=i2c_sendbyte(address);
299 data = i2c_readbyte(0);
300 }
301 i2c_stop();
302 if (error>0) LOG(8,("I2C: MAVR ERROR - %x\n",error));
303 return data;
304 }
305
i2c_maven_write(unsigned char address,unsigned char data)306 void i2c_maven_write(unsigned char address, unsigned char data)
307 {
308 int error=0;
309
310 i2c_start();
311 {
312 error+=i2c_sendbyte(MAVEN_WRITE);
313 error+=i2c_sendbyte(address);
314 error+=i2c_sendbyte(data);
315 }
316 i2c_stop();
317 if (error>0) LOG(8,("I2C: MAVW ERROR - %x\n",error));
318 }
319
i2c_init(void)320 status_t i2c_init(void)
321 {
322 /*init g400 i2c*/
323 // DXIW(GENIODATA,0x00); /*to zero*/
324 // DXIW(GENIOCTRL,0x30); /*drive clock and data*/
325 // DXIW(GENIOCTRL,0x00); /*stop driving*/
326
327 return B_OK;
328 }
329
i2c_maven_probe(void)330 status_t i2c_maven_probe(void)
331 {
332 int ack;
333
334 /*scan the bus for the MAVEN*/
335 i2c_start();
336 {
337 ack = i2c_sendbyte(MAVEN_READ);
338 }
339 i2c_stop();
340 if (ack==0)
341 {
342 return B_OK;
343 }
344 else
345 {
346 return B_ERROR;
347 }
348 }
349