1 /* 2 * Copyright 2016 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 * Authors: AMD 23 * 24 */ 25 26 #include <linux/slab.h> 27 28 #include "dm_services.h" 29 #include "dc.h" 30 #include "mod_freesync.h" 31 #include "core_types.h" 32 33 #define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32 34 35 #define MIN_REFRESH_RANGE_IN_US 10000000 36 /* Refresh rate ramp at a fixed rate of 65 Hz/second */ 37 #define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65) 38 /* Number of elements in the render times cache array */ 39 #define RENDER_TIMES_MAX_COUNT 10 40 /* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */ 41 #define BTR_EXIT_MARGIN 2000 42 /* Threshold to change BTR multiplier (to avoid frequent changes) */ 43 #define BTR_DRIFT_MARGIN 2000 44 /*Threshold to exit fixed refresh rate*/ 45 #define FIXED_REFRESH_EXIT_MARGIN_IN_HZ 4 46 /* Number of consecutive frames to check before entering/exiting fixed refresh*/ 47 #define FIXED_REFRESH_ENTER_FRAME_COUNT 5 48 #define FIXED_REFRESH_EXIT_FRAME_COUNT 5 49 50 struct core_freesync { 51 struct mod_freesync public; 52 struct dc *dc; 53 }; 54 55 #define MOD_FREESYNC_TO_CORE(mod_freesync)\ 56 container_of(mod_freesync, struct core_freesync, public) 57 58 struct mod_freesync *mod_freesync_create(struct dc *dc) 59 { 60 struct core_freesync *core_freesync = 61 kzalloc(sizeof(struct core_freesync), GFP_KERNEL); 62 63 if (core_freesync == NULL) 64 goto fail_alloc_context; 65 66 if (dc == NULL) 67 goto fail_construct; 68 69 core_freesync->dc = dc; 70 return &core_freesync->public; 71 72 fail_construct: 73 kfree(core_freesync); 74 75 fail_alloc_context: 76 return NULL; 77 } 78 79 void mod_freesync_destroy(struct mod_freesync *mod_freesync) 80 { 81 struct core_freesync *core_freesync = NULL; 82 if (mod_freesync == NULL) 83 return; 84 core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); 85 kfree(core_freesync); 86 } 87 88 #if 0 /* unused currently */ 89 static unsigned int calc_refresh_in_uhz_from_duration( 90 unsigned int duration_in_ns) 91 { 92 unsigned int refresh_in_uhz = 93 ((unsigned int)(div64_u64((1000000000ULL * 1000000), 94 duration_in_ns))); 95 return refresh_in_uhz; 96 } 97 #endif 98 99 static unsigned int calc_duration_in_us_from_refresh_in_uhz( 100 unsigned int refresh_in_uhz) 101 { 102 unsigned int duration_in_us = 103 ((unsigned int)(div64_u64((1000000000ULL * 1000), 104 refresh_in_uhz))); 105 return duration_in_us; 106 } 107 108 static unsigned int calc_duration_in_us_from_v_total( 109 const struct dc_stream_state *stream, 110 const struct mod_vrr_params *in_vrr, 111 unsigned int v_total) 112 { 113 unsigned int duration_in_us = 114 (unsigned int)(div64_u64(((unsigned long long)(v_total) 115 * 10000) * stream->timing.h_total, 116 stream->timing.pix_clk_100hz)); 117 118 return duration_in_us; 119 } 120 121 static unsigned int calc_v_total_from_refresh( 122 const struct dc_stream_state *stream, 123 unsigned int refresh_in_uhz) 124 { 125 unsigned int v_total = stream->timing.v_total; 126 unsigned int frame_duration_in_ns; 127 128 frame_duration_in_ns = 129 ((unsigned int)(div64_u64((1000000000ULL * 1000000), 130 refresh_in_uhz))); 131 132 v_total = div64_u64(div64_u64(((unsigned long long)( 133 frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)), 134 stream->timing.h_total), 1000000); 135 136 /* v_total cannot be less than nominal */ 137 if (v_total < stream->timing.v_total) { 138 ASSERT(v_total < stream->timing.v_total); 139 v_total = stream->timing.v_total; 140 } 141 142 return v_total; 143 } 144 145 static unsigned int calc_v_total_from_duration( 146 const struct dc_stream_state *stream, 147 const struct mod_vrr_params *vrr, 148 unsigned int duration_in_us) 149 { 150 unsigned int v_total = 0; 151 152 if (duration_in_us < vrr->min_duration_in_us) 153 duration_in_us = vrr->min_duration_in_us; 154 155 if (duration_in_us > vrr->max_duration_in_us) 156 duration_in_us = vrr->max_duration_in_us; 157 158 v_total = div64_u64(div64_u64(((unsigned long long)( 159 duration_in_us) * (stream->timing.pix_clk_100hz / 10)), 160 stream->timing.h_total), 1000); 161 162 /* v_total cannot be less than nominal */ 163 if (v_total < stream->timing.v_total) { 164 ASSERT(v_total < stream->timing.v_total); 165 v_total = stream->timing.v_total; 166 } 167 168 return v_total; 169 } 170 171 static void update_v_total_for_static_ramp( 172 struct core_freesync *core_freesync, 173 const struct dc_stream_state *stream, 174 struct mod_vrr_params *in_out_vrr) 175 { 176 unsigned int v_total = 0; 177 unsigned int current_duration_in_us = 178 calc_duration_in_us_from_v_total( 179 stream, in_out_vrr, 180 in_out_vrr->adjust.v_total_max); 181 unsigned int target_duration_in_us = 182 calc_duration_in_us_from_refresh_in_uhz( 183 in_out_vrr->fixed.target_refresh_in_uhz); 184 bool ramp_direction_is_up = (current_duration_in_us > 185 target_duration_in_us) ? true : false; 186 187 /* Calc ratio between new and current frame duration with 3 digit */ 188 unsigned int frame_duration_ratio = div64_u64(1000000, 189 (1000 + div64_u64(((unsigned long long)( 190 STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME) * 191 current_duration_in_us), 192 1000000))); 193 194 /* Calculate delta between new and current frame duration in us */ 195 unsigned int frame_duration_delta = div64_u64(((unsigned long long)( 196 current_duration_in_us) * 197 (1000 - frame_duration_ratio)), 1000); 198 199 /* Adjust frame duration delta based on ratio between current and 200 * standard frame duration (frame duration at 60 Hz refresh rate). 201 */ 202 unsigned int ramp_rate_interpolated = div64_u64(((unsigned long long)( 203 frame_duration_delta) * current_duration_in_us), 16666); 204 205 /* Going to a higher refresh rate (lower frame duration) */ 206 if (ramp_direction_is_up) { 207 /* reduce frame duration */ 208 current_duration_in_us -= ramp_rate_interpolated; 209 210 /* adjust for frame duration below min */ 211 if (current_duration_in_us <= target_duration_in_us) { 212 in_out_vrr->fixed.ramping_active = false; 213 in_out_vrr->fixed.ramping_done = true; 214 current_duration_in_us = 215 calc_duration_in_us_from_refresh_in_uhz( 216 in_out_vrr->fixed.target_refresh_in_uhz); 217 } 218 /* Going to a lower refresh rate (larger frame duration) */ 219 } else { 220 /* increase frame duration */ 221 current_duration_in_us += ramp_rate_interpolated; 222 223 /* adjust for frame duration above max */ 224 if (current_duration_in_us >= target_duration_in_us) { 225 in_out_vrr->fixed.ramping_active = false; 226 in_out_vrr->fixed.ramping_done = true; 227 current_duration_in_us = 228 calc_duration_in_us_from_refresh_in_uhz( 229 in_out_vrr->fixed.target_refresh_in_uhz); 230 } 231 } 232 233 v_total = div64_u64(div64_u64(((unsigned long long)( 234 current_duration_in_us) * (stream->timing.pix_clk_100hz / 10)), 235 stream->timing.h_total), 1000); 236 237 in_out_vrr->adjust.v_total_min = v_total; 238 in_out_vrr->adjust.v_total_max = v_total; 239 } 240 241 static void apply_below_the_range(struct core_freesync *core_freesync, 242 const struct dc_stream_state *stream, 243 unsigned int last_render_time_in_us, 244 struct mod_vrr_params *in_out_vrr) 245 { 246 unsigned int inserted_frame_duration_in_us = 0; 247 unsigned int mid_point_frames_ceil = 0; 248 unsigned int mid_point_frames_floor = 0; 249 unsigned int frame_time_in_us = 0; 250 unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF; 251 unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF; 252 unsigned int frames_to_insert = 0; 253 unsigned int min_frame_duration_in_ns = 0; 254 unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us; 255 unsigned int delta_from_mid_point_delta_in_us; 256 257 min_frame_duration_in_ns = ((unsigned int) (div64_u64( 258 (1000000000ULL * 1000000), 259 in_out_vrr->max_refresh_in_uhz))); 260 261 /* Program BTR */ 262 if (last_render_time_in_us + BTR_EXIT_MARGIN < max_render_time_in_us) { 263 /* Exit Below the Range */ 264 if (in_out_vrr->btr.btr_active) { 265 in_out_vrr->btr.frame_counter = 0; 266 in_out_vrr->btr.btr_active = false; 267 } 268 } else if (last_render_time_in_us > max_render_time_in_us) { 269 /* Enter Below the Range */ 270 in_out_vrr->btr.btr_active = true; 271 } 272 273 /* BTR set to "not active" so disengage */ 274 if (!in_out_vrr->btr.btr_active) { 275 in_out_vrr->btr.inserted_duration_in_us = 0; 276 in_out_vrr->btr.frames_to_insert = 0; 277 in_out_vrr->btr.frame_counter = 0; 278 279 /* Restore FreeSync */ 280 in_out_vrr->adjust.v_total_min = 281 calc_v_total_from_refresh(stream, 282 in_out_vrr->max_refresh_in_uhz); 283 in_out_vrr->adjust.v_total_max = 284 calc_v_total_from_refresh(stream, 285 in_out_vrr->min_refresh_in_uhz); 286 /* BTR set to "active" so engage */ 287 } else { 288 289 /* Calculate number of midPoint frames that could fit within 290 * the render time interval- take ceil of this value 291 */ 292 mid_point_frames_ceil = (last_render_time_in_us + 293 in_out_vrr->btr.mid_point_in_us - 1) / 294 in_out_vrr->btr.mid_point_in_us; 295 296 if (mid_point_frames_ceil > 0) { 297 frame_time_in_us = last_render_time_in_us / 298 mid_point_frames_ceil; 299 delta_from_mid_point_in_us_1 = 300 (in_out_vrr->btr.mid_point_in_us > 301 frame_time_in_us) ? 302 (in_out_vrr->btr.mid_point_in_us - frame_time_in_us) : 303 (frame_time_in_us - in_out_vrr->btr.mid_point_in_us); 304 } 305 306 /* Calculate number of midPoint frames that could fit within 307 * the render time interval- take floor of this value 308 */ 309 mid_point_frames_floor = last_render_time_in_us / 310 in_out_vrr->btr.mid_point_in_us; 311 312 if (mid_point_frames_floor > 0) { 313 314 frame_time_in_us = last_render_time_in_us / 315 mid_point_frames_floor; 316 delta_from_mid_point_in_us_2 = 317 (in_out_vrr->btr.mid_point_in_us > 318 frame_time_in_us) ? 319 (in_out_vrr->btr.mid_point_in_us - frame_time_in_us) : 320 (frame_time_in_us - in_out_vrr->btr.mid_point_in_us); 321 } 322 323 /* Choose number of frames to insert based on how close it 324 * can get to the mid point of the variable range. 325 */ 326 if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) { 327 frames_to_insert = mid_point_frames_ceil; 328 delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 - 329 delta_from_mid_point_in_us_1; 330 } else { 331 frames_to_insert = mid_point_frames_floor; 332 delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 - 333 delta_from_mid_point_in_us_2; 334 } 335 336 /* Prefer current frame multiplier when BTR is enabled unless it drifts 337 * too far from the midpoint 338 */ 339 if (in_out_vrr->btr.frames_to_insert != 0 && 340 delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) { 341 if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) < 342 in_out_vrr->max_duration_in_us) && 343 ((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) > 344 in_out_vrr->min_duration_in_us)) 345 frames_to_insert = in_out_vrr->btr.frames_to_insert; 346 } 347 348 /* Either we've calculated the number of frames to insert, 349 * or we need to insert min duration frames 350 */ 351 if (last_render_time_in_us / frames_to_insert < 352 in_out_vrr->min_duration_in_us){ 353 frames_to_insert -= (frames_to_insert > 1) ? 354 1 : 0; 355 } 356 357 if (frames_to_insert > 0) 358 inserted_frame_duration_in_us = last_render_time_in_us / 359 frames_to_insert; 360 361 if (inserted_frame_duration_in_us < in_out_vrr->min_duration_in_us) 362 inserted_frame_duration_in_us = in_out_vrr->min_duration_in_us; 363 364 /* Cache the calculated variables */ 365 in_out_vrr->btr.inserted_duration_in_us = 366 inserted_frame_duration_in_us; 367 in_out_vrr->btr.frames_to_insert = frames_to_insert; 368 in_out_vrr->btr.frame_counter = frames_to_insert; 369 } 370 } 371 372 static void apply_fixed_refresh(struct core_freesync *core_freesync, 373 const struct dc_stream_state *stream, 374 unsigned int last_render_time_in_us, 375 struct mod_vrr_params *in_out_vrr) 376 { 377 bool update = false; 378 unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us; 379 380 //Compute the exit refresh rate and exit frame duration 381 unsigned int exit_refresh_rate_in_milli_hz = ((1000000000/max_render_time_in_us) 382 + (1000*FIXED_REFRESH_EXIT_MARGIN_IN_HZ)); 383 unsigned int exit_frame_duration_in_us = 1000000000/exit_refresh_rate_in_milli_hz; 384 385 if (last_render_time_in_us < exit_frame_duration_in_us) { 386 /* Exit Fixed Refresh mode */ 387 if (in_out_vrr->fixed.fixed_active) { 388 in_out_vrr->fixed.frame_counter++; 389 390 if (in_out_vrr->fixed.frame_counter > 391 FIXED_REFRESH_EXIT_FRAME_COUNT) { 392 in_out_vrr->fixed.frame_counter = 0; 393 in_out_vrr->fixed.fixed_active = false; 394 in_out_vrr->fixed.target_refresh_in_uhz = 0; 395 update = true; 396 } 397 } 398 } else if (last_render_time_in_us > max_render_time_in_us) { 399 /* Enter Fixed Refresh mode */ 400 if (!in_out_vrr->fixed.fixed_active) { 401 in_out_vrr->fixed.frame_counter++; 402 403 if (in_out_vrr->fixed.frame_counter > 404 FIXED_REFRESH_ENTER_FRAME_COUNT) { 405 in_out_vrr->fixed.frame_counter = 0; 406 in_out_vrr->fixed.fixed_active = true; 407 in_out_vrr->fixed.target_refresh_in_uhz = 408 in_out_vrr->max_refresh_in_uhz; 409 update = true; 410 } 411 } 412 } 413 414 if (update) { 415 if (in_out_vrr->fixed.fixed_active) { 416 in_out_vrr->adjust.v_total_min = 417 calc_v_total_from_refresh( 418 stream, in_out_vrr->max_refresh_in_uhz); 419 in_out_vrr->adjust.v_total_max = 420 in_out_vrr->adjust.v_total_min; 421 } else { 422 in_out_vrr->adjust.v_total_min = 423 calc_v_total_from_refresh(stream, 424 in_out_vrr->max_refresh_in_uhz); 425 in_out_vrr->adjust.v_total_max = 426 calc_v_total_from_refresh(stream, 427 in_out_vrr->min_refresh_in_uhz); 428 } 429 } 430 } 431 432 static bool vrr_settings_require_update(struct core_freesync *core_freesync, 433 struct mod_freesync_config *in_config, 434 unsigned int min_refresh_in_uhz, 435 unsigned int max_refresh_in_uhz, 436 struct mod_vrr_params *in_vrr) 437 { 438 if (in_vrr->state != in_config->state) { 439 return true; 440 } else if (in_vrr->state == VRR_STATE_ACTIVE_FIXED && 441 in_vrr->fixed.target_refresh_in_uhz != 442 in_config->min_refresh_in_uhz) { 443 return true; 444 } else if (in_vrr->min_refresh_in_uhz != min_refresh_in_uhz) { 445 return true; 446 } else if (in_vrr->max_refresh_in_uhz != max_refresh_in_uhz) { 447 return true; 448 } 449 450 return false; 451 } 452 453 bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, 454 const struct dc_stream_state *stream, 455 unsigned int *vmin, 456 unsigned int *vmax) 457 { 458 *vmin = stream->adjust.v_total_min; 459 *vmax = stream->adjust.v_total_max; 460 461 return true; 462 } 463 464 bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, 465 struct dc_stream_state *stream, 466 unsigned int *nom_v_pos, 467 unsigned int *v_pos) 468 { 469 struct core_freesync *core_freesync = NULL; 470 struct crtc_position position; 471 472 if (mod_freesync == NULL) 473 return false; 474 475 core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); 476 477 if (dc_stream_get_crtc_position(core_freesync->dc, &stream, 1, 478 &position.vertical_count, 479 &position.nominal_vcount)) { 480 481 *nom_v_pos = position.nominal_vcount; 482 *v_pos = position.vertical_count; 483 484 return true; 485 } 486 487 return false; 488 } 489 490 static void build_vrr_infopacket_data(const struct mod_vrr_params *vrr, 491 struct dc_info_packet *infopacket) 492 { 493 /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */ 494 infopacket->sb[1] = 0x1A; 495 496 /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */ 497 infopacket->sb[2] = 0x00; 498 499 /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */ 500 infopacket->sb[3] = 0x00; 501 502 /* PB4 = Reserved */ 503 504 /* PB5 = Reserved */ 505 506 /* PB6 = [Bits 7:3 = Reserved] */ 507 508 /* PB6 = [Bit 0 = FreeSync Supported] */ 509 if (vrr->state != VRR_STATE_UNSUPPORTED) 510 infopacket->sb[6] |= 0x01; 511 512 /* PB6 = [Bit 1 = FreeSync Enabled] */ 513 if (vrr->state != VRR_STATE_DISABLED && 514 vrr->state != VRR_STATE_UNSUPPORTED) 515 infopacket->sb[6] |= 0x02; 516 517 /* PB6 = [Bit 2 = FreeSync Active] */ 518 if (vrr->state == VRR_STATE_ACTIVE_VARIABLE || 519 vrr->state == VRR_STATE_ACTIVE_FIXED) 520 infopacket->sb[6] |= 0x04; 521 522 /* PB7 = FreeSync Minimum refresh rate (Hz) */ 523 infopacket->sb[7] = (unsigned char)(vrr->min_refresh_in_uhz / 1000000); 524 525 /* PB8 = FreeSync Maximum refresh rate (Hz) 526 * Note: We should never go above the field rate of the mode timing set. 527 */ 528 infopacket->sb[8] = (unsigned char)(vrr->max_refresh_in_uhz / 1000000); 529 530 531 //FreeSync HDR 532 infopacket->sb[9] = 0; 533 infopacket->sb[10] = 0; 534 } 535 536 static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf, 537 struct dc_info_packet *infopacket) 538 { 539 if (app_tf != TRANSFER_FUNC_UNKNOWN) { 540 infopacket->valid = true; 541 542 infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active] 543 544 if (app_tf == TRANSFER_FUNC_GAMMA_22) { 545 infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active] 546 } 547 } 548 } 549 550 static void build_vrr_infopacket_header_v1(enum signal_type signal, 551 struct dc_info_packet *infopacket, 552 unsigned int *payload_size) 553 { 554 if (dc_is_hdmi_signal(signal)) { 555 556 /* HEADER */ 557 558 /* HB0 = Packet Type = 0x83 (Source Product 559 * Descriptor InfoFrame) 560 */ 561 infopacket->hb0 = DC_HDMI_INFOFRAME_TYPE_SPD; 562 563 /* HB1 = Version = 0x01 */ 564 infopacket->hb1 = 0x01; 565 566 /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */ 567 infopacket->hb2 = 0x08; 568 569 *payload_size = 0x08; 570 571 } else if (dc_is_dp_signal(signal)) { 572 573 /* HEADER */ 574 575 /* HB0 = Secondary-data Packet ID = 0 - Only non-zero 576 * when used to associate audio related info packets 577 */ 578 infopacket->hb0 = 0x00; 579 580 /* HB1 = Packet Type = 0x83 (Source Product 581 * Descriptor InfoFrame) 582 */ 583 infopacket->hb1 = DC_HDMI_INFOFRAME_TYPE_SPD; 584 585 /* HB2 = [Bits 7:0 = Least significant eight bits - 586 * For INFOFRAME, the value must be 1Bh] 587 */ 588 infopacket->hb2 = 0x1B; 589 590 /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1] 591 * [Bits 1:0 = Most significant two bits = 0x00] 592 */ 593 infopacket->hb3 = 0x04; 594 595 *payload_size = 0x1B; 596 } 597 } 598 599 static void build_vrr_infopacket_header_v2(enum signal_type signal, 600 struct dc_info_packet *infopacket, 601 unsigned int *payload_size) 602 { 603 if (dc_is_hdmi_signal(signal)) { 604 605 /* HEADER */ 606 607 /* HB0 = Packet Type = 0x83 (Source Product 608 * Descriptor InfoFrame) 609 */ 610 infopacket->hb0 = DC_HDMI_INFOFRAME_TYPE_SPD; 611 612 /* HB1 = Version = 0x02 */ 613 infopacket->hb1 = 0x02; 614 615 /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x09] */ 616 infopacket->hb2 = 0x09; 617 618 *payload_size = 0x0A; 619 620 } else if (dc_is_dp_signal(signal)) { 621 622 /* HEADER */ 623 624 /* HB0 = Secondary-data Packet ID = 0 - Only non-zero 625 * when used to associate audio related info packets 626 */ 627 infopacket->hb0 = 0x00; 628 629 /* HB1 = Packet Type = 0x83 (Source Product 630 * Descriptor InfoFrame) 631 */ 632 infopacket->hb1 = DC_HDMI_INFOFRAME_TYPE_SPD; 633 634 /* HB2 = [Bits 7:0 = Least significant eight bits - 635 * For INFOFRAME, the value must be 1Bh] 636 */ 637 infopacket->hb2 = 0x1B; 638 639 /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x2] 640 * [Bits 1:0 = Most significant two bits = 0x00] 641 */ 642 infopacket->hb3 = 0x08; 643 644 *payload_size = 0x1B; 645 } 646 } 647 648 static void build_vrr_infopacket_checksum(unsigned int *payload_size, 649 struct dc_info_packet *infopacket) 650 { 651 /* Calculate checksum */ 652 unsigned int idx = 0; 653 unsigned char checksum = 0; 654 655 checksum += infopacket->hb0; 656 checksum += infopacket->hb1; 657 checksum += infopacket->hb2; 658 checksum += infopacket->hb3; 659 660 for (idx = 1; idx <= *payload_size; idx++) 661 checksum += infopacket->sb[idx]; 662 663 /* PB0 = Checksum (one byte complement) */ 664 infopacket->sb[0] = (unsigned char)(0x100 - checksum); 665 666 infopacket->valid = true; 667 } 668 669 static void build_vrr_infopacket_v1(enum signal_type signal, 670 const struct mod_vrr_params *vrr, 671 struct dc_info_packet *infopacket) 672 { 673 /* SPD info packet for FreeSync */ 674 unsigned int payload_size = 0; 675 676 build_vrr_infopacket_header_v1(signal, infopacket, &payload_size); 677 build_vrr_infopacket_data(vrr, infopacket); 678 build_vrr_infopacket_checksum(&payload_size, infopacket); 679 680 infopacket->valid = true; 681 } 682 683 static void build_vrr_infopacket_v2(enum signal_type signal, 684 const struct mod_vrr_params *vrr, 685 enum color_transfer_func app_tf, 686 struct dc_info_packet *infopacket) 687 { 688 unsigned int payload_size = 0; 689 690 build_vrr_infopacket_header_v2(signal, infopacket, &payload_size); 691 build_vrr_infopacket_data(vrr, infopacket); 692 693 build_vrr_infopacket_fs2_data(app_tf, infopacket); 694 695 build_vrr_infopacket_checksum(&payload_size, infopacket); 696 697 infopacket->valid = true; 698 } 699 700 void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, 701 const struct dc_stream_state *stream, 702 const struct mod_vrr_params *vrr, 703 enum vrr_packet_type packet_type, 704 enum color_transfer_func app_tf, 705 struct dc_info_packet *infopacket) 706 { 707 /* SPD info packet for FreeSync 708 * VTEM info packet for HdmiVRR 709 * Check if Freesync is supported. Return if false. If true, 710 * set the corresponding bit in the info packet 711 */ 712 if (!vrr->supported || (!vrr->send_info_frame)) 713 return; 714 715 switch (packet_type) { 716 case PACKET_TYPE_FS2: 717 build_vrr_infopacket_v2(stream->signal, vrr, app_tf, infopacket); 718 break; 719 case PACKET_TYPE_VRR: 720 case PACKET_TYPE_FS1: 721 default: 722 build_vrr_infopacket_v1(stream->signal, vrr, infopacket); 723 } 724 } 725 726 void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, 727 const struct dc_stream_state *stream, 728 struct mod_freesync_config *in_config, 729 struct mod_vrr_params *in_out_vrr) 730 { 731 struct core_freesync *core_freesync = NULL; 732 unsigned long long nominal_field_rate_in_uhz = 0; 733 unsigned int refresh_range = 0; 734 unsigned long long min_refresh_in_uhz = 0; 735 unsigned long long max_refresh_in_uhz = 0; 736 737 if (mod_freesync == NULL) 738 return; 739 740 core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); 741 742 /* Calculate nominal field rate for stream */ 743 nominal_field_rate_in_uhz = 744 mod_freesync_calc_nominal_field_rate(stream); 745 746 min_refresh_in_uhz = in_config->min_refresh_in_uhz; 747 max_refresh_in_uhz = in_config->max_refresh_in_uhz; 748 749 // Don't allow min > max 750 if (min_refresh_in_uhz > max_refresh_in_uhz) 751 min_refresh_in_uhz = max_refresh_in_uhz; 752 753 // Full range may be larger than current video timing, so cap at nominal 754 if (max_refresh_in_uhz > nominal_field_rate_in_uhz) 755 max_refresh_in_uhz = nominal_field_rate_in_uhz; 756 757 // Full range may be larger than current video timing, so cap at nominal 758 if (min_refresh_in_uhz > nominal_field_rate_in_uhz) 759 min_refresh_in_uhz = nominal_field_rate_in_uhz; 760 761 if (!vrr_settings_require_update(core_freesync, 762 in_config, (unsigned int)min_refresh_in_uhz, (unsigned int)max_refresh_in_uhz, 763 in_out_vrr)) 764 return; 765 766 in_out_vrr->state = in_config->state; 767 in_out_vrr->send_info_frame = in_config->vsif_supported; 768 769 if (in_config->state == VRR_STATE_UNSUPPORTED) { 770 in_out_vrr->state = VRR_STATE_UNSUPPORTED; 771 in_out_vrr->supported = false; 772 in_out_vrr->adjust.v_total_min = stream->timing.v_total; 773 in_out_vrr->adjust.v_total_max = stream->timing.v_total; 774 775 return; 776 777 } else { 778 in_out_vrr->min_refresh_in_uhz = (unsigned int)min_refresh_in_uhz; 779 in_out_vrr->max_duration_in_us = 780 calc_duration_in_us_from_refresh_in_uhz( 781 (unsigned int)min_refresh_in_uhz); 782 783 in_out_vrr->max_refresh_in_uhz = (unsigned int)max_refresh_in_uhz; 784 in_out_vrr->min_duration_in_us = 785 calc_duration_in_us_from_refresh_in_uhz( 786 (unsigned int)max_refresh_in_uhz); 787 788 refresh_range = in_out_vrr->max_refresh_in_uhz - 789 in_out_vrr->min_refresh_in_uhz; 790 791 in_out_vrr->supported = true; 792 } 793 794 in_out_vrr->fixed.ramping_active = in_config->ramping; 795 796 in_out_vrr->btr.btr_enabled = in_config->btr; 797 798 if (in_out_vrr->max_refresh_in_uhz < 799 2 * in_out_vrr->min_refresh_in_uhz) 800 in_out_vrr->btr.btr_enabled = false; 801 802 in_out_vrr->btr.btr_active = false; 803 in_out_vrr->btr.inserted_duration_in_us = 0; 804 in_out_vrr->btr.frames_to_insert = 0; 805 in_out_vrr->btr.frame_counter = 0; 806 in_out_vrr->btr.mid_point_in_us = 807 (in_out_vrr->min_duration_in_us + 808 in_out_vrr->max_duration_in_us) / 2; 809 810 if (in_out_vrr->state == VRR_STATE_UNSUPPORTED) { 811 in_out_vrr->adjust.v_total_min = stream->timing.v_total; 812 in_out_vrr->adjust.v_total_max = stream->timing.v_total; 813 } else if (in_out_vrr->state == VRR_STATE_DISABLED) { 814 in_out_vrr->adjust.v_total_min = stream->timing.v_total; 815 in_out_vrr->adjust.v_total_max = stream->timing.v_total; 816 } else if (in_out_vrr->state == VRR_STATE_INACTIVE) { 817 in_out_vrr->adjust.v_total_min = stream->timing.v_total; 818 in_out_vrr->adjust.v_total_max = stream->timing.v_total; 819 } else if (in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE && 820 refresh_range >= MIN_REFRESH_RANGE_IN_US) { 821 in_out_vrr->adjust.v_total_min = 822 calc_v_total_from_refresh(stream, 823 in_out_vrr->max_refresh_in_uhz); 824 in_out_vrr->adjust.v_total_max = 825 calc_v_total_from_refresh(stream, 826 in_out_vrr->min_refresh_in_uhz); 827 } else if (in_out_vrr->state == VRR_STATE_ACTIVE_FIXED) { 828 in_out_vrr->fixed.target_refresh_in_uhz = 829 in_out_vrr->min_refresh_in_uhz; 830 if (in_out_vrr->fixed.ramping_active && 831 in_out_vrr->fixed.fixed_active) { 832 /* Do not update vtotals if ramping is already active 833 * in order to continue ramp from current refresh. 834 */ 835 in_out_vrr->fixed.fixed_active = true; 836 } else { 837 in_out_vrr->fixed.fixed_active = true; 838 in_out_vrr->adjust.v_total_min = 839 calc_v_total_from_refresh(stream, 840 in_out_vrr->fixed.target_refresh_in_uhz); 841 in_out_vrr->adjust.v_total_max = 842 in_out_vrr->adjust.v_total_min; 843 } 844 } else { 845 in_out_vrr->state = VRR_STATE_INACTIVE; 846 in_out_vrr->adjust.v_total_min = stream->timing.v_total; 847 in_out_vrr->adjust.v_total_max = stream->timing.v_total; 848 } 849 } 850 851 void mod_freesync_handle_preflip(struct mod_freesync *mod_freesync, 852 const struct dc_plane_state *plane, 853 const struct dc_stream_state *stream, 854 unsigned int curr_time_stamp_in_us, 855 struct mod_vrr_params *in_out_vrr) 856 { 857 struct core_freesync *core_freesync = NULL; 858 unsigned int last_render_time_in_us = 0; 859 unsigned int average_render_time_in_us = 0; 860 861 if (mod_freesync == NULL) 862 return; 863 864 core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); 865 866 if (in_out_vrr->supported && 867 in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE) { 868 unsigned int i = 0; 869 unsigned int oldest_index = plane->time.index + 1; 870 871 if (oldest_index >= DC_PLANE_UPDATE_TIMES_MAX) 872 oldest_index = 0; 873 874 last_render_time_in_us = curr_time_stamp_in_us - 875 plane->time.prev_update_time_in_us; 876 877 // Sum off all entries except oldest one 878 for (i = 0; i < DC_PLANE_UPDATE_TIMES_MAX; i++) { 879 average_render_time_in_us += 880 plane->time.time_elapsed_in_us[i]; 881 } 882 average_render_time_in_us -= 883 plane->time.time_elapsed_in_us[oldest_index]; 884 885 // Add render time for current flip 886 average_render_time_in_us += last_render_time_in_us; 887 average_render_time_in_us /= DC_PLANE_UPDATE_TIMES_MAX; 888 889 if (in_out_vrr->btr.btr_enabled) { 890 apply_below_the_range(core_freesync, 891 stream, 892 last_render_time_in_us, 893 in_out_vrr); 894 } else { 895 apply_fixed_refresh(core_freesync, 896 stream, 897 last_render_time_in_us, 898 in_out_vrr); 899 } 900 901 } 902 } 903 904 void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, 905 const struct dc_stream_state *stream, 906 struct mod_vrr_params *in_out_vrr) 907 { 908 struct core_freesync *core_freesync = NULL; 909 910 if ((mod_freesync == NULL) || (stream == NULL) || (in_out_vrr == NULL)) 911 return; 912 913 core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); 914 915 if (in_out_vrr->supported == false) 916 return; 917 918 /* Below the Range Logic */ 919 920 /* Only execute if in fullscreen mode */ 921 if (in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE && 922 in_out_vrr->btr.btr_active) { 923 /* TODO: pass in flag for Pre-DCE12 ASIC 924 * in order for frame variable duration to take affect, 925 * it needs to be done one VSYNC early, which is at 926 * frameCounter == 1. 927 * For DCE12 and newer updates to V_TOTAL_MIN/MAX 928 * will take affect on current frame 929 */ 930 if (in_out_vrr->btr.frames_to_insert == 931 in_out_vrr->btr.frame_counter) { 932 in_out_vrr->adjust.v_total_min = 933 calc_v_total_from_duration(stream, 934 in_out_vrr, 935 in_out_vrr->btr.inserted_duration_in_us); 936 in_out_vrr->adjust.v_total_max = 937 in_out_vrr->adjust.v_total_min; 938 } 939 940 if (in_out_vrr->btr.frame_counter > 0) 941 in_out_vrr->btr.frame_counter--; 942 943 /* Restore FreeSync */ 944 if (in_out_vrr->btr.frame_counter == 0) { 945 in_out_vrr->adjust.v_total_min = 946 calc_v_total_from_refresh(stream, 947 in_out_vrr->max_refresh_in_uhz); 948 in_out_vrr->adjust.v_total_max = 949 calc_v_total_from_refresh(stream, 950 in_out_vrr->min_refresh_in_uhz); 951 } 952 } 953 954 /* If in fullscreen freesync mode or in video, do not program 955 * static screen ramp values 956 */ 957 if (in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE) 958 in_out_vrr->fixed.ramping_active = false; 959 960 /* Gradual Static Screen Ramping Logic */ 961 /* Execute if ramp is active and user enabled freesync static screen*/ 962 if (in_out_vrr->state == VRR_STATE_ACTIVE_FIXED && 963 in_out_vrr->fixed.ramping_active) { 964 update_v_total_for_static_ramp( 965 core_freesync, stream, in_out_vrr); 966 } 967 } 968 969 void mod_freesync_get_settings(struct mod_freesync *mod_freesync, 970 const struct mod_vrr_params *vrr, 971 unsigned int *v_total_min, unsigned int *v_total_max, 972 unsigned int *event_triggers, 973 unsigned int *window_min, unsigned int *window_max, 974 unsigned int *lfc_mid_point_in_us, 975 unsigned int *inserted_frames, 976 unsigned int *inserted_duration_in_us) 977 { 978 struct core_freesync *core_freesync = NULL; 979 980 if (mod_freesync == NULL) 981 return; 982 983 core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); 984 985 if (vrr->supported) { 986 *v_total_min = vrr->adjust.v_total_min; 987 *v_total_max = vrr->adjust.v_total_max; 988 *event_triggers = 0; 989 *lfc_mid_point_in_us = vrr->btr.mid_point_in_us; 990 *inserted_frames = vrr->btr.frames_to_insert; 991 *inserted_duration_in_us = vrr->btr.inserted_duration_in_us; 992 } 993 } 994 995 unsigned long long mod_freesync_calc_nominal_field_rate( 996 const struct dc_stream_state *stream) 997 { 998 unsigned long long nominal_field_rate_in_uhz = 0; 999 1000 /* Calculate nominal field rate for stream */ 1001 nominal_field_rate_in_uhz = stream->timing.pix_clk_100hz / 10; 1002 nominal_field_rate_in_uhz *= 1000ULL * 1000ULL * 1000ULL; 1003 nominal_field_rate_in_uhz = div_u64(nominal_field_rate_in_uhz, 1004 stream->timing.h_total); 1005 nominal_field_rate_in_uhz = div_u64(nominal_field_rate_in_uhz, 1006 stream->timing.v_total); 1007 1008 return nominal_field_rate_in_uhz; 1009 } 1010 1011 bool mod_freesync_is_valid_range(struct mod_freesync *mod_freesync, 1012 const struct dc_stream_state *stream, 1013 uint32_t min_refresh_cap_in_uhz, 1014 uint32_t max_refresh_cap_in_uhz, 1015 uint32_t min_refresh_request_in_uhz, 1016 uint32_t max_refresh_request_in_uhz) 1017 { 1018 /* Calculate nominal field rate for stream */ 1019 unsigned long long nominal_field_rate_in_uhz = 1020 mod_freesync_calc_nominal_field_rate(stream); 1021 1022 /* Typically nominal refresh calculated can have some fractional part. 1023 * Allow for some rounding error of actual video timing by taking floor 1024 * of caps and request. Round the nominal refresh rate. 1025 * 1026 * Dividing will convert everything to units in Hz although input 1027 * variable name is in uHz! 1028 * 1029 * Also note, this takes care of rounding error on the nominal refresh 1030 * so by rounding error we only expect it to be off by a small amount, 1031 * such as < 0.1 Hz. i.e. 143.9xxx or 144.1xxx. 1032 * 1033 * Example 1. Caps Min = 40 Hz, Max = 144 Hz 1034 * Request Min = 40 Hz, Max = 144 Hz 1035 * Nominal = 143.5x Hz rounded to 144 Hz 1036 * This function should allow this as valid request 1037 * 1038 * Example 2. Caps Min = 40 Hz, Max = 144 Hz 1039 * Request Min = 40 Hz, Max = 144 Hz 1040 * Nominal = 144.4x Hz rounded to 144 Hz 1041 * This function should allow this as valid request 1042 * 1043 * Example 3. Caps Min = 40 Hz, Max = 144 Hz 1044 * Request Min = 40 Hz, Max = 144 Hz 1045 * Nominal = 120.xx Hz rounded to 120 Hz 1046 * This function should return NOT valid since the requested 1047 * max is greater than current timing's nominal 1048 * 1049 * Example 4. Caps Min = 40 Hz, Max = 120 Hz 1050 * Request Min = 40 Hz, Max = 120 Hz 1051 * Nominal = 144.xx Hz rounded to 144 Hz 1052 * This function should return NOT valid since the nominal 1053 * is greater than the capability's max refresh 1054 */ 1055 nominal_field_rate_in_uhz = 1056 div_u64(nominal_field_rate_in_uhz + 500000, 1000000); 1057 min_refresh_cap_in_uhz /= 1000000; 1058 max_refresh_cap_in_uhz /= 1000000; 1059 min_refresh_request_in_uhz /= 1000000; 1060 max_refresh_request_in_uhz /= 1000000; 1061 1062 // Check nominal is within range 1063 if (nominal_field_rate_in_uhz > max_refresh_cap_in_uhz || 1064 nominal_field_rate_in_uhz < min_refresh_cap_in_uhz) 1065 return false; 1066 1067 // If nominal is less than max, limit the max allowed refresh rate 1068 if (nominal_field_rate_in_uhz < max_refresh_cap_in_uhz) 1069 max_refresh_cap_in_uhz = nominal_field_rate_in_uhz; 1070 1071 // Don't allow min > max 1072 if (min_refresh_request_in_uhz > max_refresh_request_in_uhz) 1073 return false; 1074 1075 // Check min is within range 1076 if (min_refresh_request_in_uhz > max_refresh_cap_in_uhz || 1077 min_refresh_request_in_uhz < min_refresh_cap_in_uhz) 1078 return false; 1079 1080 // Check max is within range 1081 if (max_refresh_request_in_uhz > max_refresh_cap_in_uhz || 1082 max_refresh_request_in_uhz < min_refresh_cap_in_uhz) 1083 return false; 1084 1085 // For variable range, check for at least 10 Hz range 1086 if ((max_refresh_request_in_uhz != min_refresh_request_in_uhz) && 1087 (max_refresh_request_in_uhz - min_refresh_request_in_uhz < 10)) 1088 return false; 1089 1090 return true; 1091 } 1092 1093