18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: MIT */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright © 2018 Intel Corporation
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#ifndef _I915_FIXED_H_
78c2ecf20Sopenharmony_ci#define _I915_FIXED_H_
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/bug.h>
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/math64.h>
128c2ecf20Sopenharmony_ci#include <linux/types.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_citypedef struct {
158c2ecf20Sopenharmony_ci	u32 val;
168c2ecf20Sopenharmony_ci} uint_fixed_16_16_t;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define FP_16_16_MAX ((uint_fixed_16_16_t){ .val = UINT_MAX })
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic inline bool is_fixed16_zero(uint_fixed_16_16_t val)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	return val.val == 0;
238c2ecf20Sopenharmony_ci}
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic inline uint_fixed_16_16_t u32_to_fixed16(u32 val)
268c2ecf20Sopenharmony_ci{
278c2ecf20Sopenharmony_ci	uint_fixed_16_16_t fp = { .val = val << 16 };
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	WARN_ON(val > U16_MAX);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	return fp;
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic inline u32 fixed16_to_u32_round_up(uint_fixed_16_16_t fp)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	return DIV_ROUND_UP(fp.val, 1 << 16);
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic inline u32 fixed16_to_u32(uint_fixed_16_16_t fp)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	return fp.val >> 16;
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic inline uint_fixed_16_16_t min_fixed16(uint_fixed_16_16_t min1,
458c2ecf20Sopenharmony_ci					     uint_fixed_16_16_t min2)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	uint_fixed_16_16_t min = { .val = min(min1.val, min2.val) };
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	return min;
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic inline uint_fixed_16_16_t max_fixed16(uint_fixed_16_16_t max1,
538c2ecf20Sopenharmony_ci					     uint_fixed_16_16_t max2)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	uint_fixed_16_16_t max = { .val = max(max1.val, max2.val) };
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	return max;
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic inline uint_fixed_16_16_t clamp_u64_to_fixed16(u64 val)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	uint_fixed_16_16_t fp = { .val = (u32)val };
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	WARN_ON(val > U32_MAX);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	return fp;
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic inline u32 div_round_up_fixed16(uint_fixed_16_16_t val,
708c2ecf20Sopenharmony_ci				       uint_fixed_16_16_t d)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	return DIV_ROUND_UP(val.val, d.val);
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic inline u32 mul_round_up_u32_fixed16(u32 val, uint_fixed_16_16_t mul)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	u64 tmp;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	tmp = mul_u32_u32(val, mul.val);
808c2ecf20Sopenharmony_ci	tmp = DIV_ROUND_UP_ULL(tmp, 1 << 16);
818c2ecf20Sopenharmony_ci	WARN_ON(tmp > U32_MAX);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	return (u32)tmp;
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val,
878c2ecf20Sopenharmony_ci					     uint_fixed_16_16_t mul)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	u64 tmp;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	tmp = mul_u32_u32(val.val, mul.val);
928c2ecf20Sopenharmony_ci	tmp = tmp >> 16;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	return clamp_u64_to_fixed16(tmp);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic inline uint_fixed_16_16_t div_fixed16(u32 val, u32 d)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	u64 tmp;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	tmp = (u64)val << 16;
1028c2ecf20Sopenharmony_ci	tmp = DIV_ROUND_UP_ULL(tmp, d);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	return clamp_u64_to_fixed16(tmp);
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic inline u32 div_round_up_u32_fixed16(u32 val, uint_fixed_16_16_t d)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	u64 tmp;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	tmp = (u64)val << 16;
1128c2ecf20Sopenharmony_ci	tmp = DIV_ROUND_UP_ULL(tmp, d.val);
1138c2ecf20Sopenharmony_ci	WARN_ON(tmp > U32_MAX);
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	return (u32)tmp;
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic inline uint_fixed_16_16_t mul_u32_fixed16(u32 val, uint_fixed_16_16_t mul)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	u64 tmp;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	tmp = mul_u32_u32(val, mul.val);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	return clamp_u64_to_fixed16(tmp);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic inline uint_fixed_16_16_t add_fixed16(uint_fixed_16_16_t add1,
1288c2ecf20Sopenharmony_ci					     uint_fixed_16_16_t add2)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	u64 tmp;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	tmp = (u64)add1.val + add2.val;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	return clamp_u64_to_fixed16(tmp);
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic inline uint_fixed_16_16_t add_fixed16_u32(uint_fixed_16_16_t add1,
1388c2ecf20Sopenharmony_ci						 u32 add2)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	uint_fixed_16_16_t tmp_add2 = u32_to_fixed16(add2);
1418c2ecf20Sopenharmony_ci	u64 tmp;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	tmp = (u64)add1.val + tmp_add2.val;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	return clamp_u64_to_fixed16(tmp);
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci#endif /* _I915_FIXED_H_ */
149