1 /* 2 * Copyright 2019 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 "dmub_psr.h" 27 #include "dc.h" 28 #include "dc_dmub_srv.h" 29 #include "dmub/dmub_srv.h" 30 #include "core_types.h" 31 32 #define DC_TRACE_LEVEL_MESSAGE(...) do {} while (0) /* do nothing */ 33 34 #define MAX_PIPES 6 35 36 static const uint8_t DP_SINK_DEVICE_STR_ID_1[] = {7, 1, 8, 7, 3}; 37 static const uint8_t DP_SINK_DEVICE_STR_ID_2[] = {7, 1, 8, 7, 5}; 38 static const uint8_t DP_SINK_DEVICE_STR_ID_3[] = {0x42, 0x61, 0x6c, 0x73, 0x61}; 39 40 /* 41 * Convert dmcub psr state to dmcu psr state. 42 */ 43 static enum dc_psr_state convert_psr_state(uint32_t raw_state) 44 { 45 enum dc_psr_state state = PSR_STATE0; 46 47 if (raw_state == 0) 48 state = PSR_STATE0; 49 else if (raw_state == 0x10) 50 state = PSR_STATE1; 51 else if (raw_state == 0x11) 52 state = PSR_STATE1a; 53 else if (raw_state == 0x20) 54 state = PSR_STATE2; 55 else if (raw_state == 0x21) 56 state = PSR_STATE2a; 57 else if (raw_state == 0x22) 58 state = PSR_STATE2b; 59 else if (raw_state == 0x30) 60 state = PSR_STATE3; 61 else if (raw_state == 0x31) 62 state = PSR_STATE3Init; 63 else if (raw_state == 0x40) 64 state = PSR_STATE4; 65 else if (raw_state == 0x41) 66 state = PSR_STATE4a; 67 else if (raw_state == 0x42) 68 state = PSR_STATE4b; 69 else if (raw_state == 0x43) 70 state = PSR_STATE4c; 71 else if (raw_state == 0x44) 72 state = PSR_STATE4d; 73 else if (raw_state == 0x50) 74 state = PSR_STATE5; 75 else if (raw_state == 0x51) 76 state = PSR_STATE5a; 77 else if (raw_state == 0x52) 78 state = PSR_STATE5b; 79 else if (raw_state == 0x53) 80 state = PSR_STATE5c; 81 else if (raw_state == 0x4A) 82 state = PSR_STATE4_FULL_FRAME; 83 else if (raw_state == 0x4B) 84 state = PSR_STATE4a_FULL_FRAME; 85 else if (raw_state == 0x4C) 86 state = PSR_STATE4b_FULL_FRAME; 87 else if (raw_state == 0x4D) 88 state = PSR_STATE4c_FULL_FRAME; 89 else if (raw_state == 0x4E) 90 state = PSR_STATE4_FULL_FRAME_POWERUP; 91 else if (raw_state == 0x4F) 92 state = PSR_STATE4_FULL_FRAME_HW_LOCK; 93 else if (raw_state == 0x60) 94 state = PSR_STATE_HWLOCK_MGR; 95 else if (raw_state == 0x61) 96 state = PSR_STATE_POLLVUPDATE; 97 else 98 state = PSR_STATE_INVALID; 99 100 return state; 101 } 102 103 /* 104 * Get PSR state from firmware. 105 */ 106 static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state, uint8_t panel_inst) 107 { 108 uint32_t raw_state = 0; 109 uint32_t retry_count = 0; 110 111 do { 112 // Send gpint command and wait for ack 113 if (dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__GET_PSR_STATE, panel_inst, &raw_state, 114 DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) { 115 *state = convert_psr_state(raw_state); 116 } else { 117 // Return invalid state when GPINT times out 118 *state = PSR_STATE_INVALID; 119 } 120 } while (++retry_count <= 1000 && *state == PSR_STATE_INVALID); 121 122 // Assert if max retry hit 123 if (retry_count >= 1000 && *state == PSR_STATE_INVALID) { 124 ASSERT(0); 125 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 126 WPP_BIT_FLAG_Firmware_PsrState, 127 "Unable to get PSR state from FW."); 128 } else 129 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE, 130 WPP_BIT_FLAG_Firmware_PsrState, 131 "Got PSR state from FW. PSR state: %d, Retry count: %d", 132 *state, retry_count); 133 } 134 135 /* 136 * Set PSR version. 137 */ 138 static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream, uint8_t panel_inst) 139 { 140 union dmub_rb_cmd cmd; 141 struct dc_context *dc = dmub->ctx; 142 143 if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED) 144 return false; 145 146 memset(&cmd, 0, sizeof(cmd)); 147 cmd.psr_set_version.header.type = DMUB_CMD__PSR; 148 cmd.psr_set_version.header.sub_type = DMUB_CMD__PSR_SET_VERSION; 149 switch (stream->link->psr_settings.psr_version) { 150 case DC_PSR_VERSION_1: 151 cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_1; 152 break; 153 case DC_PSR_VERSION_SU_1: 154 cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_SU_1; 155 break; 156 case DC_PSR_VERSION_UNSUPPORTED: 157 default: 158 cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_UNSUPPORTED; 159 break; 160 } 161 162 if (cmd.psr_set_version.psr_set_version_data.version == PSR_VERSION_UNSUPPORTED) 163 return false; 164 165 cmd.psr_set_version.psr_set_version_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; 166 cmd.psr_set_version.psr_set_version_data.panel_inst = panel_inst; 167 cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data); 168 169 dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 170 171 return true; 172 } 173 174 /* 175 * Enable/Disable PSR. 176 */ 177 static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait, uint8_t panel_inst) 178 { 179 union dmub_rb_cmd cmd; 180 struct dc_context *dc = dmub->ctx; 181 uint32_t retry_count; 182 enum dc_psr_state state = PSR_STATE0; 183 184 memset(&cmd, 0, sizeof(cmd)); 185 cmd.psr_enable.header.type = DMUB_CMD__PSR; 186 187 cmd.psr_enable.data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; 188 cmd.psr_enable.data.panel_inst = panel_inst; 189 190 if (enable) 191 cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_ENABLE; 192 else 193 cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_DISABLE; 194 195 cmd.psr_enable.header.payload_bytes = 0; // Send header only 196 197 dc_wake_and_execute_dmub_cmd(dc->dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 198 199 /* Below loops 1000 x 500us = 500 ms. 200 * Exit PSR may need to wait 1-2 frames to power up. Timeout after at 201 * least a few frames. Should never hit the max retry assert below. 202 */ 203 if (wait) { 204 for (retry_count = 0; retry_count <= 1000; retry_count++) { 205 dmub_psr_get_state(dmub, &state, panel_inst); 206 207 if (enable) { 208 if (state != PSR_STATE0) 209 break; 210 } else { 211 if (state == PSR_STATE0) 212 break; 213 } 214 215 /* must *not* be fsleep - this can be called from high irq levels */ 216 udelay(500); 217 } 218 219 /* assert if max retry hit */ 220 if (retry_count >= 1000) 221 ASSERT(0); 222 } 223 } 224 225 /* 226 * Set PSR level. 227 */ 228 static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_t panel_inst) 229 { 230 union dmub_rb_cmd cmd; 231 enum dc_psr_state state = PSR_STATE0; 232 struct dc_context *dc = dmub->ctx; 233 234 dmub_psr_get_state(dmub, &state, panel_inst); 235 236 if (state == PSR_STATE0) 237 return; 238 239 memset(&cmd, 0, sizeof(cmd)); 240 cmd.psr_set_level.header.type = DMUB_CMD__PSR; 241 cmd.psr_set_level.header.sub_type = DMUB_CMD__PSR_SET_LEVEL; 242 cmd.psr_set_level.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_level_data); 243 cmd.psr_set_level.psr_set_level_data.psr_level = psr_level; 244 cmd.psr_set_level.psr_set_level_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; 245 cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst; 246 dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 247 } 248 249 /* 250 * Set PSR vtotal requirement for FreeSync PSR. 251 */ 252 static void dmub_psr_set_sink_vtotal_in_psr_active(struct dmub_psr *dmub, 253 uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su) 254 { 255 union dmub_rb_cmd cmd; 256 struct dc_context *dc = dmub->ctx; 257 258 memset(&cmd, 0, sizeof(cmd)); 259 cmd.psr_set_vtotal.header.type = DMUB_CMD__PSR; 260 cmd.psr_set_vtotal.header.sub_type = DMUB_CMD__SET_SINK_VTOTAL_IN_PSR_ACTIVE; 261 cmd.psr_set_vtotal.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_vtotal_data); 262 cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_idle = psr_vtotal_idle; 263 cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_su = psr_vtotal_su; 264 265 dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 266 } 267 268 /* 269 * Set PSR power optimization flags. 270 */ 271 static void dmub_psr_set_power_opt(struct dmub_psr *dmub, unsigned int power_opt, uint8_t panel_inst) 272 { 273 union dmub_rb_cmd cmd; 274 struct dc_context *dc = dmub->ctx; 275 276 memset(&cmd, 0, sizeof(cmd)); 277 cmd.psr_set_power_opt.header.type = DMUB_CMD__PSR; 278 cmd.psr_set_power_opt.header.sub_type = DMUB_CMD__SET_PSR_POWER_OPT; 279 cmd.psr_set_power_opt.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_power_opt_data); 280 cmd.psr_set_power_opt.psr_set_power_opt_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; 281 cmd.psr_set_power_opt.psr_set_power_opt_data.power_opt = power_opt; 282 cmd.psr_set_power_opt.psr_set_power_opt_data.panel_inst = panel_inst; 283 284 dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 285 } 286 287 /* 288 * Setup PSR by programming phy registers and sending psr hw context values to firmware. 289 */ 290 static bool dmub_psr_copy_settings(struct dmub_psr *dmub, 291 struct dc_link *link, 292 struct psr_context *psr_context, 293 uint8_t panel_inst) 294 { 295 union dmub_rb_cmd cmd = { 0 }; 296 struct dc_context *dc = dmub->ctx; 297 struct dmub_cmd_psr_copy_settings_data *copy_settings_data 298 = &cmd.psr_copy_settings.psr_copy_settings_data; 299 struct pipe_ctx *pipe_ctx = NULL; 300 struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx; 301 int i = 0; 302 303 for (i = 0; i < MAX_PIPES; i++) { 304 if (res_ctx->pipe_ctx[i].stream && 305 res_ctx->pipe_ctx[i].stream->link == link && 306 res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) { 307 pipe_ctx = &res_ctx->pipe_ctx[i]; 308 //TODO: refactor for multi edp support 309 break; 310 } 311 } 312 313 if (!pipe_ctx) 314 return false; 315 316 // First, set the psr version 317 if (!dmub_psr_set_version(dmub, pipe_ctx->stream, panel_inst)) 318 return false; 319 320 // Program DP DPHY fast training registers 321 link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc, 322 psr_context->psrExitLinkTrainingRequired); 323 324 // Program DP_SEC_CNTL1 register to set transmission GPS0 line num and priority to high 325 link->link_enc->funcs->psr_program_secondary_packet(link->link_enc, 326 psr_context->sdpTransmitLineNumDeadline); 327 328 memset(&cmd, 0, sizeof(cmd)); 329 cmd.psr_copy_settings.header.type = DMUB_CMD__PSR; 330 cmd.psr_copy_settings.header.sub_type = DMUB_CMD__PSR_COPY_SETTINGS; 331 cmd.psr_copy_settings.header.payload_bytes = sizeof(struct dmub_cmd_psr_copy_settings_data); 332 333 // Hw insts 334 copy_settings_data->dpphy_inst = psr_context->transmitterId; 335 copy_settings_data->aux_inst = psr_context->channel; 336 copy_settings_data->digfe_inst = psr_context->engineId; 337 copy_settings_data->digbe_inst = psr_context->transmitterId; 338 339 copy_settings_data->mpcc_inst = pipe_ctx->plane_res.mpcc_inst; 340 341 if (pipe_ctx->plane_res.dpp) 342 copy_settings_data->dpp_inst = pipe_ctx->plane_res.dpp->inst; 343 else 344 copy_settings_data->dpp_inst = 0; 345 if (pipe_ctx->stream_res.opp) 346 copy_settings_data->opp_inst = pipe_ctx->stream_res.opp->inst; 347 else 348 copy_settings_data->opp_inst = 0; 349 if (pipe_ctx->stream_res.tg) 350 copy_settings_data->otg_inst = pipe_ctx->stream_res.tg->inst; 351 else 352 copy_settings_data->otg_inst = 0; 353 354 // Misc 355 copy_settings_data->use_phy_fsm = link->ctx->dc->debug.psr_power_use_phy_fsm; 356 copy_settings_data->psr_level = psr_context->psr_level.u32all; 357 copy_settings_data->smu_optimizations_en = psr_context->allow_smu_optimizations; 358 copy_settings_data->multi_disp_optimizations_en = psr_context->allow_multi_disp_optimizations; 359 copy_settings_data->frame_delay = psr_context->frame_delay; 360 copy_settings_data->frame_cap_ind = psr_context->psrFrameCaptureIndicationReq; 361 copy_settings_data->init_sdp_deadline = psr_context->sdpTransmitLineNumDeadline; 362 copy_settings_data->debug.u32All = 0; 363 copy_settings_data->debug.bitfields.visual_confirm = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR; 364 copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1; 365 copy_settings_data->debug.bitfields.force_full_frame_update = 0; 366 367 if (psr_context->su_granularity_required == 0) 368 copy_settings_data->su_y_granularity = 0; 369 else 370 copy_settings_data->su_y_granularity = psr_context->su_y_granularity; 371 372 copy_settings_data->line_capture_indication = 0; 373 copy_settings_data->line_time_in_us = psr_context->line_time_in_us; 374 copy_settings_data->rate_control_caps = psr_context->rate_control_caps; 375 copy_settings_data->fec_enable_status = (link->fec_state == dc_link_fec_enabled); 376 copy_settings_data->fec_enable_delay_in100us = link->dc->debug.fec_enable_delay_in100us; 377 copy_settings_data->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; 378 copy_settings_data->panel_inst = panel_inst; 379 copy_settings_data->dsc_enable_status = (pipe_ctx->stream->timing.flags.DSC == 1); 380 381 /** 382 * WA for PSRSU+DSC on specific TCON, if DSC is enabled, force PSRSU as ffu mode(full frame update) 383 * Note that PSRSU+DSC is still under development. 384 */ 385 if (copy_settings_data->dsc_enable_status && 386 link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 && 387 !memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1, 388 sizeof(DP_SINK_DEVICE_STR_ID_1))) 389 link->psr_settings.force_ffu_mode = 1; 390 else 391 link->psr_settings.force_ffu_mode = 0; 392 copy_settings_data->force_ffu_mode = link->psr_settings.force_ffu_mode; 393 394 if (((link->dpcd_caps.fec_cap.bits.FEC_CAPABLE && 395 !link->dc->debug.disable_fec) && 396 (link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT && 397 !link->panel_config.dsc.disable_dsc_edp && 398 link->dc->caps.edp_dsc_support)) && 399 link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 && 400 (!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1, 401 sizeof(DP_SINK_DEVICE_STR_ID_1)) || 402 !memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_2, 403 sizeof(DP_SINK_DEVICE_STR_ID_2)))) 404 copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 1; 405 else 406 copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 0; 407 408 if (link->psr_settings.psr_version == DC_PSR_VERSION_1 && 409 link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_0022B9 && 410 !memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_3, 411 sizeof(DP_SINK_DEVICE_STR_ID_3))) { 412 copy_settings_data->poweroff_before_vertical_line = 16; 413 } 414 415 //WA for PSR1 on specific TCON, require frame delay for frame re-lock 416 copy_settings_data->relock_delay_frame_cnt = 0; 417 if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8) 418 copy_settings_data->relock_delay_frame_cnt = 2; 419 copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height; 420 421 dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 422 423 return true; 424 } 425 426 /* 427 * Send command to PSR to force static ENTER and ignore all state changes until exit 428 */ 429 static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst) 430 { 431 union dmub_rb_cmd cmd; 432 struct dc_context *dc = dmub->ctx; 433 434 memset(&cmd, 0, sizeof(cmd)); 435 436 cmd.psr_force_static.psr_force_static_data.panel_inst = panel_inst; 437 cmd.psr_force_static.psr_force_static_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; 438 cmd.psr_force_static.header.type = DMUB_CMD__PSR; 439 cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC; 440 cmd.psr_enable.header.payload_bytes = 0; 441 442 dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 443 } 444 445 /* 446 * Get PSR residency from firmware. 447 */ 448 static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency, uint8_t panel_inst) 449 { 450 uint16_t param = (uint16_t)(panel_inst << 8); 451 452 /* Send gpint command and wait for ack */ 453 dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__PSR_RESIDENCY, param, residency, 454 DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); 455 } 456 457 static const struct dmub_psr_funcs psr_funcs = { 458 .psr_copy_settings = dmub_psr_copy_settings, 459 .psr_enable = dmub_psr_enable, 460 .psr_get_state = dmub_psr_get_state, 461 .psr_set_level = dmub_psr_set_level, 462 .psr_force_static = dmub_psr_force_static, 463 .psr_get_residency = dmub_psr_get_residency, 464 .psr_set_sink_vtotal_in_psr_active = dmub_psr_set_sink_vtotal_in_psr_active, 465 .psr_set_power_opt = dmub_psr_set_power_opt, 466 }; 467 468 /* 469 * Construct PSR object. 470 */ 471 static void dmub_psr_construct(struct dmub_psr *psr, struct dc_context *ctx) 472 { 473 psr->ctx = ctx; 474 psr->funcs = &psr_funcs; 475 } 476 477 /* 478 * Allocate and initialize PSR object. 479 */ 480 struct dmub_psr *dmub_psr_create(struct dc_context *ctx) 481 { 482 struct dmub_psr *psr = kzalloc(sizeof(struct dmub_psr), GFP_KERNEL); 483 484 if (psr == NULL) { 485 BREAK_TO_DEBUGGER(); 486 return NULL; 487 } 488 489 dmub_psr_construct(psr, ctx); 490 491 return psr; 492 } 493 494 /* 495 * Deallocate PSR object. 496 */ 497 void dmub_psr_destroy(struct dmub_psr **dmub) 498 { 499 kfree(*dmub); 500 *dmub = NULL; 501 } 502