From 9b910ef0a7d3d72368c6c5daea6532804ddd0a27 Mon Sep 17 00:00:00 2001 From: Steve Markgraf Date: Thu, 12 Dec 2024 00:18:11 +0100 Subject: [PATCH] lib: add code to control a data source via EDID RAM --- include/hsdaoh.h | 12 ++++++++++++ src/libhsdaoh.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/hsdaoh.h b/include/hsdaoh.h index 0663fa8..dd7037d 100644 --- a/include/hsdaoh.h +++ b/include/hsdaoh.h @@ -130,6 +130,18 @@ HSDAOH_API int hsdaoh_start_stream(hsdaoh_dev_t *dev, */ HSDAOH_API int hsdaoh_stop_stream(hsdaoh_dev_t *dev); +/*! + * Write a datagram to the EDID RAM to control a downstream data source. + * A header with a sequence number and length is prepended to the mesage + * by the library. + * + * \param dev the device handle given by hsdaoh_open() + * \param data pointer to the datagram + * \param len length of the datagram, must not exceed 256-2 = 254 bytes + * due to the prepended header. + * \return 0 on success + */ +HSDAOH_API int hsdaoh_write_edid_cmd_data(hsdaoh_dev_t *dev, uint8_t *data, uint8_t len); #ifdef __cplusplus } #endif diff --git a/src/libhsdaoh.c b/src/libhsdaoh.c index ea8dc7b..23301c4 100644 --- a/src/libhsdaoh.c +++ b/src/libhsdaoh.c @@ -84,6 +84,7 @@ struct hsdaoh_dev { int hid_interface; + uint8_t edid_seq_cnt; int frames_since_error; int discard_start_frames; uint16_t last_frame_cnt; @@ -181,6 +182,40 @@ int hsdaoh_read_register(hsdaoh_dev_t *dev, uint16_t addr, uint8_t *val) return r; } +/* Write a datagram to the EDID RAM to control a downstream data source */ +int hsdaoh_write_edid_cmd_data(hsdaoh_dev_t *dev, uint8_t *data, uint8_t len) +{ + if (!dev || !data || (len > 254)) + return -1; + + /* increment sequence counter and avoid values 0x00 and 0xff */ + dev->edid_seq_cnt++; + if (!dev->edid_seq_cnt || (dev->edid_seq_cnt == 0xff)) + dev->edid_seq_cnt = 1; + + /* disable I2C access to EDID RAM, reading via I2C will result in a NAK */ + hsdaoh_ms_write_register(dev, 0xf063, 0x00); + + /* switch EDID RAM to 8051 */ + hsdaoh_ms_write_register(dev, 0xf062, 0x80); + + /* store header with sequence counter and length of data */ + hsdaoh_ms_write_register(dev, 0xf900, dev->edid_seq_cnt); + hsdaoh_ms_write_register(dev, 0xf901, len); + + /* store actual data to the EDID RAM */ + for (uint8_t i = 0; i < len; i++) + hsdaoh_ms_write_register(dev, 0xf902 + i, data[i]); + + /* switch EDID RAM to DDC I2C slave */ + hsdaoh_ms_write_register(dev, 0xf062, 0x00); + + /* re-enable I2C access to EDID RAM */ + hsdaoh_ms_write_register(dev, 0xf063, 0x08); + + return 0; +} + /* Switch the MS2130 to a transparent mode, YUYV data received via HDMI * will be passed through unmodified */ void hsdaoh_ms_enable_transparent_mode(hsdaoh_dev_t *dev)