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