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