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
i2c_flag_error(char ErrNo)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
i2c_select_bus_set(bool set)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
OutSCL(uint8 BusNR,bool Bit)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
OutSDA(uint8 BusNR,bool Bit)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
InSCL(uint8 BusNR)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
InSDA(uint8 BusNR)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
TXBit(uint8 BusNR,bool Bit)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
RXBit(uint8 BusNR)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
i2c_bstart(uint8 BusNR)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
i2c_bstop(uint8 BusNR)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
i2c_readbyte(uint8 BusNR,bool Ack)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
i2c_writebyte(uint8 BusNR,uint8 byte)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
i2c_readbuffer(uint8 BusNR,uint8 * buf,uint8 size)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
i2c_writebuffer(uint8 BusNR,uint8 * buf,uint8 size)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
i2c_init(void)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
i2c_DumpEDID(edid1_info * edid)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
get_signals(void * cookie,int * clk,int * data)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
set_signals(void * cookie,int clk,int data)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
i2c_ReadEDID(uint8 BusNR,edid1_info * edid)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
i2c_TestEDID(void)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
i2c_ExtractSpecsEDID(edid1_info * edid,edid_specs * specs)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
i2c_DumpSpecsEDID(edid_specs * specs)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. */
i2c_DetectScreens(void)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