diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules/freesync/freesync.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 78 |
1 files changed, 50 insertions, 28 deletions
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index eb7421e83b86..7a2500fbf3f2 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -32,7 +32,7 @@ #define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32 -#define MIN_REFRESH_RANGE_IN_US 10000000 +#define MIN_REFRESH_RANGE 10 /* Refresh rate ramp at a fixed rate of 65 Hz/second */ #define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65) /* Number of elements in the render times cache array */ @@ -760,9 +760,35 @@ static void build_vrr_infopacket_v2(enum signal_type signal, infopacket->valid = true; } +#ifndef TRIM_FSFT +static void build_vrr_infopacket_fast_transport_data( + bool ftActive, + unsigned int ftOutputRate, + struct dc_info_packet *infopacket) +{ + /* PB9 : bit7 - fast transport Active*/ + unsigned char activeBit = (ftActive) ? 1 << 7 : 0; + + infopacket->sb[1] &= ~activeBit; //clear bit + infopacket->sb[1] |= activeBit; //set bit + + /* PB13 : Target Output Pixel Rate [kHz] - bits 7:0 */ + infopacket->sb[13] = ftOutputRate & 0xFF; + + /* PB14 : Target Output Pixel Rate [kHz] - bits 15:8 */ + infopacket->sb[14] = (ftOutputRate >> 8) & 0xFF; + + /* PB15 : Target Output Pixel Rate [kHz] - bits 23:16 */ + infopacket->sb[15] = (ftOutputRate >> 16) & 0xFF; + +} +#endif static void build_vrr_infopacket_v3(enum signal_type signal, const struct mod_vrr_params *vrr, +#ifndef TRIM_FSFT + bool ftActive, unsigned int ftOutputRate, +#endif enum color_transfer_func app_tf, struct dc_info_packet *infopacket) { @@ -773,6 +799,13 @@ static void build_vrr_infopacket_v3(enum signal_type signal, build_vrr_infopacket_fs2_data(app_tf, infopacket); +#ifndef TRIM_FSFT + build_vrr_infopacket_fast_transport_data( + ftActive, + ftOutputRate, + infopacket); +#endif + build_vrr_infopacket_checksum(&payload_size, infopacket); infopacket->valid = true; @@ -790,12 +823,20 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, * Check if Freesync is supported. Return if false. If true, * set the corresponding bit in the info packet */ - if (!vrr->supported || (!vrr->send_info_frame)) + if (!vrr->send_info_frame) return; switch (packet_type) { case PACKET_TYPE_FS_V3: +#ifndef TRIM_FSFT + build_vrr_infopacket_v3( + stream->signal, vrr, + stream->timing.flags.FAST_TRANSPORT, + stream->timing.fast_transport_output_rate_100hz, + app_tf, infopacket); +#else build_vrr_infopacket_v3(stream->signal, vrr, app_tf, infopacket); +#endif break; case PACKET_TYPE_FS_V2: build_vrr_infopacket_v2(stream->signal, vrr, app_tf, infopacket); @@ -878,8 +919,8 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, else in_out_vrr->fixed_refresh_in_uhz = 0; - refresh_range = in_out_vrr->max_refresh_in_uhz - - in_out_vrr->min_refresh_in_uhz; + refresh_range = div_u64(in_out_vrr->max_refresh_in_uhz + 500000, 1000000) - ++ div_u64(in_out_vrr->min_refresh_in_uhz + 500000, 1000000); in_out_vrr->supported = true; } @@ -918,7 +959,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, in_out_vrr->adjust.v_total_min = stream->timing.v_total; in_out_vrr->adjust.v_total_max = stream->timing.v_total; } else if (in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE && - refresh_range >= MIN_REFRESH_RANGE_IN_US) { + refresh_range >= MIN_REFRESH_RANGE) { in_out_vrr->adjust.v_total_min = calc_v_total_from_refresh(stream, @@ -1105,16 +1146,10 @@ unsigned long long mod_freesync_calc_nominal_field_rate( return nominal_field_rate_in_uhz; } -bool mod_freesync_is_valid_range(struct mod_freesync *mod_freesync, - const struct dc_stream_state *stream, - uint32_t min_refresh_cap_in_uhz, +bool mod_freesync_is_valid_range(uint32_t min_refresh_cap_in_uhz, uint32_t max_refresh_cap_in_uhz, - uint32_t min_refresh_request_in_uhz, - uint32_t max_refresh_request_in_uhz) + uint32_t nominal_field_rate_in_uhz) { - /* Calculate nominal field rate for stream */ - unsigned long long nominal_field_rate_in_uhz = - mod_freesync_calc_nominal_field_rate(stream); /* Typically nominal refresh calculated can have some fractional part. * Allow for some rounding error of actual video timing by taking floor @@ -1153,8 +1188,6 @@ bool mod_freesync_is_valid_range(struct mod_freesync *mod_freesync, div_u64(nominal_field_rate_in_uhz + 500000, 1000000); min_refresh_cap_in_uhz /= 1000000; max_refresh_cap_in_uhz /= 1000000; - min_refresh_request_in_uhz /= 1000000; - max_refresh_request_in_uhz /= 1000000; // Check nominal is within range if (nominal_field_rate_in_uhz > max_refresh_cap_in_uhz || @@ -1165,23 +1198,12 @@ bool mod_freesync_is_valid_range(struct mod_freesync *mod_freesync, if (nominal_field_rate_in_uhz < max_refresh_cap_in_uhz) max_refresh_cap_in_uhz = nominal_field_rate_in_uhz; - // Don't allow min > max - if (min_refresh_request_in_uhz > max_refresh_request_in_uhz) - return false; - // Check min is within range - if (min_refresh_request_in_uhz > max_refresh_cap_in_uhz || - min_refresh_request_in_uhz < min_refresh_cap_in_uhz) - return false; - - // Check max is within range - if (max_refresh_request_in_uhz > max_refresh_cap_in_uhz || - max_refresh_request_in_uhz < min_refresh_cap_in_uhz) + if (min_refresh_cap_in_uhz > max_refresh_cap_in_uhz) return false; // For variable range, check for at least 10 Hz range - if ((max_refresh_request_in_uhz != min_refresh_request_in_uhz) && - (max_refresh_request_in_uhz - min_refresh_request_in_uhz < 10)) + if (nominal_field_rate_in_uhz - min_refresh_cap_in_uhz < 10) return false; return true; |