162306a36Sopenharmony_ci/* SPDX-License-Identifier: MIT */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright © 2018 Intel Corporation
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef _I915_FIXED_H_
762306a36Sopenharmony_ci#define _I915_FIXED_H_
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/bug.h>
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/math64.h>
1262306a36Sopenharmony_ci#include <linux/types.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_citypedef struct {
1562306a36Sopenharmony_ci	u32 val;
1662306a36Sopenharmony_ci} uint_fixed_16_16_t;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define FP_16_16_MAX ((uint_fixed_16_16_t){ .val = UINT_MAX })
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic inline bool is_fixed16_zero(uint_fixed_16_16_t val)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	return val.val == 0;
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic inline uint_fixed_16_16_t u32_to_fixed16(u32 val)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	uint_fixed_16_16_t fp = { .val = val << 16 };
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	WARN_ON(val > U16_MAX);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	return fp;
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic inline u32 fixed16_to_u32_round_up(uint_fixed_16_16_t fp)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	return DIV_ROUND_UP(fp.val, 1 << 16);
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic inline u32 fixed16_to_u32(uint_fixed_16_16_t fp)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	return fp.val >> 16;
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic inline uint_fixed_16_16_t min_fixed16(uint_fixed_16_16_t min1,
4562306a36Sopenharmony_ci					     uint_fixed_16_16_t min2)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	uint_fixed_16_16_t min = { .val = min(min1.val, min2.val) };
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	return min;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic inline uint_fixed_16_16_t max_fixed16(uint_fixed_16_16_t max1,
5362306a36Sopenharmony_ci					     uint_fixed_16_16_t max2)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	uint_fixed_16_16_t max = { .val = max(max1.val, max2.val) };
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	return max;
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic inline uint_fixed_16_16_t clamp_u64_to_fixed16(u64 val)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	uint_fixed_16_16_t fp = { .val = (u32)val };
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	WARN_ON(val > U32_MAX);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	return fp;
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic inline u32 div_round_up_fixed16(uint_fixed_16_16_t val,
7062306a36Sopenharmony_ci				       uint_fixed_16_16_t d)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	return DIV_ROUND_UP(val.val, d.val);
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic inline u32 mul_round_up_u32_fixed16(u32 val, uint_fixed_16_16_t mul)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	u64 tmp;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	tmp = mul_u32_u32(val, mul.val);
8062306a36Sopenharmony_ci	tmp = DIV_ROUND_UP_ULL(tmp, 1 << 16);
8162306a36Sopenharmony_ci	WARN_ON(tmp > U32_MAX);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	return (u32)tmp;
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val,
8762306a36Sopenharmony_ci					     uint_fixed_16_16_t mul)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	u64 tmp;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	tmp = mul_u32_u32(val.val, mul.val);
9262306a36Sopenharmony_ci	tmp = tmp >> 16;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	return clamp_u64_to_fixed16(tmp);
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cistatic inline uint_fixed_16_16_t div_fixed16(u32 val, u32 d)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	u64 tmp;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	tmp = (u64)val << 16;
10262306a36Sopenharmony_ci	tmp = DIV_ROUND_UP_ULL(tmp, d);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	return clamp_u64_to_fixed16(tmp);
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic inline u32 div_round_up_u32_fixed16(u32 val, uint_fixed_16_16_t d)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	u64 tmp;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	tmp = (u64)val << 16;
11262306a36Sopenharmony_ci	tmp = DIV_ROUND_UP_ULL(tmp, d.val);
11362306a36Sopenharmony_ci	WARN_ON(tmp > U32_MAX);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	return (u32)tmp;
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistatic inline uint_fixed_16_16_t mul_u32_fixed16(u32 val, uint_fixed_16_16_t mul)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	u64 tmp;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	tmp = mul_u32_u32(val, mul.val);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	return clamp_u64_to_fixed16(tmp);
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic inline uint_fixed_16_16_t add_fixed16(uint_fixed_16_16_t add1,
12862306a36Sopenharmony_ci					     uint_fixed_16_16_t add2)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	u64 tmp;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	tmp = (u64)add1.val + add2.val;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	return clamp_u64_to_fixed16(tmp);
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic inline uint_fixed_16_16_t add_fixed16_u32(uint_fixed_16_16_t add1,
13862306a36Sopenharmony_ci						 u32 add2)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	uint_fixed_16_16_t tmp_add2 = u32_to_fixed16(add2);
14162306a36Sopenharmony_ci	u64 tmp;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	tmp = (u64)add1.val + tmp_add2.val;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	return clamp_u64_to_fixed16(tmp);
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci#endif /* _I915_FIXED_H_ */
149