xref: /haiku/src/add-ons/accelerants/nvidia/engine/nv_i2c.c (revision cbe0a0c436162d78cc3f92a305b64918c839d079)
1 /*
2  * i2c interface.
3  * Bus should be run at max. 100kHz: see original Philips I2C specification
4  *
5  * Rudolf Cornelissen 12/2002-4/2021
6  */
7 
8 #define MODULE_BIT 0x00004000
9 
10 #include "nv_std.h"
11 
12 static void i2c_DumpSpecsEDID(edid_specs* specs);
13 
14 char i2c_flag_error (char ErrNo)
15 //error code list:
16 //0 - OK status
17 //1 - SCL locked low by device (bus is still busy)
18 //2 - SDA locked low by device (bus is still busy)
19 //3 - No Acknowledge from device (no handshake)
20 //4 - SDA not released for master to generate STOP bit
21 {
22 	static char I2CError = 0;
23 
24 	if (!I2CError) I2CError = ErrNo;
25 	if (ErrNo == -1) I2CError = 0;
26 	return I2CError;
27 }
28 
29 static void i2c_select_bus_set(bool set)
30 {
31 	/* I/O pins set selection is only valid on dualhead cards */
32 	if (!si->ps.secondary_head) return;
33 
34 	/* select GPU I/O pins set to connect to I2C 'registers' */
35 	if (set) {
36 		/* this setup wires the 'I2C registers' to unknown I/O pins on the GPU? */
37 		NV_REG32(NV32_FUNCSEL) &= ~0x00000010;
38 		NV_REG32(NV32_2FUNCSEL) |= 0x00000010;
39 	} else {
40 		/* this setup wires the 'I2C registers' to the I2C buses */
41 		NV_REG32(NV32_2FUNCSEL) &= ~0x00000010;
42 		NV_REG32(NV32_FUNCSEL) |= 0x00000010;
43 	}
44 }
45 
46 static void OutSCL(uint8 BusNR, bool Bit)
47 {
48 	uint8 data;
49 	uint32 data32;
50 
51 	if ((CFGR(DEVID) & 0xfff0ffff) == 0x024010de) {
52 		/* C51 chipset */
53 		switch (BusNR) {
54 		case 0:
55 			data32 = NV_REG32(NV32_NV4E_I2CBUS_0) & ~0x2f;
56 			if (Bit)
57 				NV_REG32(NV32_NV4E_I2CBUS_0) = data32 | 0x21;
58 			else
59 				NV_REG32(NV32_NV4E_I2CBUS_0) = data32 | 0x01;
60 			break;
61 		case 1:
62 			data32 = NV_REG32(NV32_NV4E_I2CBUS_1) & ~0x2f;
63 			if (Bit)
64 				NV_REG32(NV32_NV4E_I2CBUS_1) = data32 | 0x21;
65 			else
66 				NV_REG32(NV32_NV4E_I2CBUS_1) = data32 | 0x01;
67 			break;
68 		case 2:
69 			data32 = NV_REG32(NV32_NV4E_I2CBUS_2) & ~0x2f;
70 			if (Bit)
71 				NV_REG32(NV32_NV4E_I2CBUS_2) = data32 | 0x21;
72 			else
73 				NV_REG32(NV32_NV4E_I2CBUS_2) = data32 | 0x01;
74 			break;
75 		}
76 	} else {
77 		switch (BusNR) {
78 		case 0:
79 			data = (CRTCR(WR_I2CBUS_0) & 0xf0) | 0x01;
80 			if (Bit)
81 				CRTCW(WR_I2CBUS_0, (data | 0x20));
82 			else
83 				CRTCW(WR_I2CBUS_0, (data & ~0x20));
84 			break;
85 		case 1:
86 			data = (CRTCR(WR_I2CBUS_1) & 0xf0) | 0x01;
87 			if (Bit)
88 				CRTCW(WR_I2CBUS_1, (data | 0x20));
89 			else
90 				CRTCW(WR_I2CBUS_1, (data & ~0x20));
91 			break;
92 		case 2:
93 			data = (CRTCR(WR_I2CBUS_2) & 0xf0) | 0x01;
94 			if (Bit)
95 				CRTCW(WR_I2CBUS_2, (data | 0x20));
96 			else
97 				CRTCW(WR_I2CBUS_2, (data & ~0x20));
98 			break;
99 		}
100 	}
101 }
102 
103 static void OutSDA(uint8 BusNR, bool Bit)
104 {
105 	uint8 data;
106 	uint32 data32;
107 
108 	if ((CFGR(DEVID) & 0xfff0ffff) == 0x024010de) {
109 		/* C51 chipset */
110 		switch (BusNR) {
111 		case 0:
112 			data32 = NV_REG32(NV32_NV4E_I2CBUS_0) & ~0x1f;
113 			if (Bit)
114 				NV_REG32(NV32_NV4E_I2CBUS_0) = data32 | 0x11;
115 			else
116 				NV_REG32(NV32_NV4E_I2CBUS_0) = data32 | 0x01;
117 			break;
118 		case 1:
119 			data32 = NV_REG32(NV32_NV4E_I2CBUS_1) & ~0x1f;
120 			if (Bit)
121 				NV_REG32(NV32_NV4E_I2CBUS_1) = data32 | 0x11;
122 			else
123 				NV_REG32(NV32_NV4E_I2CBUS_1) = data32 | 0x01;
124 			break;
125 		case 2:
126 			data32 = NV_REG32(NV32_NV4E_I2CBUS_2) & ~0x1f;
127 			if (Bit)
128 				NV_REG32(NV32_NV4E_I2CBUS_2) = data32 | 0x11;
129 			else
130 				NV_REG32(NV32_NV4E_I2CBUS_2) = data32 | 0x01;
131 			break;
132 		}
133 	} else {
134 		switch (BusNR) {
135 		case 0:
136 			data = (CRTCR(WR_I2CBUS_0) & 0xf0) | 0x01;
137 			if (Bit)
138 				CRTCW(WR_I2CBUS_0, (data | 0x10));
139 			else
140 				CRTCW(WR_I2CBUS_0, (data & ~0x10));
141 			break;
142 		case 1:
143 			data = (CRTCR(WR_I2CBUS_1) & 0xf0) | 0x01;
144 			if (Bit)
145 				CRTCW(WR_I2CBUS_1, (data | 0x10));
146 			else
147 				CRTCW(WR_I2CBUS_1, (data & ~0x10));
148 			break;
149 		case 2:
150 			data = (CRTCR(WR_I2CBUS_2) & 0xf0) | 0x01;
151 			if (Bit)
152 				CRTCW(WR_I2CBUS_2, (data | 0x10));
153 			else
154 				CRTCW(WR_I2CBUS_2, (data & ~0x10));
155 			break;
156 		}
157 	}
158 }
159 
160 static bool InSCL(uint8 BusNR)
161 {
162 	if ((CFGR(DEVID) & 0xfff0ffff) == 0x024010de) {
163 		/* C51 chipset */
164 		switch (BusNR) {
165 		case 0:
166 			if (NV_REG32(NV32_NV4E_I2CBUS_0) & 0x00040000) return true;
167 			break;
168 		case 1:
169 			if (NV_REG32(NV32_NV4E_I2CBUS_1) & 0x00040000) return true;
170 			break;
171 		case 2:
172 			if (NV_REG32(NV32_NV4E_I2CBUS_2) & 0x00040000) return true;
173 			break;
174 		}
175 	} else {
176 		switch (BusNR) {
177 		case 0:
178 			if ((CRTCR(RD_I2CBUS_0) & 0x04)) return true;
179 			break;
180 		case 1:
181 			if ((CRTCR(RD_I2CBUS_1) & 0x04)) return true;
182 			break;
183 		case 2:
184 			if ((CRTCR(RD_I2CBUS_2) & 0x04)) return true;
185 			break;
186 		}
187 	}
188 
189 	return false;
190 }
191 
192 static bool InSDA(uint8 BusNR)
193 {
194 	if ((CFGR(DEVID) & 0xfff0ffff) == 0x024010de) {
195 		/* C51 chipset */
196 		switch (BusNR) {
197 		case 0:
198 			if (NV_REG32(NV32_NV4E_I2CBUS_0) & 0x00080000) return true;
199 			break;
200 		case 1:
201 			if (NV_REG32(NV32_NV4E_I2CBUS_1) & 0x00080000) return true;
202 			break;
203 		case 2:
204 			if (NV_REG32(NV32_NV4E_I2CBUS_2) & 0x00080000) return true;
205 			break;
206 		}
207 	} else {
208 		switch (BusNR) {
209 		case 0:
210 			if ((CRTCR(RD_I2CBUS_0) & 0x08)) return true;
211 			break;
212 		case 1:
213 			if ((CRTCR(RD_I2CBUS_1) & 0x08)) return true;
214 			break;
215 		case 2:
216 			if ((CRTCR(RD_I2CBUS_2) & 0x08)) return true;
217 			break;
218 		}
219 	}
220 
221 	return false;
222 }
223 
224 static void TXBit (uint8 BusNR, bool Bit)
225 {
226 	/* send out databit */
227 	if (Bit) {
228 		OutSDA(BusNR, true);
229 		snooze(3);
230 		if (!InSDA(BusNR)) i2c_flag_error (2);
231 	} else {
232 		OutSDA(BusNR, false);
233 	}
234 	/* generate clock pulse */
235 	snooze(6);
236 	OutSCL(BusNR, true);
237 	snooze(3);
238 	if (!InSCL(BusNR)) i2c_flag_error (1);
239 	snooze(6);
240 	OutSCL(BusNR, false);
241 	snooze(6);
242 }
243 
244 static uint8 RXBit (uint8 BusNR)
245 {
246 	uint8 Bit = 0;
247 
248 	/* set SDA so input is possible */
249 	OutSDA(BusNR, true);
250 	/* generate clock pulse */
251 	snooze(6);
252 	OutSCL(BusNR, true);
253 	snooze(3);
254 	if (!InSCL(BusNR)) i2c_flag_error (1);
255 	snooze(3);
256 	/* read databit */
257 	if (InSDA(BusNR)) Bit = 1;
258 	/* finish clockpulse */
259 	OutSCL(BusNR, false);
260 	snooze(6);
261 
262 	return Bit;
263 }
264 
265 void i2c_bstart (uint8 BusNR)
266 {
267 	/* enable access to primary head */
268 	set_crtc_owner(0);
269 
270 	/* make sure SDA is high */
271 	OutSDA(BusNR, true);
272 	snooze(3);
273 	OutSCL(BusNR, true);
274 	snooze(3);
275 	if (!InSCL(BusNR)) i2c_flag_error (1);
276 	snooze(6);
277 	/* clear SDA while SCL set (bus-start condition) */
278 	OutSDA(BusNR, false);
279 	snooze(6);
280 	OutSCL(BusNR, false);
281 	snooze(6);
282 
283 	LOG(4,("I2C: START condition generated on bus %d; status is %d\n",
284 		BusNR, i2c_flag_error (0)));
285 }
286 
287 void i2c_bstop (uint8 BusNR)
288 {
289 	/* enable access to primary head */
290 	set_crtc_owner(0);
291 
292 	/* make sure SDA is low */
293 	OutSDA(BusNR, false);
294 	snooze(3);
295 	OutSCL(BusNR, true);
296 	snooze(3);
297 	if (!InSCL(BusNR)) i2c_flag_error (1);
298 	snooze(6);
299 	/* set SDA while SCL set (bus-stop condition) */
300 	OutSDA(BusNR, true);
301 	snooze(3);
302 	if (!InSDA(BusNR)) i2c_flag_error (4);
303 	snooze(3);
304 
305 	LOG(4,("I2C: STOP condition generated on bus %d; status is %d\n",
306 		BusNR, i2c_flag_error (0)));
307 }
308 
309 uint8 i2c_readbyte(uint8 BusNR, bool Ack)
310 {
311 	uint8 cnt, bit, byte = 0;
312 
313 	/* enable access to primary head */
314 	set_crtc_owner(0);
315 
316 	/* read data */
317 	for (cnt = 8; cnt > 0; cnt--) {
318 		byte <<= 1;
319 		bit = RXBit (BusNR);
320 		byte += bit;
321 	}
322 	/* send acknowledge */
323 	TXBit (BusNR, Ack);
324 
325 	LOG(4,("I2C: read byte ($%02x) from bus #%d; status is %d\n",
326 		byte, BusNR, i2c_flag_error(0)));
327 
328 	return byte;
329 }
330 
331 bool i2c_writebyte (uint8 BusNR, uint8 byte)
332 {
333 	uint8 cnt;
334 	bool bit;
335 	uint8 tmp = byte;
336 
337 	/* enable access to primary head */
338 	set_crtc_owner(0);
339 
340 	/* write data */
341 	for (cnt = 8; cnt > 0; cnt--) {
342 		bit = (tmp & 0x80);
343 		TXBit (BusNR, bit);
344 		tmp <<= 1;
345 	}
346 	/* read acknowledge */
347 	bit = RXBit (BusNR);
348 	if (bit) i2c_flag_error (3);
349 
350 	LOG(4,("I2C: written byte ($%02x) to bus #%d; status is %d\n",
351 		byte, BusNR, i2c_flag_error(0)));
352 
353 	return bit;
354 }
355 
356 void i2c_readbuffer (uint8 BusNR, uint8* buf, uint8 size)
357 {
358 	uint8 cnt;
359 
360 	for (cnt = 0; cnt < size; cnt++)
361 		buf[cnt] = i2c_readbyte(BusNR, buf[cnt]);
362 }
363 
364 void i2c_writebuffer (uint8 BusNR, uint8* buf, uint8 size)
365 {
366 	uint8 cnt;
367 
368 	for (cnt = 0; cnt < size; cnt++)
369 		i2c_writebyte(BusNR, buf[cnt]);
370 }
371 
372 status_t i2c_init(void)
373 {
374 	uint8 bus, buses;
375 	bool *i2c_bus = &(si->ps.i2c_bus0);
376 	status_t result = B_ERROR;
377 
378 	LOG(4,("I2C: searching for wired I2C buses...\n"));
379 
380 	/* select GPU I/O pins for I2C buses */
381 	i2c_select_bus_set(false);
382 
383 	/* enable access to primary head */
384 	set_crtc_owner(0);
385 
386 	/* on some NV40 architecture cards the i2c busses can be disabled: enable them */
387 	if (si->ps.card_arch == NV40A)
388 		CRTCW(I2C_LOCK ,(CRTCR(I2C_LOCK) | 0x04));
389 
390 	/* preset no board wired buses */
391 	si->ps.i2c_bus0 = false;
392 	si->ps.i2c_bus1 = false;
393 	si->ps.i2c_bus2 = false;
394 
395 	/* set number of buses to test for */
396 	buses = 2;
397 
398 	/* newer cards (can) have a third bus.. */
399 	if (((si->ps.card_arch == NV10A) && (si->ps.card_type >= NV17)) || (si->ps.card_arch >= NV30A))
400 		buses = 3;
401 
402 	/* find existing buses */
403 	for (bus = 0; bus < buses; bus++) {
404 		/* reset status */
405 		i2c_flag_error (-1);
406 		snooze(6);
407 		/* init and/or stop I2C bus */
408 		i2c_bstop(bus);
409 		/* check for hardware coupling of SCL and SDA -out and -in lines */
410 		snooze(6);
411 		OutSCL(bus, false);
412 		snooze(3);
413 		OutSDA(bus, true);
414 		snooze(3);
415 		if (InSCL(bus) || !InSDA(bus)) continue;
416 		snooze(3);
417 		OutSCL(bus, true);
418 		snooze(3);
419 		OutSDA(bus, false);
420 		snooze(3);
421 		if (!InSCL(bus) || InSDA(bus)) continue;
422 		i2c_bus[bus] = true;
423 		snooze(3);
424 		/* re-init bus */
425 		i2c_bstop(bus);
426 	}
427 
428 	for (bus = 0; bus < buses; bus++) {
429 		if (i2c_bus[bus]) {
430 			LOG(4,("I2C: bus #%d wiring check: passed\n", bus));
431 			result = B_OK;
432 		} else {
433 			LOG(4,("I2C: bus #%d wiring check: failed\n", bus));
434 		}
435 	}
436 
437 	i2c_DetectScreens();
438 	LOG(4,("I2C: dumping EDID specs for connector 1:\n"));
439 	i2c_DumpSpecsEDID(&si->ps.con1_screen);
440 	LOG(4,("I2C: dumping EDID specs for connector 2:\n"));
441 	i2c_DumpSpecsEDID(&si->ps.con2_screen);
442 
443 	return result;
444 }
445 
446 /*** DDC/EDID library use ***/
447 typedef struct {
448 	uint8 port;
449 } ddc_port_info;
450 
451 /* Dump EDID info in driver's logfile */
452 static void
453 i2c_DumpEDID(edid1_info *edid)
454 {
455 	int i, j;
456 
457 	LOG(4,("Vendor: %s\n", edid->vendor.manufacturer));
458 	LOG(4,("Product ID: %d\n", (int)edid->vendor.prod_id));
459 	LOG(4,("Serial #: %d\n", (int)edid->vendor.serial));
460 	LOG(4,("Produced in week/year: %d/%d\n", edid->vendor.week, edid->vendor.year));
461 
462 	LOG(4,("EDID version: %d.%d\n", edid->version.version, edid->version.revision));
463 
464 	LOG(4,("Type: %s\n", edid->display.input_type ? "Digital" : "Analog"));
465 	LOG(4,("Size: %d cm x %d cm\n", edid->display.h_size, edid->display.v_size));
466 	LOG(4,("Gamma=%.3f\n", (edid->display.gamma + 100) / 100.0));
467 	LOG(4,("White (X,Y)=(%.3f,%.3f)\n", edid->display.white_x / 1024.0,
468 		edid->display.white_y / 1024.0));
469 
470 	LOG(4,("Supported Future Video Modes:\n"));
471 	for (i = 0; i < EDID1_NUM_STD_TIMING; ++i) {
472 		if (edid->std_timing[i].h_size <= 256)
473 			continue;
474 
475 		LOG(4,("%dx%d@%dHz (id=%d)\n",
476 			edid->std_timing[i].h_size, edid->std_timing[i].v_size,
477 			edid->std_timing[i].refresh, edid->std_timing[i].id));
478 	}
479 
480 	LOG(4,("Supported VESA Video Modes:\n"));
481 	if (edid->established_timing.res_720x400x70)
482 		LOG(4,("720x400@70\n"));
483 	if (edid->established_timing.res_720x400x88)
484 		LOG(4,("720x400@88\n"));
485 	if (edid->established_timing.res_640x480x60)
486 		LOG(4,("640x480@60\n"));
487 	if (edid->established_timing.res_640x480x67)
488 		LOG(4,("640x480x67\n"));
489 	if (edid->established_timing.res_640x480x72)
490 		LOG(4,("640x480x72\n"));
491 	if (edid->established_timing.res_640x480x75)
492 		LOG(4,("640x480x75\n"));
493 	if (edid->established_timing.res_800x600x56)
494 		LOG(4,("800x600@56\n"));
495 	if (edid->established_timing.res_800x600x60)
496 		LOG(4,("800x600@60\n"));
497 
498 	if (edid->established_timing.res_800x600x72)
499 		LOG(4,("800x600@72\n"));
500 	if (edid->established_timing.res_800x600x75)
501 		LOG(4,("800x600@75\n"));
502 	if (edid->established_timing.res_832x624x75)
503 		LOG(4,("832x624@75\n"));
504 	if (edid->established_timing.res_1024x768x87i)
505 		LOG(4,("1024x768@87 interlaced\n"));
506 	if (edid->established_timing.res_1024x768x60)
507 		LOG(4,("1024x768@60\n"));
508 	if (edid->established_timing.res_1024x768x70)
509 		LOG(4,("1024x768@70\n"));
510 	if (edid->established_timing.res_1024x768x75)
511 		LOG(4,("1024x768@75\n"));
512 	if (edid->established_timing.res_1280x1024x75)
513 		LOG(4,("1280x1024@75\n"));
514 
515 	if (edid->established_timing.res_1152x870x75)
516 		LOG(4,("1152x870@75\n"));
517 
518 	for (i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; ++i) {
519 		edid1_detailed_monitor *monitor = &edid->detailed_monitor[i];
520 
521 		switch(monitor->monitor_desc_type) {
522 			case EDID1_SERIAL_NUMBER:
523 				LOG(4,("Serial Number: %s\n", monitor->data.serial_number));
524 				break;
525 
526 			case EDID1_ASCII_DATA:
527 				LOG(4,("Ascii Data: %s\n", monitor->data.ascii_data));
528 				break;
529 
530 			case EDID1_MONITOR_RANGES:
531 			{
532 				edid1_monitor_range monitor_range = monitor->data.monitor_range;
533 
534 				LOG(4,("Horizontal frequency range = %d..%d kHz\n",
535 					monitor_range.min_h, monitor_range.max_h));
536 				LOG(4,("Vertical frequency range = %d..%d Hz\n",
537 					monitor_range.min_v, monitor_range.max_v));
538 				LOG(4,("Maximum pixel clock = %d MHz\n", (uint16)monitor_range.max_clock * 10));
539 				break;
540 			}
541 
542 			case EDID1_MONITOR_NAME:
543 				LOG(4,("Monitor Name: %s\n", monitor->data.monitor_name));
544 				break;
545 
546 			case EDID1_ADD_COLOUR_POINTER:
547 			{
548 				for (j = 0; j < EDID1_NUM_EXTRA_WHITEPOINTS; ++j) {
549 					edid1_whitepoint *whitepoint = &monitor->data.whitepoint[j];
550 
551 					if (whitepoint->index == 0)
552 						continue;
553 
554 					LOG(4,("Additional whitepoint: (X,Y)=(%f,%f) gamma=%f index=%i\n",
555 						whitepoint->white_x / 1024.0,
556 						whitepoint->white_y / 1024.0,
557 						(whitepoint->gamma + 100) / 100.0,
558 						whitepoint->index));
559 				}
560 				break;
561 			}
562 
563 			case EDID1_ADD_STD_TIMING:
564 			{
565 				for (j = 0; j < EDID1_NUM_EXTRA_STD_TIMING; ++j) {
566 					edid1_std_timing *timing = &monitor->data.std_timing[j];
567 
568 					if (timing->h_size <= 256)
569 						continue;
570 
571 					LOG(4,("%dx%d@%dHz (id=%d)\n",
572 						timing->h_size, timing->v_size,
573 						timing->refresh, timing->id));
574 				}
575 				break;
576 			}
577 
578 			case EDID1_IS_DETAILED_TIMING:
579 			{
580 				edid1_detailed_timing *timing = &monitor->data.detailed_timing;
581 
582 				LOG(4,("Additional Video Mode:\n"));
583 				LOG(4,("clock=%f MHz\n", timing->pixel_clock / 100.0));
584 				LOG(4,("h: (%d, %d, %d, %d)\n",
585 					timing->h_active, timing->h_active + timing->h_sync_off,
586 					timing->h_active + timing->h_sync_off + timing->h_sync_width,
587 					timing->h_active + timing->h_blank));
588 				LOG(4,("v: (%d, %d, %d, %d)\n",
589 					timing->v_active, timing->v_active + timing->v_sync_off,
590 					timing->v_active + timing->v_sync_off + timing->v_sync_width,
591 					timing->v_active + timing->v_blank));
592 				LOG(4,("size: %.1f cm x %.1f cm\n",
593 					timing->h_size / 10.0, timing->v_size / 10.0));
594 				LOG(4,("border: %.1f cm x %.1f cm\n",
595 					timing->h_border / 10.0, timing->v_border / 10.0));
596 				break;
597 			}
598 		}
599 	}
600 }
601 
602 /* callback for getting signals from I2C bus */
603 static status_t
604 get_signals(void *cookie, int *clk, int *data)
605 {
606 	ddc_port_info *info = (ddc_port_info *)cookie;
607 
608 	*clk = *data = 0x0000;
609 	if (InSCL(info->port)) *clk = 0x0001;
610 	if (InSDA(info->port)) *data = 0x0001;
611 
612 	return B_OK;
613 }
614 
615 /* callback for setting signals on I2C bus */
616 static status_t
617 set_signals(void *cookie, int clk, int data)
618 {
619 	ddc_port_info *info = (ddc_port_info *)cookie;
620 
621 	if (clk)
622 		OutSCL(info->port, true);
623 	else
624 		OutSCL(info->port, false);
625 
626 	if (data)
627 		OutSDA(info->port, true);
628 	else
629 		OutSDA(info->port, false);
630 
631 	return B_OK;
632 }
633 
634 /* Read EDID information from monitor via the display data channel (DDC) */
635 static status_t
636 i2c_ReadEDID(uint8 BusNR, edid1_info *edid)
637 {
638 	i2c_bus bus;
639 	ddc_port_info info;
640 
641 	info.port = BusNR;
642 
643 	bus.cookie = &info;
644 	bus.set_signals = &set_signals;
645 	bus.get_signals = &get_signals;
646 	ddc2_init_timing(&bus);
647 
648 	/* select GPU I/O pins for I2C buses */
649 	i2c_select_bus_set(false);
650 
651 	/* enable access to primary head */
652 	set_crtc_owner(0);
653 
654 	if (ddc2_read_edid1(&bus, edid, NULL, NULL) == B_OK) {
655 		LOG(4,("I2C: EDID succesfully read from monitor at bus %d\n", BusNR));
656 		LOG(4,("I2C: EDID dump follows (bus %d):\n", BusNR));
657 		i2c_DumpEDID(edid);
658 		LOG(4,("I2C: end EDID dump (bus %d).\n", BusNR));
659 	} else {
660 		LOG(4,("I2C: reading EDID failed at bus %d!\n", BusNR));
661 		return B_ERROR;
662 	}
663 
664 	return B_OK;
665 }
666 
667 void i2c_TestEDID(void)
668 {
669 	uint8 bus;
670 	edid1_info edid;
671 	bool *i2c_bus = &(si->ps.i2c_bus0);
672 
673 	/* test wired bus(es) */
674 	for (bus = 0; bus < 3; bus++) {
675 		if (i2c_bus[bus])
676 			i2c_ReadEDID(bus, &edid);
677 	}
678 }
679 
680 static status_t
681 i2c_ExtractSpecsEDID(edid1_info* edid, edid_specs* specs)
682 {
683 	uint32 i;
684 	edid1_detailed_timing edid_timing;
685 
686 	specs->have_full_edid = false;
687 	specs->have_native_edid = false;
688 	specs->timing.h_display = 0;
689 	specs->timing.v_display = 0;
690 
691 	/* find the optimum (native) modeline */
692 	for (i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; ++i) {
693 		switch(edid->detailed_monitor[i].monitor_desc_type) {
694 		case EDID1_IS_DETAILED_TIMING:
695 			// TODO: handle flags correctly!
696 			edid_timing = edid->detailed_monitor[i].data.detailed_timing;
697 
698 			if (edid_timing.pixel_clock <= 0/* || edid_timing.sync != 3*/)
699 				break;
700 
701 			/* we want the optimum (native) modeline only, widescreen if possible.
702 			 * So only check for horizontal display, not for vertical display. */
703 			if (edid_timing.h_active <= specs->timing.h_display)
704 				break;
705 
706 			specs->timing.pixel_clock = edid_timing.pixel_clock * 10;
707 			specs->timing.h_display = edid_timing.h_active;
708 			specs->timing.h_sync_start = edid_timing.h_active + edid_timing.h_sync_off;
709 			specs->timing.h_sync_end = specs->timing.h_sync_start + edid_timing.h_sync_width;
710 			specs->timing.h_total = specs->timing.h_display + edid_timing.h_blank;
711 			specs->timing.v_display = edid_timing.v_active;
712 			specs->timing.v_sync_start = edid_timing.v_active + edid_timing.v_sync_off;
713 			specs->timing.v_sync_end = specs->timing.v_sync_start + edid_timing.v_sync_width;
714 			specs->timing.v_total = specs->timing.v_display + edid_timing.v_blank;
715 			specs->timing.flags = 0;
716 			if (edid_timing.sync == 3) {
717 				if (edid_timing.misc & 1)
718 					specs->timing.flags |= B_POSITIVE_HSYNC;
719 				if (edid_timing.misc & 2)
720 					specs->timing.flags |= B_POSITIVE_VSYNC;
721 			}
722 			if (edid_timing.interlaced)
723 				specs->timing.flags |= B_TIMING_INTERLACED;
724 			break;
725 		}
726 	}
727 
728 	/* check if we actually got a modeline */
729 	if (!specs->timing.h_display || !specs->timing.v_display) return B_ERROR;
730 
731 	/* check if the mode is at least VGA. If it's not, ignore specs */
732 	if ((specs->timing.h_display < 640) || (specs->timing.v_display < 480)) {
733 		LOG(4,("I2C: specsEDID: screen reports lower than VGA native mode, ignoring specs!\n"));
734 		return B_ERROR;
735 	}
736 
737 	/* determine screen aspect ratio */
738 	specs->aspect =
739 		(specs->timing.h_display / ((float)specs->timing.v_display));
740 
741 	/* determine connection type */
742 	specs->digital = false;
743 	if (edid->display.input_type) specs->digital = true;
744 
745 	/* and also copy full edid1_info for reference */
746 	memcpy(&(specs->full_edid), edid, sizeof(specs->full_edid));
747 
748 	/* we succesfully fetched the specs we need */
749 	specs->have_native_edid = true;
750 	/* we also got full and valid EDID via DDC */
751 	specs->have_full_edid = true;
752 
753 	return B_OK;
754 }
755 
756 /* Dump EDID info in driver's logfile */
757 static void
758 i2c_DumpSpecsEDID(edid_specs* specs)
759 {
760 	LOG(4,("I2C: specsEDID: have_native_edid: %s\n", specs->have_native_edid ? "True" : "False"));
761 	if (!specs->have_native_edid) return;
762 	LOG(4,("I2C: specsEDID: timing.pixel_clock %.3f Mhz\n", specs->timing.pixel_clock / 1000.0));
763 	LOG(4,("I2C: specsEDID: timing.h_display %d\n", specs->timing.h_display));
764 	LOG(4,("I2C: specsEDID: timing.h_sync_start %d\n", specs->timing.h_sync_start));
765 	LOG(4,("I2C: specsEDID: timing.h_sync_end %d\n", specs->timing.h_sync_end));
766 	LOG(4,("I2C: specsEDID: timing.h_total %d\n", specs->timing.h_total));
767 	LOG(4,("I2C: specsEDID: timing.v_display %d\n", specs->timing.v_display));
768 	LOG(4,("I2C: specsEDID: timing.v_sync_start %d\n", specs->timing.v_sync_start));
769 	LOG(4,("I2C: specsEDID: timing.v_sync_end %d\n", specs->timing.v_sync_end));
770 	LOG(4,("I2C: specsEDID: timing.v_total %d\n", specs->timing.v_total));
771 	LOG(4,("I2C: specsEDID: timing.flags $%08x\n", specs->timing.flags));
772 	LOG(4,("I2C: specsEDID: aspect: %1.2f\n", specs->aspect));
773 	LOG(4,("I2C: specsEDID: digital: %s\n", specs->digital ? "True" : "False"));
774 }
775 
776 /* notes:
777  * - con1 resides closest to the mainboard on for example NV25 and NV28, while for
778  *   example on NV34 con2 sits closest to the mainboard.
779  * - i2c bus0 is connected to con1, and i2c bus1 is connected to con2 on all pre-NV40
780  *   architecture cards. On later cards it's vice versa. These connections do not depend
781  *   on the analog VGA switch setting (see nv_general_output_select()). It also does
782  *   not depend on the way screens are connected to the cards (DVI/VGA, 1 or 2 screens).
783  * - on some NV40 architecture cards i2c bus2 connects to con2 instead of i2c bus0. This
784  *   is confirmed on GeForce FX 6600 (NV43, id 0x0141) and GeForce 7300 (G72, id 0x01d1).
785  * - on pre-NV40 laptops i2c bus2 can connect to con2 as well: confirmed on a Geforce FX
786  *   5200 Go (NV34, id 0x0324).
787  * - con1 has CRTC1 and DAC1, and con2 has CRTC2 and DAC2 if nv_general_output_select()
788  *   is set to 'straight' and there are only VGA type screens connected. */
789 void i2c_DetectScreens(void)
790 {
791 	edid1_info edid;
792 
793 	si->ps.con1_screen.have_native_edid = false;
794 	si->ps.con2_screen.have_native_edid = false;
795 	si->ps.con1_screen.have_full_edid = false;
796 	si->ps.con2_screen.have_full_edid = false;
797 	si->ps.con1_screen.aspect = 0;
798 	si->ps.con2_screen.aspect = 0;
799 
800 	/* check existance of bus 0 */
801 	if (si->ps.i2c_bus0) {
802 		/* check I2C bus 0 for an EDID capable screen */
803 		if (i2c_ReadEDID(0, &edid) == B_OK) {
804 			/* fetch optimum (native) modeline */
805 			switch (si->ps.card_arch) {
806 			case NV40A:
807 				i2c_ExtractSpecsEDID(&edid, &si->ps.con2_screen);
808 				break;
809 			default:
810 				i2c_ExtractSpecsEDID(&edid, &si->ps.con1_screen);
811 				break;
812 			}
813 		}
814 	}
815 
816 	/* check existance of bus 1 */
817 	if (si->ps.i2c_bus1) {
818 		/* check I2C bus 1 for an EDID screen */
819 		if (i2c_ReadEDID(1, &edid) == B_OK) {
820 			/* fetch optimum (native) modeline */
821 			switch (si->ps.card_arch) {
822 			case NV40A:
823 				i2c_ExtractSpecsEDID(&edid, &si->ps.con1_screen);
824 				break;
825 			default:
826 				i2c_ExtractSpecsEDID(&edid, &si->ps.con2_screen);
827 				break;
828 			}
829 		}
830 	}
831 
832 	/* check existance of bus 2 */
833 	if (si->ps.i2c_bus2) {
834 		/* check I2C bus 2 for an EDID screen */
835 		if (i2c_ReadEDID(2, &edid) == B_OK) {
836 			/* fetch optimum (native) modeline */
837 			switch (si->ps.card_arch) {
838 			case NV40A:
839 				if (!si->ps.con2_screen.have_native_edid) {
840 					i2c_ExtractSpecsEDID(&edid, &si->ps.con2_screen);
841 				} else {
842 					LOG(4,("I2C: DetectScreens: WARNING, unexpected behaviour detected!\n"));
843 				}
844 				break;
845 			default:
846 				if (!si->ps.con2_screen.have_native_edid && si->ps.laptop) {
847 					i2c_ExtractSpecsEDID(&edid, &si->ps.con2_screen);
848 				} else {
849 					LOG(4,("I2C: DetectScreens: WARNING, unexpected behaviour detected!\n"));
850 				}
851 				break;
852 			}
853 		}
854 	}
855 }
856