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 <[email protected]>
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
Jérôme Duval
2022-04-05 10:53:04 +00:00
committed by Adrien Destugues
parent 5e6e52cfd4
commit 5f90c3726b
5 changed files with 61 additions and 18 deletions
+10 -1
View File
@@ -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);
+16 -1
View File
@@ -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
+10 -3
View File
@@ -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;
+23 -13
View File
@@ -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)
{
@@ -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);