From 5f90c3726b6bb6db21883e0d02fd9717d9979d05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sun, 27 Mar 2022 19:52:58 +0200 Subject: [PATCH] intel_extreme: change i2c_send_receive to a hook common: i2c/ddc uses a 7-bit address for EDID. Change-Id: Ic1bba2a23174c671bd7374104596c22433bd343a Reviewed-on: https://review.haiku-os.org/c/haiku/+/5171 Tested-by: Commit checker robot Reviewed-by: Adrien Destugues --- headers/private/graphics/common/i2c.h | 11 +++++- src/add-ons/accelerants/common/ddc.c | 17 ++++++++- src/add-ons/accelerants/common/i2c.c | 13 +++++-- .../accelerants/intel_extreme/Ports.cpp | 36 ++++++++++++------- src/add-ons/accelerants/intel_extreme/Ports.h | 2 ++ 5 files changed, 61 insertions(+), 18 deletions(-) diff --git a/headers/private/graphics/common/i2c.h b/headers/private/graphics/common/i2c.h index e048b6d60e..30d697c565 100644 --- a/headers/private/graphics/common/i2c.h +++ b/headers/private/graphics/common/i2c.h @@ -35,17 +35,26 @@ typedef struct i2c_timing { } i2c_timing; +struct i2c_bus; + // set signals on bus typedef status_t (*i2c_set_signals)(void *cookie, int clock, int data); // read signals from bus typedef status_t (*i2c_get_signals)(void *cookie, int *clock, int *data); +// send/receive from bus +typedef status_t (*i2c_send_receive)(const struct i2c_bus *bus, uint32 slave_address, + const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, + size_t readLength); // i2c bus definition typedef struct i2c_bus { void *cookie; // user-defined cookie + // low-level i2c_timing timing; i2c_set_signals set_signals; // callback to set signals i2c_get_signals get_signals; // callback to detect signals + // high-level + i2c_send_receive send_receive; } i2c_bus; @@ -54,7 +63,7 @@ extern "C" { #endif // send and receive data via i2c bus -status_t i2c_send_receive(const i2c_bus *bus, int slave_address, +status_t i2c_send_receive_callback(const i2c_bus *bus, uint32 slave_address, const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, size_t readLength); diff --git a/src/add-ons/accelerants/common/ddc.c b/src/add-ons/accelerants/common/ddc.c index 8b1210c75a..ab83518bd7 100644 --- a/src/add-ons/accelerants/common/ddc.c +++ b/src/add-ons/accelerants/common/ddc.c @@ -54,6 +54,19 @@ verify_checksum(const uint8 *data, size_t len) } +static status_t +call_send_receive(const i2c_bus *bus, int slave_address, + const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, + size_t readLength) +{ + i2c_send_receive send_receive = bus->send_receive; + if (send_receive == NULL) + send_receive = i2c_send_receive_callback; + return send_receive(bus, slave_address, writeBuffer, writeLength, readBuffer, + readLength); +} + + //! Read ddc2 data from monitor static status_t ddc2_read(const i2c_bus *bus, int start, uint8 *buffer, size_t length) @@ -66,7 +79,7 @@ ddc2_read(const i2c_bus *bus, int start, uint8 *buffer, size_t length) writeBuffer[1] = (start >> 8) & 0xff; for (i = 0; i < READ_RETRIES; ++i) { - status = i2c_send_receive(bus, 0xa0, writeBuffer, + status = call_send_receive(bus, 0x50, writeBuffer, start < 0x100 ? 1 : 2, buffer, length); if (status != B_OK) @@ -135,6 +148,8 @@ ddc2_read_vdif(const i2c_bus *bus, int start, void ddc2_init_timing(i2c_bus *bus) { + bus->send_receive = NULL; + i2c_get100k_timing(&bus->timing); // VESA standard diff --git a/src/add-ons/accelerants/common/i2c.c b/src/add-ons/accelerants/common/i2c.c index 6928262fe3..d5a22d4885 100644 --- a/src/add-ons/accelerants/common/i2c.c +++ b/src/add-ons/accelerants/common/i2c.c @@ -268,7 +268,7 @@ send_byte(const i2c_bus *bus, uint8 byte, bool acknowledge) //! Send slave address, obeying 10-bit addresses and general call addresses static status_t -send_slave_address(const i2c_bus *bus, int slaveAddress, bool isWrite) +send_slave_address(const i2c_bus *bus, uint8 slaveAddress, bool isWrite) { status_t status; @@ -400,10 +400,17 @@ receive_bytes(const i2c_bus *bus, uint8 *readBuffer, ssize_t readLength) //! Combined i2c send+receive format status_t -i2c_send_receive(const i2c_bus *bus, int slaveAddress, const uint8 *writeBuffer, +i2c_send_receive_callback(const i2c_bus *bus, uint32 slaveAddress, const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, size_t readLength) { - status_t status = send_start_condition(bus); + status_t status; + + // the address is 7-bit + slaveAddress <<= 1; + if (slaveAddress > 0xff) + return B_BAD_VALUE; + + status = send_start_condition(bus); if (status != B_OK) return status; diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 3dd90e8257..799cb10528 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -208,20 +208,9 @@ Port::GetEDID(edid1_info* edid, bool forceRead) if (fEDIDState == B_NO_INIT || forceRead) { TRACE("%s: trying to read EDID\n", PortName()); - addr_t ddcRegister = _DDCRegister(); - if (ddcRegister == 0) { - TRACE("%s: no DDC register found\n", PortName()); - fEDIDState = B_ERROR; - return fEDIDState; - } - - TRACE("%s: using ddc @ 0x%" B_PRIxADDR "\n", PortName(), ddcRegister); - i2c_bus bus; - bus.cookie = (void*)ddcRegister; - bus.set_signals = &_SetI2CSignals; - bus.get_signals = &_GetI2CSignals; - ddc2_init_timing(&bus); + if (SetupI2c(&bus) != B_OK) + return fEDIDState; fEDIDState = ddc2_read_edid1(&bus, &fEDIDInfo, NULL, NULL); @@ -243,6 +232,27 @@ Port::GetEDID(edid1_info* edid, bool forceRead) } +status_t +Port::SetupI2c(i2c_bus *bus) +{ + addr_t ddcRegister = _DDCRegister(); + if (ddcRegister == 0) { + TRACE("%s: no DDC register found\n", PortName()); + fEDIDState = B_ERROR; + return fEDIDState; + } + + TRACE("%s: using ddc @ 0x%" B_PRIxADDR "\n", PortName(), ddcRegister); + + ddc2_init_timing(bus); + bus->cookie = (void*)ddcRegister; + bus->set_signals = &_SetI2CSignals; + bus->get_signals = &_GetI2CSignals; + + return B_OK; +} + + status_t Port::GetPLLLimits(pll_limits& limits) { diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 0804d3a7ce..099f5e6c6a 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -21,6 +21,7 @@ #define MAX_PORTS 20 // a generous upper bound struct pll_limits; +struct i2c_bus; enum port_type { INTEL_PORT_TYPE_ANY, // wildcard for lookup functions @@ -57,6 +58,7 @@ virtual status_t Power(bool enabled); bool HasEDID(); virtual status_t GetEDID(edid1_info* edid, bool forceRead = false); +virtual status_t SetupI2c(struct i2c_bus *bus); virtual status_t GetPLLLimits(pll_limits& limits);