Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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