diff --git a/i2c_smbus/i2c_smbus.cpp b/i2c_smbus/i2c_smbus.cpp index e747180d..50e32d92 100644 --- a/i2c_smbus/i2c_smbus.cpp +++ b/i2c_smbus/i2c_smbus.cpp @@ -164,8 +164,9 @@ s32 i2c_smbus_interface::i2c_smbus_xfer_call(u8 addr, char read_write, u8 comman i2c_addr = addr; i2c_read_write = read_write; i2c_command = command; - i2c_size = size; - i2c_data = data; + i2c_size_smbus = size; + i2c_data_smbus = data; + smbus_xfer = true; std::unique_lock start_lock(i2c_smbus_start_mutex); i2c_smbus_start = true; @@ -182,6 +183,41 @@ s32 i2c_smbus_interface::i2c_smbus_xfer_call(u8 addr, char read_write, u8 comman return(i2c_ret); } +s32 i2c_smbus_interface::i2c_xfer_call(u8 addr, char read_write, int* size, u8 *data) +{ + i2c_smbus_xfer_mutex.lock(); + + i2c_addr = addr; + i2c_read_write = read_write; + i2c_size = size; + i2c_data = data; + smbus_xfer = false; + + std::unique_lock start_lock(i2c_smbus_start_mutex); + i2c_smbus_start = true; + i2c_smbus_start_cv.notify_all(); + start_lock.unlock(); + + std::unique_lock done_lock(i2c_smbus_done_mutex); + + i2c_smbus_done_cv.wait(done_lock, [this]{ return i2c_smbus_done.load(); }); + i2c_smbus_done = false; + + i2c_smbus_xfer_mutex.unlock(); + + return(i2c_ret); +} + +s32 i2c_smbus_interface::i2c_read_block(u8 addr, int* size, u8* data) +{ + return i2c_xfer_call(addr, I2C_SMBUS_READ, size, data); +} + +s32 i2c_smbus_interface::i2c_write_block(u8 addr, int size, u8 *data) +{ + return i2c_xfer_call(addr, I2C_SMBUS_WRITE, &size, data); +} + void i2c_smbus_interface::i2c_smbus_thread_function() { while(1) @@ -196,11 +232,18 @@ void i2c_smbus_interface::i2c_smbus_thread_function() break; } - i2c_ret = i2c_smbus_xfer(i2c_addr, i2c_read_write, i2c_command, i2c_size, i2c_data); + if(smbus_xfer) + { + i2c_ret = i2c_smbus_xfer(i2c_addr, i2c_read_write, i2c_command, i2c_size_smbus, i2c_data_smbus); + } + else + { + i2c_ret = i2c_xfer(i2c_addr, i2c_read_write, i2c_size, i2c_data); + } std::unique_lock done_lock(i2c_smbus_done_mutex); i2c_smbus_done = true; i2c_smbus_done_cv.notify_all(); done_lock.unlock(); } -} +} \ No newline at end of file diff --git a/i2c_smbus/i2c_smbus.h b/i2c_smbus/i2c_smbus.h index 0fecc950..0da27959 100644 --- a/i2c_smbus/i2c_smbus.h +++ b/i2c_smbus/i2c_smbus.h @@ -70,6 +70,7 @@ union i2c_smbus_data #define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ #define I2C_SMBUS_I2C_BLOCK_DATA 8 + class i2c_smbus_interface { public: @@ -99,10 +100,16 @@ public: s32 i2c_smbus_read_i2c_block_data(u8 addr, u8 command, u8 length, u8 *values); s32 i2c_smbus_write_i2c_block_data(u8 addr, u8 command, u8 length, const u8 *values); - s32 i2c_smbus_xfer_call(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); + //Addtional functions added for pure I2C block operations + s32 i2c_read_block(u8 addr, int* size, u8* data); + s32 i2c_write_block(u8 addr, int size, u8* data); + + //Handle SMBus and I2C transfer calls in a single thread + s32 i2c_smbus_xfer_call(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); + s32 i2c_xfer_call(u8 addr, char read_write, int* size, u8 *data); - //Virtual function to be implemented by the driver virtual s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data) = 0; + virtual s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data) = 0; private: std::thread * i2c_smbus_thread; @@ -121,9 +128,12 @@ private: u8 i2c_addr; char i2c_read_write; u16 i2c_command; - int i2c_size; - i2c_smbus_data* i2c_data; + int i2c_size_smbus; + int* i2c_size; + i2c_smbus_data* i2c_data_smbus; + u8* i2c_data; s32 i2c_ret; + bool smbus_xfer; }; #endif /* I2C_SMBUS_H */ diff --git a/i2c_smbus/i2c_smbus_amdadl.cpp b/i2c_smbus/i2c_smbus_amdadl.cpp index a42dd786..71155d47 100644 --- a/i2c_smbus/i2c_smbus_amdadl.cpp +++ b/i2c_smbus/i2c_smbus_amdadl.cpp @@ -194,6 +194,11 @@ s32 i2c_smbus_amdadl::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int s return (ret); }; +s32 i2c_smbus_amdadl::i2c_xfer(u8 addr, char read_write, int* size, u8* data) +{ + return -1; +} + #include "Detector.h" bool i2c_smbus_amdadl_detect() diff --git a/i2c_smbus/i2c_smbus_amdadl.h b/i2c_smbus/i2c_smbus_amdadl.h index 29b69a44..c91d0273 100644 --- a/i2c_smbus/i2c_smbus_amdadl.h +++ b/i2c_smbus/i2c_smbus_amdadl.h @@ -30,5 +30,6 @@ public: private: s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); + s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); ADL_CONTEXT_HANDLE context = NULL; }; diff --git a/i2c_smbus/i2c_smbus_i801.cpp b/i2c_smbus/i2c_smbus_i801.cpp index 7a998289..cd9c9cc1 100644 --- a/i2c_smbus/i2c_smbus_i801.cpp +++ b/i2c_smbus/i2c_smbus_i801.cpp @@ -484,6 +484,11 @@ s32 i2c_smbus_i801::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int siz return i801_access(addr, read_write, command, size, data); } +s32 i2c_smbus_i801::i2c_xfer(u8 addr, char read_write, int* size, u8* data) +{ + return -1; +} + #include "Detector.h" #include "wmi.h" diff --git a/i2c_smbus/i2c_smbus_i801.h b/i2c_smbus/i2c_smbus_i801.h index 34f1b1e9..5d59ddab 100644 --- a/i2c_smbus/i2c_smbus_i801.h +++ b/i2c_smbus/i2c_smbus_i801.h @@ -92,5 +92,5 @@ private: int i801_wait_byte_done(); int i801_wait_intr(); s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); - + s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); }; \ No newline at end of file diff --git a/i2c_smbus/i2c_smbus_linux.cpp b/i2c_smbus/i2c_smbus_linux.cpp index 95658050..a020b078 100644 --- a/i2c_smbus/i2c_smbus_linux.cpp +++ b/i2c_smbus/i2c_smbus_linux.cpp @@ -12,9 +12,11 @@ #include #include #include +#include s32 i2c_smbus_linux::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, union i2c_smbus_data* data) { + struct i2c_smbus_ioctl_data args; //Tell I2C host which slave address to transfer to @@ -28,6 +30,24 @@ s32 i2c_smbus_linux::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int si return ioctl(handle, I2C_SMBUS, &args); } +s32 i2c_smbus_linux::i2c_xfer(u8 addr, char read_write, int* size, u8* data) +{ + i2c_rdwr_ioctl_data rdwr; + i2c_msg msg; + + msg.addr = addr; + msg.flags = read_write; + msg.len = *size; + msg.buf = (u8*)malloc(*size); + memcpy(&msg.buf, &data, *size); + + rdwr.msgs = &msg; + rdwr.nmsgs = 1; + + ioctl(handle, I2C_SLAVE, addr); + return ioctl(handle, I2C_RDWR, &rdwr); +} + #include "Detector.h" #include #include diff --git a/i2c_smbus/i2c_smbus_linux.h b/i2c_smbus/i2c_smbus_linux.h index 939886ab..fc037086 100644 --- a/i2c_smbus/i2c_smbus_linux.h +++ b/i2c_smbus/i2c_smbus_linux.h @@ -16,4 +16,5 @@ public: private: s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); + s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); }; diff --git a/i2c_smbus/i2c_smbus_nct6775.cpp b/i2c_smbus/i2c_smbus_nct6775.cpp index 6d85619b..80ce9fd9 100644 --- a/i2c_smbus/i2c_smbus_nct6775.cpp +++ b/i2c_smbus/i2c_smbus_nct6775.cpp @@ -189,6 +189,11 @@ s32 i2c_smbus_nct6775::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int return nct6775_access(addr, read_write, command, size, data); } +s32 i2c_smbus_nct6775::i2c_xfer(u8 addr, char read_write, int* size, u8* data) +{ + return -1; +} + #include "Detector.h" #include "super_io.h" diff --git a/i2c_smbus/i2c_smbus_nct6775.h b/i2c_smbus/i2c_smbus_nct6775.h index 37e210da..a9af8fb7 100644 --- a/i2c_smbus/i2c_smbus_nct6775.h +++ b/i2c_smbus/i2c_smbus_nct6775.h @@ -53,5 +53,6 @@ public: private: s32 nct6775_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data); s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); + s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); }; diff --git a/i2c_smbus/i2c_smbus_nvapi.cpp b/i2c_smbus/i2c_smbus_nvapi.cpp index 363e2ffe..d78e0e08 100644 --- a/i2c_smbus/i2c_smbus_nvapi.cpp +++ b/i2c_smbus/i2c_smbus_nvapi.cpp @@ -20,7 +20,7 @@ s32 i2c_smbus_nvapi::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int mo NV_I2C_INFO_V3 i2c_data; uint8_t data_buf[I2C_SMBUS_BLOCK_MAX]; uint8_t chip_addr; - + // Set up chip register address to command, one byte in length chip_addr = command; i2c_data.i2c_reg_address = &chip_addr; @@ -114,7 +114,48 @@ s32 i2c_smbus_nvapi::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int mo break; } } - + + return(ret); +} + +s32 i2c_smbus_nvapi::i2c_xfer(u8 addr, char read_write, int* size, u8* data) +{ + NV_STATUS ret; + unsigned int unknown = 0; + NV_I2C_INFO_V3 i2c_data; + + i2c_data.i2c_reg_address = NULL; + i2c_data.reg_addr_size = 0; + + // Set up data buffer, zero bytes in length + i2c_data.data = data; + i2c_data.size = *size; + + // Always use GPU port 1 - this is where RGB controllers are attached + i2c_data.is_ddc_port = 0; + i2c_data.port_id = 1; + i2c_data.is_port_id_set = 1; + + // Use default speed + i2c_data.i2c_speed = 0xFFFF; + i2c_data.i2c_speed_khz = NV_I2C_SPEED::NVAPI_I2C_SPEED_DEFAULT; + + // Load device address + i2c_data.i2c_dev_address = (addr << 1); + + // Perform read or write + if(read_write == I2C_SMBUS_WRITE) + { + ret = NvAPI_I2CWriteEx(handle, &i2c_data, &unknown); + } + else + { + ret = NvAPI_I2CReadEx(handle, &i2c_data, &unknown); + + *size = i2c_data.size; + memcpy(data, i2c_data.data, i2c_data.size); + } + return(ret); } diff --git a/i2c_smbus/i2c_smbus_nvapi.h b/i2c_smbus/i2c_smbus_nvapi.h index 0f6b8448..70ce7a41 100644 --- a/i2c_smbus/i2c_smbus_nvapi.h +++ b/i2c_smbus/i2c_smbus_nvapi.h @@ -16,9 +16,11 @@ class i2c_smbus_nvapi : public i2c_smbus_interface { public: i2c_smbus_nvapi(NV_PHYSICAL_GPU_HANDLE handle); + s32 i2c_read_block_data(u8 addr, u8 length, u8 *values); + s32 i2c_write_block_data(u8 addr, u8 length, u8 *values); private: s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int mode, i2c_smbus_data* data); - + s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); NV_PHYSICAL_GPU_HANDLE handle; }; diff --git a/i2c_smbus/i2c_smbus_piix4.cpp b/i2c_smbus/i2c_smbus_piix4.cpp index 9610621f..124092ae 100644 --- a/i2c_smbus/i2c_smbus_piix4.cpp +++ b/i2c_smbus/i2c_smbus_piix4.cpp @@ -178,6 +178,11 @@ s32 i2c_smbus_piix4::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int si return piix4_access(addr, read_write, command, size, data); } +s32 i2c_smbus_piix4::i2c_xfer(u8 addr, char read_write, int* size, u8* data) +{ + return -1; +} + #include "Detector.h" #include "wmi.h" diff --git a/i2c_smbus/i2c_smbus_piix4.h b/i2c_smbus/i2c_smbus_piix4.h index 262e0c58..fe3308d6 100644 --- a/i2c_smbus/i2c_smbus_piix4.h +++ b/i2c_smbus/i2c_smbus_piix4.h @@ -45,4 +45,5 @@ private: int piix4_transaction(); s32 piix4_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data); s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); + s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); }; \ No newline at end of file