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 #include "basics/conversion.h" 28 29 30 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 39 uint16_t result; 40 41 uint16_t d = (uint16_t)dc_fixpt_floor( 42 dc_fixpt_abs( 43 arg)); 44 45 if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) 46 numerator = (uint16_t)dc_fixpt_round( 47 dc_fixpt_mul_int( 48 arg, 49 divisor)); 50 else { 51 numerator = dc_fixpt_floor( 52 dc_fixpt_sub( 53 dc_fixpt_from_int( 54 1LL << integer_bits), 55 dc_fixpt_recip( 56 dc_fixpt_from_int( 57 divisor)))); 58 } 59 60 if (numerator >= 0) 61 result = (uint16_t)numerator; 62 else 63 result = (uint16_t)( 64 (1 << (integer_bits + fractional_bits + 1)) + numerator); 65 66 if ((result != 0) && dc_fixpt_lt( 67 arg, dc_fixpt_zero)) 68 result |= 1 << (integer_bits + fractional_bits); 69 70 return result; 71 } 72 /* 73 * convert_float_matrix - This converts a double into HW register spec defined format S2D13 / S3D12. 74 */ 75 void convert_float_matrix( 76 uint16_t *matrix, 77 const struct fixed31_32 *flt, 78 enum cm_gamut_coef_format format, 79 uint32_t buffer_size) 80 { 81 struct fixed31_32 min; 82 struct fixed31_32 max; 83 uint8_t num_int_bits; 84 uint8_t num_dec_bits; 85 uint32_t i; 86 87 if (format == CM_GAMUT_REMAP_COEF_FORMAT_S2_13) { 88 min = dc_fixpt_from_fraction(S2D13_MIN, DIVIDER); 89 max = dc_fixpt_from_fraction(S2D13_MAX, DIVIDER); 90 num_int_bits = 2; 91 num_dec_bits = 13; 92 } else if (format == CM_GAMUT_REMAP_COEF_FORMAT_S3_12) { 93 min = dc_fixpt_from_fraction(S3D12_MIN, DIVIDER); 94 max = dc_fixpt_from_fraction(S3D12_MAX, DIVIDER); 95 num_int_bits = 3; 96 num_dec_bits = 12; 97 } else { 98 ASSERT(false); 99 return; 100 } 101 102 for (i = 0; i < buffer_size; ++i) { 103 uint32_t reg_value = 104 fixed_point_to_int_frac( 105 dc_fixpt_clamp( 106 flt[i], 107 min, 108 max), 109 num_int_bits, 110 num_dec_bits); 111 112 matrix[i] = (uint16_t)reg_value; 113 } 114 } 115 116 static struct fixed31_32 int_frac_to_fixed_point(uint16_t arg, 117 uint8_t integer_bits, 118 uint8_t fractional_bits) 119 { 120 struct fixed31_32 result; 121 uint16_t sign_mask = 1 << (fractional_bits + integer_bits); 122 uint16_t value_mask = sign_mask - 1; 123 124 result.value = (long long)(arg & value_mask) << 125 (FIXED31_32_BITS_PER_FRACTIONAL_PART - fractional_bits); 126 127 if (arg & sign_mask) 128 result = dc_fixpt_neg(result); 129 130 return result; 131 } 132 133 /** 134 * convert_hw_matrix - converts HW values into fixed31_32 matrix. 135 * @matrix: fixed point 31.32 matrix 136 * @reg: array of register values 137 * @buffer_size: size of the array of register values 138 * 139 * Converts HW register spec defined format S2D13 into a fixed-point 31.32 140 * matrix. 141 */ 142 void convert_hw_matrix(struct fixed31_32 *matrix, 143 uint16_t *reg, 144 enum cm_gamut_coef_format format, 145 uint32_t buffer_size) 146 { 147 uint8_t num_int_bits; 148 uint8_t num_dec_bits; 149 uint32_t i; 150 151 if (format == CM_GAMUT_REMAP_COEF_FORMAT_S2_13) { 152 num_int_bits = 2; 153 num_dec_bits = 13; 154 } else if (format == CM_GAMUT_REMAP_COEF_FORMAT_S3_12) { 155 num_int_bits = 3; 156 num_dec_bits = 12; 157 } else { 158 ASSERT(false); 159 return; 160 } 161 162 for (i = 0; i < buffer_size; ++i) 163 matrix[i] = int_frac_to_fixed_point(reg[i], 164 num_int_bits, num_dec_bits); 165 } 166 167 static uint32_t find_gcd(uint32_t a, uint32_t b) 168 { 169 uint32_t remainder; 170 171 while (b != 0) { 172 remainder = a % b; 173 a = b; 174 b = remainder; 175 } 176 return a; 177 } 178 179 void reduce_fraction(uint32_t num, uint32_t den, 180 uint32_t *out_num, uint32_t *out_den) 181 { 182 uint32_t gcd = 0; 183 184 gcd = find_gcd(num, den); 185 *out_num = num / gcd; 186 *out_den = den / gcd; 187 } 188