2018-11-16 14:07:25 +02:00
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2018 Intel Corporation
*/
# ifndef _I915_FIXED_H_
# define _I915_FIXED_H_
2019-06-26 17:40:10 +03:00
# include <linux/bug.h>
# include <linux/kernel.h>
# include <linux/math64.h>
# include <linux/types.h>
2018-11-16 14:07:25 +02:00
typedef struct {
2018-11-16 14:07:26 +02:00
u32 val ;
2018-11-16 14:07:25 +02:00
} uint_fixed_16_16_t ;
2018-11-16 14:07:27 +02:00
# define FP_16_16_MAX ((uint_fixed_16_16_t){ .val = UINT_MAX })
2018-11-16 14:07:25 +02:00
static inline bool is_fixed16_zero ( uint_fixed_16_16_t val )
{
2018-11-16 14:07:28 +02:00
return val . val = = 0 ;
2018-11-16 14:07:25 +02:00
}
2018-11-16 14:07:26 +02:00
static inline uint_fixed_16_16_t u32_to_fixed16 ( u32 val )
2018-11-16 14:07:25 +02:00
{
2018-11-16 14:07:29 +02:00
uint_fixed_16_16_t fp = { . val = val < < 16 } ;
2018-11-16 14:07:25 +02:00
WARN_ON ( val > U16_MAX ) ;
return fp ;
}
2018-11-16 14:07:26 +02:00
static inline u32 fixed16_to_u32_round_up ( uint_fixed_16_16_t fp )
2018-11-16 14:07:25 +02:00
{
return DIV_ROUND_UP ( fp . val , 1 < < 16 ) ;
}
2018-11-16 14:07:26 +02:00
static inline u32 fixed16_to_u32 ( uint_fixed_16_16_t fp )
2018-11-16 14:07:25 +02:00
{
return fp . val > > 16 ;
}
static inline uint_fixed_16_16_t min_fixed16 ( uint_fixed_16_16_t min1 ,
uint_fixed_16_16_t min2 )
{
2018-11-16 14:07:29 +02:00
uint_fixed_16_16_t min = { . val = min ( min1 . val , min2 . val ) } ;
2018-11-16 14:07:25 +02:00
return min ;
}
static inline uint_fixed_16_16_t max_fixed16 ( uint_fixed_16_16_t max1 ,
uint_fixed_16_16_t max2 )
{
2018-11-16 14:07:29 +02:00
uint_fixed_16_16_t max = { . val = max ( max1 . val , max2 . val ) } ;
2018-11-16 14:07:25 +02:00
return max ;
}
2018-11-16 14:07:26 +02:00
static inline uint_fixed_16_16_t clamp_u64_to_fixed16 ( u64 val )
2018-11-16 14:07:25 +02:00
{
2018-11-16 14:07:29 +02:00
uint_fixed_16_16_t fp = { . val = ( u32 ) val } ;
2018-11-16 14:07:25 +02:00
WARN_ON ( val > U32_MAX ) ;
2018-11-16 14:07:29 +02:00
2018-11-16 14:07:25 +02:00
return fp ;
}
2018-11-16 14:07:26 +02:00
static inline u32 div_round_up_fixed16 ( uint_fixed_16_16_t val ,
uint_fixed_16_16_t d )
2018-11-16 14:07:25 +02:00
{
return DIV_ROUND_UP ( val . val , d . val ) ;
}
2018-11-16 14:07:26 +02:00
static inline u32 mul_round_up_u32_fixed16 ( u32 val , uint_fixed_16_16_t mul )
2018-11-16 14:07:25 +02:00
{
2018-11-16 14:07:29 +02:00
u64 tmp ;
2019-04-08 18:27:01 +03:00
tmp = mul_u32_u32 ( val , mul . val ) ;
2018-11-16 14:07:29 +02:00
tmp = DIV_ROUND_UP_ULL ( tmp , 1 < < 16 ) ;
WARN_ON ( tmp > U32_MAX ) ;
2018-11-16 14:07:25 +02:00
2018-11-16 14:07:29 +02:00
return ( u32 ) tmp ;
2018-11-16 14:07:25 +02:00
}
static inline uint_fixed_16_16_t mul_fixed16 ( uint_fixed_16_16_t val ,
uint_fixed_16_16_t mul )
{
2018-11-16 14:07:29 +02:00
u64 tmp ;
2018-11-16 14:07:25 +02:00
2019-04-08 18:27:01 +03:00
tmp = mul_u32_u32 ( val . val , mul . val ) ;
2018-11-16 14:07:29 +02:00
tmp = tmp > > 16 ;
return clamp_u64_to_fixed16 ( tmp ) ;
2018-11-16 14:07:25 +02:00
}
2018-11-16 14:07:26 +02:00
static inline uint_fixed_16_16_t div_fixed16 ( u32 val , u32 d )
2018-11-16 14:07:25 +02:00
{
2018-11-16 14:07:29 +02:00
u64 tmp ;
tmp = ( u64 ) val < < 16 ;
tmp = DIV_ROUND_UP_ULL ( tmp , d ) ;
2018-11-16 14:07:25 +02:00
2018-11-16 14:07:29 +02:00
return clamp_u64_to_fixed16 ( tmp ) ;
2018-11-16 14:07:25 +02:00
}
2018-11-16 14:07:26 +02:00
static inline u32 div_round_up_u32_fixed16 ( u32 val , uint_fixed_16_16_t d )
2018-11-16 14:07:25 +02:00
{
2018-11-16 14:07:29 +02:00
u64 tmp ;
2018-11-16 14:07:25 +02:00
2018-11-16 14:07:29 +02:00
tmp = ( u64 ) val < < 16 ;
tmp = DIV_ROUND_UP_ULL ( tmp , d . val ) ;
WARN_ON ( tmp > U32_MAX ) ;
return ( u32 ) tmp ;
2018-11-16 14:07:25 +02:00
}
2018-11-16 14:07:26 +02:00
static inline uint_fixed_16_16_t mul_u32_fixed16 ( u32 val , uint_fixed_16_16_t mul )
2018-11-16 14:07:25 +02:00
{
2018-11-16 14:07:29 +02:00
u64 tmp ;
2019-04-08 18:27:01 +03:00
tmp = mul_u32_u32 ( val , mul . val ) ;
2018-11-16 14:07:25 +02:00
2018-11-16 14:07:29 +02:00
return clamp_u64_to_fixed16 ( tmp ) ;
2018-11-16 14:07:25 +02:00
}
static inline uint_fixed_16_16_t add_fixed16 ( uint_fixed_16_16_t add1 ,
uint_fixed_16_16_t add2 )
{
2018-11-16 14:07:29 +02:00
u64 tmp ;
2018-11-16 14:07:25 +02:00
2018-11-16 14:07:29 +02:00
tmp = ( u64 ) add1 . val + add2 . val ;
return clamp_u64_to_fixed16 ( tmp ) ;
2018-11-16 14:07:25 +02:00
}
static inline uint_fixed_16_16_t add_fixed16_u32 ( uint_fixed_16_16_t add1 ,
2018-11-16 14:07:26 +02:00
u32 add2 )
2018-11-16 14:07:25 +02:00
{
2018-11-16 14:07:29 +02:00
uint_fixed_16_16_t tmp_add2 = u32_to_fixed16 ( add2 ) ;
u64 tmp ;
tmp = ( u64 ) add1 . val + tmp_add2 . val ;
2018-11-16 14:07:25 +02:00
2018-11-16 14:07:29 +02:00
return clamp_u64_to_fixed16 ( tmp ) ;
2018-11-16 14:07:25 +02:00
}
# endif /* _I915_FIXED_H_ */