1 /*
2  * Copyright 2012-15 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25 
26 #include "dm_services.h"
27 
28 #define DIVIDER 10000
29 
30 /* S2D13 value in [-3.00...0.9999] */
31 #define S2D13_MIN (-3 * DIVIDER)
32 #define S2D13_MAX (3 * DIVIDER)
33 
34 uint16_t fixed_point_to_int_frac(
35 	struct fixed31_32 arg,
36 	uint8_t integer_bits,
37 	uint8_t fractional_bits)
38 {
39 	int32_t numerator;
40 	int32_t divisor = 1 << fractional_bits;
41 
42 	uint16_t result;
43 
44 	uint16_t d = (uint16_t)dal_fixed31_32_floor(
45 		dal_fixed31_32_abs(
46 			arg));
47 
48 	if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
49 		numerator = (uint16_t)dal_fixed31_32_round(
50 			dal_fixed31_32_mul_int(
51 				arg,
52 				divisor));
53 	else {
54 		numerator = dal_fixed31_32_floor(
55 			dal_fixed31_32_sub(
56 				dal_fixed31_32_from_int(
57 					1LL << integer_bits),
58 				dal_fixed31_32_recip(
59 					dal_fixed31_32_from_int(
60 						divisor))));
61 	}
62 
63 	if (numerator >= 0)
64 		result = (uint16_t)numerator;
65 	else
66 		result = (uint16_t)(
67 		(1 << (integer_bits + fractional_bits + 1)) + numerator);
68 
69 	if ((result != 0) && dal_fixed31_32_lt(
70 		arg, dal_fixed31_32_zero))
71 		result |= 1 << (integer_bits + fractional_bits);
72 
73 	return result;
74 }
75 /**
76 * convert_float_matrix
77 * This converts a double into HW register spec defined format S2D13.
78 * @param :
79 * @return None
80 */
81 void convert_float_matrix(
82 	uint16_t *matrix,
83 	struct fixed31_32 *flt,
84 	uint32_t buffer_size)
85 {
86 	const struct fixed31_32 min_2_13 =
87 		dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER);
88 	const struct fixed31_32 max_2_13 =
89 		dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER);
90 	uint32_t i;
91 
92 	for (i = 0; i < buffer_size; ++i) {
93 		uint32_t reg_value =
94 				fixed_point_to_int_frac(
95 					dal_fixed31_32_clamp(
96 						flt[i],
97 						min_2_13,
98 						max_2_13),
99 						2,
100 						13);
101 
102 		matrix[i] = (uint16_t)reg_value;
103 	}
104 }
105