linux/drivers/gpu/drm/amd/display/dc/basics/conversion.c
<<
>>
Prefs
   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
  28#define DIVIDER 10000
  29
  30/* S2D13 value in [-3.00...0.9999] */
  31#define S2D13_MIN (-3 * DIVIDER)
  32#define S2D13_MAX (3 * DIVIDER)
  33
  34uint16_t fixed_point_to_int_frac(
  35        struct fixed31_32 arg,
  36        uint8_t integer_bits,
  37        uint8_t fractional_bits)
  38{
  39        int32_t numerator;
  40        int32_t divisor = 1 << fractional_bits;
  41
  42        uint16_t result;
  43
  44        uint16_t d = (uint16_t)dc_fixpt_floor(
  45                dc_fixpt_abs(
  46                        arg));
  47
  48        if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
  49                numerator = (uint16_t)dc_fixpt_round(
  50                        dc_fixpt_mul_int(
  51                                arg,
  52                                divisor));
  53        else {
  54                numerator = dc_fixpt_floor(
  55                        dc_fixpt_sub(
  56                                dc_fixpt_from_int(
  57                                        1LL << integer_bits),
  58                                dc_fixpt_recip(
  59                                        dc_fixpt_from_int(
  60                                                divisor))));
  61        }
  62
  63        if (numerator >= 0)
  64                result = (uint16_t)numerator;
  65        else
  66                result = (uint16_t)(
  67                (1 << (integer_bits + fractional_bits + 1)) + numerator);
  68
  69        if ((result != 0) && dc_fixpt_lt(
  70                arg, dc_fixpt_zero))
  71                result |= 1 << (integer_bits + fractional_bits);
  72
  73        return result;
  74}
  75/**
  76* convert_float_matrix
  77* This converts a double into HW register spec defined format S2D13.
  78* @param :
  79* @return None
  80*/
  81void convert_float_matrix(
  82        uint16_t *matrix,
  83        struct fixed31_32 *flt,
  84        uint32_t buffer_size)
  85{
  86        const struct fixed31_32 min_2_13 =
  87                dc_fixpt_from_fraction(S2D13_MIN, DIVIDER);
  88        const struct fixed31_32 max_2_13 =
  89                dc_fixpt_from_fraction(S2D13_MAX, DIVIDER);
  90        uint32_t i;
  91
  92        for (i = 0; i < buffer_size; ++i) {
  93                uint32_t reg_value =
  94                                fixed_point_to_int_frac(
  95                                        dc_fixpt_clamp(
  96                                                flt[i],
  97                                                min_2_13,
  98                                                max_2_13),
  99                                                2,
 100                                                13);
 101
 102                matrix[i] = (uint16_t)reg_value;
 103        }
 104}
 105