video: code cleanup in spd/spare packets handling and fix for freesync mode.
This commit is contained in:
340
video.cpp
340
video.cpp
@@ -59,6 +59,7 @@
|
||||
#define VRR_VESA 0x02
|
||||
|
||||
static int use_vrr = 0;
|
||||
static int use_freesync_spd = 0;
|
||||
static uint8_t vrr_min_fr = 0;
|
||||
static uint8_t vrr_max_fr = 0;
|
||||
|
||||
@@ -1108,30 +1109,13 @@ void video_loadPreset(char *name, bool save)
|
||||
}
|
||||
}
|
||||
|
||||
static void hdmi_config_set_spd(bool val)
|
||||
static void hdmi_packet_enable(uint8_t mask, bool enable)
|
||||
{
|
||||
int fd = i2c_open(0x39, 0);
|
||||
if (fd >= 0)
|
||||
{
|
||||
uint8_t packet_val = i2c_smbus_read_byte_data(fd, 0x40);
|
||||
if (val)
|
||||
packet_val |= 0x40;
|
||||
else
|
||||
packet_val &= ~0x40;
|
||||
int res = i2c_smbus_write_byte_data(fd, 0x40, packet_val);
|
||||
if (res < 0) printf("i2c: write error (%02X %02X): %d\n", 0x40, packet_val, res);
|
||||
i2c_close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
static void hdmi_config_set_spare(int packet, bool enabled)
|
||||
{
|
||||
int fd = i2c_open(0x39, 0);
|
||||
uint8_t mask = packet == 0 ? 0x01 : 0x02;
|
||||
if (fd >= 0)
|
||||
{
|
||||
uint8_t packet_val = i2c_smbus_read_byte_data(fd, 0x40);
|
||||
if (enabled)
|
||||
if (enable)
|
||||
packet_val |= mask;
|
||||
else
|
||||
packet_val &= ~mask;
|
||||
@@ -1141,6 +1125,48 @@ static void hdmi_config_set_spare(int packet, bool enabled)
|
||||
}
|
||||
}
|
||||
|
||||
static void hdmi_packet_set_data(uint8_t mask, uint8_t offset, uint8_t *data, int size)
|
||||
{
|
||||
if (!data)
|
||||
{
|
||||
hdmi_packet_enable(mask, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
int fd = i2c_open(0x38, 0);
|
||||
if (fd >= 0)
|
||||
{
|
||||
int res;
|
||||
hdmi_packet_enable(mask, 1);
|
||||
|
||||
res = i2c_smbus_write_byte_data(fd, offset + 0x1F, 0x80);
|
||||
if (res < 0)
|
||||
{
|
||||
printf("i2c: Couldn't update packet change register (0x%02X, 0x80) %d\n", offset + 0x1F, res);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
res = i2c_smbus_write_byte_data(fd, offset + i, data[i]);
|
||||
if (res < 0) printf("i2c: SPD register write error (%02X %02x): %d\n", offset + i, data[i], res);
|
||||
}
|
||||
|
||||
res = i2c_smbus_write_byte_data(fd, offset + 0x1F, 0x00);
|
||||
if (res < 0) printf("i2c: Couldn't update packet change register (0x%02X, 0x00) %d\n", offset + 0x1F, res);
|
||||
}
|
||||
i2c_close(fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdmi_packet_enable(mask, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#define hdmi_spd_config(data) hdmi_packet_set_data(0x40, 0x00, data, sizeof(data))
|
||||
|
||||
#define hdmi_spare_config(packet, data) hdmi_packet_set_data(packet == 0 ? 0x01 : 0x02, packet == 0 ? 0xC0 : 0xE0, data, sizeof(data))
|
||||
|
||||
static void hdmi_config_set_csc()
|
||||
{
|
||||
// default color conversion matrices
|
||||
@@ -1535,94 +1561,6 @@ static void hdmi_config_init()
|
||||
hdmi_config_set_csc();
|
||||
}
|
||||
|
||||
static void spd_config(uint8_t *data)
|
||||
{
|
||||
int fd = i2c_open(0x38, 0);
|
||||
if (fd >= 0)
|
||||
{
|
||||
int res;
|
||||
hdmi_config_set_spd(1);
|
||||
|
||||
res = i2c_smbus_write_byte_data(fd, 0x1F, 0x80);
|
||||
if (res < 0)
|
||||
{
|
||||
printf("i2c: Couldn't update SPD change register (0x1F, 0x80) %d\n", res);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 31; i++)
|
||||
{
|
||||
res = i2c_smbus_write_byte_data(fd, i, data[i]);
|
||||
if (res < 0) printf("i2c: SPD register write error (%02X %02x): %d\n", i, data[i], res);
|
||||
}
|
||||
|
||||
res = i2c_smbus_write_byte_data(fd, 0x1F, 0x00);
|
||||
if (res < 0) printf("i2c: Couldn't update SPD change register (0x1F, 0x00), %d\n", res);
|
||||
}
|
||||
i2c_close(fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdmi_config_set_spd(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void spd_config_update()
|
||||
{
|
||||
VideoInfo *vi = ¤t_video_info;
|
||||
if (!vi->width)
|
||||
return;
|
||||
|
||||
uint8_t data[32] = {
|
||||
0x83, 0x01, 25, 0,
|
||||
cfg.direct_video ? 'D' : 'V',
|
||||
cfg.direct_video ? 'V' : 'I',
|
||||
cfg.direct_video ? '1' : '1', // version
|
||||
(uint8_t)((vi->interlaced ? 1 : 0) | (menu_present() ? 4 : 0) | (vi->rotated ? 8 : 0)),
|
||||
(uint8_t)(vi->pixrep ? vi->pixrep : (vi->ctime / vi->width)),
|
||||
(uint8_t)vi->de_h,
|
||||
(uint8_t)(vi->de_h >> 8),
|
||||
(uint8_t)vi->de_v,
|
||||
(uint8_t)(vi->de_v >> 8),
|
||||
(uint8_t)vi->width,
|
||||
(uint8_t)(vi->width >> 8),
|
||||
(uint8_t)vi->height,
|
||||
(uint8_t)(vi->height >> 8)
|
||||
};
|
||||
|
||||
char *name = user_io_get_core_name2();
|
||||
for (int i = 17; i < 32; i++)
|
||||
{
|
||||
if (!*name) break;
|
||||
data[i] = (uint8_t)(*name);
|
||||
name++;
|
||||
}
|
||||
|
||||
spd_config(data);
|
||||
}
|
||||
|
||||
/*
|
||||
static void spd_config_hdmi()
|
||||
{
|
||||
uint8_t data[32] = {
|
||||
0x83, 0x01, 25, 0,
|
||||
'M', 'i', 'S', 'T', 'e', 'r', 0, 0,
|
||||
};
|
||||
|
||||
char *name = user_io_get_core_name();
|
||||
for (int i = 12; i < 27; i++)
|
||||
{
|
||||
if (!*name) break;
|
||||
data[i] = (uint8_t)(*name);
|
||||
name++;
|
||||
}
|
||||
|
||||
data[27] = 8; // GAME
|
||||
|
||||
spd_config(data);
|
||||
}
|
||||
*/
|
||||
|
||||
static void hdmi_config_set_hdr()
|
||||
{
|
||||
// Grab desired nits values
|
||||
@@ -1673,38 +1611,17 @@ static void hdmi_config_set_hdr()
|
||||
};
|
||||
|
||||
// now we calculate the checksum for this packet (2s complement sum)
|
||||
uint16_t checksum = 0;
|
||||
for (uint i = 0; i < sizeof(hdr_data); i++)
|
||||
checksum += hdr_data[i];
|
||||
|
||||
checksum = checksum & 0xFF;
|
||||
checksum = ~checksum + 1;
|
||||
|
||||
hdr_data[3] = checksum;
|
||||
uint8_t checksum = 0;
|
||||
for (uint i = 0; i < sizeof(hdr_data); i++) checksum += hdr_data[i];
|
||||
hdr_data[3] = ~checksum + 1;
|
||||
|
||||
if (cfg.hdr == 0)
|
||||
{
|
||||
hdmi_config_set_spare(1, false);
|
||||
hdmi_spare_config(1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdmi_config_set_spare(1, true);
|
||||
int fd = i2c_open(0x38, 0);
|
||||
int res = i2c_smbus_write_byte_data(fd, 0xFF, 0b10000000);
|
||||
if (res < 0)
|
||||
{
|
||||
printf("i2c: hdr: Couldn't update Spare Packet change register (0xDF, 0x80) %d\n", res);
|
||||
}
|
||||
|
||||
uint8_t addr = 0xe0;
|
||||
for (uint i = 0; i < sizeof(hdr_data); i++)
|
||||
{
|
||||
res = i2c_smbus_write_byte_data(fd, addr, hdr_data[i]);
|
||||
if (res < 0) printf("i2c: hdr register write error (%02X %02x): %d\n", addr, hdr_data[i], res);
|
||||
addr += 1;
|
||||
}
|
||||
res = i2c_smbus_write_byte_data(fd, 0xfF, 0x00);
|
||||
if (res < 0) printf("i2c: hdr: Couldn't update Spare Packet change register (0xDF, 0x00), %d\n", res);
|
||||
hdmi_spare_config(1, hdr_data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2035,10 +1952,11 @@ static void set_vrr_mode()
|
||||
{
|
||||
if (last_vrr_mode != 0)
|
||||
{
|
||||
hdmi_config_set_spd(false);
|
||||
hdmi_config_set_spare(0, false);
|
||||
hdmi_spd_config(0);
|
||||
hdmi_spare_config(0, 0);
|
||||
}
|
||||
last_vrr_mode = 0;
|
||||
use_freesync_spd = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2111,89 +2029,44 @@ static void set_vrr_mode()
|
||||
|
||||
int16_t vrateh_i = (int16_t)vrateh;
|
||||
|
||||
//These are only sent in the case that freesync or vesa vrr is enabled
|
||||
uint8_t freesync_data[] = {
|
||||
//header
|
||||
0x00, 0x83,
|
||||
0x01, 0x01,
|
||||
0x02, 0x08,
|
||||
//data
|
||||
0x04, 0x1A,
|
||||
0x05, 0x00,
|
||||
0x06, 0x00,
|
||||
//0x07
|
||||
//0x08
|
||||
0x09, 0x07,
|
||||
0x0A, vrr_min_fr,
|
||||
0x0B, vrr_max_fr,
|
||||
};
|
||||
|
||||
uint8_t vesa_data[] = {
|
||||
0xC0, 0x7F,
|
||||
0xC1, 0xC0,
|
||||
0xC2, 0x00,
|
||||
|
||||
0xC3, 0x40,
|
||||
0xC5, 0x01,
|
||||
0xC6, 0x00,
|
||||
0xC7, 0x01,
|
||||
0xC8, 0x00,
|
||||
0xC9, 0x04,
|
||||
|
||||
0xCA, 0x01,
|
||||
0xCB, (uint8_t)v_cur.param.vfp,
|
||||
0xCC, (uint8_t)((vrateh_i >> 8) & 0x03),
|
||||
0xCD, (uint8_t)(vrateh_i & 0xFF),
|
||||
};
|
||||
|
||||
int res = 0;
|
||||
int fd = i2c_open(0x38, 0);
|
||||
if (fd >= 0)
|
||||
if (use_vrr == VRR_FREESYNC)
|
||||
{
|
||||
if (use_vrr == VRR_FREESYNC)
|
||||
{
|
||||
hdmi_config_set_spd(1);
|
||||
res = i2c_smbus_write_byte_data(fd, 0x1F, 0b10000000);
|
||||
if (res < 0)
|
||||
{
|
||||
printf("i2c: Vrr: Couldn't update SPD change register (0x1F, 0x80) %d\n", res);
|
||||
}
|
||||
for (uint i = 0; i < sizeof(freesync_data); i += 2)
|
||||
{
|
||||
res = i2c_smbus_write_byte_data(fd, freesync_data[i], freesync_data[i + 1]);
|
||||
if (res < 0) printf("i2c: Vrr register write error (%02X %02x): %d\n", freesync_data[i], freesync_data[i + 1], res);
|
||||
}
|
||||
res = i2c_smbus_write_byte_data(fd, 0x1F, 0x00);
|
||||
if (res < 0) printf("i2c: Vrr: Couldn't update SPD change register (0x1F, 0x00), %d\n", res);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdmi_config_set_spd(0);
|
||||
}
|
||||
uint8_t freesync_data[] = {
|
||||
//header
|
||||
0x83, 0x01, 0x08, 0x00,
|
||||
//data
|
||||
0x1A, 0x00, 0x00, 0x00, 0x00, 0x07,
|
||||
vrr_min_fr,
|
||||
vrr_max_fr,
|
||||
};
|
||||
|
||||
if (use_vrr == VRR_VESA)
|
||||
{
|
||||
hdmi_config_set_spare(0, true);
|
||||
res = i2c_smbus_write_byte_data(fd, 0xDF, 0b10000000);
|
||||
if (res < 0)
|
||||
{
|
||||
printf("i2c: Vrr: Couldn't update Spare Packet change register (0xDF, 0x80) %d\n", res);
|
||||
}
|
||||
|
||||
for (uint i = 0; i < sizeof(vesa_data); i += 2)
|
||||
{
|
||||
res = i2c_smbus_write_byte_data(fd, vesa_data[i], vesa_data[i + 1]);
|
||||
if (res < 0) printf("i2c: Vrr register write error (%02X %02x): %d\n", vesa_data[i], vesa_data[i + 1], res);
|
||||
}
|
||||
res = i2c_smbus_write_byte_data(fd, 0xDF, 0x00);
|
||||
if (res < 0) printf("i2c: Vrr: Couldn't update Spare Packet change register (0xDF, 0x00), %d\n", res);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdmi_config_set_spare(0, false);
|
||||
}
|
||||
i2c_close(fd);
|
||||
use_freesync_spd = 1;
|
||||
hdmi_spd_config(freesync_data);
|
||||
}
|
||||
else if(use_freesync_spd)
|
||||
{
|
||||
use_freesync_spd = 0;
|
||||
hdmi_spd_config(0);
|
||||
}
|
||||
|
||||
if (use_vrr == VRR_VESA)
|
||||
{
|
||||
uint8_t vesa_data[] = {
|
||||
0x7F, 0xC0, 0x00,
|
||||
0x40, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04,
|
||||
0x01,
|
||||
(uint8_t)v_cur.param.vfp,
|
||||
(uint8_t)((vrateh_i >> 8) & 0x03),
|
||||
(uint8_t)(vrateh_i & 0xFF),
|
||||
};
|
||||
|
||||
hdmi_spare_config(0, vesa_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdmi_spare_config(0, 0);
|
||||
}
|
||||
|
||||
last_vrr_mode = cfg.vrr_mode;
|
||||
last_vrr_rate = vrateh;
|
||||
last_vrr_vfp = v_cur.param.vfp;
|
||||
@@ -3083,6 +2956,42 @@ static void set_yc_mode()
|
||||
}
|
||||
}
|
||||
|
||||
static void spd_config_update()
|
||||
{
|
||||
if (use_freesync_spd) return;
|
||||
|
||||
VideoInfo *vi = ¤t_video_info;
|
||||
if (!vi->width) return;
|
||||
|
||||
uint8_t data[31] =
|
||||
{
|
||||
0x83, 0x01, 25, 0,
|
||||
cfg.direct_video ? 'D' : 'V',
|
||||
cfg.direct_video ? 'V' : 'I',
|
||||
cfg.direct_video ? '1' : '1', // version
|
||||
(uint8_t)((vi->interlaced ? 1 : 0) | (menu_present() ? 4 : 0) | (vi->rotated ? 8 : 0)),
|
||||
(uint8_t)(vi->pixrep ? vi->pixrep : (vi->ctime / vi->width)),
|
||||
(uint8_t)vi->de_h,
|
||||
(uint8_t)(vi->de_h >> 8),
|
||||
(uint8_t)vi->de_v,
|
||||
(uint8_t)(vi->de_v >> 8),
|
||||
(uint8_t)vi->width,
|
||||
(uint8_t)(vi->width >> 8),
|
||||
(uint8_t)vi->height,
|
||||
(uint8_t)(vi->height >> 8)
|
||||
};
|
||||
|
||||
char *name = user_io_get_core_name2();
|
||||
for (int i = 17; i < 31; i++)
|
||||
{
|
||||
if (!*name) break;
|
||||
data[i] = (uint8_t)(*name);
|
||||
name++;
|
||||
}
|
||||
|
||||
hdmi_spd_config(data);
|
||||
}
|
||||
|
||||
void video_mode_adjust()
|
||||
{
|
||||
static bool force = false;
|
||||
@@ -3097,7 +3006,6 @@ void video_mode_adjust()
|
||||
show_video_info(&video_info, &v_cur);
|
||||
set_yc_mode();
|
||||
spd_config_update();
|
||||
//else if(use_vrr != VRR_FREESYNC) spd_config_hdmi();
|
||||
}
|
||||
force = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user