From c9bc9f50753d20d24836831d40e1efe74c21b0ef Mon Sep 17 00:00:00 2001 From: Prashant Laddha Date: Tue, 5 May 2015 10:16:27 -0300 Subject: [PATCH] [media] v4l2-dv-timings: fix overflow in gtf timings calculation The intermediate calculation in the expression for hblank can exceed 32 bit signed range. This overflow can lead to negative values for hblank. Typecasting intermediate variable to higher precision. Cc: Martin Bugge Signed-off-by: Prashant Laddha [hans.verkuil@cisco.com: made the denominator u32, since that's what div_u64 expects] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dv-timings.c | 28 +++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index 37f0d6f89878..5792192bce6c 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -25,6 +25,7 @@ #include #include #include +#include MODULE_AUTHOR("Hans Verkuil"); MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions"); @@ -554,16 +555,23 @@ bool v4l2_detect_gtf(unsigned frame_height, image_width = (image_width + GTF_CELL_GRAN/2) & ~(GTF_CELL_GRAN - 1); /* Horizontal */ - if (default_gtf) - h_blank = ((image_width * GTF_D_C_PRIME * hfreq) - - (image_width * GTF_D_M_PRIME * 1000) + - (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) / 2) / - (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000); - else - h_blank = ((image_width * GTF_S_C_PRIME * hfreq) - - (image_width * GTF_S_M_PRIME * 1000) + - (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) / 2) / - (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000); + if (default_gtf) { + u64 num; + u32 den; + + num = ((image_width * GTF_D_C_PRIME * (u64)hfreq) - + ((u64)image_width * GTF_D_M_PRIME * 1000)); + den = hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000; + h_blank = div_u64((num + (den >> 1)), den); + } else { + u64 num; + u32 den; + + num = ((image_width * GTF_S_C_PRIME * (u64)hfreq) - + ((u64)image_width * GTF_S_M_PRIME * 1000)); + den = hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000; + h_blank = div_u64((num + (den >> 1)), den); + } h_blank = ((h_blank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN)) * (2 * GTF_CELL_GRAN); -- 2.20.1