1f5fbb83fSMauro Carvalho Chehab /* SPDX-License-Identifier: GPL-2.0 */
29d4fa1a1SMauro Carvalho Chehab /*
39d4fa1a1SMauro Carvalho Chehab  * Support for Intel Camera Imaging ISP subsystem.
49d4fa1a1SMauro Carvalho Chehab  * Copyright (c) 2015, Intel Corporation.
59d4fa1a1SMauro Carvalho Chehab  *
69d4fa1a1SMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or modify it
79d4fa1a1SMauro Carvalho Chehab  * under the terms and conditions of the GNU General Public License,
89d4fa1a1SMauro Carvalho Chehab  * version 2, as published by the Free Software Foundation.
99d4fa1a1SMauro Carvalho Chehab  *
109d4fa1a1SMauro Carvalho Chehab  * This program is distributed in the hope it will be useful, but WITHOUT
119d4fa1a1SMauro Carvalho Chehab  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
129d4fa1a1SMauro Carvalho Chehab  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
139d4fa1a1SMauro Carvalho Chehab  * more details.
149d4fa1a1SMauro Carvalho Chehab  */
159d4fa1a1SMauro Carvalho Chehab 
169d4fa1a1SMauro Carvalho Chehab #ifndef __MATH_SUPPORT_H
179d4fa1a1SMauro Carvalho Chehab #define __MATH_SUPPORT_H
189d4fa1a1SMauro Carvalho Chehab 
199d4fa1a1SMauro Carvalho Chehab #include <linux/kernel.h> /* Override the definition of max/min from linux kernel*/
209d4fa1a1SMauro Carvalho Chehab 
219d4fa1a1SMauro Carvalho Chehab #define IS_ODD(a)            ((a) & 0x1)
229d4fa1a1SMauro Carvalho Chehab #define IS_EVEN(a)           (!IS_ODD(a))
239d4fa1a1SMauro Carvalho Chehab 
249d4fa1a1SMauro Carvalho Chehab /* force a value to a lower even value */
259d4fa1a1SMauro Carvalho Chehab #define EVEN_FLOOR(x)        ((x) & ~1)
269d4fa1a1SMauro Carvalho Chehab 
279d4fa1a1SMauro Carvalho Chehab /* ISP2401 */
289d4fa1a1SMauro Carvalho Chehab /* If the number is odd, find the next even number */
299d4fa1a1SMauro Carvalho Chehab #define EVEN_CEIL(x)         ((IS_ODD(x)) ? ((x) + 1) : (x))
309d4fa1a1SMauro Carvalho Chehab 
319d4fa1a1SMauro Carvalho Chehab /* A => B */
329d4fa1a1SMauro Carvalho Chehab #define IMPLIES(a, b)        (!(a) || (b))
339d4fa1a1SMauro Carvalho Chehab 
349d4fa1a1SMauro Carvalho Chehab /* for preprocessor and array sizing use MIN and MAX
359d4fa1a1SMauro Carvalho Chehab    otherwise use min and max */
369d4fa1a1SMauro Carvalho Chehab #define MAX(a, b)            (((a) > (b)) ? (a) : (b))
379d4fa1a1SMauro Carvalho Chehab #define MIN(a, b)            (((a) < (b)) ? (a) : (b))
389d4fa1a1SMauro Carvalho Chehab 
399d4fa1a1SMauro Carvalho Chehab #define ROUND_DIV(a, b)      (((b) != 0) ? ((a) + ((b) >> 1)) / (b) : 0)
409d4fa1a1SMauro Carvalho Chehab #define CEIL_DIV(a, b)       (((b) != 0) ? ((a) + (b) - 1) / (b) : 0)
419d4fa1a1SMauro Carvalho Chehab #define CEIL_MUL(a, b)       (CEIL_DIV(a, b) * (b))
429d4fa1a1SMauro Carvalho Chehab #define CEIL_MUL2(a, b)      (((a) + (b) - 1) & ~((b) - 1))
439d4fa1a1SMauro Carvalho Chehab #define CEIL_SHIFT(a, b)     (((a) + (1 << (b)) - 1) >> (b))
449d4fa1a1SMauro Carvalho Chehab #define CEIL_SHIFT_MUL(a, b) (CEIL_SHIFT(a, b) << (b))
459d4fa1a1SMauro Carvalho Chehab #define ROUND_HALF_DOWN_DIV(a, b)	(((b) != 0) ? ((a) + (b / 2) - 1) / (b) : 0)
469d4fa1a1SMauro Carvalho Chehab #define ROUND_HALF_DOWN_MUL(a, b)	(ROUND_HALF_DOWN_DIV(a, b) * (b))
479d4fa1a1SMauro Carvalho Chehab 
489d4fa1a1SMauro Carvalho Chehab /*To Find next power of 2 number from x */
499d4fa1a1SMauro Carvalho Chehab #define bit2(x)            ((x)      | ((x) >> 1))
509d4fa1a1SMauro Carvalho Chehab #define bit4(x)            (bit2(x)  | (bit2(x) >> 2))
519d4fa1a1SMauro Carvalho Chehab #define bit8(x)            (bit4(x)  | (bit4(x) >> 4))
529d4fa1a1SMauro Carvalho Chehab #define bit16(x)           (bit8(x)  | (bit8(x) >> 8))
539d4fa1a1SMauro Carvalho Chehab #define bit32(x)           (bit16(x) | (bit16(x) >> 16))
549d4fa1a1SMauro Carvalho Chehab #define NEXT_POWER_OF_2(x) (bit32(x - 1) + 1)
559d4fa1a1SMauro Carvalho Chehab 
569d4fa1a1SMauro Carvalho Chehab /* min and max should not be macros as they will evaluate their arguments twice.
579d4fa1a1SMauro Carvalho Chehab    if you really need a macro (e.g. for CPP or for initializing an array)
589d4fa1a1SMauro Carvalho Chehab    use MIN() and MAX(), otherwise use min() and max().
599d4fa1a1SMauro Carvalho Chehab 
609d4fa1a1SMauro Carvalho Chehab */
619d4fa1a1SMauro Carvalho Chehab 
629d4fa1a1SMauro Carvalho Chehab #if !defined(PIPE_GENERATION)
639d4fa1a1SMauro Carvalho Chehab 
649d4fa1a1SMauro Carvalho Chehab /*
659d4fa1a1SMauro Carvalho Chehab This macro versions are added back as we are mixing types in usage of inline.
669d4fa1a1SMauro Carvalho Chehab This causes corner cases of calculations to be incorrect due to conversions
679d4fa1a1SMauro Carvalho Chehab between signed and unsigned variables or overflows.
689d4fa1a1SMauro Carvalho Chehab Before the addition of the inline functions, max, min and ceil_div were macros
699d4fa1a1SMauro Carvalho Chehab and therefore adding them back.
709d4fa1a1SMauro Carvalho Chehab 
719d4fa1a1SMauro Carvalho Chehab Leaving out the other math utility functions as they are newly added
729d4fa1a1SMauro Carvalho Chehab */
739d4fa1a1SMauro Carvalho Chehab 
749d4fa1a1SMauro Carvalho Chehab #define ceil_div(a, b)		(CEIL_DIV(a, b))
759d4fa1a1SMauro Carvalho Chehab 
ceil_mul(unsigned int a,unsigned int b)769d4fa1a1SMauro Carvalho Chehab static inline unsigned int ceil_mul(unsigned int a, unsigned int b)
779d4fa1a1SMauro Carvalho Chehab {
789d4fa1a1SMauro Carvalho Chehab 	return CEIL_MUL(a, b);
799d4fa1a1SMauro Carvalho Chehab }
809d4fa1a1SMauro Carvalho Chehab 
ceil_mul2(unsigned int a,unsigned int b)819d4fa1a1SMauro Carvalho Chehab static inline unsigned int ceil_mul2(unsigned int a, unsigned int b)
829d4fa1a1SMauro Carvalho Chehab {
839d4fa1a1SMauro Carvalho Chehab 	return CEIL_MUL2(a, b);
849d4fa1a1SMauro Carvalho Chehab }
859d4fa1a1SMauro Carvalho Chehab 
ceil_shift(unsigned int a,unsigned int b)869d4fa1a1SMauro Carvalho Chehab static inline unsigned int ceil_shift(unsigned int a, unsigned int b)
879d4fa1a1SMauro Carvalho Chehab {
889d4fa1a1SMauro Carvalho Chehab 	return CEIL_SHIFT(a, b);
899d4fa1a1SMauro Carvalho Chehab }
909d4fa1a1SMauro Carvalho Chehab 
ceil_shift_mul(unsigned int a,unsigned int b)919d4fa1a1SMauro Carvalho Chehab static inline unsigned int ceil_shift_mul(unsigned int a, unsigned int b)
929d4fa1a1SMauro Carvalho Chehab {
939d4fa1a1SMauro Carvalho Chehab 	return CEIL_SHIFT_MUL(a, b);
949d4fa1a1SMauro Carvalho Chehab }
959d4fa1a1SMauro Carvalho Chehab 
969d4fa1a1SMauro Carvalho Chehab /* ISP2401 */
round_half_down_div(unsigned int a,unsigned int b)979d4fa1a1SMauro Carvalho Chehab static inline unsigned int round_half_down_div(unsigned int a, unsigned int b)
989d4fa1a1SMauro Carvalho Chehab {
999d4fa1a1SMauro Carvalho Chehab 	return ROUND_HALF_DOWN_DIV(a, b);
1009d4fa1a1SMauro Carvalho Chehab }
1019d4fa1a1SMauro Carvalho Chehab 
1029d4fa1a1SMauro Carvalho Chehab /* ISP2401 */
round_half_down_mul(unsigned int a,unsigned int b)1039d4fa1a1SMauro Carvalho Chehab static inline unsigned int round_half_down_mul(unsigned int a, unsigned int b)
1049d4fa1a1SMauro Carvalho Chehab {
1059d4fa1a1SMauro Carvalho Chehab 	return ROUND_HALF_DOWN_MUL(a, b);
1069d4fa1a1SMauro Carvalho Chehab }
1079d4fa1a1SMauro Carvalho Chehab 
1089d4fa1a1SMauro Carvalho Chehab /* @brief Next Power of Two
1099d4fa1a1SMauro Carvalho Chehab  *
1109d4fa1a1SMauro Carvalho Chehab  *  @param[in] unsigned number
1119d4fa1a1SMauro Carvalho Chehab  *
1129d4fa1a1SMauro Carvalho Chehab  *  @return next power of two
1139d4fa1a1SMauro Carvalho Chehab  *
1149d4fa1a1SMauro Carvalho Chehab  * This function rounds input to the nearest power of 2 (2^x)
1159d4fa1a1SMauro Carvalho Chehab  * towards infinity
1169d4fa1a1SMauro Carvalho Chehab  *
1179d4fa1a1SMauro Carvalho Chehab  * Input Range: 0 .. 2^(8*sizeof(int)-1)
1189d4fa1a1SMauro Carvalho Chehab  *
1199d4fa1a1SMauro Carvalho Chehab  * IF input is a power of 2
1209d4fa1a1SMauro Carvalho Chehab  *     out = in
1219d4fa1a1SMauro Carvalho Chehab  * OTHERWISE
1229d4fa1a1SMauro Carvalho Chehab  *     out = 2^(ceil(log2(in))
1239d4fa1a1SMauro Carvalho Chehab  *
1249d4fa1a1SMauro Carvalho Chehab  */
1259d4fa1a1SMauro Carvalho Chehab 
ceil_pow2(unsigned int a)1269d4fa1a1SMauro Carvalho Chehab static inline unsigned int ceil_pow2(unsigned int a)
1279d4fa1a1SMauro Carvalho Chehab {
1289d4fa1a1SMauro Carvalho Chehab 	if (a == 0) {
1299d4fa1a1SMauro Carvalho Chehab 		return 1;
1309d4fa1a1SMauro Carvalho Chehab 	}
1319d4fa1a1SMauro Carvalho Chehab 	/* IF input is already a power of two*/
1329d4fa1a1SMauro Carvalho Chehab 	else if ((!((a) & ((a) - 1)))) {
1339d4fa1a1SMauro Carvalho Chehab 		return a;
1349d4fa1a1SMauro Carvalho Chehab 	} else {
1359d4fa1a1SMauro Carvalho Chehab 		unsigned int v = a;
1369d4fa1a1SMauro Carvalho Chehab 
1379d4fa1a1SMauro Carvalho Chehab 		v |= v >> 1;
1389d4fa1a1SMauro Carvalho Chehab 		v |= v >> 2;
1399d4fa1a1SMauro Carvalho Chehab 		v |= v >> 4;
1409d4fa1a1SMauro Carvalho Chehab 		v |= v >> 8;
1419d4fa1a1SMauro Carvalho Chehab 		v |= v >> 16;
1429d4fa1a1SMauro Carvalho Chehab 		return (v + 1);
1439d4fa1a1SMauro Carvalho Chehab 	}
1449d4fa1a1SMauro Carvalho Chehab }
1459d4fa1a1SMauro Carvalho Chehab 
1469d4fa1a1SMauro Carvalho Chehab #endif /* !defined(PIPE_GENERATION) */
1479d4fa1a1SMauro Carvalho Chehab 
1489d4fa1a1SMauro Carvalho Chehab /*
1499d4fa1a1SMauro Carvalho Chehab  * For SP and ISP, SDK provides the definition of OP_std_modadd.
1509d4fa1a1SMauro Carvalho Chehab  * We need it only for host
1519d4fa1a1SMauro Carvalho Chehab  */
1529d4fa1a1SMauro Carvalho Chehab #define OP_std_modadd(base, offset, size) ((base + offset) % (size))
1539d4fa1a1SMauro Carvalho Chehab 
1549d4fa1a1SMauro Carvalho Chehab #endif /* __MATH_SUPPORT_H */
155