/*
* 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 "dc_hw_types.h"
#include "dsc.h"
#include <drm/drm_dp_helper.h>
#include "dc.h"
/* This module's internal functions */
/* default DSC policy target bitrate limit is 16bpp */
static uint32_t dsc_policy_max_target_bpp_limit = 16;
static uint32_t dc_dsc_bandwidth_in_kbps_from_timing(
const struct dc_crtc_timing *timing)
{
uint32_t bits_per_channel = 0;
uint32_t kbps;
if (timing->flags.DSC) {
kbps = (timing->pix_clk_100hz * timing->dsc_cfg.bits_per_pixel);
kbps = kbps / 160 + ((kbps % 160) ? 1 : 0);
return kbps;
}
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:
break;
}
ASSERT(bits_per_channel != 0);
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 == PIXEL_ENCODING_YCBCR422)
kbps = kbps * 2 / 3;
}
return kbps;
}
static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size)
{
switch (dpcd_buff_block_size) {
case DP_DSC_RC_BUF_BLK_SIZE_1:
*buff_block_size = 1024;
break;
case DP_DSC_RC_BUF_BLK_SIZE_4:
*buff_block_size = 4 * 1024;
break;
case DP_DSC_RC_BUF_BLK_SIZE_16:
*buff_block_size = 16 * 1024;
break;
case DP_DSC_RC_BUF_BLK_SIZE_64:
*buff_block_size = 64 * 1024;
break;
default: {
dm_error("%s: DPCD DSC buffer size not recognized.\n", __func__);
return false;
}
}
return true;
}
static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *line_buff_bit_depth)
{
if (0 <= dpcd_line_buff_bit_depth && dpcd_line_buff_bit_depth <= 7)
*line_buff_bit_depth = dpcd_line_buff_bit_depth + 9;
else if (dpcd_line_buff_bit_depth == 8)
*line_buff_bit_depth = 8;
else {
dm_error("%s: DPCD DSC buffer depth not recognized.\n", __func__);
return false;
}
return true;
}
static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput)
{
switch (dpcd_throughput) {
case DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED:
*throughput = 0;
break;
case DP_DSC_THROUGHPUT_MODE_0_170:
*throughput = 170;
break;
case DP_DSC_THROUGHPUT_MODE_0_340:
*throughput = 340;
break;
case DP_DSC_THROUGHPUT_MODE_0_400:
*throughput = 400;
break;
case DP_DSC_THROUGHPUT_MODE_0_450:
*throughput = 450;
break;
case DP_DSC_THROUGHPUT_MODE_0_500:
*throughput = 500;
break;
case DP_DSC_THROUGHPUT_MODE_0_550:
*throughput = 550;
break;
case DP_DSC_THROUGHPUT_MODE_0_600:
*throughput = 600;
break;
case DP_DSC_THROUGHPUT_MODE_0_650:
*throughput = 650;
break;
case DP_DSC_THROUGHPUT_MODE_0_700:
*throughput = 700;
break;
case DP_DSC_THROUGHPUT_MODE_0_750:
*throughput = 750;
break;
case DP_DSC_THROUGHPUT_MODE_0_800:
*throughput