Add fixed-refresh preset group for workstation modes

get_pure_lm_mode() picks the preset with the nearest total line count.
Several workstation display modes share line counts with each other or with
VESA modes while having one fixed refresh rate (e.g. Sun 1152x900 is 937
lines at both 66 Hz and 76.6 Hz on cg6 boards, and Sun 1280x1024@76 has the
1066 lines of VESA 1280x1024).

Add GROUP_FIXED_VHZ. Presets in this group are candidates only when the
measured refresh is within +-0.3 Hz of the preset (the measured refresh is
exact to about 0.01 Hz). They are appended at the end of the table, so the
early exit of the search loop is replaced by a flag that skips the
remaining regular presets exactly as before but still lets fixed-refresh
presets take part, including the existing equal-line refresh tie-break
(group >= GROUP_720P). Group-indexed arrays in video_modes.c and
controls.c get the extra entry.

No preset uses the group yet, so behaviour is unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WiXHy7Jhh5yTdsBaenucgw
This commit is contained in:
Peter YooandClaude Opus 5 committed 2026-09-18 22:10:33 +09:00
1 parent e800f095de
commit b2fd00d439
3 files changed
+22 -7

No files matched your search

@@ -70,8 +70,11 @@ typedef enum {
GROUP_720P = 8,
GROUP_1080I = 9,
GROUP_1080P = 10,
GROUP_FIXED_VHZ = 11, // fixed-refresh workstation modes: only matched when the input refresh is within FIXED_VHZ_TOL_X100
} video_group;
#define FIXED_VHZ_TOL_X100 30 // +-0.30 Hz (measured refresh is exact to ~0.01 Hz)
typedef enum {
MODE_INTERLACED = (1<<0), //deprecated
MODE_CRT = (1<<1),
+3 -3
View File
@@ -173,8 +173,8 @@ int parse_control()
unsigned uart_rx_arg;
// one for each video_group
alt_u8* pmcfg_ptr[] = { &pt_only, &tc.pm_240p, &tc.pm_240p, &tc.pm_384p, &tc.pm_480i, &tc.pm_480i, &tc.pm_480p, &tc.pm_480p, &pt_only, &tc.pm_1080i, &pt_only };
alt_u8 valid_pm[] = { 0x1, 0x3f, 0x3f, 0x7, 0xf, 0xf, 0x7, 0x7, 0x1, 0x3, 0x1 };
alt_u8* pmcfg_ptr[] = { &pt_only, &tc.pm_240p, &tc.pm_240p, &tc.pm_384p, &tc.pm_480i, &tc.pm_480i, &tc.pm_480p, &tc.pm_480p, &pt_only, &tc.pm_1080i, &pt_only, &pt_only };
alt_u8 valid_pm[] = { 0x1, 0x3f, 0x3f, 0x7, 0xf, 0xf, 0x7, 0x7, 0x1, 0x3, 0x1, 0x1 };
avinput_t next_input = (cm.avinput == AV3_YPBPR) ? AV1_RGBs : (cm.avinput+1);
@@ -315,7 +315,7 @@ int parse_control()
break;
}
if (video_modes_plm[cm.id].group > GROUP_1080P) {
if (video_modes_plm[cm.id].group > GROUP_FIXED_VHZ) {
printf("WARNING: Corrupted mode (id %d)\n", cm.id);
break;
}
+16 -4
View File
@@ -133,7 +133,7 @@ uint32_t calculate_pclk(uint32_t src_clk_hz, mode_data_t *vm_out, vm_proc_config
int get_pure_lm_mode(avconfig_t *cc, mode_data_t *vm_in, mode_data_t *vm_out, vm_proc_config_t *vm_conf)
{
int i, diff_lines, diff_v_hz_x100, mindiff_id=0, mindiff_lines=1000, mindiff_v_hz_x100=10000, x_rpt_decr=0, skip_hv_mult=0;
int i, diff_lines, diff_v_hz_x100, mindiff_id=0, mindiff_lines=1000, mindiff_v_hz_x100=10000, x_rpt_decr=0, skip_hv_mult=0, settled=0;
mode_data_t *mode_preset;
mode_flags valid_lm[] = { (MODE_PT | (cc->pt_mode ? (MODE_L5_GEN_4_3<<(cc->pt_mode-1)) : 0)),
(MODE_L2 | (MODE_L2<<cc->l2_mode)),
@@ -146,11 +146,23 @@ int get_pure_lm_mode(avconfig_t *cc, mode_data_t *vm_in, mode_data_t *vm_out, vm
uint8_t upsample2x = cc->upsample2x;
// one for each video_group
uint8_t* group_ptr[] = { &pt_only, &cc->pm_240p, &cc->pm_240p, &cc->pm_384p, &cc->pm_480i, &cc->pm_480i, &cc->pm_480p, &cc->pm_480p, &pt_only, &cc->pm_1080i, &pt_only };
uint8_t* group_ptr[] = { &pt_only, &cc->pm_240p, &cc->pm_240p, &cc->pm_384p, &cc->pm_480i, &cc->pm_480i, &cc->pm_480p, &cc->pm_480p, &pt_only, &cc->pm_1080i, &pt_only, &pt_only };
for (i=0; i<num_video_modes_plm; i++) {
mode_preset = &video_modes_plm[i];
// Workstation presets share line counts with each other and with VESA modes but each has one fixed refresh
// rate; consider them only when the refresh matches, so other sources are matched exactly as before and a
// small line-count wobble cannot flip between them.
if ((mode_preset->group == GROUP_FIXED_VHZ) &&
(abs((int)vm_in->timings.v_hz_x100 - (int)mode_preset->timings.v_hz_x100) > FIXED_VHZ_TOL_X100))
continue;
// After the early exit below, only the fixed-refresh presets (appended at the end of the table) may still
// compete, so a preset sharing its line count with a VESA mode can win the equal-line refresh tie-break.
if (settled && (mode_preset->group != GROUP_FIXED_VHZ))
continue;
switch (mode_preset->group) {
case GROUP_384P:
//fixed Line2x/3x mode for 240x360p/400p
@@ -213,8 +225,8 @@ int get_pure_lm_mode(avconfig_t *cc, mode_data_t *vm_in, mode_data_t *vm_out, vm
mindiff_v_hz_x100 = diff_v_hz_x100;
mindiff_lm = target_lm;
} else if ((mindiff_lines <= 2) && (diff_lines > mindiff_lines)) {
// Break out if suitable mode already found
break;
// Stop considering regular presets once a suitable mode has been found
settled = 1;
}
}
}