added more EDID stuff. Now extracting needed monitor specs and placing them in shared_info. More dumping to logfile added. The EDID info is not yet actually used: more testing is needed.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30880 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rudolf Cornelissen
2009-05-27 18:46:07 +00:00
parent c533f813a2
commit 21bade017a
4 changed files with 163 additions and 17 deletions
@@ -5,7 +5,7 @@
Other authors:
Mark Watson;
Apsed;
Rudolf Cornelissen 10/2002-3/2009.
Rudolf Cornelissen 10/2002-5/2009.
*/
#ifndef DRIVERINTERFACE_H
@@ -229,6 +229,14 @@ typedef struct { // apsed, see comments in nvidia.settings
uint32 ram_clk;
} nv_settings;
/* monitor info gathered via EDID */
typedef struct {
bool have_edid; /* have read useable edid info from screen */
bool digital; /* screen connection type: analog (VGA) or digital (DVI) */
display_timing timing; /* 'native modeline' fetched for screen */
float aspect; /* screen's aspect ratio */
} edid_specs;
/* shared info */
typedef struct {
/* a few ID things */
@@ -342,6 +350,8 @@ typedef struct {
display_timing p2_timing; /* 'modeline' fetched for panel 2 */
float panel1_aspect; /* panel's aspect ratio */
float panel2_aspect; /* panel's aspect ratio */
edid_specs con1_screen; /* EDID properties of the screen connected to connector 1 */
edid_specs con2_screen; /* EDID properties of the screen connected to connector 1 */
bool crtc2_prim; /* using CRTC2 as primary CRTC */
bool i2c_bus0; /* we have a wired I2C bus 0 on board */
bool i2c_bus1; /* we have a wired I2C bus 1 on board */
+144 -5
View File
@@ -9,6 +9,8 @@
#include "nv_std.h"
static void i2c_DumpSpecsEDID(edid_specs* specs);
char i2c_flag_error (char ErrNo)
//error code list:
//0 - OK status
@@ -340,7 +342,12 @@ status_t i2c_init(void)
LOG(4,("I2C: bus #%d wiring check: failed\n", bus));
}
i2c_TestEDID();
//i2c_TestEDID();
i2c_DetectScreens();
LOG(4,("I2C: dumping EDID specs for connector 1:\n"));
i2c_DumpSpecsEDID(&si->ps.con1_screen);
LOG(4,("I2C: dumping EDID specs for connector 2:\n"));
i2c_DumpSpecsEDID(&si->ps.con2_screen);
return result;
}
@@ -352,7 +359,7 @@ typedef struct {
/* Dump EDID info in driver's logfile */
static void
i2c_edid_dump(edid1_info *edid)
i2c_DumpEDID(edid1_info *edid)
{
int i, j;
@@ -534,7 +541,7 @@ set_signals(void *cookie, int clk, int data)
}
/* Read EDID information from monitor via the display data channel (DDC) */
status_t
static status_t
i2c_ReadEDID(uint8 BusNR, edid1_info *edid)
{
i2c_bus bus;
@@ -556,8 +563,7 @@ i2c_ReadEDID(uint8 BusNR, edid1_info *edid)
if (ddc2_read_edid1(&bus, edid, NULL, NULL) == B_OK) {
LOG(4,("I2C: EDID succesfully read from monitor at bus %d\n", BusNR));
LOG(4,("I2C: EDID dump follows (bus %d):\n", BusNR));
// has_edid = true;
i2c_edid_dump(edid);
i2c_DumpEDID(edid);
LOG(4,("I2C: end EDID dump (bus %d).\n", BusNR));
} else {
LOG(4,("I2C: reading EDID failed at bus %d!\n", BusNR));
@@ -579,3 +585,136 @@ void i2c_TestEDID(void)
i2c_ReadEDID(bus, &edid);
}
}
static status_t
i2c_ExtractSpecsEDID(edid1_info* edid, edid_specs* specs)
{
uint32 i;
edid1_detailed_timing edid_timing;
specs->have_edid = false;
specs->timing.h_display = 0;
specs->timing.v_display = 0;
/* find the optimum (native) modeline */
for (i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; ++i) {
switch(edid->detailed_monitor[i].monitor_desc_type) {
case EDID1_IS_DETAILED_TIMING:
// TODO: handle flags correctly!
edid_timing = edid->detailed_monitor[i].data.detailed_timing;
if (edid_timing.pixel_clock <= 0/* || edid_timing.sync != 3*/)
break;
/* we want the optimum (native) modeline only, widescreen if possible.
* So only check for horizontal display, not for vertical display. */
if (edid_timing.h_active <= specs->timing.h_display)
break;
specs->timing.pixel_clock = edid_timing.pixel_clock * 10;
specs->timing.h_display = edid_timing.h_active;
specs->timing.h_sync_start = edid_timing.h_active + edid_timing.h_sync_off;
specs->timing.h_sync_end = specs->timing.h_sync_start + edid_timing.h_sync_width;
specs->timing.h_total = specs->timing.h_display + edid_timing.h_blank;
specs->timing.v_display = edid_timing.v_active;
specs->timing.v_sync_start = edid_timing.v_active + edid_timing.v_sync_off;
specs->timing.v_sync_end = specs->timing.v_sync_start + edid_timing.v_sync_width;
specs->timing.v_total = specs->timing.v_display + edid_timing.v_blank;
specs->timing.flags = 0;
if (edid_timing.sync == 3) {
if (edid_timing.misc & 1)
specs->timing.flags |= B_POSITIVE_HSYNC;
if (edid_timing.misc & 2)
specs->timing.flags |= B_POSITIVE_VSYNC;
}
if (edid_timing.interlaced)
specs->timing.flags |= B_TIMING_INTERLACED;
break;
}
}
/* check if we actually got a modeline */
if (!specs->timing.h_display || !specs->timing.v_display) return B_ERROR;
/* we succesfully fetched the specs we need */
specs->have_edid = true;
/* determine screen aspect ratio */
specs->aspect =
(specs->timing.h_display / ((float)specs->timing.v_display));
/* determine connection type */
specs->digital = false;
if (edid->display.input_type) specs->digital = true;
return B_OK;
}
/* Dump EDID info in driver's logfile */
static void
i2c_DumpSpecsEDID(edid_specs* specs)
{
LOG(4,("I2C: specsEDID: have_edid: %s\n", specs->have_edid ? "True" : "False"));
if (!specs->have_edid) return;
LOG(4,("I2C: specsEDID: timing.pixel_clock %.3f Mhz\n", specs->timing.pixel_clock / 1000.0));
LOG(4,("I2C: specsEDID: timing.h_display %d\n", specs->timing.h_display));
LOG(4,("I2C: specsEDID: timing.h_sync_start %d\n", specs->timing.h_sync_start));
LOG(4,("I2C: specsEDID: timing.h_sync_end %d\n", specs->timing.h_sync_end));
LOG(4,("I2C: specsEDID: timing.h_total %d\n", specs->timing.h_total));
LOG(4,("I2C: specsEDID: timing.v_display %d\n", specs->timing.v_display));
LOG(4,("I2C: specsEDID: timing.v_sync_start %d\n", specs->timing.v_sync_start));
LOG(4,("I2C: specsEDID: timing.v_sync_end %d\n", specs->timing.v_sync_end));
LOG(4,("I2C: specsEDID: timing.v_total %d\n", specs->timing.v_total));
LOG(4,("I2C: specsEDID: timing.flags $%08x\n", specs->timing.flags));
LOG(4,("I2C: specsEDID: aspect: %1.2f\n", specs->aspect));
LOG(4,("I2C: specsEDID: digital: %s\n", specs->digital ? "True" : "False"));
}
/* notes:
* - con1 resides closest to the mainboard on for example NV25 and NV28, while for
* example on NV34 con2 sits closest to the mainboard.
* - con1 is connected to DAC1, and con2 is connected to DAC2 on all pre-NV40
* architecture cards. On later cards it's vice versa. */
//>>>fixme:
//- re-check if the latter note is true,
//- and check if it's dependant on the DAC cross connection switch..
//- and check if analog or digital connection type influences this..
void i2c_DetectScreens(void)
{
edid1_info edid;
si->ps.con1_screen.have_edid = false;
si->ps.con2_screen.have_edid = false;
/* check existance of bus 0 */
if (!si->ps.i2c_bus0) return;
/* check I2C bus 0 for an EDID capable screen */
if (i2c_ReadEDID(0, &edid) == B_OK) {
/* fetch optimum (native) modeline */
switch (si->ps.card_arch) {
case NV40A:
i2c_ExtractSpecsEDID(&edid, &si->ps.con2_screen);
break;
default:
i2c_ExtractSpecsEDID(&edid, &si->ps.con1_screen);
break;
}
}
/* check existance of bus 1 */
if (!si->ps.i2c_bus1) return;
/* check I2C bus 1 for an EDID screen */
if (i2c_ReadEDID(1, &edid) == B_OK) {
/* fetch optimum (native) modeline */
switch (si->ps.card_arch) {
case NV40A:
i2c_ExtractSpecsEDID(&edid, &si->ps.con1_screen);
break;
default:
i2c_ExtractSpecsEDID(&edid, &si->ps.con2_screen);
break;
}
}
}
@@ -3175,8 +3175,7 @@ void dump_pins(void)
char *msg = "";
LOG(2,("INFO: pinsdump follows:\n"));
LOG(2,("PLL type: "));
if (si->ps.ext_pll) LOG(2,("extended\n")); else LOG(2,("standard\n"));
LOG(2,("PLL type: %s\n", si->ps.ext_pll ? "extended" : "standard"));
LOG(2,("f_ref: %fMhz\n", si->ps.f_ref));
LOG(2,("max_system_vco: %dMhz\n", si->ps.max_system_vco));
LOG(2,("min_system_vco: %dMhz\n", si->ps.min_system_vco));
@@ -3198,10 +3197,8 @@ void dump_pins(void)
LOG(2,("max_dac2_clock_24: %dMhz\n", si->ps.max_dac2_clock_24));
LOG(2,("max_dac2_clock_32: %dMhz\n", si->ps.max_dac2_clock_32));
LOG(2,("max_dac2_clock_32dh: %dMhz\n", si->ps.max_dac2_clock_32dh));
LOG(2,("secondary_head: "));
if (si->ps.secondary_head) LOG(2,("present\n")); else LOG(2,("absent\n"));
LOG(2,("tvout: "));
if (si->ps.tvout) LOG(2,("present\n")); else LOG(2,("absent\n"));
LOG(2,("secondary_head: %s\n", si->ps.secondary_head ? "present" : "absent"));
LOG(2,("tvout: %s\n", si->ps.tvout ? "present" : "absent"));
/* setup TVout logmessage text */
switch (si->ps.tv_encoder.type)
{
@@ -3268,15 +3265,15 @@ void dump_pins(void)
if (si->ps.laptop) LOG(2,("yes\n")); else LOG(2,("no\n"));
if (si->ps.tmds1_active)
{
LOG(2,("found DFP (digital flatpanel) on CRTC1; CRTC1 is "));
if (si->ps.slaved_tmds1) LOG(2,("slaved\n")); else LOG(2,("master\n"));
LOG(2,("found DFP (digital flatpanel) on CRTC1; CRTC1 is %s\n",
si->ps.slaved_tmds1 ? "slaved" : "master"));
LOG(2,("panel width: %d, height: %d, aspect ratio: %1.2f\n",
si->ps.p1_timing.h_display, si->ps.p1_timing.v_display, si->ps.panel1_aspect));
}
if (si->ps.tmds2_active)
{
LOG(2,("found DFP (digital flatpanel) on CRTC2; CRTC2 is "));
if (si->ps.slaved_tmds2) LOG(2,("slaved\n")); else LOG(2,("master\n"));
LOG(2,("found DFP (digital flatpanel) on CRTC2; CRTC2 is %s\n",
si->ps.slaved_tmds2 ? "slaved" : "master"));
LOG(2,("panel width: %d, height: %d, aspect ratio: %1.2f\n",
si->ps.p2_timing.h_display, si->ps.p2_timing.v_display, si->ps.panel2_aspect));
}
@@ -34,8 +34,8 @@ bool i2c_writebyte (uint8 BusNR, uint8 byte);
void i2c_readbuffer (uint8 BusNR, uint8* buf, uint8 size);
void i2c_writebuffer (uint8 BusNR, uint8* buf, uint8 size);
status_t i2c_init(void);
status_t i2c_ReadEDID(uint8 BusNR, edid1_info *edid);
void i2c_TestEDID(void);
void i2c_DetectScreens(void);
/* card info functions */
status_t parse_pins(void);