From b2fd00d439810423b87a05356ef86767c2a984e8 Mon Sep 17 00:00:00 2001 From: Peter Yoo Date: Fri, 18 Sep 2026 22:10:33 +0900 Subject: [PATCH] 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) Claude-Session: https://claude.ai/code/session_01WiXHy7Jhh5yTdsBaenucgw --- software/sys_controller/inc/video_modes.h | 3 +++ software/sys_controller/src/controls.c | 6 +++--- software/sys_controller/src/video_modes.c | 20 ++++++++++++++++---- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/software/sys_controller/inc/video_modes.h b/software/sys_controller/inc/video_modes.h index fbd05df..f71930a 100644 --- a/software/sys_controller/inc/video_modes.h +++ b/software/sys_controller/inc/video_modes.h @@ -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), diff --git a/software/sys_controller/src/controls.c b/software/sys_controller/src/controls.c index eb2fb83..63f971b 100644 --- a/software/sys_controller/src/controls.c +++ b/software/sys_controller/src/controls.c @@ -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; } diff --git a/software/sys_controller/src/video_modes.c b/software/sys_controller/src/video_modes.c index 96cfc73..473813b 100644 --- a/software/sys_controller/src/video_modes.c +++ b/software/sys_controller/src/video_modes.c @@ -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<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; igroup == 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; } } }