drm/amd/dc: Add dc display driver (v2)

Supported DCE versions: 8.0, 10.0, 11.0, 11.2

v2: rebase against 4.11

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Harry Wentland
2017-09-12 15:58:20 -04:00
committed by Alex Deucher
parent 9c5b2b0d40
commit 4562236b3b
315 changed files with 99491 additions and 37 deletions

View File

@@ -0,0 +1,11 @@
#
# Makefile for the 'utils' sub-component of DAL.
# It provides the general basic services required by other DAL
# subcomponents.
BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \
logger.o log_helpers.o register_logger.o signal_types.o vector.o
AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS))
AMD_DISPLAY_FILES += $(AMD_DAL_BASICS)

View File

@@ -0,0 +1,223 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dm_services.h"
#define DIVIDER 10000
/* S2D13 value in [-3.00...0.9999] */
#define S2D13_MIN (-3 * DIVIDER)
#define S2D13_MAX (3 * DIVIDER)
uint16_t fixed_point_to_int_frac(
struct fixed31_32 arg,
uint8_t integer_bits,
uint8_t fractional_bits)
{
int32_t numerator;
int32_t divisor = 1 << fractional_bits;
uint16_t result;
uint16_t d = (uint16_t)dal_fixed31_32_floor(
dal_fixed31_32_abs(
arg));
if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
numerator = (uint16_t)dal_fixed31_32_floor(
dal_fixed31_32_mul_int(
arg,
divisor));
else {
numerator = dal_fixed31_32_floor(
dal_fixed31_32_sub(
dal_fixed31_32_from_int(
1LL << integer_bits),
dal_fixed31_32_recip(
dal_fixed31_32_from_int(
divisor))));
}
if (numerator >= 0)
result = (uint16_t)numerator;
else
result = (uint16_t)(
(1 << (integer_bits + fractional_bits + 1)) + numerator);
if ((result != 0) && dal_fixed31_32_lt(
arg, dal_fixed31_32_zero))
result |= 1 << (integer_bits + fractional_bits);
return result;
}
/**
* convert_float_matrix
* This converts a double into HW register spec defined format S2D13.
* @param :
* @return None
*/
void convert_float_matrix(
uint16_t *matrix,
struct fixed31_32 *flt,
uint32_t buffer_size)
{
const struct fixed31_32 min_2_13 =
dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER);
const struct fixed31_32 max_2_13 =
dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER);
uint32_t i;
for (i = 0; i < buffer_size; ++i) {
uint32_t reg_value =
fixed_point_to_int_frac(
dal_fixed31_32_clamp(
flt[i],
min_2_13,
max_2_13),
2,
13);
matrix[i] = (uint16_t)reg_value;
}
}
static void calculate_adjustments_common(
const struct fixed31_32 *ideal_matrix,
const struct dc_csc_adjustments *adjustments,
struct fixed31_32 *matrix)
{
const struct fixed31_32 sin_hue =
dal_fixed31_32_sin(adjustments->hue);
const struct fixed31_32 cos_hue =
dal_fixed31_32_cos(adjustments->hue);
const struct fixed31_32 multiplier =
dal_fixed31_32_mul(
adjustments->contrast,
adjustments->saturation);
matrix[0] = dal_fixed31_32_mul(
ideal_matrix[0],
adjustments->contrast);
matrix[1] = dal_fixed31_32_mul(
ideal_matrix[1],
adjustments->contrast);
matrix[2] = dal_fixed31_32_mul(
ideal_matrix[2],
adjustments->contrast);
matrix[4] = dal_fixed31_32_mul(
multiplier,
dal_fixed31_32_add(
dal_fixed31_32_mul(
ideal_matrix[8],
sin_hue),
dal_fixed31_32_mul(
ideal_matrix[4],
cos_hue)));
matrix[5] = dal_fixed31_32_mul(
multiplier,
dal_fixed31_32_add(
dal_fixed31_32_mul(
ideal_matrix[9],
sin_hue),
dal_fixed31_32_mul(
ideal_matrix[5],
cos_hue)));
matrix[6] = dal_fixed31_32_mul(
multiplier,
dal_fixed31_32_add(
dal_fixed31_32_mul(
ideal_matrix[10],
sin_hue),
dal_fixed31_32_mul(
ideal_matrix[6],
cos_hue)));
matrix[7] = ideal_matrix[7];
matrix[8] = dal_fixed31_32_mul(
multiplier,
dal_fixed31_32_sub(
dal_fixed31_32_mul(
ideal_matrix[8],
cos_hue),
dal_fixed31_32_mul(
ideal_matrix[4],
sin_hue)));
matrix[9] = dal_fixed31_32_mul(
multiplier,
dal_fixed31_32_sub(
dal_fixed31_32_mul(
ideal_matrix[9],
cos_hue),
dal_fixed31_32_mul(
ideal_matrix[5],
sin_hue)));
matrix[10] = dal_fixed31_32_mul(
multiplier,
dal_fixed31_32_sub(
dal_fixed31_32_mul(
ideal_matrix[10],
cos_hue),
dal_fixed31_32_mul(
ideal_matrix[6],
sin_hue)));
matrix[11] = ideal_matrix[11];
}
void calculate_adjustments(
const struct fixed31_32 *ideal_matrix,
const struct dc_csc_adjustments *adjustments,
struct fixed31_32 *matrix)
{
calculate_adjustments_common(ideal_matrix, adjustments, matrix);
matrix[3] = dal_fixed31_32_add(
ideal_matrix[3],
dal_fixed31_32_mul(
adjustments->brightness,
dal_fixed31_32_from_fraction(86, 100)));
}
void calculate_adjustments_y_only(
const struct fixed31_32 *ideal_matrix,
const struct dc_csc_adjustments *adjustments,
struct fixed31_32 *matrix)
{
calculate_adjustments_common(ideal_matrix, adjustments, matrix);
matrix[3] = dal_fixed31_32_add(
ideal_matrix[3],
adjustments->brightness);
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#ifndef __DAL_CONVERSION_H__
#define __DAL_CONVERSION_H__
#include "include/fixed31_32.h"
uint16_t fixed_point_to_int_frac(
struct fixed31_32 arg,
uint8_t integer_bits,
uint8_t fractional_bits);
void convert_float_matrix(
uint16_t *matrix,
struct fixed31_32 *flt,
uint32_t buffer_size);
void calculate_adjustments(
const struct fixed31_32 *ideal_matrix,
const struct dc_csc_adjustments *adjustments,
struct fixed31_32 *matrix);
void calculate_adjustments_y_only(
const struct fixed31_32 *ideal_matrix,
const struct dc_csc_adjustments *adjustments,
struct fixed31_32 *matrix);
#endif

View File

@@ -0,0 +1,691 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dm_services.h"
#include "include/fixed31_32.h"
static inline uint64_t abs_i64(
int64_t arg)
{
if (arg > 0)
return (uint64_t)arg;
else
return (uint64_t)(-arg);
}
/*
* @brief
* result = dividend / divisor
* *remainder = dividend % divisor
*/
static inline uint64_t complete_integer_division_u64(
uint64_t dividend,
uint64_t divisor,
uint64_t *remainder)
{
uint64_t result;
ASSERT(divisor);
result = div64_u64_rem(dividend, divisor, remainder);
return result;
}
#define BITS_PER_FRACTIONAL_PART \
32
#define FRACTIONAL_PART_MASK \
((1ULL << BITS_PER_FRACTIONAL_PART) - 1)
#define GET_INTEGER_PART(x) \
((x) >> BITS_PER_FRACTIONAL_PART)
#define GET_FRACTIONAL_PART(x) \
(FRACTIONAL_PART_MASK & (x))
struct fixed31_32 dal_fixed31_32_from_fraction(
int64_t numerator,
int64_t denominator)
{
struct fixed31_32 res;
bool arg1_negative = numerator < 0;
bool arg2_negative = denominator < 0;
uint64_t arg1_value = arg1_negative ? -numerator : numerator;
uint64_t arg2_value = arg2_negative ? -denominator : denominator;
uint64_t remainder;
/* determine integer part */
uint64_t res_value = complete_integer_division_u64(
arg1_value, arg2_value, &remainder);
ASSERT(res_value <= LONG_MAX);
/* determine fractional part */
{
uint32_t i = BITS_PER_FRACTIONAL_PART;
do {
remainder <<= 1;
res_value <<= 1;
if (remainder >= arg2_value) {
res_value |= 1;
remainder -= arg2_value;
}
} while (--i != 0);
}
/* round up LSB */
{
uint64_t summand = (remainder << 1) >= arg2_value;
ASSERT(res_value <= LLONG_MAX - summand);
res_value += summand;
}
res.value = (int64_t)res_value;
if (arg1_negative ^ arg2_negative)
res.value = -res.value;
return res;
}
struct fixed31_32 dal_fixed31_32_from_int(
int64_t arg)
{
struct fixed31_32 res;
ASSERT((LONG_MIN <= arg) && (arg <= LONG_MAX));
res.value = arg << BITS_PER_FRACTIONAL_PART;
return res;
}
struct fixed31_32 dal_fixed31_32_neg(
struct fixed31_32 arg)
{
struct fixed31_32 res;
res.value = -arg.value;
return res;
}
struct fixed31_32 dal_fixed31_32_abs(
struct fixed31_32 arg)
{
if (arg.value < 0)
return dal_fixed31_32_neg(arg);
else
return arg;
}
bool dal_fixed31_32_lt(
struct fixed31_32 arg1,
struct fixed31_32 arg2)
{
return arg1.value < arg2.value;
}
bool dal_fixed31_32_le(
struct fixed31_32 arg1,
struct fixed31_32 arg2)
{
return arg1.value <= arg2.value;
}
bool dal_fixed31_32_eq(
struct fixed31_32 arg1,
struct fixed31_32 arg2)
{
return arg1.value == arg2.value;
}
struct fixed31_32 dal_fixed31_32_min(
struct fixed31_32 arg1,
struct fixed31_32 arg2)
{
if (arg1.value <= arg2.value)
return arg1;
else
return arg2;
}
struct fixed31_32 dal_fixed31_32_max(
struct fixed31_32 arg1,
struct fixed31_32 arg2)
{
if (arg1.value <= arg2.value)
return arg2;
else
return arg1;
}
struct fixed31_32 dal_fixed31_32_clamp(
struct fixed31_32 arg,
struct fixed31_32 min_value,
struct fixed31_32 max_value)
{
if (dal_fixed31_32_le(arg, min_value))
return min_value;
else if (dal_fixed31_32_le(max_value, arg))
return max_value;
else
return arg;
}
struct fixed31_32 dal_fixed31_32_shl(
struct fixed31_32 arg,
uint8_t shift)
{
struct fixed31_32 res;
ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) ||
((arg.value < 0) && (arg.value >= LLONG_MIN >> shift)));
res.value = arg.value << shift;
return res;
}
struct fixed31_32 dal_fixed31_32_shr(
struct fixed31_32 arg,
uint8_t shift)
{
struct fixed31_32 res;
ASSERT(shift < 64);
res.value = arg.value >> shift;
return res;
}
struct fixed31_32 dal_fixed31_32_add(
struct fixed31_32 arg1,
struct fixed31_32 arg2)
{
struct fixed31_32 res;
ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) ||
((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value)));
res.value = arg1.value + arg2.value;
return res;
}
struct fixed31_32 dal_fixed31_32_sub_int(
struct fixed31_32 arg1,
int32_t arg2)
{
return dal_fixed31_32_sub(
arg1,
dal_fixed31_32_from_int(arg2));
}
struct fixed31_32 dal_fixed31_32_sub(
struct fixed31_32 arg1,
struct fixed31_32 arg2)
{
struct fixed31_32 res;
ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) ||
((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value)));
res.value = arg1.value - arg2.value;
return res;
}
struct fixed31_32 dal_fixed31_32_mul_int(
struct fixed31_32 arg1,
int32_t arg2)
{
return dal_fixed31_32_mul(
arg1,
dal_fixed31_32_from_int(arg2));
}
struct fixed31_32 dal_fixed31_32_mul(
struct fixed31_32 arg1,
struct fixed31_32 arg2)
{
struct fixed31_32 res;
bool arg1_negative = arg1.value < 0;
bool arg2_negative = arg2.value < 0;
uint64_t arg1_value = arg1_negative ? -arg1.value : arg1.value;
uint64_t arg2_value = arg2_negative ? -arg2.value : arg2.value;
uint64_t arg1_int = GET_INTEGER_PART(arg1_value);
uint64_t arg2_int = GET_INTEGER_PART(arg2_value);
uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value);
uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value);
uint64_t tmp;
res.value = arg1_int * arg2_int;
ASSERT(res.value <= LONG_MAX);
res.value <<= BITS_PER_FRACTIONAL_PART;
tmp = arg1_int * arg2_fra;
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
res.value += tmp;
tmp = arg2_int * arg1_fra;
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
res.value += tmp;
tmp = arg1_fra * arg2_fra;
tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
(tmp >= (uint64_t)dal_fixed31_32_half.value);
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
res.value += tmp;
if (arg1_negative ^ arg2_negative)
res.value = -res.value;
return res;
}
struct fixed31_32 dal_fixed31_32_sqr(
struct fixed31_32 arg)
{
struct fixed31_32 res;
uint64_t arg_value = abs_i64(arg.value);
uint64_t arg_int = GET_INTEGER_PART(arg_value);
uint64_t arg_fra = GET_FRACTIONAL_PART(arg_value);
uint64_t tmp;
res.value = arg_int * arg_int;
ASSERT(res.value <= LONG_MAX);
res.value <<= BITS_PER_FRACTIONAL_PART;
tmp = arg_int * arg_fra;
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
res.value += tmp;
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
res.value += tmp;
tmp = arg_fra * arg_fra;
tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
(tmp >= (uint64_t)dal_fixed31_32_half.value);
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
res.value += tmp;
return res;
}
struct fixed31_32 dal_fixed31_32_div_int(
struct fixed31_32 arg1,
int64_t arg2)
{
return dal_fixed31_32_from_fraction(
arg1.value,
dal_fixed31_32_from_int(arg2).value);
}
struct fixed31_32 dal_fixed31_32_div(
struct fixed31_32 arg1,
struct fixed31_32 arg2)
{
return dal_fixed31_32_from_fraction(
arg1.value,
arg2.value);
}
struct fixed31_32 dal_fixed31_32_recip(
struct fixed31_32 arg)
{
/*
* @note
* Good idea to use Newton's method
*/
ASSERT(arg.value);
return dal_fixed31_32_from_fraction(
dal_fixed31_32_one.value,
arg.value);
}
struct fixed31_32 dal_fixed31_32_sinc(
struct fixed31_32 arg)
{
struct fixed31_32 square;
struct fixed31_32 res = dal_fixed31_32_one;
int32_t n = 27;
struct fixed31_32 arg_norm = arg;
if (dal_fixed31_32_le(
dal_fixed31_32_two_pi,
dal_fixed31_32_abs(arg))) {
arg_norm = dal_fixed31_32_sub(
arg_norm,
dal_fixed31_32_mul_int(
dal_fixed31_32_two_pi,
(int32_t)div64_s64(
arg_norm.value,
dal_fixed31_32_two_pi.value)));
}
square = dal_fixed31_32_sqr(arg_norm);
do {
res = dal_fixed31_32_sub(
dal_fixed31_32_one,
dal_fixed31_32_div_int(
dal_fixed31_32_mul(
square,
res),
n * (n - 1)));
n -= 2;
} while (n > 2);
if (arg.value != arg_norm.value)
res = dal_fixed31_32_div(
dal_fixed31_32_mul(res, arg_norm),
arg);
return res;
}
struct fixed31_32 dal_fixed31_32_sin(
struct fixed31_32 arg)
{
return dal_fixed31_32_mul(
arg,
dal_fixed31_32_sinc(arg));
}
struct fixed31_32 dal_fixed31_32_cos(
struct fixed31_32 arg)
{
/* TODO implement argument normalization */
const struct fixed31_32 square = dal_fixed31_32_sqr(arg);
struct fixed31_32 res = dal_fixed31_32_one;
int32_t n = 26;
do {
res = dal_fixed31_32_sub(
dal_fixed31_32_one,
dal_fixed31_32_div_int(
dal_fixed31_32_mul(
square,
res),
n * (n - 1)));
n -= 2;
} while (n != 0);
return res;
}
/*
* @brief
* result = exp(arg),
* where abs(arg) < 1
*
* Calculated as Taylor series.
*/
static struct fixed31_32 fixed31_32_exp_from_taylor_series(
struct fixed31_32 arg)
{
uint32_t n = 9;
struct fixed31_32 res = dal_fixed31_32_from_fraction(
n + 2,
n + 1);
/* TODO find correct res */
ASSERT(dal_fixed31_32_lt(arg, dal_fixed31_32_one));
do
res = dal_fixed31_32_add(
dal_fixed31_32_one,
dal_fixed31_32_div_int(
dal_fixed31_32_mul(
arg,
res),
n));
while (--n != 1);
return dal_fixed31_32_add(
dal_fixed31_32_one,
dal_fixed31_32_mul(
arg,
res));
}
struct fixed31_32 dal_fixed31_32_exp(
struct fixed31_32 arg)
{
/*
* @brief
* Main equation is:
* exp(x) = exp(r + m * ln(2)) = (1 << m) * exp(r),
* where m = round(x / ln(2)), r = x - m * ln(2)
*/
if (dal_fixed31_32_le(
dal_fixed31_32_ln2_div_2,
dal_fixed31_32_abs(arg))) {
int32_t m = dal_fixed31_32_round(
dal_fixed31_32_div(
arg,
dal_fixed31_32_ln2));
struct fixed31_32 r = dal_fixed31_32_sub(
arg,
dal_fixed31_32_mul_int(
dal_fixed31_32_ln2,
m));
ASSERT(m != 0);
ASSERT(dal_fixed31_32_lt(
dal_fixed31_32_abs(r),
dal_fixed31_32_one));
if (m > 0)
return dal_fixed31_32_shl(
fixed31_32_exp_from_taylor_series(r),
(uint8_t)m);
else
return dal_fixed31_32_div_int(
fixed31_32_exp_from_taylor_series(r),
1LL << -m);
} else if (arg.value != 0)
return fixed31_32_exp_from_taylor_series(arg);
else
return dal_fixed31_32_one;
}
struct fixed31_32 dal_fixed31_32_log(
struct fixed31_32 arg)
{
struct fixed31_32 res = dal_fixed31_32_neg(dal_fixed31_32_one);
/* TODO improve 1st estimation */
struct fixed31_32 error;
ASSERT(arg.value > 0);
/* TODO if arg is negative, return NaN */
/* TODO if arg is zero, return -INF */
do {
struct fixed31_32 res1 = dal_fixed31_32_add(
dal_fixed31_32_sub(
res,
dal_fixed31_32_one),
dal_fixed31_32_div(
arg,
dal_fixed31_32_exp(res)));
error = dal_fixed31_32_sub(
res,
res1);
res = res1;
/* TODO determine max_allowed_error based on quality of exp() */
} while (abs_i64(error.value) > 100ULL);
return res;
}
struct fixed31_32 dal_fixed31_32_pow(
struct fixed31_32 arg1,
struct fixed31_32 arg2)
{
return dal_fixed31_32_exp(
dal_fixed31_32_mul(
dal_fixed31_32_log(arg1),
arg2));
}
int32_t dal_fixed31_32_floor(
struct fixed31_32 arg)
{
uint64_t arg_value = abs_i64(arg.value);
if (arg.value >= 0)
return (int32_t)GET_INTEGER_PART(arg_value);
else
return -(int32_t)GET_INTEGER_PART(arg_value);
}
int32_t dal_fixed31_32_round(
struct fixed31_32 arg)
{
uint64_t arg_value = abs_i64(arg.value);
const int64_t summand = dal_fixed31_32_half.value;
ASSERT(LLONG_MAX - (int64_t)arg_value >= summand);
arg_value += summand;
if (arg.value >= 0)
return (int32_t)GET_INTEGER_PART(arg_value);
else
return -(int32_t)GET_INTEGER_PART(arg_value);
}
int32_t dal_fixed31_32_ceil(
struct fixed31_32 arg)
{
uint64_t arg_value = abs_i64(arg.value);
const int64_t summand = dal_fixed31_32_one.value -
dal_fixed31_32_epsilon.value;
ASSERT(LLONG_MAX - (int64_t)arg_value >= summand);
arg_value += summand;
if (arg.value >= 0)
return (int32_t)GET_INTEGER_PART(arg_value);
else
return -(int32_t)GET_INTEGER_PART(arg_value);
}
/* this function is a generic helper to translate fixed point value to
* specified integer format that will consist of integer_bits integer part and
* fractional_bits fractional part. For example it is used in
* dal_fixed31_32_u2d19 to receive 2 bits integer part and 19 bits fractional
* part in 32 bits. It is used in hw programming (scaler)
*/
static inline uint32_t ux_dy(
int64_t value,
uint32_t integer_bits,
uint32_t fractional_bits)
{
/* 1. create mask of integer part */
uint32_t result = (1 << integer_bits) - 1;
/* 2. mask out fractional part */
uint32_t fractional_part = FRACTIONAL_PART_MASK & value;
/* 3. shrink fixed point integer part to be of integer_bits width*/
result &= GET_INTEGER_PART(value);
/* 4. make space for fractional part to be filled in after integer */
result <<= fractional_bits;
/* 5. shrink fixed point fractional part to of fractional_bits width*/
fractional_part >>= BITS_PER_FRACTIONAL_PART - fractional_bits;
/* 6. merge the result */
return result | fractional_part;
}
uint32_t dal_fixed31_32_u2d19(
struct fixed31_32 arg)
{
return ux_dy(arg.value, 2, 19);
}
uint32_t dal_fixed31_32_u0d19(
struct fixed31_32 arg)
{
return ux_dy(arg.value, 0, 19);
}

View File

@@ -0,0 +1,221 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dm_services.h"
#include "include/fixed32_32.h"
static uint64_t u64_div(uint64_t n, uint64_t d)
{
uint32_t i = 0;
uint64_t r;
uint64_t q = div64_u64_rem(n, d, &r);
for (i = 0; i < 32; ++i) {
uint64_t sbit = q & (1ULL<<63);
r <<= 1;
r |= sbit ? 1 : 0;
q <<= 1;
if (r >= d) {
r -= d;
q |= 1;
}
}
if (2*r >= d)
q += 1;
return q;
}
struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d)
{
struct fixed32_32 fx;
fx.value = u64_div((uint64_t)n << 32, (uint64_t)d << 32);
return fx;
}
struct fixed32_32 dal_fixed32_32_from_int(uint32_t value)
{
struct fixed32_32 fx;
fx.value = (uint64_t)value<<32;
return fx;
}
struct fixed32_32 dal_fixed32_32_add(
struct fixed32_32 lhs,
struct fixed32_32 rhs)
{
struct fixed32_32 fx = {lhs.value + rhs.value};
ASSERT(fx.value >= rhs.value);
return fx;
}
struct fixed32_32 dal_fixed32_32_add_int(struct fixed32_32 lhs, uint32_t rhs)
{
struct fixed32_32 fx = {lhs.value + ((uint64_t)rhs << 32)};
ASSERT(fx.value >= (uint64_t)rhs << 32);
return fx;
}
struct fixed32_32 dal_fixed32_32_sub(
struct fixed32_32 lhs,
struct fixed32_32 rhs)
{
struct fixed32_32 fx;
ASSERT(lhs.value >= rhs.value);
fx.value = lhs.value - rhs.value;
return fx;
}
struct fixed32_32 dal_fixed32_32_sub_int(struct fixed32_32 lhs, uint32_t rhs)
{
struct fixed32_32 fx;
ASSERT(lhs.value >= ((uint64_t)rhs<<32));
fx.value = lhs.value - ((uint64_t)rhs<<32);
return fx;
}
struct fixed32_32 dal_fixed32_32_mul(
struct fixed32_32 lhs,
struct fixed32_32 rhs)
{
struct fixed32_32 fx;
uint64_t lhs_int = lhs.value>>32;
uint64_t lhs_frac = (uint32_t)lhs.value;
uint64_t rhs_int = rhs.value>>32;
uint64_t rhs_frac = (uint32_t)rhs.value;
uint64_t ahbh = lhs_int * rhs_int;
uint64_t ahbl = lhs_int * rhs_frac;
uint64_t albh = lhs_frac * rhs_int;
uint64_t albl = lhs_frac * rhs_frac;
ASSERT((ahbh>>32) == 0);
fx.value = (ahbh<<32) + ahbl + albh + (albl>>32);
return fx;
}
struct fixed32_32 dal_fixed32_32_mul_int(struct fixed32_32 lhs, uint32_t rhs)
{
struct fixed32_32 fx;
uint64_t lhsi = (lhs.value>>32) * (uint64_t)rhs;
uint64_t lhsf;
ASSERT((lhsi>>32) == 0);
lhsf = ((uint32_t)lhs.value) * (uint64_t)rhs;
ASSERT((lhsi<<32) + lhsf >= lhsf);
fx.value = (lhsi<<32) + lhsf;
return fx;
}
struct fixed32_32 dal_fixed32_32_div(
struct fixed32_32 lhs,
struct fixed32_32 rhs)
{
struct fixed32_32 fx;
fx.value = u64_div(lhs.value, rhs.value);
return fx;
}
struct fixed32_32 dal_fixed32_32_div_int(struct fixed32_32 lhs, uint32_t rhs)
{
struct fixed32_32 fx;
fx.value = u64_div(lhs.value, (uint64_t)rhs << 32);
return fx;
}
struct fixed32_32 dal_fixed32_32_min(
struct fixed32_32 lhs,
struct fixed32_32 rhs)
{
return (lhs.value < rhs.value) ? lhs : rhs;
}
struct fixed32_32 dal_fixed32_32_max(
struct fixed32_32 lhs,
struct fixed32_32 rhs)
{
return (lhs.value > rhs.value) ? lhs : rhs;
}
bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs)
{
return lhs.value > rhs.value;
}
bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs)
{
return lhs.value > ((uint64_t)rhs<<32);
}
bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs)
{
return lhs.value < rhs.value;
}
bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs)
{
return lhs.value <= rhs.value;
}
bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs)
{
return lhs.value < ((uint64_t)rhs<<32);
}
bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs)
{
return lhs.value <= ((uint64_t)rhs<<32);
}
uint32_t dal_fixed32_32_ceil(struct fixed32_32 v)
{
ASSERT((uint32_t)v.value ? (v.value >> 32) + 1 >= 1 : true);
return (v.value>>32) + ((uint32_t)v.value ? 1 : 0);
}
uint32_t dal_fixed32_32_floor(struct fixed32_32 v)
{
return v.value>>32;
}
uint32_t dal_fixed32_32_round(struct fixed32_32 v)
{
ASSERT(v.value + (1ULL<<31) >= (1ULL<<31));
return (v.value + (1ULL<<31))>>32;
}
bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs)
{
return lhs.value == rhs.value;
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dm_services.h"
#include "include/grph_object_id.h"
bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
{
bool rc = true;
switch (id.type) {
case OBJECT_TYPE_UNKNOWN:
rc = false;
break;
case OBJECT_TYPE_GPU:
case OBJECT_TYPE_ENGINE:
/* do NOT check for id.id == 0 */
if (id.enum_id == ENUM_ID_UNKNOWN)
rc = false;
break;
default:
if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
rc = false;
break;
}
return rc;
}
bool dal_graphics_object_id_is_equal(
struct graphics_object_id id1,
struct graphics_object_id id2)
{
if (false == dal_graphics_object_id_is_valid(id1)) {
dm_output_to_console(
"%s: Warning: comparing invalid object 'id1'!\n", __func__);
return false;
}
if (false == dal_graphics_object_id_is_valid(id2)) {
dm_output_to_console(
"%s: Warning: comparing invalid object 'id2'!\n", __func__);
return false;
}
if (id1.id == id2.id && id1.enum_id == id2.enum_id
&& id1.type == id2.type)
return true;
return false;
}
/* Based on internal data members memory layout */
uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id)
{
uint32_t object_id = 0;
object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc);
return object_id;
}
/*
* ******* get specific ID - internal safe cast into specific type *******
*/
enum controller_id dal_graphics_object_id_get_controller_id(
struct graphics_object_id id)
{
if (id.type == OBJECT_TYPE_CONTROLLER)
return id.id;
return CONTROLLER_ID_UNDEFINED;
}
enum clock_source_id dal_graphics_object_id_get_clock_source_id(
struct graphics_object_id id)
{
if (id.type == OBJECT_TYPE_CLOCK_SOURCE)
return id.id;
return CLOCK_SOURCE_ID_UNDEFINED;
}
enum encoder_id dal_graphics_object_id_get_encoder_id(
struct graphics_object_id id)
{
if (id.type == OBJECT_TYPE_ENCODER)
return id.id;
return ENCODER_ID_UNKNOWN;
}
enum connector_id dal_graphics_object_id_get_connector_id(
struct graphics_object_id id)
{
if (id.type == OBJECT_TYPE_CONNECTOR)
return id.id;
return CONNECTOR_ID_UNKNOWN;
}
enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id)
{
if (id.type == OBJECT_TYPE_AUDIO)
return id.id;
return AUDIO_ID_UNKNOWN;
}
enum engine_id dal_graphics_object_id_get_engine_id(
struct graphics_object_id id)
{
if (id.type == OBJECT_TYPE_ENGINE)
return id.id;
return ENGINE_ID_UNKNOWN;
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2012-16 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "core_types.h"
#include "logger.h"
#include "include/logger_interface.h"
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
struct dc_signal_type_info {
enum signal_type type;
char name[MAX_NAME_LEN];
};
static const struct dc_signal_type_info signal_type_info_tbl[] = {
{SIGNAL_TYPE_NONE, "NC"},
{SIGNAL_TYPE_DVI_SINGLE_LINK, "DVI"},
{SIGNAL_TYPE_DVI_DUAL_LINK, "DDVI"},
{SIGNAL_TYPE_HDMI_TYPE_A, "HDMIA"},
{SIGNAL_TYPE_LVDS, "LVDS"},
{SIGNAL_TYPE_RGB, "VGA"},
{SIGNAL_TYPE_DISPLAY_PORT, "DP"},
{SIGNAL_TYPE_DISPLAY_PORT_MST, "MST"},
{SIGNAL_TYPE_EDP, "eDP"},
{SIGNAL_TYPE_WIRELESS, "Wireless"},
{SIGNAL_TYPE_VIRTUAL, "Virtual"}
};
void dc_conn_log(struct dc_context *ctx,
const struct dc_link *link,
uint8_t *hex_data,
int hex_data_count,
enum dc_log_type event,
const char *msg,
...)
{
int i;
va_list args;
struct log_entry entry = { 0 };
enum signal_type signal;
if (link->local_sink)
signal = link->local_sink->sink_signal;
else
signal = link->connector_signal;
if (link->type == dc_connection_mst_branch)
signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
dm_logger_open(ctx->logger, &entry, event);
for (i = 0; i < NUM_ELEMENTS(signal_type_info_tbl); i++)
if (signal == signal_type_info_tbl[i].type)
break;
dm_logger_append(&entry, "[%s][ConnIdx:%d] ",
signal_type_info_tbl[i].name,
link->link_index);
va_start(args, msg);
entry.buf_offset += dm_log_to_buffer(
&entry.buf[entry.buf_offset],
LOG_MAX_LINE_SIZE - entry.buf_offset,
msg, args);
if (entry.buf[strlen(entry.buf) - 1] == '\n') {
entry.buf[strlen(entry.buf) - 1] = '\0';
entry.buf_offset--;
}
if (hex_data)
for (i = 0; i < hex_data_count; i++)
dm_logger_append(&entry, "%2.2X ", hex_data[i]);
dm_logger_append(&entry, "^\n");
dm_logger_close(&entry);
va_end(args);
}

View File

@@ -0,0 +1,457 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dm_services.h"
#include "include/logger_interface.h"
#include "logger.h"
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
static const struct dc_log_type_info log_type_info_tbl[] = {
{LOG_ERROR, "Error"},
{LOG_WARNING, "Warning"},
{LOG_DC, "DC_Interface"},
{LOG_SURFACE, "Surface"},
{LOG_HW_HOTPLUG, "HW_Hotplug"},
{LOG_HW_LINK_TRAINING, "HW_LKTN"},
{LOG_HW_SET_MODE, "HW_Mode"},
{LOG_HW_RESUME_S3, "HW_Resume"},
{LOG_HW_AUDIO, "HW_Audio"},
{LOG_HW_HPD_IRQ, "HW_HPDIRQ"},
{LOG_MST, "MST"},
{LOG_SCALER, "Scaler"},
{LOG_BIOS, "BIOS"},
{LOG_BANDWIDTH_CALCS, "BWCalcs"},
{LOG_BANDWIDTH_VALIDATION, "BWValidation"},
{LOG_I2C_AUX, "I2C_AUX"},
{LOG_SYNC, "Sync"},
{LOG_BACKLIGHT, "Backlight"},
{LOG_FEATURE_OVERRIDE, "Override"},
{LOG_DETECTION_EDID_PARSER, "Edid"},
{LOG_DETECTION_DP_CAPS, "DP_Caps"},
{LOG_RESOURCE, "Resource"},
{LOG_DML, "DML"},
{LOG_EVENT_MODE_SET, "Mode"},
{LOG_EVENT_DETECTION, "Detect"},
{LOG_EVENT_LINK_TRAINING, "LKTN"},
{LOG_EVENT_LINK_LOSS, "LinkLoss"},
{LOG_EVENT_UNDERFLOW, "Underflow"},
{LOG_IF_TRACE, "InterfaceTrace"}
};
#define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \
(1 << LOG_WARNING) | \
(1 << LOG_EVENT_MODE_SET) | \
(1 << LOG_EVENT_DETECTION) | \
(1 << LOG_EVENT_LINK_TRAINING) | \
(1 << LOG_EVENT_LINK_LOSS) | \
(1 << LOG_EVENT_UNDERFLOW) | \
(1 << LOG_RESOURCE) | \
(1 << LOG_FEATURE_OVERRIDE) | \
(1 << LOG_DETECTION_EDID_PARSER) | \
(1 << LOG_DC) | \
(1 << LOG_HW_HOTPLUG) | \
(1 << LOG_HW_SET_MODE) | \
(1 << LOG_HW_RESUME_S3) | \
(1 << LOG_HW_HPD_IRQ) | \
(1 << LOG_SYNC) | \
(1 << LOG_BANDWIDTH_VALIDATION) | \
(1 << LOG_MST) | \
(1 << LOG_BIOS) | \
(1 << LOG_DETECTION_EDID_PARSER) | \
(1 << LOG_DETECTION_DP_CAPS) | \
(1 << LOG_BACKLIGHT)) | \
(1 << LOG_I2C_AUX) | \
(1 << LOG_IF_TRACE) /* | \
(1 << LOG_SURFACE) | \
(1 << LOG_SCALER) | \
(1 << LOG_DML) | \
(1 << LOG_HW_LINK_TRAINING) | \
(1 << LOG_HW_AUDIO)| \
(1 << LOG_BANDWIDTH_CALCS)*/
/* ----------- Object init and destruction ----------- */
static bool construct(struct dc_context *ctx, struct dal_logger *logger)
{
/* malloc buffer and init offsets */
logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE;
logger->log_buffer = (char *)dm_alloc(logger->log_buffer_size *
sizeof(char));
if (!logger->log_buffer)
return false;
/* Initialize both offsets to start of buffer (empty) */
logger->buffer_read_offset = 0;
logger->buffer_write_offset = 0;
logger->write_wrap_count = 0;
logger->read_wrap_count = 0;
logger->open_count = 0;
logger->flags.bits.ENABLE_CONSOLE = 1;
logger->flags.bits.ENABLE_BUFFER = 0;
logger->ctx = ctx;
logger->mask = DC_DEFAULT_LOG_MASK;
return true;
}
static void destruct(struct dal_logger *logger)
{
if (logger->log_buffer) {
dm_free(logger->log_buffer);
logger->log_buffer = NULL;
}
}
struct dal_logger *dal_logger_create(struct dc_context *ctx)
{
/* malloc struct */
struct dal_logger *logger = dm_alloc(sizeof(struct dal_logger));
if (!logger)
return NULL;
if (!construct(ctx, logger)) {
dm_free(logger);
return NULL;
}
return logger;
}
uint32_t dal_logger_destroy(struct dal_logger **logger)
{
if (logger == NULL || *logger == NULL)
return 1;
destruct(*logger);
dm_free(*logger);
*logger = NULL;
return 0;
}
/* ------------------------------------------------------------------------ */
static bool dal_logger_should_log(
struct dal_logger *logger,
enum dc_log_type log_type)
{
if (logger->mask & (1 << log_type))
return true;
return false;
}
static void log_to_debug_console(struct log_entry *entry)
{
struct dal_logger *logger = entry->logger;
if (logger->flags.bits.ENABLE_CONSOLE == 0)
return;
if (entry->buf_offset) {
switch (entry->type) {
case LOG_ERROR:
dm_error("%s", entry->buf);
break;
default:
dm_output_to_console("%s", entry->buf);
break;
}
}
}
/* Print everything unread existing in log_buffer to debug console*/
static void flush_to_debug_console(struct dal_logger *logger)
{
int i = logger->buffer_read_offset;
char *string_start = &logger->log_buffer[i];
dm_output_to_console(
"---------------- FLUSHING LOG BUFFER ----------------\n");
while (i < logger->buffer_write_offset) {
if (logger->log_buffer[i] == '\0') {
dm_output_to_console("%s", string_start);
string_start = (char *)logger->log_buffer + i + 1;
}
i++;
}
dm_output_to_console(
"-------------- END FLUSHING LOG BUFFER --------------\n\n");
}
static void log_to_internal_buffer(struct log_entry *entry)
{
uint32_t size = entry->buf_offset;
struct dal_logger *logger = entry->logger;
if (logger->flags.bits.ENABLE_BUFFER == 0)
return;
if (logger->log_buffer == NULL)
return;
if (size > 0 && size < logger->log_buffer_size) {
int total_free_space = 0;
int space_before_wrap = 0;
if (logger->buffer_write_offset > logger->buffer_read_offset) {
total_free_space = logger->log_buffer_size -
logger->buffer_write_offset +
logger->buffer_read_offset;
space_before_wrap = logger->log_buffer_size -
logger->buffer_write_offset;
} else if (logger->buffer_write_offset <
logger->buffer_read_offset) {
total_free_space = logger->log_buffer_size -
logger->buffer_read_offset +
logger->buffer_write_offset;
space_before_wrap = total_free_space;
} else if (logger->write_wrap_count !=
logger->read_wrap_count) {
/* Buffer is completely full already */
total_free_space = 0;
space_before_wrap = 0;
} else {
/* Buffer is empty, start writing at beginning */
total_free_space = logger->log_buffer_size;
space_before_wrap = logger->log_buffer_size;
logger->buffer_write_offset = 0;
logger->buffer_read_offset = 0;
}
if (space_before_wrap > size) {
/* No wrap around, copy 'size' bytes
* from 'entry->buf' to 'log_buffer'
*/
memmove(logger->log_buffer +
logger->buffer_write_offset,
entry->buf, size);
logger->buffer_write_offset += size;
} else if (total_free_space > size) {
/* We have enough room without flushing,
* but need to wrap around */
int space_after_wrap = total_free_space -
space_before_wrap;
memmove(logger->log_buffer +
logger->buffer_write_offset,
entry->buf, space_before_wrap);
memmove(logger->log_buffer, entry->buf +
space_before_wrap, space_after_wrap);
logger->buffer_write_offset = space_after_wrap;
logger->write_wrap_count++;
} else {
/* Not enough room remaining, we should flush
* existing logs */
/* Flush existing unread logs to console */
flush_to_debug_console(logger);
/* Start writing to beginning of buffer */
memmove(logger->log_buffer, entry->buf, size);
logger->buffer_write_offset = size;
logger->buffer_read_offset = 0;
}
}
}
static void log_heading(struct log_entry *entry)
{
int j;
for (j = 0; j < NUM_ELEMENTS(log_type_info_tbl); j++) {
const struct dc_log_type_info *info = &log_type_info_tbl[j];
if (info->type == entry->type)
dm_logger_append(entry, "[%s]\t", info->name);
}
}
static void append_entry(
struct log_entry *entry,
char *buffer,
uint32_t buf_size)
{
if (!entry->buf ||
entry->buf_offset + buf_size > entry->max_buf_bytes
) {
BREAK_TO_DEBUGGER();
return;
}
/* Todo: check if off by 1 byte due to \0 anywhere */
memmove(entry->buf + entry->buf_offset, buffer, buf_size);
entry->buf_offset += buf_size;
}
/* ------------------------------------------------------------------------ */
/* Warning: Be careful that 'msg' is null terminated and the total size is
* less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0'
*/
void dm_logger_write(
struct dal_logger *logger,
enum dc_log_type log_type,
const char *msg,
...)
{
if (logger && dal_logger_should_log(logger, log_type)) {
uint32_t size;
va_list args;
char buffer[LOG_MAX_LINE_SIZE];
struct log_entry entry;
va_start(args, msg);
entry.logger = logger;
entry.buf = buffer;
entry.buf_offset = 0;
entry.max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char);
entry.type = log_type;
log_heading(&entry);
size = dm_log_to_buffer(
buffer, LOG_MAX_LINE_SIZE, msg, args);
entry.buf_offset += size;
/* --Flush log_entry buffer-- */
/* print to kernel console */
log_to_debug_console(&entry);
/* log internally for dsat */
log_to_internal_buffer(&entry);
va_end(args);
}
}
/* Same as dm_logger_write, except without open() and close(), which must
* be done separately.
*/
void dm_logger_append(
struct log_entry *entry,
const char *msg,
...)
{
struct dal_logger *logger;
if (!entry) {
BREAK_TO_DEBUGGER();
return;
}
logger = entry->logger;
if (logger && logger->open_count > 0 &&
dal_logger_should_log(logger, entry->type)) {
uint32_t size;
va_list args;
char buffer[LOG_MAX_LINE_SIZE];
va_start(args, msg);
size = dm_log_to_buffer(
buffer, LOG_MAX_LINE_SIZE, msg, args);
if (size < LOG_MAX_LINE_SIZE - 1) {
append_entry(entry, buffer, size);
} else {
append_entry(entry, "LOG_ERROR, line too long\n", 27);
}
va_end(args);
}
}
void dm_logger_open(
struct dal_logger *logger,
struct log_entry *entry, /* out */
enum dc_log_type log_type)
{
if (!entry) {
BREAK_TO_DEBUGGER();
return;
}
entry->type = log_type;
entry->logger = logger;
entry->buf = dm_alloc(DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char));
entry->buf_offset = 0;
entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char);
logger->open_count++;
log_heading(entry);
}
void dm_logger_close(struct log_entry *entry)
{
struct dal_logger *logger = entry->logger;
if (logger && logger->open_count > 0) {
logger->open_count--;
} else {
BREAK_TO_DEBUGGER();
goto cleanup;
}
/* --Flush log_entry buffer-- */
/* print to kernel console */
log_to_debug_console(entry);
/* log internally for dsat */
log_to_internal_buffer(entry);
/* TODO: Write end heading */
cleanup:
if (entry->buf) {
dm_free(entry->buf);
entry->buf = NULL;
entry->buf_offset = 0;
entry->max_buf_bytes = 0;
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#ifndef __DAL_LOGGER_H__
#define __DAL_LOGGER_H__
/* Structure for keeping track of offsets, buffer, etc */
#define DAL_LOGGER_BUFFER_MAX_SIZE 2048
/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes,
* change log line size to 896 to meet the request.
*/
#define LOG_MAX_LINE_SIZE 896
#include "include/logger_types.h"
struct dal_logger {
/* How far into the circular buffer has been read by dsat
* Read offset should never cross write offset. Write \0's to
* read data just to be sure?
*/
uint32_t buffer_read_offset;
/* How far into the circular buffer we have written
* Write offset should never cross read offset
*/
uint32_t buffer_write_offset;
uint32_t write_wrap_count;
uint32_t read_wrap_count;
uint32_t open_count;
char *log_buffer; /* Pointer to malloc'ed buffer */
uint32_t log_buffer_size; /* Size of circular buffer */
uint32_t mask; /*array of masks for major elements*/
union logger_flags flags;
struct dc_context *ctx;
};
#endif /* __DAL_LOGGER_H__ */

View File

@@ -0,0 +1,197 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dm_services.h"
#include "include/dal_types.h"
#include "include/logger_interface.h"
#include "logger.h"
/******************************************************************************
* Register Logger.
* A facility to create register R/W logs.
* Currently used for DAL Test.
*****************************************************************************/
/******************************************************************************
* Private structures
*****************************************************************************/
struct dal_reg_dump_stack_location {
const char *current_caller_func;
long current_pid;
long current_tgid;
uint32_t rw_count;/* register access counter for current function. */
};
/* This the maximum number of nested calls to the 'reg_dump' facility. */
#define DAL_REG_DUMP_STACK_MAX_SIZE 32
struct dal_reg_dump_stack {
int32_t stack_pointer;
struct dal_reg_dump_stack_location
stack_locations[DAL_REG_DUMP_STACK_MAX_SIZE];
uint32_t total_rw_count; /* Total count for *all* functions. */
};
static struct dal_reg_dump_stack reg_dump_stack = {0};
/******************************************************************************
* Private functions
*****************************************************************************/
/* Check if current process is the one which requested register dump.
* The reason for the check:
* mmCRTC_STATUS_FRAME_COUNT is accessed by dal_controller_get_vblank_counter().
* Which runs all the time when at least one display is connected.
* (Triggered by drm_mode_page_flip_ioctl()). */
static bool is_reg_dump_process(void)
{
uint32_t i;
/* walk the list of our processes */
for (i = 0; i < reg_dump_stack.stack_pointer; i++) {
struct dal_reg_dump_stack_location *stack_location
= &reg_dump_stack.stack_locations[i];
if (stack_location->current_pid == dm_get_pid()
&& stack_location->current_tgid == dm_get_tgid())
return true;
}
return false;
}
static bool dal_reg_dump_stack_is_empty(void)
{
if (reg_dump_stack.stack_pointer <= 0)
return true;
else
return false;
}
static struct dal_reg_dump_stack_location *dal_reg_dump_stack_push(void)
{
struct dal_reg_dump_stack_location *current_location = NULL;
if (reg_dump_stack.stack_pointer >= DAL_REG_DUMP_STACK_MAX_SIZE) {
/* stack is full */
dm_output_to_console("[REG_DUMP]: %s: stack is full!\n",
__func__);
} else {
current_location =
&reg_dump_stack.stack_locations[reg_dump_stack.stack_pointer];
++reg_dump_stack.stack_pointer;
}
return current_location;
}
static struct dal_reg_dump_stack_location *dal_reg_dump_stack_pop(void)
{
struct dal_reg_dump_stack_location *current_location = NULL;
if (dal_reg_dump_stack_is_empty()) {
/* stack is empty */
dm_output_to_console("[REG_DUMP]: %s: stack is empty!\n",
__func__);
} else {
--reg_dump_stack.stack_pointer;
current_location =
&reg_dump_stack.stack_locations[reg_dump_stack.stack_pointer];
}
return current_location;
}
/******************************************************************************
* Public functions
*****************************************************************************/
void dal_reg_logger_push(const char *caller_func)
{
struct dal_reg_dump_stack_location *free_stack_location;
free_stack_location = dal_reg_dump_stack_push();
if (NULL == free_stack_location)
return;
memset(free_stack_location, 0, sizeof(*free_stack_location));
free_stack_location->current_caller_func = caller_func;
free_stack_location->current_pid = dm_get_pid();
free_stack_location->current_tgid = dm_get_tgid();
dm_output_to_console("[REG_DUMP]:%s - start (pid:%ld, tgid:%ld)\n",
caller_func,
free_stack_location->current_pid,
free_stack_location->current_tgid);
}
void dal_reg_logger_pop(void)
{
struct dal_reg_dump_stack_location *top_stack_location;
top_stack_location = dal_reg_dump_stack_pop();
if (NULL == top_stack_location) {
dm_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n",
__func__);
return;
}
dm_output_to_console(
"[REG_DUMP]:%s - end."\
" Reg R/W Count: Total=%d Function=%d. (pid:%ld, tgid:%ld)\n",
top_stack_location->current_caller_func,
reg_dump_stack.total_rw_count,
top_stack_location->rw_count,
dm_get_pid(),
dm_get_tgid());
memset(top_stack_location, 0, sizeof(*top_stack_location));
}
void dal_reg_logger_rw_count_increment(void)
{
++reg_dump_stack.total_rw_count;
++reg_dump_stack.stack_locations
[reg_dump_stack.stack_pointer - 1].rw_count;
}
bool dal_reg_logger_should_dump_register(void)
{
if (true == dal_reg_dump_stack_is_empty())
return false;
if (false == is_reg_dump_process())
return false;
return true;
}
/******************************************************************************
* End of File.
*****************************************************************************/

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dm_services.h"
#include "include/signal_types.h"
bool dc_is_hdmi_signal(enum signal_type signal)
{
return (signal == SIGNAL_TYPE_HDMI_TYPE_A);
}
bool dc_is_dp_sst_signal(enum signal_type signal)
{
return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
signal == SIGNAL_TYPE_EDP);
}
bool dc_is_dp_signal(enum signal_type signal)
{
return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
signal == SIGNAL_TYPE_EDP ||
signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
}
bool dc_is_dp_external_signal(enum signal_type signal)
{
return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
}
bool dc_is_analog_signal(enum signal_type signal)
{
switch (signal) {
case SIGNAL_TYPE_RGB:
return true;
break;
default:
return false;
}
}
bool dc_is_embedded_signal(enum signal_type signal)
{
return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS);
}
bool dc_is_dvi_signal(enum signal_type signal)
{
switch (signal) {
case SIGNAL_TYPE_DVI_SINGLE_LINK:
case SIGNAL_TYPE_DVI_DUAL_LINK:
return true;
break;
default:
return false;
}
}
bool dc_is_dvi_single_link_signal(enum signal_type signal)
{
return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK);
}
bool dc_is_dual_link_signal(enum signal_type signal)
{
return (signal == SIGNAL_TYPE_DVI_DUAL_LINK);
}
bool dc_is_audio_capable_signal(enum signal_type signal)
{
return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
dc_is_hdmi_signal(signal) ||
signal == SIGNAL_TYPE_WIRELESS);
}
/*
* @brief
* Returns whether the signal is compatible
* with other digital encoder signal types.
* This is true for DVI, LVDS, and HDMI signal types.
*/
bool dc_is_digital_encoder_compatible_signal(enum signal_type signal)
{
switch (signal) {
case SIGNAL_TYPE_DVI_SINGLE_LINK:
case SIGNAL_TYPE_DVI_DUAL_LINK:
case SIGNAL_TYPE_HDMI_TYPE_A:
case SIGNAL_TYPE_LVDS:
return true;
default:
return false;
}
}

View File

@@ -0,0 +1,307 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dm_services.h"
#include "include/vector.h"
bool dal_vector_construct(
struct vector *vector,
struct dc_context *ctx,
uint32_t capacity,
uint32_t struct_size)
{
vector->container = NULL;
if (!struct_size || !capacity) {
/* Container must be non-zero size*/
BREAK_TO_DEBUGGER();
return false;
}
vector->container = dm_alloc(struct_size * capacity);
if (vector->container == NULL)
return false;
vector->capacity = capacity;
vector->struct_size = struct_size;
vector->count = 0;
vector->ctx = ctx;
return true;
}
bool dal_vector_presized_costruct(
struct vector *vector,
struct dc_context *ctx,
uint32_t count,
void *initial_value,
uint32_t struct_size)
{
uint32_t i;
vector->container = NULL;
if (!struct_size || !count) {
/* Container must be non-zero size*/
BREAK_TO_DEBUGGER();
return false;
}
vector->container = dm_alloc(struct_size * count);
if (vector->container == NULL)
return false;
/* If caller didn't supply initial value then the default
* of all zeros is expected, which is exactly what dal_alloc()
* initialises the memory to. */
if (NULL != initial_value) {
for (i = 0; i < count; ++i)
memmove(
vector->container + i * struct_size,
initial_value,
struct_size);
}
vector->capacity = count;
vector->struct_size = struct_size;
vector->count = count;
return true;
}
struct vector *dal_vector_presized_create(
struct dc_context *ctx,
uint32_t size,
void *initial_value,
uint32_t struct_size)
{
struct vector *vector = dm_alloc(sizeof(struct vector));
if (vector == NULL)
return NULL;
if (dal_vector_presized_costruct(
vector, ctx, size, initial_value, struct_size))
return vector;
BREAK_TO_DEBUGGER();
dm_free(vector);
return NULL;
}
struct vector *dal_vector_create(
struct dc_context *ctx,
uint32_t capacity,
uint32_t struct_size)
{
struct vector *vector = dm_alloc(sizeof(struct vector));
if (vector == NULL)
return NULL;
if (dal_vector_construct(vector, ctx, capacity, struct_size))
return vector;
BREAK_TO_DEBUGGER();
dm_free(vector);
return NULL;
}
void dal_vector_destruct(
struct vector *vector)
{
if (vector->container != NULL)
dm_free(vector->container);
vector->count = 0;
vector->capacity = 0;
}
void dal_vector_destroy(
struct vector **vector)
{
if (vector == NULL || *vector == NULL)
return;
dal_vector_destruct(*vector);
dm_free(*vector);
*vector = NULL;
}
uint32_t dal_vector_get_count(
const struct vector *vector)
{
return vector->count;
}
void *dal_vector_at_index(
const struct vector *vector,
uint32_t index)
{
if (vector->container == NULL || index >= vector->count)
return NULL;
return vector->container + (index * vector->struct_size);
}
bool dal_vector_remove_at_index(
struct vector *vector,
uint32_t index)
{
if (index >= vector->count)
return false;
if (index != vector->count - 1)
memmove(
vector->container + (index * vector->struct_size),
vector->container + ((index + 1) * vector->struct_size),
(vector->count - index - 1) * vector->struct_size);
vector->count -= 1;
return true;
}
void dal_vector_set_at_index(
const struct vector *vector,
const void *what,
uint32_t index)
{
void *where = dal_vector_at_index(vector, index);
if (!where) {
BREAK_TO_DEBUGGER();
return;
}
memmove(
where,
what,
vector->struct_size);
}
static inline uint32_t calc_increased_capacity(
uint32_t old_capacity)
{
return old_capacity * 2;
}
bool dal_vector_insert_at(
struct vector *vector,
const void *what,
uint32_t position)
{
uint8_t *insert_address;
if (vector->count == vector->capacity) {
if (!dal_vector_reserve(
vector,
calc_increased_capacity(vector->capacity)))
return false;
}
insert_address = vector->container + (vector->struct_size * position);
if (vector->count && position < vector->count)
memmove(
insert_address + vector->struct_size,
insert_address,
vector->struct_size * (vector->count - position));
memmove(
insert_address,
what,
vector->struct_size);
vector->count++;
return true;
}
bool dal_vector_append(
struct vector *vector,
const void *item)
{
return dal_vector_insert_at(vector, item, vector->count);
}
struct vector *dal_vector_clone(
const struct vector *vector)
{
struct vector *vec_cloned;
uint32_t count;
/* create new vector */
count = dal_vector_get_count(vector);
if (count == 0)
/* when count is 0 we still want to create clone of the vector
*/
vec_cloned = dal_vector_create(
vector->ctx,
vector->capacity,
vector->struct_size);
else
/* Call "presized create" version, independently of how the
* original vector was created.
* The owner of original vector must know how to treat the new
* vector - as "presized" or as "regular".
* But from vector point of view it doesn't matter. */
vec_cloned = dal_vector_presized_create(vector->ctx, count,
NULL,/* no initial value */
vector->struct_size);
if (NULL == vec_cloned) {
BREAK_TO_DEBUGGER();
return NULL;
}
/* copy vector's data */
memmove(vec_cloned->container, vector->container,
vec_cloned->struct_size * vec_cloned->capacity);
return vec_cloned;
}
uint32_t dal_vector_capacity(const struct vector *vector)
{
return vector->capacity;
}
bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
{
void *new_container;
if (capacity <= vector->capacity)
return true;
new_container = dm_realloc(vector->container, capacity * vector->struct_size);
if (new_container) {
vector->container = new_container;
vector->capacity = capacity;
return true;
}
return false;
}
void dal_vector_clear(struct vector *vector)
{
vector->count = 0;
}