From bb0ac35825c8070bea812e39037b50ad568d8af6 Mon Sep 17 00:00:00 2001 From: Rudolf Cornelissen Date: Sat, 2 May 2009 09:58:11 +0000 Subject: [PATCH] added partial DDC/EDID support using the accelerants common staticlibrary. Only dumping config, monitor info to logfile. logfiles are welcome as the CRTC/DAC to I2Cport relationchip is not known by me yet. Bumped version to 0.89. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30553 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/accelerants/nvidia/Jamfile | 3 +- src/add-ons/accelerants/nvidia/acc_std.h | 8 +- src/add-ons/accelerants/nvidia/engine/Jamfile | 4 +- .../accelerants/nvidia/engine/nv_general.c | 2 +- .../accelerants/nvidia/engine/nv_i2c.c | 241 +++++++++++++++++- .../accelerants/nvidia/engine/nv_proto.h | 2 + .../accelerants/nvidia/engine/nv_std.h | 8 +- .../drivers/graphics/nvidia/UPDATE.html | 3 +- 8 files changed, 264 insertions(+), 7 deletions(-) diff --git a/src/add-ons/accelerants/nvidia/Jamfile b/src/add-ons/accelerants/nvidia/Jamfile index 881fa26d25..a23fa61676 100644 --- a/src/add-ons/accelerants/nvidia/Jamfile +++ b/src/add-ons/accelerants/nvidia/Jamfile @@ -4,6 +4,7 @@ SetSubDirSupportedPlatformsBeOSCompatible ; UsePrivateHeaders graphics ; UsePrivateHeaders [ FDirName graphics nvidia ] ; +UsePrivateHeaders [ FDirName graphics common ] ; UseHeaders [ FDirName $(SUBDIR) engine ] ; Addon nvidia.accelerant : @@ -18,7 +19,7 @@ Addon nvidia.accelerant : Overlay.c ProposeDisplayMode.c SetDisplayMode.c - : libnvidia_engine.a + : libnvidia_engine.a libaccelerantscommon.a ; Package haiku-nvidia-cvs : diff --git a/src/add-ons/accelerants/nvidia/acc_std.h b/src/add-ons/accelerants/nvidia/acc_std.h index 560ab04a67..273b055bfe 100644 --- a/src/add-ons/accelerants/nvidia/acc_std.h +++ b/src/add-ons/accelerants/nvidia/acc_std.h @@ -8,9 +8,15 @@ #include #include + +/* DDC/EDID library */ +//#include +#include +//#include + +/* Nvidia driver */ #include "DriverInterface.h" #include "nv_globals.h" -//apsed #include "nv_extern.h" #include "nv_proto.h" #include "be_driver_proto.h" diff --git a/src/add-ons/accelerants/nvidia/engine/Jamfile b/src/add-ons/accelerants/nvidia/engine/Jamfile index 7b0d849b7a..6c1c598d5b 100644 --- a/src/add-ons/accelerants/nvidia/engine/Jamfile +++ b/src/add-ons/accelerants/nvidia/engine/Jamfile @@ -4,6 +4,7 @@ SetSubDirSupportedPlatformsBeOSCompatible ; UsePrivateHeaders graphics ; UsePrivateHeaders [ FDirName graphics nvidia ] ; +UsePrivateHeaders [ FDirName graphics common ] ; StaticLibrary libnvidia_engine.a : nv_acc.c @@ -20,4 +21,5 @@ StaticLibrary libnvidia_engine.a : nv_i2c.c nv_info.c nv_support.c - ; + : +; diff --git a/src/add-ons/accelerants/nvidia/engine/nv_general.c b/src/add-ons/accelerants/nvidia/engine/nv_general.c index 296df34829..6aa9543c59 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_general.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_general.c @@ -92,7 +92,7 @@ status_t nv_general_powerup() { status_t status; - LOG(1,("POWERUP: Haiku nVidia Accelerant 0.88 running.\n")); + LOG(1,("POWERUP: Haiku nVidia Accelerant 0.89 running.\n")); /* log VBLANK INT usability status */ if (si->ps.int_assigned) diff --git a/src/add-ons/accelerants/nvidia/engine/nv_i2c.c b/src/add-ons/accelerants/nvidia/engine/nv_i2c.c index 1106604377..93b9ad77cc 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_i2c.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_i2c.c @@ -2,7 +2,7 @@ * i2c interface. * Bus should be run at max. 100kHz: see original Philips I2C specification * - * Rudolf Cornelissen 12/2002-10/2005 + * Rudolf Cornelissen 12/2002-5/2009 */ #define MODULE_BIT 0x00004000 @@ -340,5 +340,244 @@ status_t i2c_init(void) LOG(4,("I2C: bus #%d wiring check: failed\n", bus)); } + i2c_TestEDID(); + return result; } + +/*** DDC/EDID library use ***/ +typedef struct { + uint32 port; +} ddc_port_info; + +/* Dump EDID info in driver's logfile */ +static void +i2c_edid_dump(edid1_info *edid) +{ + int i, j; + + LOG(4,("Vendor: %s\n", edid->vendor.manufacturer)); + LOG(4,("Product ID: %d\n", (int)edid->vendor.prod_id)); + LOG(4,("Serial #: %d\n", (int)edid->vendor.serial)); + LOG(4,("Produced in week/year: %d/%d\n", edid->vendor.week, edid->vendor.year)); + + LOG(4,("EDID version: %d.%d\n", edid->version.version, edid->version.revision)); + + LOG(4,("Type: %s\n", edid->display.input_type ? "Digital" : "Analog")); + LOG(4,("Size: %d cm x %d cm\n", edid->display.h_size, edid->display.v_size)); + LOG(4,("Gamma=%.3f\n", (edid->display.gamma + 100) / 100.0)); + LOG(4,("White (X,Y)=(%.3f,%.3f)\n", edid->display.white_x / 1024.0, + edid->display.white_y / 1024.0)); + + LOG(4,("Supported Future Video Modes:\n")); + for (i = 0; i < EDID1_NUM_STD_TIMING; ++i) { + if (edid->std_timing[i].h_size <= 256) + continue; + + LOG(4,("%dx%d@%dHz (id=%d)\n", + edid->std_timing[i].h_size, edid->std_timing[i].v_size, + edid->std_timing[i].refresh, edid->std_timing[i].id)); + } + + LOG(4,("Supported VESA Video Modes:\n")); + if (edid->established_timing.res_720x400x70) + LOG(4,("720x400@70\n")); + if (edid->established_timing.res_720x400x88) + LOG(4,("720x400@88\n")); + if (edid->established_timing.res_640x480x60) + LOG(4,("640x480@60\n")); + if (edid->established_timing.res_640x480x67) + LOG(4,("640x480x67\n")); + if (edid->established_timing.res_640x480x72) + LOG(4,("640x480x72\n")); + if (edid->established_timing.res_640x480x75) + LOG(4,("640x480x75\n")); + if (edid->established_timing.res_800x600x56) + LOG(4,("800x600@56\n")); + if (edid->established_timing.res_800x600x60) + LOG(4,("800x600@60\n")); + + if (edid->established_timing.res_800x600x72) + LOG(4,("800x600@72\n")); + if (edid->established_timing.res_800x600x75) + LOG(4,("800x600@75\n")); + if (edid->established_timing.res_832x624x75) + LOG(4,("832x624@75\n")); + if (edid->established_timing.res_1024x768x87i) + LOG(4,("1024x768@87 interlaced\n")); + if (edid->established_timing.res_1024x768x60) + LOG(4,("1024x768@60\n")); + if (edid->established_timing.res_1024x768x70) + LOG(4,("1024x768@70\n")); + if (edid->established_timing.res_1024x768x75) + LOG(4,("1024x768@75\n")); + if (edid->established_timing.res_1280x1024x75) + LOG(4,("1280x1024@75\n")); + + if (edid->established_timing.res_1152x870x75) + LOG(4,("1152x870@75\n")); + + for (i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; ++i) { + edid1_detailed_monitor *monitor = &edid->detailed_monitor[i]; + + switch(monitor->monitor_desc_type) { + case EDID1_SERIAL_NUMBER: + LOG(4,("Serial Number: %s\n", monitor->data.serial_number)); + break; + + case EDID1_ASCII_DATA: + LOG(4,(" %s\n", monitor->data.serial_number)); + break; + + case EDID1_MONITOR_RANGES: + { + edid1_monitor_range monitor_range = monitor->data.monitor_range; + + LOG(4,("Horizontal frequency range = %d..%d kHz\n", + monitor_range.min_h, monitor_range.max_h)); + LOG(4,("Vertical frequency range = %d..%d Hz\n", + monitor_range.min_v, monitor_range.max_v)); + LOG(4,("Maximum pixel clock = %d MHz\n", (uint16)monitor_range.max_clock * 10)); + break; + } + + case EDID1_MONITOR_NAME: + LOG(4,("Monitor Name: %s\n", monitor->data.monitor_name)); + break; + + case EDID1_ADD_COLOUR_POINTER: + { + for (j = 0; j < EDID1_NUM_EXTRA_WHITEPOINTS; ++j) { + edid1_whitepoint *whitepoint = &monitor->data.whitepoint[j]; + + if (whitepoint->index == 0) + continue; + + LOG(4,("Additional whitepoint: (X,Y)=(%f,%f) gamma=%f index=%i\n", + whitepoint->white_x / 1024.0, + whitepoint->white_y / 1024.0, + (whitepoint->gamma + 100) / 100.0, + whitepoint->index)); + } + break; + } + + case EDID1_ADD_STD_TIMING: + { + for (j = 0; j < EDID1_NUM_EXTRA_STD_TIMING; ++j) { + edid1_std_timing *timing = &monitor->data.std_timing[j]; + + if (timing->h_size <= 256) + continue; + + LOG(4,("%dx%d@%dHz (id=%d)\n", + timing->h_size, timing->v_size, + timing->refresh, timing->id)); + } + break; + } + + case EDID1_IS_DETAILED_TIMING: + { + edid1_detailed_timing *timing = &monitor->data.detailed_timing; + + LOG(4,("Additional Video Mode:\n")); + LOG(4,("clock=%f MHz\n", timing->pixel_clock / 100.0)); + LOG(4,("h: (%d, %d, %d, %d)\n", + timing->h_active, timing->h_active + timing->h_sync_off, + timing->h_active + timing->h_sync_off + timing->h_sync_width, + timing->h_active + timing->h_blank)); + LOG(4,("v: (%d, %d, %d, %d)\n", + timing->v_active, timing->v_active + timing->v_sync_off, + timing->v_active + timing->v_sync_off + timing->v_sync_width, + timing->v_active + timing->v_blank)); + LOG(4,("size: %.1f cm x %.1f cm\n", + timing->h_size / 10.0, timing->v_size / 10.0)); + LOG(4,("border: %.1f cm x %.1f cm\n", + timing->h_border / 10.0, timing->v_border / 10.0)); + break; + } + } + } +} + +/* callback for getting signals from I2C bus */ +static status_t +get_signals(void *cookie, int *clk, int *data) +{ + ddc_port_info *info = (ddc_port_info *)cookie; + + *clk = *data = 0x0000; + if (InSCL(info->port)) *clk = 0x0001; + if (InSDA(info->port)) *data = 0x0001; + + return B_OK; +} + +/* callback for setting signals on I2C bus */ +static status_t +set_signals(void *cookie, int clk, int data) +{ + ddc_port_info *info = (ddc_port_info *)cookie; + + if (clk) + OutSCL(info->port, true); + else + OutSCL(info->port, false); + + if (data) + OutSDA(info->port, true); + else + OutSDA(info->port, false); + + return B_OK; +} + +/* Read EDID information from monitor via the display data channel (DDC) */ +status_t +i2c_ReadEDID(uint8 BusNR, edid1_info *edid) +{ + i2c_bus bus; + ddc_port_info info; + + info.port = BusNR; + + bus.cookie = &info; + bus.set_signals = &set_signals; + bus.get_signals = &get_signals; + ddc2_init_timing(&bus); + + /* select GPU I/O pins set */ + i2c_select_bus_set(BusNR & 0x02); + + /* enable access to primary head */ + set_crtc_owner(0); + + 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); + LOG(4,("I2C: end EDID dump (bus %d).\n", BusNR)); + } else { + LOG(4,("I2C: reading EDID failed at bus %d!\n", BusNR)); + return B_ERROR; + } + + return B_OK; +} + +void i2c_TestEDID(void) +{ + uint8 bus, buses; + + /* set number of buses to test for */ + buses = 2; + if (si->ps.secondary_head) buses = 4; + + /* test bus */ + for (bus = 0; bus < buses; bus++) { + edid1_info edid; + i2c_ReadEDID(bus, &edid); + } +} diff --git a/src/add-ons/accelerants/nvidia/engine/nv_proto.h b/src/add-ons/accelerants/nvidia/engine/nv_proto.h index 42dc7a9d9e..193532823a 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_proto.h +++ b/src/add-ons/accelerants/nvidia/engine/nv_proto.h @@ -34,6 +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); /* card info functions */ status_t parse_pins(void); diff --git a/src/add-ons/accelerants/nvidia/engine/nv_std.h b/src/add-ons/accelerants/nvidia/engine/nv_std.h index cc21aaecb0..c3e84f0cbd 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_std.h +++ b/src/add-ons/accelerants/nvidia/engine/nv_std.h @@ -2,9 +2,15 @@ #include #include #include + +/* DDC/EDID library */ +//#include +#include +//#include + +/* Nvidia driver */ #include "DriverInterface.h" #include "nv_globals.h" -//apsed #include "nv_extern.h" #include "nv_proto.h" #include "nv_macros.h" #include "nv_acc.h" diff --git a/src/add-ons/kernel/drivers/graphics/nvidia/UPDATE.html b/src/add-ons/kernel/drivers/graphics/nvidia/UPDATE.html index 466f44fc5e..12ff62d46c 100644 --- a/src/add-ons/kernel/drivers/graphics/nvidia/UPDATE.html +++ b/src/add-ons/kernel/drivers/graphics/nvidia/UPDATE.html @@ -4,7 +4,7 @@

Changes done for each driverversion:

-

head (SVN 0.88, Rudolf)

+

head (SVN 0.89, Rudolf)

  • Fixed driver assuming enabling AGP mode succeeded on some occasions if it did not block it itself. Blocking AGP mode completely via the AGP busmanager (option 'block_agp') resulted in a crashing acceleration engine because it was setup for AGP transfers instead of using PCI transfers. Error was solved with help from user kraton.
  • Fixed shared_info struct problem occuring when 3D 'accelerant' is used (tested Alpha 4.1): the TVencoder type definition list apparantly gets some memory assigned these days when done inside the definition of shared_info. Moved encoder list outside the shared_info definition. @@ -18,6 +18,7 @@
  • Added 'block_acc' option in nvidia.settings to completely disable the acceleration engine. Use this as a work-around if the acceleration engine misbehaves.
  • Fixed card/system hanging after trying to log LVDS/TMDS distinction info. This (at least) fixes one NV34 trying to startup after a failed kernel VESA modeswitch without using the driver's coldstart option. Might very well help on other type cards too.
  • HDTV video upto/including 1920x1080p can now be played back using overlay on Geforce cards where overlay is supported. On TNT1/TNT2/TNT2-M64 this can't be done and bitmap output is used. +
  • Added partial DDC/EDID support: dumping monitor specs to logfile only for now.

nv_driver 0.80 (Rudolf)