}
bool dc_link_setup_psr(const struct dc_link *dc_link,
- const struct dc_stream *stream, struct psr_config *psr_config)
+ const struct dc_stream *stream, struct psr_config *psr_config,
+ struct psr_context *psr_context)
{
struct core_link *link = DC_LINK_TO_CORE(dc_link);
struct dc_context *ctx = link->ctx;
struct core_dc *core_dc = DC_TO_CORE(ctx->dc);
struct dmcu *dmcu = core_dc->res_pool->dmcu;
struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
- struct psr_context psr_context = {0};
int i;
- psr_context.controllerId = CONTROLLER_ID_UNDEFINED;
+ psr_context->controllerId = CONTROLLER_ID_UNDEFINED;
if (dc_link != NULL &&
dmcu != NULL) {
&psr_configuration.raw,
sizeof(psr_configuration.raw));
- psr_context.channel = link->public.ddc->ddc_pin->hw_info.ddc_channel;
- psr_context.transmitterId = link->link_enc->transmitter;
- psr_context.engineId = link->link_enc->preferred_engine;
+ psr_context->channel = link->public.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_context->res_ctx.pipe_ctx[i].stream
/* dmcu -1 for all controller id values,
* therefore +1 here
*/
- psr_context.controllerId =
+ psr_context->controllerId =
core_dc->current_context->res_ctx.
pipe_ctx[i].tg->inst + 1;
break;
}
/* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/
- psr_context.phyType = PHY_TYPE_UNIPHY;
+ psr_context->phyType = PHY_TYPE_UNIPHY;
/*PhyId is associated with the transmitter id*/
- psr_context.smuPhyId = link->link_enc->transmitter;
+ psr_context->smuPhyId = link->link_enc->transmitter;
- psr_context.crtcTimingVerticalTotal = stream->timing.v_total;
- psr_context.vsyncRateHz = div64_u64(div64_u64((stream->
+ psr_context->crtcTimingVerticalTotal = stream->timing.v_total;
+ psr_context->vsyncRateHz = div64_u64(div64_u64((stream->
timing.pix_clk_khz * 1000),
stream->timing.v_total),
stream->timing.h_total);
- psr_context.psrSupportedDisplayConfig = true;
- psr_context.psrExitLinkTrainingRequired =
+ psr_context->psrSupportedDisplayConfig = true;
+ psr_context->psrExitLinkTrainingRequired =
psr_config->psr_exit_link_training_required;
- psr_context.sdpTransmitLineNumDeadline =
+ psr_context->sdpTransmitLineNumDeadline =
psr_config->psr_sdp_transmit_line_num_deadline;
- psr_context.psrFrameCaptureIndicationReq =
+ psr_context->psrFrameCaptureIndicationReq =
psr_config->psr_frame_capture_indication_req;
- psr_context.skipPsrWaitForPllLock = 0; /* only = 1 in KV */
+ psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */
- psr_context.numberOfControllers =
+ psr_context->numberOfControllers =
link->dc->res_pool->res_cap->num_timing_generator;
- psr_context.rfb_update_auto_en = true;
+ psr_context->rfb_update_auto_en = true;
/* 2 frames before enter PSR. */
- psr_context.timehyst_frames = 2;
+ 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->hyst_lines = stream->timing.v_total / 2 / 100;
+ psr_context->aux_repeats = 10;
- psr_context.psr_level.u32all = 0;
+ psr_context->psr_level.u32all = 0;
/* 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.psr_level.bits.SKIP_SMU_NOTIFICATION = 1;
+ psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION = 1;
/* Complete PSR entry before aborting to prevent intermittent
* freezes on certain eDPs
*/
- psr_context.psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1;
+ 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;
+ psr_context->frame_delay = 0;
link->psr_enabled = true;
- dmcu->funcs->setup_psr(dmcu, link, &psr_context);
+ dmcu->funcs->setup_psr(dmcu, link, psr_context);
return true;
} else
return false;
bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state);
bool dc_link_setup_psr(const struct dc_link *dc_link,
- const struct dc_stream *stream, struct psr_config *psr_config);
+ const struct dc_stream *stream, struct psr_config *psr_config,
+ struct psr_context *psr_context);
/* Request DC to detect if there is a Panel connected.
* boot - If this call is during initial boot.
#include "dc_dp_types.h"
#include "dc_hw_types.h"
#include "dal_types.h"
+#include "grph_object_defs.h"
/* forward declarations */
struct dc_surface;
unsigned int psr_sdp_transmit_line_num_deadline;
};
+union dmcu_psr_level {
+ struct {
+ unsigned int SKIP_CRC:1;
+ unsigned int SKIP_DP_VID_STREAM_DISABLE:1;
+ unsigned int SKIP_PHY_POWER_DOWN:1;
+ unsigned int SKIP_AUX_ACK_CHECK:1;
+ unsigned int SKIP_CRTC_DISABLE:1;
+ unsigned int SKIP_AUX_RFB_CAPTURE_CHECK:1;
+ unsigned int SKIP_SMU_NOTIFICATION:1;
+ unsigned int SKIP_AUTO_STATE_ADVANCE:1;
+ unsigned int DISABLE_PSR_ENTRY_ABORT:1;
+ unsigned int RESERVED:23;
+ } bits;
+ unsigned int u32all;
+};
+
+enum physical_phy_id {
+ PHYLD_0,
+ PHYLD_1,
+ PHYLD_2,
+ PHYLD_3,
+ PHYLD_4,
+ PHYLD_5,
+ PHYLD_6,
+ PHYLD_7,
+ PHYLD_8,
+ PHYLD_9,
+ PHYLD_COUNT,
+ PHYLD_UNKNOWN = (-1L)
+};
+
+enum phy_type {
+ PHY_TYPE_UNKNOWN = 1,
+ PHY_TYPE_PCIE_PHY = 2,
+ PHY_TYPE_UNIPHY = 3,
+};
+
+struct psr_context {
+ /* ddc line */
+ enum channel_id channel;
+ /* Transmitter id */
+ enum transmitter transmitterId;
+ /* Engine Id is used for Dig Be source select */
+ enum engine_id engineId;
+ /* Controller Id used for Dig Fe source select */
+ enum controller_id controllerId;
+ /* Pcie or Uniphy */
+ enum phy_type phyType;
+ /* Physical PHY Id used by SMU interpretation */
+ enum physical_phy_id smuPhyId;
+ /* Vertical total pixels from crtc timing.
+ * This is used for static screen detection.
+ * ie. If we want to detect half a frame,
+ * we use this to determine the hyst lines.
+ */
+ unsigned int crtcTimingVerticalTotal;
+ /* PSR supported from panel capabilities and
+ * current display configuration
+ */
+ bool psrSupportedDisplayConfig;
+ /* Whether fast link training is supported by the panel */
+ bool psrExitLinkTrainingRequired;
+ /* If RFB setup time is greater than the total VBLANK time,
+ * it is not possible for the sink to capture the video frame
+ * in the same frame the SDP is sent. In this case,
+ * the frame capture indication bit should be set and an extra
+ * static frame should be transmitted to the sink.
+ */
+ bool psrFrameCaptureIndicationReq;
+ /* Set the last possible line SDP may be transmitted without violating
+ * the RFB setup time or entering the active video frame.
+ */
+ unsigned int sdpTransmitLineNumDeadline;
+ /* The VSync rate in Hz used to calculate the
+ * step size for smooth brightness feature
+ */
+ unsigned int vsyncRateHz;
+ unsigned int skipPsrWaitForPllLock;
+ unsigned int numberOfControllers;
+ /* Unused, for future use. To indicate that first changed frame from
+ * state3 shouldn't result in psr_inactive, but rather to perform
+ * an automatic single frame rfb_update.
+ */
+ bool rfb_update_auto_en;
+ /* Number of frame before entering static screen */
+ unsigned int timehyst_frames;
+ /* Partial frames before entering static screen */
+ unsigned int hyst_lines;
+ /* # of repeated AUX transaction attempts to make before
+ * indicating failure to the driver
+ */
+ unsigned int aux_repeats;
+ /* Controls hw blocks to power down during PSR active state */
+ union dmcu_psr_level psr_level;
+ /* Controls additional delay after remote frame capture before
+ * continuing powerd own
+ */
+ unsigned int frame_delay;
+};
+
struct colorspace_transform {
struct fixed31_32 matrix[12];
bool enable_remap;
#include "dc.h"
#include "core_dc.h"
#include "dce_abm.h"
+#include "dmcu.h"
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
#include "dcn_calcs.h"
#include "core_dc.h"
clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
}
-#define PSR_SET_WAITLOOP 0x31
-
-union dce110_dmcu_psr_config_data_wait_loop_reg1 {
- struct {
- unsigned int wait_loop:16; /* [15:0] */
- unsigned int reserved:16; /* [31:16] */
- } bits;
- unsigned int u32;
-};
-
-static void dce_psr_wait_loop(
- struct dce_disp_clk *clk_dce, unsigned int display_clk_khz)
-{
- struct dc_context *ctx = clk_dce->base.ctx;
- union dce110_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1;
-
- /* waitDMCUReadyForCmd */
- REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100);
-
- masterCmdData1.u32 = 0;
- masterCmdData1.bits.wait_loop = display_clk_khz / 1000 / 7;
- dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32);
-
- /* setDMCUParam_Cmd */
- REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP);
-
- /* notifyDMCUMsg */
- REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
-}
-
static void dce_psr_set_clock(
struct display_clock *clk,
int requested_clk_khz)
{
struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk);
+ struct dc_context *ctx = clk_dce->base.ctx;
+ struct core_dc *core_dc = DC_TO_CORE(ctx->dc);
+ struct dmcu *dmcu = core_dc->res_pool->dmcu;
dce_set_clock(clk, requested_clk_khz);
- dce_psr_wait_loop(clk_dce, requested_clk_khz);
+
+ dmcu->funcs->set_psr_wait_loop(dmcu, requested_clk_khz / 1000 / 7);
}
static void dce112_set_clock(
struct dc_bios *bp = clk->ctx->dc_bios;
struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc);
struct abm *abm = core_dc->res_pool->abm;
+ struct dmcu *dmcu = core_dc->res_pool->dmcu;
/* Prepare to program display clock*/
memset(&dce_clk_params, 0, sizeof(dce_clk_params));
bp->funcs->set_dce_clock(bp, &dce_clk_params);
if (abm->funcs->is_dmcu_initialized(abm))
- dce_psr_wait_loop(clk_dce, requested_clk_khz);
+ dmcu->funcs->set_psr_wait_loop(dmcu,
+ requested_clk_khz / 1000 / 7);
}
#define PSR_ENABLE 0x20
#define PSR_EXIT 0x21
#define PSR_SET 0x23
+#define PSR_SET_WAITLOOP 0x31
#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L
+unsigned int cached_wait_loop_number = 0;
bool dce_dmcu_load_iram(struct dmcu *dmcu,
unsigned int start_offset,
REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
}
+static void dce_psr_wait_loop(
+ struct dmcu *dmcu,
+ unsigned int wait_loop_number)
+{
+ struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
+ union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1;
+
+ /* waitDMCUReadyForCmd */
+ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100);
+
+ masterCmdData1.u32 = 0;
+ masterCmdData1.bits.wait_loop = wait_loop_number;
+ cached_wait_loop_number = wait_loop_number;
+ dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32);
+
+ /* setDMCUParam_Cmd */
+ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP);
+
+ /* notifyDMCUMsg */
+ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+}
+
+static void dce_get_psr_wait_loop(unsigned int *psr_wait_loop_number)
+{
+ *psr_wait_loop_number = cached_wait_loop_number;
+ return;
+}
+
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
bool dcn10_dmcu_load_iram(struct dmcu *dmcu,
unsigned int start_offset,
REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
}
+static void dcn10_psr_wait_loop(
+ struct dmcu *dmcu,
+ unsigned int wait_loop_number)
+{
+ struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
+ union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1;
+
+ /* waitDMCUReadyForCmd */
+ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100);
+
+ masterCmdData1.u32 = 0;
+ masterCmdData1.bits.wait_loop = wait_loop_number;
+ cached_wait_loop_number = wait_loop_number;
+ dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32);
+
+ /* setDMCUParam_Cmd */
+ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP);
+
+ /* notifyDMCUMsg */
+ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+}
+
+static void dcn10_get_psr_wait_loop(unsigned int *psr_wait_loop_number)
+{
+ *psr_wait_loop_number = cached_wait_loop_number;
+ return;
+}
+
#endif
static const struct dmcu_funcs dce_funcs = {
.load_iram = dce_dmcu_load_iram,
.set_psr_enable = dce_dmcu_set_psr_enable,
.setup_psr = dce_dmcu_setup_psr,
- .get_psr_state = dce_get_dmcu_psr_state
+ .get_psr_state = dce_get_dmcu_psr_state,
+ .set_psr_wait_loop = dce_psr_wait_loop,
+ .get_psr_wait_loop = dce_get_psr_wait_loop
};
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
.load_iram = dcn10_dmcu_load_iram,
.set_psr_enable = dcn10_dmcu_set_psr_enable,
.setup_psr = dcn10_dmcu_setup_psr,
- .get_psr_state = dcn10_get_dmcu_psr_state
+ .get_psr_state = dcn10_get_dmcu_psr_state,
+ .set_psr_wait_loop = dcn10_psr_wait_loop,
+ .get_psr_wait_loop = dcn10_get_psr_wait_loop
};
#endif
unsigned int u32All;
};
+union dce_dmcu_psr_config_data_wait_loop_reg1 {
+ struct {
+ unsigned int wait_loop:16; /* [15:0] */
+ unsigned int reserved:16; /* [31:16] */
+ } bits;
+ unsigned int u32;
+};
+
struct dmcu *dce_dmcu_create(
struct dc_context *ctx,
const struct dce_dmcu_registers *regs,
struct core_link *link,
struct psr_context *psr_context);
void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state);
+ void (*set_psr_wait_loop)(struct dmcu *dmcu,
+ unsigned int wait_loop_number);
+ void (*get_psr_wait_loop)(unsigned int *psr_wait_loop_number);
};
#endif
bool ycbcr420_supported;
};
-enum physical_phy_id {
- PHYLD_0,
- PHYLD_1,
- PHYLD_2,
- PHYLD_3,
- PHYLD_4,
- PHYLD_5,
- PHYLD_6,
- PHYLD_7,
- PHYLD_8,
- PHYLD_9,
- PHYLD_COUNT,
- PHYLD_UNKNOWN = (-1L)
-};
-
-enum phy_type {
- PHY_TYPE_UNKNOWN = 1,
- PHY_TYPE_PCIE_PHY = 2,
- PHY_TYPE_UNIPHY = 3,
-};
-
-union dmcu_psr_level {
- struct {
- unsigned int SKIP_CRC:1;
- unsigned int SKIP_DP_VID_STREAM_DISABLE:1;
- unsigned int SKIP_PHY_POWER_DOWN:1;
- unsigned int SKIP_AUX_ACK_CHECK:1;
- unsigned int SKIP_CRTC_DISABLE:1;
- unsigned int SKIP_AUX_RFB_CAPTURE_CHECK:1;
- unsigned int SKIP_SMU_NOTIFICATION:1;
- unsigned int SKIP_AUTO_STATE_ADVANCE:1;
- unsigned int DISABLE_PSR_ENTRY_ABORT:1;
- unsigned int RESERVED:23;
- } bits;
- unsigned int u32all;
-};
-
union dpcd_psr_configuration {
struct {
unsigned char ENABLE : 1;
unsigned char raw;
};
-struct psr_context {
- /* ddc line */
- enum channel_id channel;
- /* Transmitter id */
- enum transmitter transmitterId;
- /* Engine Id is used for Dig Be source select */
- enum engine_id engineId;
- /* Controller Id used for Dig Fe source select */
- enum controller_id controllerId;
- /* Pcie or Uniphy */
- enum phy_type phyType;
- /* Physical PHY Id used by SMU interpretation */
- enum physical_phy_id smuPhyId;
- /* Vertical total pixels from crtc timing.
- * This is used for static screen detection.
- * ie. If we want to detect half a frame,
- * we use this to determine the hyst lines.
- */
- unsigned int crtcTimingVerticalTotal;
- /* PSR supported from panel capabilities and
- * current display configuration
- */
- bool psrSupportedDisplayConfig;
- /* Whether fast link training is supported by the panel */
- bool psrExitLinkTrainingRequired;
- /* If RFB setup time is greater than the total VBLANK time,
- * it is not possible for the sink to capture the video frame
- * in the same frame the SDP is sent. In this case,
- * the frame capture indication bit should be set and an extra
- * static frame should be transmitted to the sink.
- */
- bool psrFrameCaptureIndicationReq;
- /* Set the last possible line SDP may be transmitted without violating
- * the RFB setup time or entering the active video frame.
- */
- unsigned int sdpTransmitLineNumDeadline;
- /* The VSync rate in Hz used to calculate the
- * step size for smooth brightness feature
- */
- unsigned int vsyncRateHz;
- unsigned int skipPsrWaitForPllLock;
- unsigned int numberOfControllers;
- /* Unused, for future use. To indicate that first changed frame from
- * state3 shouldn't result in psr_inactive, but rather to perform
- * an automatic single frame rfb_update.
- */
- bool rfb_update_auto_en;
- /* Number of frame before entering static screen */
- unsigned int timehyst_frames;
- /* Partial frames before entering static screen */
- unsigned int hyst_lines;
- /* # of repeated AUX transaction attempts to make before
- * indicating failure to the driver
- */
- unsigned int aux_repeats;
- /* Controls hw blocks to power down during PSR active state */
- union dmcu_psr_level psr_level;
- /* Controls additional delay after remote frame capture before
- * continuing powerd own
- */
- unsigned int frame_delay;
-};
-
-
struct link_encoder {
const struct link_encoder_funcs *funcs;
int32_t aux_channel_offset;