File Index
Files and directories
Sign in
FILE

spl_custom_float.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.c C
  1// SPDX-License-Identifier: MIT
  2//
  3// Copyright 2024 Advanced Micro Devices, Inc.
  4
  5#include "spl_debug.h"
  6#include "spl_custom_float.h"
  7
  8static bool spl_build_custom_float(struct spl_fixed31_32 value,
  9			       const struct spl_custom_float_format *format,
 10			       bool *negative,
 11			       uint32_t *mantissa,
 12			       uint32_t *exponenta)
 13{
 14	uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
 15
 16	const struct spl_fixed31_32 mantissa_constant_plus_max_fraction =
 17		spl_fixpt_from_fraction((1LL << (format->mantissa_bits + 1)) - 1,
 18				       1LL << format->mantissa_bits);
 19
 20	struct spl_fixed31_32 mantiss;
 21
 22	if (spl_fixpt_eq(value, spl_fixpt_zero)) {
 23		*negative = false;
 24		*mantissa = 0;
 25		*exponenta = 0;
 26		return true;
 27	}
 28
 29	if (spl_fixpt_lt(value, spl_fixpt_zero)) {
 30		*negative = format->sign;
 31		value = spl_fixpt_neg(value);
 32	} else {
 33		*negative = false;
 34	}
 35
 36	if (spl_fixpt_lt(value, spl_fixpt_one)) {
 37		uint32_t i = 1;
 38
 39		do {
 40			value = spl_fixpt_shl(value, 1);
 41			++i;
 42		} while (spl_fixpt_lt(value, spl_fixpt_one));
 43
 44		--i;
 45
 46		if (exp_offset <= i) {
 47			*mantissa = 0;
 48			*exponenta = 0;
 49			return true;
 50		}
 51
 52		*exponenta = exp_offset - i;
 53	} else if (spl_fixpt_le(mantissa_constant_plus_max_fraction, value)) {
 54		uint32_t i = 1;
 55
 56		do {
 57			value = spl_fixpt_shr(value, 1);
 58			++i;
 59		} while (spl_fixpt_lt(mantissa_constant_plus_max_fraction, value));
 60
 61		*exponenta = exp_offset + i - 1;
 62	} else {
 63		*exponenta = exp_offset;
 64	}
 65
 66	mantiss = spl_fixpt_sub(value, spl_fixpt_one);
 67
 68	if (spl_fixpt_lt(mantiss, spl_fixpt_zero) ||
 69	    spl_fixpt_lt(spl_fixpt_one, mantiss))
 70		mantiss = spl_fixpt_zero;
 71	else
 72		mantiss = spl_fixpt_shl(mantiss, format->mantissa_bits);
 73
 74	*mantissa = spl_fixpt_floor(mantiss);
 75
 76	return true;
 77}
 78
 79static bool spl_setup_custom_float(const struct spl_custom_float_format *format,
 80			       bool negative,
 81			       uint32_t mantissa,
 82			       uint32_t exponenta,
 83			       uint32_t *result)
 84{
 85	uint32_t i = 0;
 86	uint32_t j = 0;
 87	uint32_t value = 0;
 88
 89	/* verification code:
 90	 * once calculation is ok we can remove it
 91	 */
 92
 93	const uint32_t mantissa_mask =
 94		(1 << (format->mantissa_bits + 1)) - 1;
 95
 96	const uint32_t exponenta_mask =
 97		(1 << (format->exponenta_bits + 1)) - 1;
 98
 99	if (mantissa & ~mantissa_mask) {
100		SPL_BREAK_TO_DEBUGGER();
101		mantissa = mantissa_mask;
102	}
103
104	if (exponenta & ~exponenta_mask) {
105		SPL_BREAK_TO_DEBUGGER();
106		exponenta = exponenta_mask;
107	}
108
109	/* end of verification code */
110
111	while (i < format->mantissa_bits) {
112		uint32_t mask = 1 << i;
113
114		if (mantissa & mask)
115			value |= mask;
116
117		++i;
118	}
119
120	while (j < format->exponenta_bits) {
121		uint32_t mask = 1 << j;
122
123		if (exponenta & mask)
124			value |= mask << i;
125
126		++j;
127	}
128
129	if (negative && format->sign)
130		value |= 1 << (i + j);
131
132	*result = value;
133
134	return true;
135}
136
137bool spl_convert_to_custom_float_format(struct spl_fixed31_32 value,
138				    const struct spl_custom_float_format *format,
139				    uint32_t *result)
140{
141	uint32_t mantissa;
142	uint32_t exponenta;
143	bool negative;
144
145	return spl_build_custom_float(value, format, &negative, &mantissa, &exponenta) &&
146				  spl_setup_custom_float(format,
147						     negative,
148						     mantissa,
149						     exponenta,
150						     result);
151}
~/ Read-only file preview.