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