1 1.3 riastrad /* $NetBSD: drm_dsc.c,v 1.3 2021/12/19 09:45:49 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad // SPDX-License-Identifier: MIT 4 1.1 riastrad /* 5 1.1 riastrad * Copyright 2018 Intel Corp 6 1.1 riastrad * 7 1.1 riastrad * Author: 8 1.1 riastrad * Manasi Navare <manasi.d.navare (at) intel.com> 9 1.1 riastrad */ 10 1.1 riastrad 11 1.1 riastrad #include <sys/cdefs.h> 12 1.3 riastrad __KERNEL_RCSID(0, "$NetBSD: drm_dsc.c,v 1.3 2021/12/19 09:45:49 riastradh Exp $"); 13 1.1 riastrad 14 1.3 riastrad #include <linux/bug.h> 15 1.1 riastrad #include <linux/kernel.h> 16 1.1 riastrad #include <linux/module.h> 17 1.1 riastrad #include <linux/init.h> 18 1.1 riastrad #include <linux/errno.h> 19 1.1 riastrad #include <linux/byteorder/generic.h> 20 1.1 riastrad #include <drm/drm_print.h> 21 1.1 riastrad #include <drm/drm_dp_helper.h> 22 1.1 riastrad #include <drm/drm_dsc.h> 23 1.1 riastrad 24 1.1 riastrad /** 25 1.1 riastrad * DOC: dsc helpers 26 1.1 riastrad * 27 1.1 riastrad * VESA specification for DP 1.4 adds a new feature called Display Stream 28 1.1 riastrad * Compression (DSC) used to compress the pixel bits before sending it on 29 1.1 riastrad * DP/eDP/MIPI DSI interface. DSC is required to be enabled so that the existing 30 1.1 riastrad * display interfaces can support high resolutions at higher frames rates uisng 31 1.1 riastrad * the maximum available link capacity of these interfaces. 32 1.1 riastrad * 33 1.1 riastrad * These functions contain some common logic and helpers to deal with VESA 34 1.1 riastrad * Display Stream Compression standard required for DSC on Display Port/eDP or 35 1.1 riastrad * MIPI display interfaces. 36 1.1 riastrad */ 37 1.1 riastrad 38 1.1 riastrad /** 39 1.1 riastrad * drm_dsc_dp_pps_header_init() - Initializes the PPS Header 40 1.1 riastrad * for DisplayPort as per the DP 1.4 spec. 41 1.1 riastrad * @pps_header: Secondary data packet header for DSC Picture 42 1.1 riastrad * Parameter Set as defined in &struct dp_sdp_header 43 1.1 riastrad * 44 1.1 riastrad * DP 1.4 spec defines the secondary data packet for sending the 45 1.1 riastrad * picture parameter infoframes from the source to the sink. 46 1.1 riastrad * This function populates the SDP header defined in 47 1.1 riastrad * &struct dp_sdp_header. 48 1.1 riastrad */ 49 1.1 riastrad void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header) 50 1.1 riastrad { 51 1.1 riastrad memset(pps_header, 0, sizeof(*pps_header)); 52 1.1 riastrad 53 1.1 riastrad pps_header->HB1 = DP_SDP_PPS; 54 1.1 riastrad pps_header->HB2 = DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1; 55 1.1 riastrad } 56 1.1 riastrad EXPORT_SYMBOL(drm_dsc_dp_pps_header_init); 57 1.1 riastrad 58 1.1 riastrad /** 59 1.1 riastrad * drm_dsc_pps_payload_pack() - Populates the DSC PPS 60 1.1 riastrad * 61 1.1 riastrad * @pps_payload: 62 1.1 riastrad * Bitwise struct for DSC Picture Parameter Set. This is defined 63 1.1 riastrad * by &struct drm_dsc_picture_parameter_set 64 1.1 riastrad * @dsc_cfg: 65 1.1 riastrad * DSC Configuration data filled by driver as defined by 66 1.1 riastrad * &struct drm_dsc_config 67 1.1 riastrad * 68 1.1 riastrad * DSC source device sends a picture parameter set (PPS) containing the 69 1.1 riastrad * information required by the sink to decode the compressed frame. Driver 70 1.1 riastrad * populates the DSC PPS struct using the DSC configuration parameters in 71 1.1 riastrad * the order expected by the DSC Display Sink device. For the DSC, the sink 72 1.1 riastrad * device expects the PPS payload in big endian format for fields 73 1.1 riastrad * that span more than 1 byte. 74 1.1 riastrad */ 75 1.1 riastrad void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_payload, 76 1.1 riastrad const struct drm_dsc_config *dsc_cfg) 77 1.1 riastrad { 78 1.1 riastrad int i; 79 1.1 riastrad 80 1.1 riastrad /* Protect against someone accidently changing struct size */ 81 1.1 riastrad BUILD_BUG_ON(sizeof(*pps_payload) != 82 1.1 riastrad DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1 + 1); 83 1.1 riastrad 84 1.1 riastrad memset(pps_payload, 0, sizeof(*pps_payload)); 85 1.1 riastrad 86 1.1 riastrad /* PPS 0 */ 87 1.1 riastrad pps_payload->dsc_version = 88 1.1 riastrad dsc_cfg->dsc_version_minor | 89 1.1 riastrad dsc_cfg->dsc_version_major << DSC_PPS_VERSION_MAJOR_SHIFT; 90 1.1 riastrad 91 1.1 riastrad /* PPS 1, 2 is 0 */ 92 1.1 riastrad 93 1.1 riastrad /* PPS 3 */ 94 1.1 riastrad pps_payload->pps_3 = 95 1.1 riastrad dsc_cfg->line_buf_depth | 96 1.1 riastrad dsc_cfg->bits_per_component << DSC_PPS_BPC_SHIFT; 97 1.1 riastrad 98 1.1 riastrad /* PPS 4 */ 99 1.1 riastrad pps_payload->pps_4 = 100 1.1 riastrad ((dsc_cfg->bits_per_pixel & DSC_PPS_BPP_HIGH_MASK) >> 101 1.1 riastrad DSC_PPS_MSB_SHIFT) | 102 1.1 riastrad dsc_cfg->vbr_enable << DSC_PPS_VBR_EN_SHIFT | 103 1.1 riastrad dsc_cfg->simple_422 << DSC_PPS_SIMPLE422_SHIFT | 104 1.1 riastrad dsc_cfg->convert_rgb << DSC_PPS_CONVERT_RGB_SHIFT | 105 1.1 riastrad dsc_cfg->block_pred_enable << DSC_PPS_BLOCK_PRED_EN_SHIFT; 106 1.1 riastrad 107 1.1 riastrad /* PPS 5 */ 108 1.1 riastrad pps_payload->bits_per_pixel_low = 109 1.1 riastrad (dsc_cfg->bits_per_pixel & DSC_PPS_LSB_MASK); 110 1.1 riastrad 111 1.1 riastrad /* 112 1.1 riastrad * The DSC panel expects the PPS packet to have big endian format 113 1.1 riastrad * for data spanning 2 bytes. Use a macro cpu_to_be16() to convert 114 1.1 riastrad * to big endian format. If format is little endian, it will swap 115 1.1 riastrad * bytes to convert to Big endian else keep it unchanged. 116 1.1 riastrad */ 117 1.1 riastrad 118 1.1 riastrad /* PPS 6, 7 */ 119 1.1 riastrad pps_payload->pic_height = cpu_to_be16(dsc_cfg->pic_height); 120 1.1 riastrad 121 1.1 riastrad /* PPS 8, 9 */ 122 1.1 riastrad pps_payload->pic_width = cpu_to_be16(dsc_cfg->pic_width); 123 1.1 riastrad 124 1.1 riastrad /* PPS 10, 11 */ 125 1.1 riastrad pps_payload->slice_height = cpu_to_be16(dsc_cfg->slice_height); 126 1.1 riastrad 127 1.1 riastrad /* PPS 12, 13 */ 128 1.1 riastrad pps_payload->slice_width = cpu_to_be16(dsc_cfg->slice_width); 129 1.1 riastrad 130 1.1 riastrad /* PPS 14, 15 */ 131 1.1 riastrad pps_payload->chunk_size = cpu_to_be16(dsc_cfg->slice_chunk_size); 132 1.1 riastrad 133 1.1 riastrad /* PPS 16 */ 134 1.1 riastrad pps_payload->initial_xmit_delay_high = 135 1.1 riastrad ((dsc_cfg->initial_xmit_delay & 136 1.1 riastrad DSC_PPS_INIT_XMIT_DELAY_HIGH_MASK) >> 137 1.1 riastrad DSC_PPS_MSB_SHIFT); 138 1.1 riastrad 139 1.1 riastrad /* PPS 17 */ 140 1.1 riastrad pps_payload->initial_xmit_delay_low = 141 1.1 riastrad (dsc_cfg->initial_xmit_delay & DSC_PPS_LSB_MASK); 142 1.1 riastrad 143 1.1 riastrad /* PPS 18, 19 */ 144 1.1 riastrad pps_payload->initial_dec_delay = 145 1.1 riastrad cpu_to_be16(dsc_cfg->initial_dec_delay); 146 1.1 riastrad 147 1.1 riastrad /* PPS 20 is 0 */ 148 1.1 riastrad 149 1.1 riastrad /* PPS 21 */ 150 1.1 riastrad pps_payload->initial_scale_value = 151 1.1 riastrad dsc_cfg->initial_scale_value; 152 1.1 riastrad 153 1.1 riastrad /* PPS 22, 23 */ 154 1.1 riastrad pps_payload->scale_increment_interval = 155 1.1 riastrad cpu_to_be16(dsc_cfg->scale_increment_interval); 156 1.1 riastrad 157 1.1 riastrad /* PPS 24 */ 158 1.1 riastrad pps_payload->scale_decrement_interval_high = 159 1.1 riastrad ((dsc_cfg->scale_decrement_interval & 160 1.1 riastrad DSC_PPS_SCALE_DEC_INT_HIGH_MASK) >> 161 1.1 riastrad DSC_PPS_MSB_SHIFT); 162 1.1 riastrad 163 1.1 riastrad /* PPS 25 */ 164 1.1 riastrad pps_payload->scale_decrement_interval_low = 165 1.1 riastrad (dsc_cfg->scale_decrement_interval & DSC_PPS_LSB_MASK); 166 1.1 riastrad 167 1.1 riastrad /* PPS 26[7:0], PPS 27[7:5] RESERVED */ 168 1.1 riastrad 169 1.1 riastrad /* PPS 27 */ 170 1.1 riastrad pps_payload->first_line_bpg_offset = 171 1.1 riastrad dsc_cfg->first_line_bpg_offset; 172 1.1 riastrad 173 1.1 riastrad /* PPS 28, 29 */ 174 1.1 riastrad pps_payload->nfl_bpg_offset = 175 1.1 riastrad cpu_to_be16(dsc_cfg->nfl_bpg_offset); 176 1.1 riastrad 177 1.1 riastrad /* PPS 30, 31 */ 178 1.1 riastrad pps_payload->slice_bpg_offset = 179 1.1 riastrad cpu_to_be16(dsc_cfg->slice_bpg_offset); 180 1.1 riastrad 181 1.1 riastrad /* PPS 32, 33 */ 182 1.1 riastrad pps_payload->initial_offset = 183 1.1 riastrad cpu_to_be16(dsc_cfg->initial_offset); 184 1.1 riastrad 185 1.1 riastrad /* PPS 34, 35 */ 186 1.1 riastrad pps_payload->final_offset = cpu_to_be16(dsc_cfg->final_offset); 187 1.1 riastrad 188 1.1 riastrad /* PPS 36 */ 189 1.1 riastrad pps_payload->flatness_min_qp = dsc_cfg->flatness_min_qp; 190 1.1 riastrad 191 1.1 riastrad /* PPS 37 */ 192 1.1 riastrad pps_payload->flatness_max_qp = dsc_cfg->flatness_max_qp; 193 1.1 riastrad 194 1.1 riastrad /* PPS 38, 39 */ 195 1.1 riastrad pps_payload->rc_model_size = 196 1.1 riastrad cpu_to_be16(DSC_RC_MODEL_SIZE_CONST); 197 1.1 riastrad 198 1.1 riastrad /* PPS 40 */ 199 1.1 riastrad pps_payload->rc_edge_factor = DSC_RC_EDGE_FACTOR_CONST; 200 1.1 riastrad 201 1.1 riastrad /* PPS 41 */ 202 1.1 riastrad pps_payload->rc_quant_incr_limit0 = 203 1.1 riastrad dsc_cfg->rc_quant_incr_limit0; 204 1.1 riastrad 205 1.1 riastrad /* PPS 42 */ 206 1.1 riastrad pps_payload->rc_quant_incr_limit1 = 207 1.1 riastrad dsc_cfg->rc_quant_incr_limit1; 208 1.1 riastrad 209 1.1 riastrad /* PPS 43 */ 210 1.1 riastrad pps_payload->rc_tgt_offset = DSC_RC_TGT_OFFSET_LO_CONST | 211 1.1 riastrad DSC_RC_TGT_OFFSET_HI_CONST << DSC_PPS_RC_TGT_OFFSET_HI_SHIFT; 212 1.1 riastrad 213 1.1 riastrad /* PPS 44 - 57 */ 214 1.1 riastrad for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++) 215 1.1 riastrad pps_payload->rc_buf_thresh[i] = 216 1.1 riastrad dsc_cfg->rc_buf_thresh[i]; 217 1.1 riastrad 218 1.1 riastrad /* PPS 58 - 87 */ 219 1.1 riastrad /* 220 1.1 riastrad * For DSC sink programming the RC Range parameter fields 221 1.1 riastrad * are as follows: Min_qp[15:11], max_qp[10:6], offset[5:0] 222 1.1 riastrad */ 223 1.1 riastrad for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { 224 1.1 riastrad pps_payload->rc_range_parameters[i] = 225 1.1 riastrad cpu_to_be16((dsc_cfg->rc_range_params[i].range_min_qp << 226 1.1 riastrad DSC_PPS_RC_RANGE_MINQP_SHIFT) | 227 1.1 riastrad (dsc_cfg->rc_range_params[i].range_max_qp << 228 1.1 riastrad DSC_PPS_RC_RANGE_MAXQP_SHIFT) | 229 1.1 riastrad (dsc_cfg->rc_range_params[i].range_bpg_offset)); 230 1.1 riastrad } 231 1.1 riastrad 232 1.1 riastrad /* PPS 88 */ 233 1.1 riastrad pps_payload->native_422_420 = dsc_cfg->native_422 | 234 1.1 riastrad dsc_cfg->native_420 << DSC_PPS_NATIVE_420_SHIFT; 235 1.1 riastrad 236 1.1 riastrad /* PPS 89 */ 237 1.1 riastrad pps_payload->second_line_bpg_offset = 238 1.1 riastrad dsc_cfg->second_line_bpg_offset; 239 1.1 riastrad 240 1.1 riastrad /* PPS 90, 91 */ 241 1.1 riastrad pps_payload->nsl_bpg_offset = 242 1.1 riastrad cpu_to_be16(dsc_cfg->nsl_bpg_offset); 243 1.1 riastrad 244 1.1 riastrad /* PPS 92, 93 */ 245 1.1 riastrad pps_payload->second_line_offset_adj = 246 1.1 riastrad cpu_to_be16(dsc_cfg->second_line_offset_adj); 247 1.1 riastrad 248 1.1 riastrad /* PPS 94 - 127 are O */ 249 1.1 riastrad } 250 1.1 riastrad EXPORT_SYMBOL(drm_dsc_pps_payload_pack); 251 1.1 riastrad 252 1.1 riastrad /** 253 1.1 riastrad * drm_dsc_compute_rc_parameters() - Write rate control 254 1.1 riastrad * parameters to the dsc configuration defined in 255 1.1 riastrad * &struct drm_dsc_config in accordance with the DSC 1.2 256 1.1 riastrad * specification. Some configuration fields must be present 257 1.1 riastrad * beforehand. 258 1.1 riastrad * 259 1.1 riastrad * @vdsc_cfg: 260 1.1 riastrad * DSC Configuration data partially filled by driver 261 1.1 riastrad */ 262 1.1 riastrad int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg) 263 1.1 riastrad { 264 1.1 riastrad unsigned long groups_per_line = 0; 265 1.1 riastrad unsigned long groups_total = 0; 266 1.1 riastrad unsigned long num_extra_mux_bits = 0; 267 1.1 riastrad unsigned long slice_bits = 0; 268 1.1 riastrad unsigned long hrd_delay = 0; 269 1.1 riastrad unsigned long final_scale = 0; 270 1.1 riastrad unsigned long rbs_min = 0; 271 1.1 riastrad 272 1.1 riastrad if (vdsc_cfg->native_420 || vdsc_cfg->native_422) { 273 1.1 riastrad /* Number of groups used to code each line of a slice */ 274 1.1 riastrad groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width / 2, 275 1.1 riastrad DSC_RC_PIXELS_PER_GROUP); 276 1.1 riastrad 277 1.1 riastrad /* chunksize in Bytes */ 278 1.1 riastrad vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width / 2 * 279 1.1 riastrad vdsc_cfg->bits_per_pixel, 280 1.1 riastrad (8 * 16)); 281 1.1 riastrad } else { 282 1.1 riastrad /* Number of groups used to code each line of a slice */ 283 1.1 riastrad groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width, 284 1.1 riastrad DSC_RC_PIXELS_PER_GROUP); 285 1.1 riastrad 286 1.1 riastrad /* chunksize in Bytes */ 287 1.1 riastrad vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width * 288 1.1 riastrad vdsc_cfg->bits_per_pixel, 289 1.1 riastrad (8 * 16)); 290 1.1 riastrad } 291 1.1 riastrad 292 1.1 riastrad if (vdsc_cfg->convert_rgb) 293 1.1 riastrad num_extra_mux_bits = 3 * (vdsc_cfg->mux_word_size + 294 1.1 riastrad (4 * vdsc_cfg->bits_per_component + 4) 295 1.1 riastrad - 2); 296 1.1 riastrad else if (vdsc_cfg->native_422) 297 1.1 riastrad num_extra_mux_bits = 4 * vdsc_cfg->mux_word_size + 298 1.1 riastrad (4 * vdsc_cfg->bits_per_component + 4) + 299 1.1 riastrad 3 * (4 * vdsc_cfg->bits_per_component) - 2; 300 1.1 riastrad else 301 1.1 riastrad num_extra_mux_bits = 3 * vdsc_cfg->mux_word_size + 302 1.1 riastrad (4 * vdsc_cfg->bits_per_component + 4) + 303 1.1 riastrad 2 * (4 * vdsc_cfg->bits_per_component) - 2; 304 1.1 riastrad /* Number of bits in one Slice */ 305 1.1 riastrad slice_bits = 8 * vdsc_cfg->slice_chunk_size * vdsc_cfg->slice_height; 306 1.1 riastrad 307 1.1 riastrad while ((num_extra_mux_bits > 0) && 308 1.1 riastrad ((slice_bits - num_extra_mux_bits) % vdsc_cfg->mux_word_size)) 309 1.1 riastrad num_extra_mux_bits--; 310 1.1 riastrad 311 1.1 riastrad if (groups_per_line < vdsc_cfg->initial_scale_value - 8) 312 1.1 riastrad vdsc_cfg->initial_scale_value = groups_per_line + 8; 313 1.1 riastrad 314 1.1 riastrad /* scale_decrement_interval calculation according to DSC spec 1.11 */ 315 1.1 riastrad if (vdsc_cfg->initial_scale_value > 8) 316 1.1 riastrad vdsc_cfg->scale_decrement_interval = groups_per_line / 317 1.1 riastrad (vdsc_cfg->initial_scale_value - 8); 318 1.1 riastrad else 319 1.1 riastrad vdsc_cfg->scale_decrement_interval = DSC_SCALE_DECREMENT_INTERVAL_MAX; 320 1.1 riastrad 321 1.1 riastrad vdsc_cfg->final_offset = vdsc_cfg->rc_model_size - 322 1.1 riastrad (vdsc_cfg->initial_xmit_delay * 323 1.1 riastrad vdsc_cfg->bits_per_pixel + 8) / 16 + num_extra_mux_bits; 324 1.1 riastrad 325 1.1 riastrad if (vdsc_cfg->final_offset >= vdsc_cfg->rc_model_size) { 326 1.1 riastrad DRM_DEBUG_KMS("FinalOfs < RcModelSze for this InitialXmitDelay\n"); 327 1.1 riastrad return -ERANGE; 328 1.1 riastrad } 329 1.1 riastrad 330 1.1 riastrad final_scale = (vdsc_cfg->rc_model_size * 8) / 331 1.1 riastrad (vdsc_cfg->rc_model_size - vdsc_cfg->final_offset); 332 1.1 riastrad if (vdsc_cfg->slice_height > 1) 333 1.1 riastrad /* 334 1.1 riastrad * NflBpgOffset is 16 bit value with 11 fractional bits 335 1.1 riastrad * hence we multiply by 2^11 for preserving the 336 1.1 riastrad * fractional part 337 1.1 riastrad */ 338 1.1 riastrad vdsc_cfg->nfl_bpg_offset = DIV_ROUND_UP((vdsc_cfg->first_line_bpg_offset << 11), 339 1.1 riastrad (vdsc_cfg->slice_height - 1)); 340 1.1 riastrad else 341 1.1 riastrad vdsc_cfg->nfl_bpg_offset = 0; 342 1.1 riastrad 343 1.1 riastrad /* Number of groups used to code the entire slice */ 344 1.1 riastrad groups_total = groups_per_line * vdsc_cfg->slice_height; 345 1.1 riastrad 346 1.1 riastrad /* slice_bpg_offset is 16 bit value with 11 fractional bits */ 347 1.1 riastrad vdsc_cfg->slice_bpg_offset = DIV_ROUND_UP(((vdsc_cfg->rc_model_size - 348 1.1 riastrad vdsc_cfg->initial_offset + 349 1.1 riastrad num_extra_mux_bits) << 11), 350 1.1 riastrad groups_total); 351 1.1 riastrad 352 1.1 riastrad if (final_scale > 9) { 353 1.1 riastrad /* 354 1.1 riastrad * ScaleIncrementInterval = 355 1.1 riastrad * finaloffset/((NflBpgOffset + SliceBpgOffset)*8(finalscale - 1.125)) 356 1.1 riastrad * as (NflBpgOffset + SliceBpgOffset) has 11 bit fractional value, 357 1.1 riastrad * we need divide by 2^11 from pstDscCfg values 358 1.1 riastrad */ 359 1.1 riastrad vdsc_cfg->scale_increment_interval = 360 1.1 riastrad (vdsc_cfg->final_offset * (1 << 11)) / 361 1.1 riastrad ((vdsc_cfg->nfl_bpg_offset + 362 1.1 riastrad vdsc_cfg->slice_bpg_offset) * 363 1.1 riastrad (final_scale - 9)); 364 1.1 riastrad } else { 365 1.1 riastrad /* 366 1.1 riastrad * If finalScaleValue is less than or equal to 9, a value of 0 should 367 1.1 riastrad * be used to disable the scale increment at the end of the slice 368 1.1 riastrad */ 369 1.1 riastrad vdsc_cfg->scale_increment_interval = 0; 370 1.1 riastrad } 371 1.1 riastrad 372 1.1 riastrad /* 373 1.1 riastrad * DSC spec mentions that bits_per_pixel specifies the target 374 1.1 riastrad * bits/pixel (bpp) rate that is used by the encoder, 375 1.1 riastrad * in steps of 1/16 of a bit per pixel 376 1.1 riastrad */ 377 1.1 riastrad rbs_min = vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset + 378 1.1 riastrad DIV_ROUND_UP(vdsc_cfg->initial_xmit_delay * 379 1.1 riastrad vdsc_cfg->bits_per_pixel, 16) + 380 1.1 riastrad groups_per_line * vdsc_cfg->first_line_bpg_offset; 381 1.1 riastrad 382 1.1 riastrad hrd_delay = DIV_ROUND_UP((rbs_min * 16), vdsc_cfg->bits_per_pixel); 383 1.1 riastrad vdsc_cfg->rc_bits = (hrd_delay * vdsc_cfg->bits_per_pixel) / 16; 384 1.1 riastrad vdsc_cfg->initial_dec_delay = hrd_delay - vdsc_cfg->initial_xmit_delay; 385 1.1 riastrad 386 1.1 riastrad return 0; 387 1.1 riastrad } 388 1.1 riastrad EXPORT_SYMBOL(drm_dsc_compute_rc_parameters); 389