/*
* Copyright 2019 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.
*
* Author: AMD
*/
#include <drm/display/drm_dp_helper.h>
#include <drm/display/drm_dsc_helper.h>
#include "dc_hw_types.h"
#include "dsc.h"
#include "dc.h"
#include "rc_calc.h"
#include "fixed31_32.h"
/* This module's internal functions */
/* default DSC policy target bitrate limit is 16bpp */
static uint32_t dsc_policy_max_target_bpp_limit = 16;
/* default DSC policy enables DSC only when needed */
static bool dsc_policy_enable_dsc_when_not_needed;
static bool dsc_policy_disable_dsc_stream_overhead;
static bool disable_128b_132b_stream_overhead;
#ifndef MAX
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
#endif
#ifndef MIN
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
#endif
/* Need to account for padding due to pixel-to-symbol packing
* for uncompressed 128b/132b streams.
*/
static uint32_t apply_128b_132b_stream_overhead(
const struct dc_crtc_timing *timing, const uint32_t kbps)
{
uint32_t total_kbps = kbps;
if (disable_128b_132b_stream_overhead)
return kbps;
if (!timing->flags.DSC) {
struct fixed31_32 bpp;
struct fixed31_32 overhead_factor;
bpp = dc_fixpt_from_int(kbps);
bpp = dc_fixpt_div_int(bpp, timing->pix_clk_100hz / 10);
/* Symbols_per_HActive = HActive * bpp / (4 lanes * 32-bit symbol size)
* Overhead_factor = ceil(Symbols_per_HActive) / Symbols_per_HActive
*/
overhead_factor = dc_fixpt_from_int(timing->h_addressable);
overhead_factor = dc_fixpt_mul(overhead_factor, bpp);
overhead_factor = dc_fixpt_div_int(overhead_factor, 128);
overhead_factor = dc_fixpt_div(
dc_fixpt_from_int(dc_fixpt_ceil(overhead_factor)),
overhead_factor);
total_kbps = dc_fixpt_ceil(
dc_fixpt_mul_int(overhead_factor, total_kbps));
}
return total_kbps;
}
uint32_t dc_bandwidth_in_kbps_from_timing(
const struct dc_crtc_timing *timing,
const enum dc_link_encoding_format link_encoding)
{
uint32_t bits_per_channel = 0;
uint32_t kbps;
if (timing->flags.DSC)
return dc_dsc_stream_bandwidth_in_kbps(timing,
timing->dsc_cfg.bits_per_pixel,
timing->dsc_cfg.num_slices_h,
timing->dsc_cfg.is_dp);
switch (timing->display_color_depth) {
case COLOR_DEPTH_666:
bits_per_channel = 6;
break;
case COLOR_DEPTH_888:
bits_per_channel = 8;
break;
case COLOR_DEPTH_101010:
bits_per_channel = 10;
break;
case COLOR_DEPTH_121212:
bits_per_channel = 12;
break;
case COLOR_DEPTH_141414:
bits_per_channel = 14;
break;
case COLOR_DEPTH_161616:
bits_per_channel = 16;
break;
default:
ASSERT(bits_per_channel != 0);
bits_per_channel = 8;
break;
}
kbps = timing->pix_clk_100hz / 10;
kbps *= bits_per_channel;
if (timing->flags.Y_ONLY != 1) {
/*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
kbps *= 3;
if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
kbps /= 2;
else if (timing->pixel_encoding ==