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