drm/amd/display: Add debugfs entry for reading psr state
[Why] For upcoming PSR stupport it's useful to have debug entry to verify psr state. [How] - Enable psr dc api for Linux - Add psr_state file to eDP connector debugfs usage e.g.: cat /sys/kernel/debug/dri/0/DP-1/psr_state Signed-off-by: Roman Li <Roman.Li@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Leo Li <sunpeng.li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
		
							parent
							
								
									37b970d1d7
								
							
						
					
					
						commit
						e0d08a40a6
					
				| @ -969,6 +969,25 @@ static int force_yuv420_output_get(void *data, u64 *val) | ||||
| DEFINE_DEBUGFS_ATTRIBUTE(force_yuv420_output_fops, force_yuv420_output_get, | ||||
| 			 force_yuv420_output_set, "%llu\n"); | ||||
| 
 | ||||
| /*
 | ||||
|  *  Read PSR state | ||||
|  */ | ||||
| static int psr_get(void *data, u64 *val) | ||||
| { | ||||
| 	struct amdgpu_dm_connector *connector = data; | ||||
| 	struct dc_link *link = connector->dc_link; | ||||
| 	uint32_t psr_state = 0; | ||||
| 
 | ||||
| 	dc_link_get_psr_state(link, &psr_state); | ||||
| 
 | ||||
| 	*val = psr_state; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n"); | ||||
| 
 | ||||
| void connector_debugfs_init(struct amdgpu_dm_connector *connector) | ||||
| { | ||||
| 	int i; | ||||
| @ -982,6 +1001,8 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector) | ||||
| 					    dp_debugfs_entries[i].fops); | ||||
| 		} | ||||
| 	} | ||||
| 	if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) | ||||
| 		debugfs_create_file_unsafe("psr_state", 0444, dir, connector, &psr_fops); | ||||
| 
 | ||||
| 	debugfs_create_file_unsafe("force_yuv420_output", 0644, dir, connector, | ||||
| 				   &force_yuv420_output_fops); | ||||
|  | ||||
| @ -2436,6 +2436,155 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) | ||||
| { | ||||
| 	struct dc  *core_dc = link->ctx->dc; | ||||
| 	struct dmcu *dmcu = core_dc->res_pool->dmcu; | ||||
| 
 | ||||
| 	if (dmcu != NULL && link->psr_feature_enabled) | ||||
| 		dmcu->funcs->get_psr_state(dmcu, psr_state); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool dc_link_setup_psr(struct dc_link *link, | ||||
| 		const struct dc_stream_state *stream, struct psr_config *psr_config, | ||||
| 		struct psr_context *psr_context) | ||||
| { | ||||
| 	struct dc *core_dc; | ||||
| 	struct dmcu *dmcu; | ||||
| 	int i; | ||||
| 	/* updateSinkPsrDpcdConfig*/ | ||||
| 	union dpcd_psr_configuration psr_configuration; | ||||
| 
 | ||||
| 	psr_context->controllerId = CONTROLLER_ID_UNDEFINED; | ||||
| 
 | ||||
| 	if (!link) | ||||
| 		return false; | ||||
| 
 | ||||
| 	core_dc = link->ctx->dc; | ||||
| 	dmcu = core_dc->res_pool->dmcu; | ||||
| 
 | ||||
| 	if (!dmcu) | ||||
| 		return false; | ||||
| 
 | ||||
| 
 | ||||
| 	memset(&psr_configuration, 0, sizeof(psr_configuration)); | ||||
| 
 | ||||
| 	psr_configuration.bits.ENABLE                    = 1; | ||||
| 	psr_configuration.bits.CRC_VERIFICATION          = 1; | ||||
| 	psr_configuration.bits.FRAME_CAPTURE_INDICATION  = | ||||
| 			psr_config->psr_frame_capture_indication_req; | ||||
| 
 | ||||
| 	/* Check for PSR v2*/ | ||||
| 	if (psr_config->psr_version == 0x2) { | ||||
| 		/* For PSR v2 selective update.
 | ||||
| 		 * Indicates whether sink should start capturing | ||||
| 		 * immediately following active scan line, | ||||
| 		 * or starting with the 2nd active scan line. | ||||
| 		 */ | ||||
| 		psr_configuration.bits.LINE_CAPTURE_INDICATION = 0; | ||||
| 		/*For PSR v2, determines whether Sink should generate
 | ||||
| 		 * IRQ_HPD when CRC mismatch is detected. | ||||
| 		 */ | ||||
| 		psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR    = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	dm_helpers_dp_write_dpcd( | ||||
| 		link->ctx, | ||||
| 		link, | ||||
| 		368, | ||||
| 		&psr_configuration.raw, | ||||
| 		sizeof(psr_configuration.raw)); | ||||
| 
 | ||||
| 	psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel; | ||||
| 	psr_context->transmitterId = link->link_enc->transmitter; | ||||
| 	psr_context->engineId = link->link_enc->preferred_engine; | ||||
| 
 | ||||
| 	for (i = 0; i < MAX_PIPES; i++) { | ||||
| 		if (core_dc->current_state->res_ctx.pipe_ctx[i].stream | ||||
| 				== stream) { | ||||
| 			/* dmcu -1 for all controller id values,
 | ||||
| 			 * therefore +1 here | ||||
| 			 */ | ||||
| 			psr_context->controllerId = | ||||
| 				core_dc->current_state->res_ctx. | ||||
| 				pipe_ctx[i].stream_res.tg->inst + 1; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Hardcoded for now.  Can be Pcie or Uniphy (or Unknown)*/ | ||||
| 	psr_context->phyType = PHY_TYPE_UNIPHY; | ||||
| 	/*PhyId is associated with the transmitter id*/ | ||||
| 	psr_context->smuPhyId = link->link_enc->transmitter; | ||||
| 
 | ||||
| 	psr_context->crtcTimingVerticalTotal = stream->timing.v_total; | ||||
| 	psr_context->vsyncRateHz = div64_u64(div64_u64((stream-> | ||||
| 					timing.pix_clk_100hz * 100), | ||||
| 					stream->timing.v_total), | ||||
| 					stream->timing.h_total); | ||||
| 
 | ||||
| 	psr_context->psrSupportedDisplayConfig = true; | ||||
| 	psr_context->psrExitLinkTrainingRequired = | ||||
| 		psr_config->psr_exit_link_training_required; | ||||
| 	psr_context->sdpTransmitLineNumDeadline = | ||||
| 		psr_config->psr_sdp_transmit_line_num_deadline; | ||||
| 	psr_context->psrFrameCaptureIndicationReq = | ||||
| 		psr_config->psr_frame_capture_indication_req; | ||||
| 
 | ||||
| 	psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */ | ||||
| 
 | ||||
| 	psr_context->numberOfControllers = | ||||
| 			link->dc->res_pool->timing_generator_count; | ||||
| 
 | ||||
| 	psr_context->rfb_update_auto_en = true; | ||||
| 
 | ||||
| 	/* 2 frames before enter PSR. */ | ||||
| 	psr_context->timehyst_frames = 2; | ||||
| 	/* half a frame
 | ||||
| 	 * (units in 100 lines, i.e. a value of 1 represents 100 lines) | ||||
| 	 */ | ||||
| 	psr_context->hyst_lines = stream->timing.v_total / 2 / 100; | ||||
| 	psr_context->aux_repeats = 10; | ||||
| 
 | ||||
| 	psr_context->psr_level.u32all = 0; | ||||
| 
 | ||||
| #if defined(CONFIG_DRM_AMD_DC_DCN1_0) | ||||
| 	/*skip power down the single pipe since it blocks the cstate*/ | ||||
| 	if (ASICREV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) | ||||
| 		psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; | ||||
| #endif | ||||
| 
 | ||||
| 	/* SMU will perform additional powerdown sequence.
 | ||||
| 	 * For unsupported ASICs, set psr_level flag to skip PSR | ||||
| 	 *  static screen notification to SMU. | ||||
| 	 *  (Always set for DAL2, did not check ASIC) | ||||
| 	 */ | ||||
| 	psr_context->allow_smu_optimizations = psr_config->allow_smu_optimizations; | ||||
| 
 | ||||
| 	/* Complete PSR entry before aborting to prevent intermittent
 | ||||
| 	 * freezes on certain eDPs | ||||
| 	 */ | ||||
| 	psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; | ||||
| 
 | ||||
| 	/* Controls additional delay after remote frame capture before
 | ||||
| 	 * continuing power down, default = 0 | ||||
| 	 */ | ||||
| 	psr_context->frame_delay = 0; | ||||
| 
 | ||||
| 	link->psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context); | ||||
| 
 | ||||
| 	/* psr_enabled == 0 indicates setup_psr did not succeed, but this
 | ||||
| 	 * should not happen since firmware should be running at this point | ||||
| 	 */ | ||||
| 	if (link->psr_feature_enabled == 0) | ||||
| 		ASSERT(0); | ||||
| 
 | ||||
| 	return true; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| const struct dc_link_status *dc_link_get_status(const struct dc_link *link) | ||||
| { | ||||
| 	return &link->link_status; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user