diff options
| author | David Francis <David.Francis@amd.com> | 2019-02-21 15:19:59 -0500 |
|---|---|---|
| committer | Harry Wentland <harry.wentland@amd.com> | 2019-03-05 13:24:31 -0500 |
| commit | dc43332b7af6f7aecd6b8867caeab272d5934d60 (patch) | |
| tree | d35378d902524d0ae228b47885e17d4d485c9d00 | |
| parent | 8ff62645eab9e0883c0e90fd558b5e8a50872d64 (diff) | |
drm/i915: Move dsc rate params compute into drm
The function intel_compute_rc_parameters is part of the dsc spec
and is not driver-specific. Other drm drivers might like to use
it. The function is not changed; just moved and renamed.
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: David Francis <David.Francis@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190221202001.28430-2-David.Francis@amd.com
| -rw-r--r-- | drivers/gpu/drm/drm_dsc.c | 135 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_vdsc.c | 125 | ||||
| -rw-r--r-- | include/drm/drm_dsc.h | 1 |
3 files changed, 137 insertions, 124 deletions
diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c index bce99f95c1a3..b7f1903508a4 100644 --- a/drivers/gpu/drm/drm_dsc.c +++ b/drivers/gpu/drm/drm_dsc.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| 13 | #include <linux/byteorder/generic.h> | 13 | #include <linux/byteorder/generic.h> |
| 14 | #include <drm/drm_print.h> | ||
| 14 | #include <drm/drm_dp_helper.h> | 15 | #include <drm/drm_dp_helper.h> |
| 15 | #include <drm/drm_dsc.h> | 16 | #include <drm/drm_dsc.h> |
| 16 | 17 | ||
| @@ -244,3 +245,137 @@ void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe *pps_sdp, | |||
| 244 | /* PPS 94 - 127 are O */ | 245 | /* PPS 94 - 127 are O */ |
| 245 | } | 246 | } |
| 246 | EXPORT_SYMBOL(drm_dsc_pps_infoframe_pack); | 247 | EXPORT_SYMBOL(drm_dsc_pps_infoframe_pack); |
| 248 | |||
| 249 | /** | ||
| 250 | * drm_dsc_compute_rc_parameters() - Write rate control | ||
| 251 | * parameters to the dsc configuration defined in | ||
| 252 | * &struct drm_dsc_config in accordance with the DSC 1.1 | ||
| 253 | * specification. Some configuration fields must be present | ||
| 254 | * beforehand. | ||
| 255 | * | ||
| 256 | * @vdsc_cfg: | ||
| 257 | * DSC Configuration data partially filled by driver | ||
| 258 | */ | ||
| 259 | int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg) | ||
| 260 | { | ||
| 261 | unsigned long groups_per_line = 0; | ||
| 262 | unsigned long groups_total = 0; | ||
| 263 | unsigned long num_extra_mux_bits = 0; | ||
| 264 | unsigned long slice_bits = 0; | ||
| 265 | unsigned long hrd_delay = 0; | ||
| 266 | unsigned long final_scale = 0; | ||
| 267 | unsigned long rbs_min = 0; | ||
| 268 | |||
| 269 | /* Number of groups used to code each line of a slice */ | ||
| 270 | groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width, | ||
| 271 | DSC_RC_PIXELS_PER_GROUP); | ||
| 272 | |||
| 273 | /* chunksize in Bytes */ | ||
| 274 | vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width * | ||
| 275 | vdsc_cfg->bits_per_pixel, | ||
| 276 | (8 * 16)); | ||
| 277 | |||
| 278 | if (vdsc_cfg->convert_rgb) | ||
| 279 | num_extra_mux_bits = 3 * (vdsc_cfg->mux_word_size + | ||
| 280 | (4 * vdsc_cfg->bits_per_component + 4) | ||
| 281 | - 2); | ||
| 282 | else | ||
| 283 | num_extra_mux_bits = 3 * vdsc_cfg->mux_word_size + | ||
| 284 | (4 * vdsc_cfg->bits_per_component + 4) + | ||
| 285 | 2 * (4 * vdsc_cfg->bits_per_component) - 2; | ||
| 286 | /* Number of bits in one Slice */ | ||
| 287 | slice_bits = 8 * vdsc_cfg->slice_chunk_size * vdsc_cfg->slice_height; | ||
| 288 | |||
| 289 | while ((num_extra_mux_bits > 0) && | ||
| 290 | ((slice_bits - num_extra_mux_bits) % vdsc_cfg->mux_word_size)) | ||
| 291 | num_extra_mux_bits--; | ||
| 292 | |||
| 293 | if (groups_per_line < vdsc_cfg->initial_scale_value - 8) | ||
| 294 | vdsc_cfg->initial_scale_value = groups_per_line + 8; | ||
| 295 | |||
| 296 | /* scale_decrement_interval calculation according to DSC spec 1.11 */ | ||
| 297 | if (vdsc_cfg->initial_scale_value > 8) | ||
| 298 | vdsc_cfg->scale_decrement_interval = groups_per_line / | ||
| 299 | (vdsc_cfg->initial_scale_value - 8); | ||
| 300 | else | ||
| 301 | vdsc_cfg->scale_decrement_interval = DSC_SCALE_DECREMENT_INTERVAL_MAX; | ||
| 302 | |||
| 303 | vdsc_cfg->final_offset = vdsc_cfg->rc_model_size - | ||
| 304 | (vdsc_cfg->initial_xmit_delay * | ||
| 305 | vdsc_cfg->bits_per_pixel + 8) / 16 + num_extra_mux_bits; | ||
| 306 | |||
| 307 | if (vdsc_cfg->final_offset >= vdsc_cfg->rc_model_size) { | ||
| 308 | DRM_DEBUG_KMS("FinalOfs < RcModelSze for this InitialXmitDelay\n"); | ||
| 309 | return -ERANGE; | ||
| 310 | } | ||
| 311 | |||
| 312 | final_scale = (vdsc_cfg->rc_model_size * 8) / | ||
| 313 | (vdsc_cfg->rc_model_size - vdsc_cfg->final_offset); | ||
| 314 | if (vdsc_cfg->slice_height > 1) | ||
| 315 | /* | ||
| 316 | * NflBpgOffset is 16 bit value with 11 fractional bits | ||
| 317 | * hence we multiply by 2^11 for preserving the | ||
| 318 | * fractional part | ||
| 319 | */ | ||
| 320 | vdsc_cfg->nfl_bpg_offset = DIV_ROUND_UP((vdsc_cfg->first_line_bpg_offset << 11), | ||
| 321 | (vdsc_cfg->slice_height - 1)); | ||
| 322 | else | ||
| 323 | vdsc_cfg->nfl_bpg_offset = 0; | ||
| 324 | |||
| 325 | /* 2^16 - 1 */ | ||
| 326 | if (vdsc_cfg->nfl_bpg_offset > 65535) { | ||
| 327 | DRM_DEBUG_KMS("NflBpgOffset is too large for this slice height\n"); | ||
| 328 | return -ERANGE; | ||
| 329 | } | ||
| 330 | |||
| 331 | /* Number of groups used to code the entire slice */ | ||
| 332 | groups_total = groups_per_line * vdsc_cfg->slice_height; | ||
| 333 | |||
| 334 | /* slice_bpg_offset is 16 bit value with 11 fractional bits */ | ||
| 335 | vdsc_cfg->slice_bpg_offset = DIV_ROUND_UP(((vdsc_cfg->rc_model_size - | ||
| 336 | vdsc_cfg->initial_offset + | ||
| 337 | num_extra_mux_bits) << 11), | ||
| 338 | groups_total); | ||
| 339 | |||
| 340 | if (final_scale > 9) { | ||
| 341 | /* | ||
| 342 | * ScaleIncrementInterval = | ||
| 343 | * finaloffset/((NflBpgOffset + SliceBpgOffset)*8(finalscale - 1.125)) | ||
| 344 | * as (NflBpgOffset + SliceBpgOffset) has 11 bit fractional value, | ||
| 345 | * we need divide by 2^11 from pstDscCfg values | ||
| 346 | */ | ||
| 347 | vdsc_cfg->scale_increment_interval = | ||
| 348 | (vdsc_cfg->final_offset * (1 << 11)) / | ||
| 349 | ((vdsc_cfg->nfl_bpg_offset + | ||
| 350 | vdsc_cfg->slice_bpg_offset) * | ||
| 351 | (final_scale - 9)); | ||
| 352 | } else { | ||
| 353 | /* | ||
| 354 | * If finalScaleValue is less than or equal to 9, a value of 0 should | ||
| 355 | * be used to disable the scale increment at the end of the slice | ||
| 356 | */ | ||
| 357 | vdsc_cfg->scale_increment_interval = 0; | ||
| 358 | } | ||
| 359 | |||
| 360 | if (vdsc_cfg->scale_increment_interval > 65535) { | ||
| 361 | DRM_DEBUG_KMS("ScaleIncrementInterval is large for slice height\n"); | ||
| 362 | return -ERANGE; | ||
| 363 | } | ||
| 364 | |||
| 365 | /* | ||
| 366 | * DSC spec mentions that bits_per_pixel specifies the target | ||
| 367 | * bits/pixel (bpp) rate that is used by the encoder, | ||
| 368 | * in steps of 1/16 of a bit per pixel | ||
| 369 | */ | ||
| 370 | rbs_min = vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset + | ||
| 371 | DIV_ROUND_UP(vdsc_cfg->initial_xmit_delay * | ||
| 372 | vdsc_cfg->bits_per_pixel, 16) + | ||
| 373 | groups_per_line * vdsc_cfg->first_line_bpg_offset; | ||
| 374 | |||
| 375 | hrd_delay = DIV_ROUND_UP((rbs_min * 16), vdsc_cfg->bits_per_pixel); | ||
| 376 | vdsc_cfg->rc_bits = (hrd_delay * vdsc_cfg->bits_per_pixel) / 16; | ||
| 377 | vdsc_cfg->initial_dec_delay = hrd_delay - vdsc_cfg->initial_xmit_delay; | ||
| 378 | |||
| 379 | return 0; | ||
| 380 | } | ||
| 381 | EXPORT_SYMBOL(drm_dsc_compute_rc_parameters); | ||
diff --git a/drivers/gpu/drm/i915/intel_vdsc.c b/drivers/gpu/drm/i915/intel_vdsc.c index 23abf03736e7..2d059ebc9bd0 100644 --- a/drivers/gpu/drm/i915/intel_vdsc.c +++ b/drivers/gpu/drm/i915/intel_vdsc.c | |||
| @@ -317,129 +317,6 @@ static int get_column_index_for_rc_params(u8 bits_per_component) | |||
| 317 | } | 317 | } |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | static int intel_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg) | ||
| 321 | { | ||
| 322 | unsigned long groups_per_line = 0; | ||
| 323 | unsigned long groups_total = 0; | ||
| 324 | unsigned long num_extra_mux_bits = 0; | ||
| 325 | unsigned long slice_bits = 0; | ||
| 326 | unsigned long hrd_delay = 0; | ||
| 327 | unsigned long final_scale = 0; | ||
| 328 | unsigned long rbs_min = 0; | ||
| 329 | |||
| 330 | /* Number of groups used to code each line of a slice */ | ||
| 331 | groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width, | ||
| 332 | DSC_RC_PIXELS_PER_GROUP); | ||
| 333 | |||
| 334 | /* chunksize in Bytes */ | ||
| 335 | vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width * | ||
| 336 | vdsc_cfg->bits_per_pixel, | ||
| 337 | (8 * 16)); | ||
| 338 | |||
| 339 | if (vdsc_cfg->convert_rgb) | ||
| 340 | num_extra_mux_bits = 3 * (vdsc_cfg->mux_word_size + | ||
| 341 | (4 * vdsc_cfg->bits_per_component + 4) | ||
| 342 | - 2); | ||
| 343 | else | ||
| 344 | num_extra_mux_bits = 3 * vdsc_cfg->mux_word_size + | ||
| 345 | (4 * vdsc_cfg->bits_per_component + 4) + | ||
| 346 | 2 * (4 * vdsc_cfg->bits_per_component) - 2; | ||
| 347 | /* Number of bits in one Slice */ | ||
| 348 | slice_bits = 8 * vdsc_cfg->slice_chunk_size * vdsc_cfg->slice_height; | ||
| 349 | |||
| 350 | while ((num_extra_mux_bits > 0) && | ||
| 351 | ((slice_bits - num_extra_mux_bits) % vdsc_cfg->mux_word_size)) | ||
| 352 | num_extra_mux_bits--; | ||
| 353 | |||
| 354 | if (groups_per_line < vdsc_cfg->initial_scale_value - 8) | ||
| 355 | vdsc_cfg->initial_scale_value = groups_per_line + 8; | ||
| 356 | |||
| 357 | /* scale_decrement_interval calculation according to DSC spec 1.11 */ | ||
| 358 | if (vdsc_cfg->initial_scale_value > 8) | ||
| 359 | vdsc_cfg->scale_decrement_interval = groups_per_line / | ||
| 360 | (vdsc_cfg->initial_scale_value - 8); | ||
| 361 | else | ||
| 362 | vdsc_cfg->scale_decrement_interval = DSC_SCALE_DECREMENT_INTERVAL_MAX; | ||
| 363 | |||
| 364 | vdsc_cfg->final_offset = vdsc_cfg->rc_model_size - | ||
| 365 | (vdsc_cfg->initial_xmit_delay * | ||
| 366 | vdsc_cfg->bits_per_pixel + 8) / 16 + num_extra_mux_bits; | ||
| 367 | |||
| 368 | if (vdsc_cfg->final_offset >= vdsc_cfg->rc_model_size) { | ||
| 369 | DRM_DEBUG_KMS("FinalOfs < RcModelSze for this InitialXmitDelay\n"); | ||
| 370 | return -ERANGE; | ||
| 371 | } | ||
| 372 | |||
| 373 | final_scale = (vdsc_cfg->rc_model_size * 8) / | ||
| 374 | (vdsc_cfg->rc_model_size - vdsc_cfg->final_offset); | ||
| 375 | if (vdsc_cfg->slice_height > 1) | ||
| 376 | /* | ||
| 377 | * NflBpgOffset is 16 bit value with 11 fractional bits | ||
| 378 | * hence we multiply by 2^11 for preserving the | ||
| 379 | * fractional part | ||
| 380 | */ | ||
| 381 | vdsc_cfg->nfl_bpg_offset = DIV_ROUND_UP((vdsc_cfg->first_line_bpg_offset << 11), | ||
| 382 | (vdsc_cfg->slice_height - 1)); | ||
| 383 | else | ||
| 384 | vdsc_cfg->nfl_bpg_offset = 0; | ||
| 385 | |||
| 386 | /* 2^16 - 1 */ | ||
| 387 | if (vdsc_cfg->nfl_bpg_offset > 65535) { | ||
| 388 | DRM_DEBUG_KMS("NflBpgOffset is too large for this slice height\n"); | ||
| 389 | return -ERANGE; | ||
| 390 | } | ||
| 391 | |||
| 392 | /* Number of groups used to code the entire slice */ | ||
| 393 | groups_total = groups_per_line * vdsc_cfg->slice_height; | ||
| 394 | |||
| 395 | /* slice_bpg_offset is 16 bit value with 11 fractional bits */ | ||
| 396 | vdsc_cfg->slice_bpg_offset = DIV_ROUND_UP(((vdsc_cfg->rc_model_size - | ||
| 397 | vdsc_cfg->initial_offset + | ||
| 398 | num_extra_mux_bits) << 11), | ||
| 399 | groups_total); | ||
| 400 | |||
| 401 | if (final_scale > 9) { | ||
| 402 | /* | ||
| 403 | * ScaleIncrementInterval = | ||
| 404 | * finaloffset/((NflBpgOffset + SliceBpgOffset)*8(finalscale - 1.125)) | ||
| 405 | * as (NflBpgOffset + SliceBpgOffset) has 11 bit fractional value, | ||
| 406 | * we need divide by 2^11 from pstDscCfg values | ||
| 407 | */ | ||
| 408 | vdsc_cfg->scale_increment_interval = | ||
| 409 | (vdsc_cfg->final_offset * (1 << 11)) / | ||
| 410 | ((vdsc_cfg->nfl_bpg_offset + | ||
| 411 | vdsc_cfg->slice_bpg_offset) * | ||
| 412 | (final_scale - 9)); | ||
| 413 | } else { | ||
| 414 | /* | ||
| 415 | * If finalScaleValue is less than or equal to 9, a value of 0 should | ||
| 416 | * be used to disable the scale increment at the end of the slice | ||
| 417 | */ | ||
| 418 | vdsc_cfg->scale_increment_interval = 0; | ||
| 419 | } | ||
| 420 | |||
| 421 | if (vdsc_cfg->scale_increment_interval > 65535) { | ||
| 422 | DRM_DEBUG_KMS("ScaleIncrementInterval is large for slice height\n"); | ||
| 423 | return -ERANGE; | ||
| 424 | } | ||
| 425 | |||
| 426 | /* | ||
| 427 | * DSC spec mentions that bits_per_pixel specifies the target | ||
| 428 | * bits/pixel (bpp) rate that is used by the encoder, | ||
| 429 | * in steps of 1/16 of a bit per pixel | ||
| 430 | */ | ||
| 431 | rbs_min = vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset + | ||
| 432 | DIV_ROUND_UP(vdsc_cfg->initial_xmit_delay * | ||
| 433 | vdsc_cfg->bits_per_pixel, 16) + | ||
| 434 | groups_per_line * vdsc_cfg->first_line_bpg_offset; | ||
| 435 | |||
| 436 | hrd_delay = DIV_ROUND_UP((rbs_min * 16), vdsc_cfg->bits_per_pixel); | ||
| 437 | vdsc_cfg->rc_bits = (hrd_delay * vdsc_cfg->bits_per_pixel) / 16; | ||
| 438 | vdsc_cfg->initial_dec_delay = hrd_delay - vdsc_cfg->initial_xmit_delay; | ||
| 439 | |||
| 440 | return 0; | ||
| 441 | } | ||
| 442 | |||
| 443 | int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, | 320 | int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, |
| 444 | struct intel_crtc_state *pipe_config) | 321 | struct intel_crtc_state *pipe_config) |
| 445 | { | 322 | { |
| @@ -574,7 +451,7 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, | |||
| 574 | vdsc_cfg->initial_scale_value = (vdsc_cfg->rc_model_size << 3) / | 451 | vdsc_cfg->initial_scale_value = (vdsc_cfg->rc_model_size << 3) / |
| 575 | (vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset); | 452 | (vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset); |
| 576 | 453 | ||
| 577 | return intel_compute_rc_parameters(vdsc_cfg); | 454 | return drm_dsc_compute_rc_parameters(vdsc_cfg); |
| 578 | } | 455 | } |
| 579 | 456 | ||
| 580 | enum intel_display_power_domain | 457 | enum intel_display_power_domain |
diff --git a/include/drm/drm_dsc.h b/include/drm/drm_dsc.h index 9c26f083c70f..5a98b8dfdf43 100644 --- a/include/drm/drm_dsc.h +++ b/include/drm/drm_dsc.h | |||
| @@ -604,5 +604,6 @@ struct drm_dsc_pps_infoframe { | |||
| 604 | void drm_dsc_dp_pps_header_init(struct drm_dsc_pps_infoframe *pps_sdp); | 604 | void drm_dsc_dp_pps_header_init(struct drm_dsc_pps_infoframe *pps_sdp); |
| 605 | void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe *pps_sdp, | 605 | void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe *pps_sdp, |
| 606 | const struct drm_dsc_config *dsc_cfg); | 606 | const struct drm_dsc_config *dsc_cfg); |
| 607 | int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg); | ||
| 607 | 608 | ||
| 608 | #endif /* _DRM_DSC_H_ */ | 609 | #endif /* _DRM_DSC_H_ */ |
