From 41bf84e591a8fbae1f0da6ec9a14ca9034ea9b4a Mon Sep 17 00:00:00 2001 From: Mohit Ingale Date: Wed, 23 Apr 2025 21:15:41 +0000 Subject: [PATCH] tegra: fsync: Fix tick calculation for freq generation Use DIV_ROUND_DOWN_ULL consistently for frequency calculations to match QNX implementation. For 30Hz signals, reference ticks were calculated as 1041667 for a value of 1041666.67, while QNX correctly uses 1041666. When generating precise frequencies, this rounding difference affects how extra ticks distribute across periods (covering the 0.67 gap over 3 periods). The QNX implementation works correctly because it rounds down, while the Linux implementation was rounding up. This change ensures proper fractional tick distribution and prevents signal drift over time for frequencies that aren't exact multiples of the TSC clock unit. Bug 5223558 Change-Id: I5fbeafd1e37c92fe95f2f3605d1ae225eacb88c8 Signed-off-by: Mohit Ingale Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3348278 Reviewed-by: Justin Kim (SW-TEGRA) GVS: buildbot_gerritrpt Reviewed-by: Frank Chen Reviewed-by: Ian Kaszubski --- drivers/media/platform/tegra/cam_fsync/cam_fsync.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/tegra/cam_fsync/cam_fsync.c b/drivers/media/platform/tegra/cam_fsync/cam_fsync.c index a3cddc0b..a473858a 100644 --- a/drivers/media/platform/tegra/cam_fsync/cam_fsync.c +++ b/drivers/media/platform/tegra/cam_fsync/cam_fsync.c @@ -541,12 +541,12 @@ static int cam_fsync_program_group_generator_edges(struct fsync_generator_group { struct cam_fsync_generator *generator; u32 max_freq_hz_lcm = cam_fsync_find_max_freq_hz_lcm(group); - u32 const ticks_per_hz = DIV_ROUND_CLOSEST(NS_PER_SEC, group->features->ns_per_tick); + u32 const ticks_per_hz = DIV_ROUND_DOWN_ULL(NS_PER_SEC, group->features->ns_per_tick); bool const can_generate_precise_freq = cam_fsync_can_generate_precise_freq(group); struct cam_fsync_extra_ticks_and_period extra = {0, 1}; list_for_each_entry(generator, &group->generators, list) { - u32 ref_ticks_in_period = DIV_ROUND_CLOSEST(ticks_per_hz, max_freq_hz_lcm); + u32 ref_ticks_in_period = DIV_ROUND_DOWN_ULL(ticks_per_hz, max_freq_hz_lcm); u64 ticks_in_period = (u64)ref_ticks_in_period * (u64)(max_freq_hz_lcm / generator->config.freq_hz); u64 ticks_active = mult_frac(ticks_in_period, generator->config.duty_cycle, 100);