cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dc_dsc.c (35669B)


      1/*
      2 * Copyright 2019 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 * Author: AMD
     23 */
     24
     25#include <drm/display/drm_dp_helper.h>
     26#include <drm/display/drm_dsc_helper.h>
     27#include "dc_hw_types.h"
     28#include "dsc.h"
     29#include "dc.h"
     30#include "rc_calc.h"
     31#include "fixed31_32.h"
     32
     33/* This module's internal functions */
     34
     35/* default DSC policy target bitrate limit is 16bpp */
     36static uint32_t dsc_policy_max_target_bpp_limit = 16;
     37
     38/* default DSC policy enables DSC only when needed */
     39static bool dsc_policy_enable_dsc_when_not_needed;
     40
     41static bool dsc_policy_disable_dsc_stream_overhead;
     42
     43#ifndef MAX
     44#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
     45#endif
     46#ifndef MIN
     47#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
     48#endif
     49
     50/* Forward Declerations */
     51static bool decide_dsc_bandwidth_range(
     52		const uint32_t min_bpp_x16,
     53		const uint32_t max_bpp_x16,
     54		const uint32_t num_slices_h,
     55		const struct dsc_enc_caps *dsc_caps,
     56		const struct dc_crtc_timing *timing,
     57		struct dc_dsc_bw_range *range);
     58
     59static uint32_t compute_bpp_x16_from_target_bandwidth(
     60		const uint32_t bandwidth_in_kbps,
     61		const struct dc_crtc_timing *timing,
     62		const uint32_t num_slices_h,
     63		const uint32_t bpp_increment_div,
     64		const bool is_dp);
     65
     66static void get_dsc_enc_caps(
     67		const struct display_stream_compressor *dsc,
     68		struct dsc_enc_caps *dsc_enc_caps,
     69		int pixel_clock_100Hz);
     70
     71static bool intersect_dsc_caps(
     72		const struct dsc_dec_dpcd_caps *dsc_sink_caps,
     73		const struct dsc_enc_caps *dsc_enc_caps,
     74		enum dc_pixel_encoding pixel_encoding,
     75		struct dsc_enc_caps *dsc_common_caps);
     76
     77static bool setup_dsc_config(
     78		const struct dsc_dec_dpcd_caps *dsc_sink_caps,
     79		const struct dsc_enc_caps *dsc_enc_caps,
     80		int target_bandwidth_kbps,
     81		const struct dc_crtc_timing *timing,
     82		int min_slice_height_override,
     83		int max_dsc_target_bpp_limit_override_x16,
     84		struct dc_dsc_config *dsc_cfg);
     85
     86static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size)
     87{
     88
     89	switch (dpcd_buff_block_size) {
     90	case DP_DSC_RC_BUF_BLK_SIZE_1:
     91		*buff_block_size = 1024;
     92		break;
     93	case DP_DSC_RC_BUF_BLK_SIZE_4:
     94		*buff_block_size = 4 * 1024;
     95		break;
     96	case DP_DSC_RC_BUF_BLK_SIZE_16:
     97		*buff_block_size = 16 * 1024;
     98		break;
     99	case DP_DSC_RC_BUF_BLK_SIZE_64:
    100		*buff_block_size = 64 * 1024;
    101		break;
    102	default: {
    103			dm_error("%s: DPCD DSC buffer size not recognized.\n", __func__);
    104			return false;
    105		}
    106	}
    107
    108	return true;
    109}
    110
    111
    112static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *line_buff_bit_depth)
    113{
    114	if (0 <= dpcd_line_buff_bit_depth && dpcd_line_buff_bit_depth <= 7)
    115		*line_buff_bit_depth = dpcd_line_buff_bit_depth + 9;
    116	else if (dpcd_line_buff_bit_depth == 8)
    117		*line_buff_bit_depth = 8;
    118	else {
    119		dm_error("%s: DPCD DSC buffer depth not recognized.\n", __func__);
    120		return false;
    121	}
    122
    123	return true;
    124}
    125
    126
    127static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput)
    128{
    129	switch (dpcd_throughput) {
    130	case DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED:
    131		*throughput = 0;
    132		break;
    133	case DP_DSC_THROUGHPUT_MODE_0_170:
    134		*throughput = 170;
    135		break;
    136	case DP_DSC_THROUGHPUT_MODE_0_340:
    137		*throughput = 340;
    138		break;
    139	case DP_DSC_THROUGHPUT_MODE_0_400:
    140		*throughput = 400;
    141		break;
    142	case DP_DSC_THROUGHPUT_MODE_0_450:
    143		*throughput = 450;
    144		break;
    145	case DP_DSC_THROUGHPUT_MODE_0_500:
    146		*throughput = 500;
    147		break;
    148	case DP_DSC_THROUGHPUT_MODE_0_550:
    149		*throughput = 550;
    150		break;
    151	case DP_DSC_THROUGHPUT_MODE_0_600:
    152		*throughput = 600;
    153		break;
    154	case DP_DSC_THROUGHPUT_MODE_0_650:
    155		*throughput = 650;
    156		break;
    157	case DP_DSC_THROUGHPUT_MODE_0_700:
    158		*throughput = 700;
    159		break;
    160	case DP_DSC_THROUGHPUT_MODE_0_750:
    161		*throughput = 750;
    162		break;
    163	case DP_DSC_THROUGHPUT_MODE_0_800:
    164		*throughput = 800;
    165		break;
    166	case DP_DSC_THROUGHPUT_MODE_0_850:
    167		*throughput = 850;
    168		break;
    169	case DP_DSC_THROUGHPUT_MODE_0_900:
    170		*throughput = 900;
    171		break;
    172	case DP_DSC_THROUGHPUT_MODE_0_950:
    173		*throughput = 950;
    174		break;
    175	case DP_DSC_THROUGHPUT_MODE_0_1000:
    176		*throughput = 1000;
    177		break;
    178	default: {
    179			dm_error("%s: DPCD DSC throughput mode not recognized.\n", __func__);
    180			return false;
    181		}
    182	}
    183
    184	return true;
    185}
    186
    187
    188static bool dsc_bpp_increment_div_from_dpcd(uint8_t bpp_increment_dpcd, uint32_t *bpp_increment_div)
    189{
    190	// Mask bpp increment dpcd field to avoid reading other fields
    191	bpp_increment_dpcd &= 0x7;
    192
    193	switch (bpp_increment_dpcd) {
    194	case 0:
    195		*bpp_increment_div = 16;
    196		break;
    197	case 1:
    198		*bpp_increment_div = 8;
    199		break;
    200	case 2:
    201		*bpp_increment_div = 4;
    202		break;
    203	case 3:
    204		*bpp_increment_div = 2;
    205		break;
    206	case 4:
    207		*bpp_increment_div = 1;
    208		break;
    209	default: {
    210		dm_error("%s: DPCD DSC bits-per-pixel increment not recognized.\n", __func__);
    211		return false;
    212	}
    213	}
    214
    215	return true;
    216}
    217
    218
    219
    220bool dc_dsc_parse_dsc_dpcd(const struct dc *dc,
    221		const uint8_t *dpcd_dsc_basic_data,
    222		const uint8_t *dpcd_dsc_branch_decoder_caps,
    223		struct dsc_dec_dpcd_caps *dsc_sink_caps)
    224{
    225	if (!dpcd_dsc_basic_data)
    226		return false;
    227
    228	dsc_sink_caps->is_dsc_supported =
    229		(dpcd_dsc_basic_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;
    230	if (!dsc_sink_caps->is_dsc_supported)
    231		return false;
    232
    233	dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT];
    234
    235	{
    236		int buff_block_size;
    237		int buff_size;
    238
    239		if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT],
    240										   &buff_block_size))
    241			return false;
    242
    243		buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;
    244		dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size;
    245	}
    246
    247	dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
    248	if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_basic_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT],
    249									   &dsc_sink_caps->lb_bit_depth))
    250		return false;
    251
    252	dsc_sink_caps->is_block_pred_supported =
    253		(dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] &
    254		 DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;
    255
    256	dsc_sink_caps->edp_max_bits_per_pixel =
    257		dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
    258		dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;
    259
    260	dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];
    261	dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
    262
    263	{
    264		int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
    265
    266		if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK,
    267									  &dsc_sink_caps->throughput_mode_0_mps))
    268			return false;
    269
    270		dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT;
    271		if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps))
    272			return false;
    273	}
    274
    275	dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
    276	dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
    277
    278	if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_basic_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT],
    279										 &dsc_sink_caps->bpp_increment_div))
    280		return false;
    281
    282	if (dc->debug.dsc_bpp_increment_div) {
    283		/* dsc_bpp_increment_div should onl be 1, 2, 4, 8 or 16, but rather than rejecting invalid values,
    284		 * we'll accept all and get it into range. This also makes the above check against 0 redundant,
    285		 * but that one stresses out the override will be only used if it's not 0.
    286		 */
    287		if (dc->debug.dsc_bpp_increment_div >= 1)
    288			dsc_sink_caps->bpp_increment_div = 1;
    289		if (dc->debug.dsc_bpp_increment_div >= 2)
    290			dsc_sink_caps->bpp_increment_div = 2;
    291		if (dc->debug.dsc_bpp_increment_div >= 4)
    292			dsc_sink_caps->bpp_increment_div = 4;
    293		if (dc->debug.dsc_bpp_increment_div >= 8)
    294			dsc_sink_caps->bpp_increment_div = 8;
    295		if (dc->debug.dsc_bpp_increment_div >= 16)
    296			dsc_sink_caps->bpp_increment_div = 16;
    297	}
    298
    299	/* Extended caps */
    300	if (dpcd_dsc_branch_decoder_caps == NULL) { // branch decoder DPCD DSC data can be null for non branch device
    301		dsc_sink_caps->branch_overall_throughput_0_mps = 0;
    302		dsc_sink_caps->branch_overall_throughput_1_mps = 0;
    303		dsc_sink_caps->branch_max_line_width = 0;
    304		return true;
    305	}
    306
    307	dsc_sink_caps->branch_overall_throughput_0_mps =
    308		dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
    309	if (dsc_sink_caps->branch_overall_throughput_0_mps == 0)
    310		dsc_sink_caps->branch_overall_throughput_0_mps = 0;
    311	else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1)
    312		dsc_sink_caps->branch_overall_throughput_0_mps = 680;
    313	else {
    314		dsc_sink_caps->branch_overall_throughput_0_mps *= 50;
    315		dsc_sink_caps->branch_overall_throughput_0_mps += 600;
    316	}
    317
    318	dsc_sink_caps->branch_overall_throughput_1_mps =
    319		dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
    320	if (dsc_sink_caps->branch_overall_throughput_1_mps == 0)
    321		dsc_sink_caps->branch_overall_throughput_1_mps = 0;
    322	else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1)
    323		dsc_sink_caps->branch_overall_throughput_1_mps = 680;
    324	else {
    325		dsc_sink_caps->branch_overall_throughput_1_mps *= 50;
    326		dsc_sink_caps->branch_overall_throughput_1_mps += 600;
    327	}
    328
    329	dsc_sink_caps->branch_max_line_width =
    330		dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320;
    331	ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120);
    332
    333	dsc_sink_caps->is_dp = true;
    334	return true;
    335}
    336
    337
    338/* If DSC is possbile, get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range and
    339 * timing's pixel clock and uncompressed bandwidth.
    340 * If DSC is not possible, leave '*range' untouched.
    341 */
    342bool dc_dsc_compute_bandwidth_range(
    343		const struct display_stream_compressor *dsc,
    344		uint32_t dsc_min_slice_height_override,
    345		uint32_t min_bpp_x16,
    346		uint32_t max_bpp_x16,
    347		const struct dsc_dec_dpcd_caps *dsc_sink_caps,
    348		const struct dc_crtc_timing *timing,
    349		struct dc_dsc_bw_range *range)
    350{
    351	bool is_dsc_possible = false;
    352	struct dsc_enc_caps dsc_enc_caps;
    353	struct dsc_enc_caps dsc_common_caps;
    354	struct dc_dsc_config config;
    355
    356	get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
    357
    358	is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps,
    359			timing->pixel_encoding, &dsc_common_caps);
    360
    361	if (is_dsc_possible)
    362		is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, 0, timing,
    363				dsc_min_slice_height_override, max_bpp_x16, &config);
    364
    365	if (is_dsc_possible)
    366		is_dsc_possible = decide_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16,
    367				config.num_slices_h, &dsc_common_caps, timing, range);
    368
    369	return is_dsc_possible;
    370}
    371
    372static void get_dsc_enc_caps(
    373		const struct display_stream_compressor *dsc,
    374		struct dsc_enc_caps *dsc_enc_caps,
    375		int pixel_clock_100Hz)
    376{
    377	// This is a static HW query, so we can use any DSC
    378
    379	memset(dsc_enc_caps, 0, sizeof(struct dsc_enc_caps));
    380	if (dsc) {
    381		if (!dsc->ctx->dc->debug.disable_dsc)
    382			dsc->funcs->dsc_get_enc_caps(dsc_enc_caps, pixel_clock_100Hz);
    383		if (dsc->ctx->dc->debug.native422_support)
    384			dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 1;
    385	}
    386}
    387
    388/* Returns 'false' if no intersection was found for at least one capability.
    389 * It also implicitly validates some sink caps against invalid value of zero.
    390 */
    391static bool intersect_dsc_caps(
    392		const struct dsc_dec_dpcd_caps *dsc_sink_caps,
    393		const struct dsc_enc_caps *dsc_enc_caps,
    394		enum dc_pixel_encoding pixel_encoding,
    395		struct dsc_enc_caps *dsc_common_caps)
    396{
    397	int32_t max_slices;
    398	int32_t total_sink_throughput;
    399
    400	memset(dsc_common_caps, 0, sizeof(struct dsc_enc_caps));
    401
    402	dsc_common_caps->dsc_version = min(dsc_sink_caps->dsc_version, dsc_enc_caps->dsc_version);
    403	if (!dsc_common_caps->dsc_version)
    404		return false;
    405
    406	dsc_common_caps->slice_caps.bits.NUM_SLICES_1 =
    407		dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1;
    408	dsc_common_caps->slice_caps.bits.NUM_SLICES_2 =
    409		dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2;
    410	dsc_common_caps->slice_caps.bits.NUM_SLICES_4 =
    411		dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4;
    412	dsc_common_caps->slice_caps.bits.NUM_SLICES_8 =
    413		dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8;
    414	if (!dsc_common_caps->slice_caps.raw)
    415		return false;
    416
    417	dsc_common_caps->lb_bit_depth = min(dsc_sink_caps->lb_bit_depth, dsc_enc_caps->lb_bit_depth);
    418	if (!dsc_common_caps->lb_bit_depth)
    419		return false;
    420
    421	dsc_common_caps->is_block_pred_supported =
    422		dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported;
    423
    424	dsc_common_caps->color_formats.raw = dsc_sink_caps->color_formats.raw & dsc_enc_caps->color_formats.raw;
    425	if (!dsc_common_caps->color_formats.raw)
    426		return false;
    427
    428	dsc_common_caps->color_depth.raw = dsc_sink_caps->color_depth.raw & dsc_enc_caps->color_depth.raw;
    429	if (!dsc_common_caps->color_depth.raw)
    430		return false;
    431
    432	max_slices = 0;
    433	if (dsc_common_caps->slice_caps.bits.NUM_SLICES_1)
    434		max_slices = 1;
    435
    436	if (dsc_common_caps->slice_caps.bits.NUM_SLICES_2)
    437		max_slices = 2;
    438
    439	if (dsc_common_caps->slice_caps.bits.NUM_SLICES_4)
    440		max_slices = 4;
    441
    442	total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_0_mps;
    443	if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420)
    444		total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_1_mps;
    445
    446	dsc_common_caps->max_total_throughput_mps = min(total_sink_throughput, dsc_enc_caps->max_total_throughput_mps);
    447
    448	dsc_common_caps->max_slice_width = min(dsc_sink_caps->max_slice_width, dsc_enc_caps->max_slice_width);
    449	if (!dsc_common_caps->max_slice_width)
    450		return false;
    451
    452	dsc_common_caps->bpp_increment_div = min(dsc_sink_caps->bpp_increment_div, dsc_enc_caps->bpp_increment_div);
    453
    454	// TODO DSC: Remove this workaround for N422 and 420 once it's fixed, or move it to get_dsc_encoder_caps()
    455	if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420)
    456		dsc_common_caps->bpp_increment_div = min(dsc_common_caps->bpp_increment_div, (uint32_t)8);
    457
    458	dsc_common_caps->edp_sink_max_bits_per_pixel = dsc_sink_caps->edp_max_bits_per_pixel;
    459	dsc_common_caps->is_dp = dsc_sink_caps->is_dp;
    460	return true;
    461}
    462
    463static inline uint32_t dsc_div_by_10_round_up(uint32_t value)
    464{
    465	return (value + 9) / 10;
    466}
    467
    468static uint32_t compute_bpp_x16_from_target_bandwidth(
    469	const uint32_t bandwidth_in_kbps,
    470	const struct dc_crtc_timing *timing,
    471	const uint32_t num_slices_h,
    472	const uint32_t bpp_increment_div,
    473	const bool is_dp)
    474{
    475	uint32_t overhead_in_kbps;
    476	struct fixed31_32 effective_bandwidth_in_kbps;
    477	struct fixed31_32 bpp_x16;
    478
    479	overhead_in_kbps = dc_dsc_stream_bandwidth_overhead_in_kbps(
    480				timing, num_slices_h, is_dp);
    481	effective_bandwidth_in_kbps = dc_fixpt_from_int(bandwidth_in_kbps);
    482	effective_bandwidth_in_kbps = dc_fixpt_sub_int(effective_bandwidth_in_kbps,
    483			overhead_in_kbps);
    484	bpp_x16 = dc_fixpt_mul_int(effective_bandwidth_in_kbps, 10);
    485	bpp_x16 = dc_fixpt_div_int(bpp_x16, timing->pix_clk_100hz);
    486	bpp_x16 = dc_fixpt_from_int(dc_fixpt_floor(dc_fixpt_mul_int(bpp_x16, bpp_increment_div)));
    487	bpp_x16 = dc_fixpt_div_int(bpp_x16, bpp_increment_div);
    488	bpp_x16 = dc_fixpt_mul_int(bpp_x16, 16);
    489	return dc_fixpt_floor(bpp_x16);
    490}
    491
    492/* Decide DSC bandwidth range based on signal, timing, specs specific and input min and max
    493 * requirements.
    494 * The range output includes decided min/max target bpp, the respective bandwidth requirements
    495 * and native timing bandwidth requirement when DSC is not used.
    496 */
    497static bool decide_dsc_bandwidth_range(
    498		const uint32_t min_bpp_x16,
    499		const uint32_t max_bpp_x16,
    500		const uint32_t num_slices_h,
    501		const struct dsc_enc_caps *dsc_caps,
    502		const struct dc_crtc_timing *timing,
    503		struct dc_dsc_bw_range *range)
    504{
    505	uint32_t preferred_bpp_x16 = timing->dsc_fixed_bits_per_pixel_x16;
    506
    507	memset(range, 0, sizeof(*range));
    508
    509	/* apply signal, timing, specs and explicitly specified DSC range requirements */
    510	if (preferred_bpp_x16) {
    511		if (preferred_bpp_x16 <= max_bpp_x16 &&
    512				preferred_bpp_x16 >= min_bpp_x16) {
    513			range->max_target_bpp_x16 = preferred_bpp_x16;
    514			range->min_target_bpp_x16 = preferred_bpp_x16;
    515		}
    516	}
    517	/* TODO - make this value generic to all signal types */
    518	else if (dsc_caps->edp_sink_max_bits_per_pixel) {
    519		/* apply max bpp limitation from edp sink */
    520		range->max_target_bpp_x16 = MIN(dsc_caps->edp_sink_max_bits_per_pixel,
    521				max_bpp_x16);
    522		range->min_target_bpp_x16 = min_bpp_x16;
    523	}
    524	else {
    525		range->max_target_bpp_x16 = max_bpp_x16;
    526		range->min_target_bpp_x16 = min_bpp_x16;
    527	}
    528
    529	/* populate output structure */
    530	if (range->max_target_bpp_x16 >= range->min_target_bpp_x16 && range->min_target_bpp_x16 > 0) {
    531		/* native stream bandwidth */
    532		range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing);
    533
    534		/* max dsc target bpp */
    535		range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing,
    536				range->max_target_bpp_x16, num_slices_h, dsc_caps->is_dp);
    537
    538		/* min dsc target bpp */
    539		range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing,
    540				range->min_target_bpp_x16, num_slices_h, dsc_caps->is_dp);
    541	}
    542
    543	return range->max_kbps >= range->min_kbps && range->min_kbps > 0;
    544}
    545
    546/* Decides if DSC should be used and calculates target bpp if it should, applying DSC policy.
    547 *
    548 * Returns:
    549 *     - 'true' if target bpp is decided
    550 *     - 'false' if target bpp cannot be decided (e.g. cannot fit even with min DSC bpp),
    551 */
    552static bool decide_dsc_target_bpp_x16(
    553		const struct dc_dsc_policy *policy,
    554		const struct dsc_enc_caps *dsc_common_caps,
    555		const int target_bandwidth_kbps,
    556		const struct dc_crtc_timing *timing,
    557		const int num_slices_h,
    558		int *target_bpp_x16)
    559{
    560	struct dc_dsc_bw_range range;
    561
    562	*target_bpp_x16 = 0;
    563
    564	if (decide_dsc_bandwidth_range(policy->min_target_bpp * 16, policy->max_target_bpp * 16,
    565			num_slices_h, dsc_common_caps, timing, &range)) {
    566		if (target_bandwidth_kbps >= range.stream_kbps) {
    567			if (policy->enable_dsc_when_not_needed)
    568				/* enable max bpp even dsc is not needed */
    569				*target_bpp_x16 = range.max_target_bpp_x16;
    570		} else if (target_bandwidth_kbps >= range.max_kbps) {
    571			/* use max target bpp allowed */
    572			*target_bpp_x16 = range.max_target_bpp_x16;
    573		} else if (target_bandwidth_kbps >= range.min_kbps) {
    574			/* use target bpp that can take entire target bandwidth */
    575			*target_bpp_x16 = compute_bpp_x16_from_target_bandwidth(
    576					target_bandwidth_kbps, timing, num_slices_h,
    577					dsc_common_caps->bpp_increment_div,
    578					dsc_common_caps->is_dp);
    579		}
    580	}
    581
    582	return *target_bpp_x16 != 0;
    583}
    584
    585#define MIN_AVAILABLE_SLICES_SIZE  6
    586
    587static int get_available_dsc_slices(union dsc_enc_slice_caps slice_caps, int *available_slices)
    588{
    589	int idx = 0;
    590
    591	memset(available_slices, -1, MIN_AVAILABLE_SLICES_SIZE);
    592
    593	if (slice_caps.bits.NUM_SLICES_1)
    594		available_slices[idx++] = 1;
    595
    596	if (slice_caps.bits.NUM_SLICES_2)
    597		available_slices[idx++] = 2;
    598
    599	if (slice_caps.bits.NUM_SLICES_4)
    600		available_slices[idx++] = 4;
    601
    602	if (slice_caps.bits.NUM_SLICES_8)
    603		available_slices[idx++] = 8;
    604
    605	return idx;
    606}
    607
    608
    609static int get_max_dsc_slices(union dsc_enc_slice_caps slice_caps)
    610{
    611	int max_slices = 0;
    612	int available_slices[MIN_AVAILABLE_SLICES_SIZE];
    613	int end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
    614
    615	if (end_idx > 0)
    616		max_slices = available_slices[end_idx - 1];
    617
    618	return max_slices;
    619}
    620
    621
    622// Increment sice number in available sice numbers stops if possible, or just increment if not
    623static int inc_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices)
    624{
    625	// Get next bigger num slices available in common caps
    626	int available_slices[MIN_AVAILABLE_SLICES_SIZE];
    627	int end_idx;
    628	int i;
    629	int new_num_slices = num_slices;
    630
    631	end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
    632	if (end_idx == 0) {
    633		// No available slices found
    634		new_num_slices++;
    635		return new_num_slices;
    636	}
    637
    638	// Numbers of slices found - get the next bigger number
    639	for (i = 0; i < end_idx; i++) {
    640		if (new_num_slices < available_slices[i]) {
    641			new_num_slices = available_slices[i];
    642			break;
    643		}
    644	}
    645
    646	if (new_num_slices == num_slices) // No biger number of slices found
    647		new_num_slices++;
    648
    649	return new_num_slices;
    650}
    651
    652
    653// Decrement sice number in available sice numbers stops if possible, or just decrement if not. Stop at zero.
    654static int dec_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices)
    655{
    656	// Get next bigger num slices available in common caps
    657	int available_slices[MIN_AVAILABLE_SLICES_SIZE];
    658	int end_idx;
    659	int i;
    660	int new_num_slices = num_slices;
    661
    662	end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
    663	if (end_idx == 0 && new_num_slices > 0) {
    664		// No numbers of slices found
    665		new_num_slices++;
    666		return new_num_slices;
    667	}
    668
    669	// Numbers of slices found - get the next smaller number
    670	for (i = end_idx - 1; i >= 0; i--) {
    671		if (new_num_slices > available_slices[i]) {
    672			new_num_slices = available_slices[i];
    673			break;
    674		}
    675	}
    676
    677	if (new_num_slices == num_slices) {
    678		// No smaller number of slices found
    679		new_num_slices--;
    680		if (new_num_slices < 0)
    681			new_num_slices = 0;
    682	}
    683
    684	return new_num_slices;
    685}
    686
    687
    688// Choose next bigger number of slices if the requested number of slices is not available
    689static int fit_num_slices_up(union dsc_enc_slice_caps slice_caps, int num_slices)
    690{
    691	// Get next bigger num slices available in common caps
    692	int available_slices[MIN_AVAILABLE_SLICES_SIZE];
    693	int end_idx;
    694	int i;
    695	int new_num_slices = num_slices;
    696
    697	end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
    698	if (end_idx == 0) {
    699		// No available slices found
    700		new_num_slices++;
    701		return new_num_slices;
    702	}
    703
    704	// Numbers of slices found - get the equal or next bigger number
    705	for (i = 0; i < end_idx; i++) {
    706		if (new_num_slices <= available_slices[i]) {
    707			new_num_slices = available_slices[i];
    708			break;
    709		}
    710	}
    711
    712	return new_num_slices;
    713}
    714
    715
    716/* Attempts to set DSC configuration for the stream, applying DSC policy.
    717 * Returns 'true' if successful or 'false' if not.
    718 *
    719 * Parameters:
    720 *
    721 * dsc_sink_caps       - DSC sink decoder capabilities (from DPCD)
    722 *
    723 * dsc_enc_caps        - DSC encoder capabilities
    724 *
    725 * target_bandwidth_kbps  - Target bandwidth to fit the stream into.
    726 *                          If 0, do not calculate target bpp.
    727 *
    728 * timing              - The stream timing to fit into 'target_bandwidth_kbps' or apply
    729 *                       maximum compression to, if 'target_badwidth == 0'
    730 *
    731 * dsc_cfg             - DSC configuration to use if it was possible to come up with
    732 *                       one for the given inputs.
    733 *                       The target bitrate after DSC can be calculated by multiplying
    734 *                       dsc_cfg.bits_per_pixel (in U6.4 format) by pixel rate, e.g.
    735 *
    736 *                       dsc_stream_bitrate_kbps = (int)ceil(timing->pix_clk_khz * dsc_cfg.bits_per_pixel / 16.0);
    737 */
    738static bool setup_dsc_config(
    739		const struct dsc_dec_dpcd_caps *dsc_sink_caps,
    740		const struct dsc_enc_caps *dsc_enc_caps,
    741		int target_bandwidth_kbps,
    742		const struct dc_crtc_timing *timing,
    743		int min_slice_height_override,
    744		int max_dsc_target_bpp_limit_override_x16,
    745		struct dc_dsc_config *dsc_cfg)
    746{
    747	struct dsc_enc_caps dsc_common_caps;
    748	int max_slices_h;
    749	int min_slices_h;
    750	int num_slices_h;
    751	int pic_width;
    752	int slice_width;
    753	int target_bpp;
    754	int sink_per_slice_throughput_mps;
    755	int branch_max_throughput_mps = 0;
    756	bool is_dsc_possible = false;
    757	int pic_height;
    758	int slice_height;
    759	struct dc_dsc_policy policy;
    760
    761	memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));
    762
    763	dc_dsc_get_policy_for_timing(timing, max_dsc_target_bpp_limit_override_x16, &policy);
    764	pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right;
    765	pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
    766
    767	if (!dsc_sink_caps->is_dsc_supported)
    768		goto done;
    769
    770	if (dsc_sink_caps->branch_max_line_width && dsc_sink_caps->branch_max_line_width < pic_width)
    771		goto done;
    772
    773	// Intersect decoder with encoder DSC caps and validate DSC settings
    774	is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps, timing->pixel_encoding, &dsc_common_caps);
    775	if (!is_dsc_possible)
    776		goto done;
    777
    778	sink_per_slice_throughput_mps = 0;
    779
    780	// Validate available DSC settings against the mode timing
    781
    782	// Validate color format (and pick up the throughput values)
    783	dsc_cfg->ycbcr422_simple = false;
    784	switch (timing->pixel_encoding)	{
    785	case PIXEL_ENCODING_RGB:
    786		is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.RGB;
    787		sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps;
    788		branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps;
    789		break;
    790	case PIXEL_ENCODING_YCBCR444:
    791		is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_444;
    792		sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps;
    793		branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps;
    794		break;
    795	case PIXEL_ENCODING_YCBCR422:
    796		is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_422;
    797		sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps;
    798		branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps;
    799		if (!is_dsc_possible) {
    800			is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_SIMPLE_422;
    801			dsc_cfg->ycbcr422_simple = is_dsc_possible;
    802			sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps;
    803		}
    804		break;
    805	case PIXEL_ENCODING_YCBCR420:
    806		is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_420;
    807		sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps;
    808		branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps;
    809		break;
    810	default:
    811		is_dsc_possible = false;
    812	}
    813
    814	// Validate branch's maximum throughput
    815	if (branch_max_throughput_mps && dsc_div_by_10_round_up(timing->pix_clk_100hz) > branch_max_throughput_mps * 1000)
    816		is_dsc_possible = false;
    817
    818	if (!is_dsc_possible)
    819		goto done;
    820
    821	// Color depth
    822	switch (timing->display_color_depth) {
    823	case COLOR_DEPTH_888:
    824		is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_8_BPC;
    825		break;
    826	case COLOR_DEPTH_101010:
    827		is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_10_BPC;
    828		break;
    829	case COLOR_DEPTH_121212:
    830		is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_12_BPC;
    831		break;
    832	default:
    833		is_dsc_possible = false;
    834	}
    835
    836	if (!is_dsc_possible)
    837		goto done;
    838
    839	// Slice width (i.e. number of slices per line)
    840	max_slices_h = get_max_dsc_slices(dsc_common_caps.slice_caps);
    841
    842	while (max_slices_h > 0) {
    843		if (pic_width % max_slices_h == 0)
    844			break;
    845
    846		max_slices_h = dec_num_slices(dsc_common_caps.slice_caps, max_slices_h);
    847	}
    848
    849	is_dsc_possible = (dsc_common_caps.max_slice_width > 0);
    850	if (!is_dsc_possible)
    851		goto done;
    852
    853	min_slices_h = pic_width / dsc_common_caps.max_slice_width;
    854	if (pic_width % dsc_common_caps.max_slice_width)
    855		min_slices_h++;
    856
    857	min_slices_h = fit_num_slices_up(dsc_common_caps.slice_caps, min_slices_h);
    858
    859	while (min_slices_h <= max_slices_h) {
    860		int pix_clk_per_slice_khz = dsc_div_by_10_round_up(timing->pix_clk_100hz) / min_slices_h;
    861		if (pix_clk_per_slice_khz <= sink_per_slice_throughput_mps * 1000)
    862			break;
    863
    864		min_slices_h = inc_num_slices(dsc_common_caps.slice_caps, min_slices_h);
    865	}
    866
    867	is_dsc_possible = (min_slices_h <= max_slices_h);
    868
    869	if (pic_width % min_slices_h != 0)
    870		min_slices_h = 0; // DSC TODO: Maybe try increasing the number of slices first?
    871
    872	if (min_slices_h == 0 && max_slices_h == 0)
    873		is_dsc_possible = false;
    874
    875	if (!is_dsc_possible)
    876		goto done;
    877
    878	if (policy.use_min_slices_h) {
    879		if (min_slices_h > 0)
    880			num_slices_h = min_slices_h;
    881		else if (max_slices_h > 0) { // Fall back to max slices if min slices is not working out
    882			if (policy.max_slices_h)
    883				num_slices_h = min(policy.max_slices_h, max_slices_h);
    884			else
    885				num_slices_h = max_slices_h;
    886		} else
    887			is_dsc_possible = false;
    888	} else {
    889		if (max_slices_h > 0) {
    890			if (policy.max_slices_h)
    891				num_slices_h = min(policy.max_slices_h, max_slices_h);
    892			else
    893				num_slices_h = max_slices_h;
    894		} else if (min_slices_h > 0) // Fall back to min slices if max slices is not possible
    895			num_slices_h = min_slices_h;
    896		else
    897			is_dsc_possible = false;
    898	}
    899
    900	if (!is_dsc_possible)
    901		goto done;
    902
    903	dsc_cfg->num_slices_h = num_slices_h;
    904	slice_width = pic_width / num_slices_h;
    905
    906	is_dsc_possible = slice_width <= dsc_common_caps.max_slice_width;
    907	if (!is_dsc_possible)
    908		goto done;
    909
    910	// Slice height (i.e. number of slices per column): start with policy and pick the first one that height is divisible by.
    911	// For 4:2:0 make sure the slice height is divisible by 2 as well.
    912	if (min_slice_height_override == 0)
    913		slice_height = min(policy.min_slice_height, pic_height);
    914	else
    915		slice_height = min(min_slice_height_override, pic_height);
    916
    917	while (slice_height < pic_height && (pic_height % slice_height != 0 ||
    918		(timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && slice_height % 2 != 0)))
    919		slice_height++;
    920
    921	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) // For the case when pic_height < dsc_policy.min_sice_height
    922		is_dsc_possible = (slice_height % 2 == 0);
    923
    924	if (!is_dsc_possible)
    925		goto done;
    926
    927	dsc_cfg->num_slices_v = pic_height/slice_height;
    928
    929	if (target_bandwidth_kbps > 0) {
    930		is_dsc_possible = decide_dsc_target_bpp_x16(
    931				&policy,
    932				&dsc_common_caps,
    933				target_bandwidth_kbps,
    934				timing,
    935				num_slices_h,
    936				&target_bpp);
    937		dsc_cfg->bits_per_pixel = target_bpp;
    938	}
    939	if (!is_dsc_possible)
    940		goto done;
    941
    942	// Final decission: can we do DSC or not?
    943	if (is_dsc_possible) {
    944		// Fill out the rest of DSC settings
    945		dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported;
    946		dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth;
    947		dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4;
    948		dsc_cfg->is_dp = dsc_sink_caps->is_dp;
    949	}
    950
    951done:
    952	if (!is_dsc_possible)
    953		memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));
    954
    955	return is_dsc_possible;
    956}
    957
    958bool dc_dsc_compute_config(
    959		const struct display_stream_compressor *dsc,
    960		const struct dsc_dec_dpcd_caps *dsc_sink_caps,
    961		uint32_t dsc_min_slice_height_override,
    962		uint32_t max_target_bpp_limit_override,
    963		uint32_t target_bandwidth_kbps,
    964		const struct dc_crtc_timing *timing,
    965		struct dc_dsc_config *dsc_cfg)
    966{
    967	bool is_dsc_possible = false;
    968	struct dsc_enc_caps dsc_enc_caps;
    969
    970	get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
    971	is_dsc_possible = setup_dsc_config(dsc_sink_caps,
    972		&dsc_enc_caps,
    973		target_bandwidth_kbps,
    974		timing, dsc_min_slice_height_override,
    975		max_target_bpp_limit_override * 16, dsc_cfg);
    976	return is_dsc_possible;
    977}
    978
    979uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing,
    980	uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp)
    981{
    982	uint32_t overhead_in_kbps;
    983	struct fixed31_32 bpp;
    984	struct fixed31_32 actual_bandwidth_in_kbps;
    985
    986	overhead_in_kbps = dc_dsc_stream_bandwidth_overhead_in_kbps(
    987		timing, num_slices_h, is_dp);
    988	bpp = dc_fixpt_from_fraction(bpp_x16, 16);
    989	actual_bandwidth_in_kbps = dc_fixpt_from_fraction(timing->pix_clk_100hz, 10);
    990	actual_bandwidth_in_kbps = dc_fixpt_mul(actual_bandwidth_in_kbps, bpp);
    991	actual_bandwidth_in_kbps = dc_fixpt_add_int(actual_bandwidth_in_kbps, overhead_in_kbps);
    992	return dc_fixpt_ceil(actual_bandwidth_in_kbps);
    993}
    994
    995uint32_t dc_dsc_stream_bandwidth_overhead_in_kbps(
    996		const struct dc_crtc_timing *timing,
    997		const int num_slices_h,
    998		const bool is_dp)
    999{
   1000	struct fixed31_32 max_dsc_overhead;
   1001	struct fixed31_32 refresh_rate;
   1002
   1003	if (dsc_policy_disable_dsc_stream_overhead || !is_dp)
   1004		return 0;
   1005
   1006	/* use target bpp that can take entire target bandwidth */
   1007	refresh_rate = dc_fixpt_from_int(timing->pix_clk_100hz);
   1008	refresh_rate = dc_fixpt_div_int(refresh_rate, timing->h_total);
   1009	refresh_rate = dc_fixpt_div_int(refresh_rate, timing->v_total);
   1010	refresh_rate = dc_fixpt_mul_int(refresh_rate, 100);
   1011
   1012	max_dsc_overhead = dc_fixpt_from_int(num_slices_h);
   1013	max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, timing->v_total);
   1014	max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, 256);
   1015	max_dsc_overhead = dc_fixpt_div_int(max_dsc_overhead, 1000);
   1016	max_dsc_overhead = dc_fixpt_mul(max_dsc_overhead, refresh_rate);
   1017
   1018	return dc_fixpt_ceil(max_dsc_overhead);
   1019}
   1020
   1021void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing,
   1022		uint32_t max_target_bpp_limit_override_x16,
   1023		struct dc_dsc_policy *policy)
   1024{
   1025	uint32_t bpc = 0;
   1026
   1027	policy->min_target_bpp = 0;
   1028	policy->max_target_bpp = 0;
   1029
   1030	/* DSC Policy: Use minimum number of slices that fits the pixel clock */
   1031	policy->use_min_slices_h = true;
   1032
   1033	/* DSC Policy: Use max available slices
   1034	 * (in our case 4 for or 8, depending on the mode)
   1035	 */
   1036	policy->max_slices_h = 0;
   1037
   1038	/* DSC Policy: Use slice height recommended
   1039	 * by VESA DSC Spreadsheet user guide
   1040	 */
   1041	policy->min_slice_height = 108;
   1042
   1043	/* DSC Policy: follow DP specs with an internal upper limit to 16 bpp
   1044	 * for better interoperability
   1045	 */
   1046	switch (timing->display_color_depth) {
   1047	case COLOR_DEPTH_888:
   1048		bpc = 8;
   1049		break;
   1050	case COLOR_DEPTH_101010:
   1051		bpc = 10;
   1052		break;
   1053	case COLOR_DEPTH_121212:
   1054		bpc = 12;
   1055		break;
   1056	default:
   1057		return;
   1058	}
   1059	switch (timing->pixel_encoding) {
   1060	case PIXEL_ENCODING_RGB:
   1061	case PIXEL_ENCODING_YCBCR444:
   1062	case PIXEL_ENCODING_YCBCR422: /* assume no YCbCr422 native support */
   1063		/* DP specs limits to 8 */
   1064		policy->min_target_bpp = 8;
   1065		/* DP specs limits to 3 x bpc */
   1066		policy->max_target_bpp = 3 * bpc;
   1067		break;
   1068	case PIXEL_ENCODING_YCBCR420:
   1069		/* DP specs limits to 6 */
   1070		policy->min_target_bpp = 6;
   1071		/* DP specs limits to 1.5 x bpc assume bpc is an even number */
   1072		policy->max_target_bpp = bpc * 3 / 2;
   1073		break;
   1074	default:
   1075		return;
   1076	}
   1077
   1078	/* internal upper limit, default 16 bpp */
   1079	if (policy->max_target_bpp > dsc_policy_max_target_bpp_limit)
   1080		policy->max_target_bpp = dsc_policy_max_target_bpp_limit;
   1081
   1082	/* apply override */
   1083	if (max_target_bpp_limit_override_x16 && policy->max_target_bpp > max_target_bpp_limit_override_x16 / 16)
   1084		policy->max_target_bpp = max_target_bpp_limit_override_x16 / 16;
   1085
   1086	/* enable DSC when not needed, default false */
   1087	if (dsc_policy_enable_dsc_when_not_needed)
   1088		policy->enable_dsc_when_not_needed = dsc_policy_enable_dsc_when_not_needed;
   1089	else
   1090		policy->enable_dsc_when_not_needed = false;
   1091}
   1092
   1093void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit)
   1094{
   1095	dsc_policy_max_target_bpp_limit = limit;
   1096}
   1097
   1098void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable)
   1099{
   1100	dsc_policy_enable_dsc_when_not_needed = enable;
   1101}
   1102
   1103void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable)
   1104{
   1105	dsc_policy_disable_dsc_stream_overhead = disable;
   1106}