conversion.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. #include "dm_services.h"
  26. #include "basics/conversion.h"
  27. #define DIVIDER 10000
  28. /* S2D13 value in [-3.00...0.9999] */
  29. #define S2D13_MIN (-3 * DIVIDER)
  30. #define S2D13_MAX (3 * DIVIDER)
  31. uint16_t fixed_point_to_int_frac(
  32. struct fixed31_32 arg,
  33. uint8_t integer_bits,
  34. uint8_t fractional_bits)
  35. {
  36. int32_t numerator;
  37. int32_t divisor = 1 << fractional_bits;
  38. uint16_t result;
  39. uint16_t d = (uint16_t)dc_fixpt_floor(
  40. dc_fixpt_abs(
  41. arg));
  42. if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
  43. numerator = (uint16_t)dc_fixpt_round(
  44. dc_fixpt_mul_int(
  45. arg,
  46. divisor));
  47. else {
  48. numerator = dc_fixpt_floor(
  49. dc_fixpt_sub(
  50. dc_fixpt_from_int(
  51. 1LL << integer_bits),
  52. dc_fixpt_recip(
  53. dc_fixpt_from_int(
  54. divisor))));
  55. }
  56. if (numerator >= 0)
  57. result = (uint16_t)numerator;
  58. else
  59. result = (uint16_t)(
  60. (1 << (integer_bits + fractional_bits + 1)) + numerator);
  61. if ((result != 0) && dc_fixpt_lt(
  62. arg, dc_fixpt_zero))
  63. result |= 1 << (integer_bits + fractional_bits);
  64. return result;
  65. }
  66. /*
  67. * convert_float_matrix - This converts a double into HW register spec defined format S2D13.
  68. */
  69. void convert_float_matrix(
  70. uint16_t *matrix,
  71. struct fixed31_32 *flt,
  72. uint32_t buffer_size)
  73. {
  74. const struct fixed31_32 min_2_13 =
  75. dc_fixpt_from_fraction(S2D13_MIN, DIVIDER);
  76. const struct fixed31_32 max_2_13 =
  77. dc_fixpt_from_fraction(S2D13_MAX, DIVIDER);
  78. uint32_t i;
  79. for (i = 0; i < buffer_size; ++i) {
  80. uint32_t reg_value =
  81. fixed_point_to_int_frac(
  82. dc_fixpt_clamp(
  83. flt[i],
  84. min_2_13,
  85. max_2_13),
  86. 2,
  87. 13);
  88. matrix[i] = (uint16_t)reg_value;
  89. }
  90. }
  91. static struct fixed31_32 int_frac_to_fixed_point(uint16_t arg,
  92. uint8_t integer_bits,
  93. uint8_t fractional_bits)
  94. {
  95. struct fixed31_32 result;
  96. uint16_t sign_mask = 1 << (fractional_bits + integer_bits);
  97. uint16_t value_mask = sign_mask - 1;
  98. result.value = (long long)(arg & value_mask) <<
  99. (FIXED31_32_BITS_PER_FRACTIONAL_PART - fractional_bits);
  100. if (arg & sign_mask)
  101. result = dc_fixpt_neg(result);
  102. return result;
  103. }
  104. /**
  105. * convert_hw_matrix - converts HW values into fixed31_32 matrix.
  106. * @matrix: fixed point 31.32 matrix
  107. * @reg: array of register values
  108. * @buffer_size: size of the array of register values
  109. *
  110. * Converts HW register spec defined format S2D13 into a fixed-point 31.32
  111. * matrix.
  112. */
  113. void convert_hw_matrix(struct fixed31_32 *matrix,
  114. uint16_t *reg,
  115. uint32_t buffer_size)
  116. {
  117. for (int i = 0; i < buffer_size; ++i)
  118. matrix[i] = int_frac_to_fixed_point(reg[i], 2, 13);
  119. }
  120. static uint32_t find_gcd(uint32_t a, uint32_t b)
  121. {
  122. uint32_t remainder;
  123. while (b != 0) {
  124. remainder = a % b;
  125. a = b;
  126. b = remainder;
  127. }
  128. return a;
  129. }
  130. void reduce_fraction(uint32_t num, uint32_t den,
  131. uint32_t *out_num, uint32_t *out_den)
  132. {
  133. uint32_t gcd = 0;
  134. gcd = find_gcd(num, den);
  135. *out_num = num / gcd;
  136. *out_den = den / gcd;
  137. }