Commit 3bc8d921 authored by Fangzhi Zuo's avatar Fangzhi Zuo Committed by Alex Deucher

drm/amd/display: Add DP 2.0 HPO Link Encoder

HW Blocks:

        +--------+  +-----+  +------+
        |  OPTC  |  | HDA |  | HUBP |
        +--------+  +-----+  +------+
            |          |        |
            |          |        |
    HPO ====|==========|========|====
     |      |          v        |
     |      |       +-----+     |
     |      |       | APG |     |
     |      |       +-----+     |
     |      |          |        |
     |      v          v        v
     |     +---------------------+
     |     |  HPO Stream Encoder |
     |     +---------------------+
     |                 |
     |                 v
     |      +--------------------+
     |      |  HPO Link Encoder  |
     v      +--------------------+

[squash in warning fixes - Alex]
Signed-off-by: default avatarFangzhi Zuo <Jerry.Zuo@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 83228ebb
...@@ -45,6 +45,10 @@ struct dc_link_status { ...@@ -45,6 +45,10 @@ struct dc_link_status {
struct link_mst_stream_allocation { struct link_mst_stream_allocation {
/* DIG front */ /* DIG front */
const struct stream_encoder *stream_enc; const struct stream_encoder *stream_enc;
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* HPO DP Stream Encoder */
const struct hpo_dp_stream_encoder *hpo_dp_stream_enc;
#endif
/* associate DRM payload table with DC stream encoder */ /* associate DRM payload table with DC stream encoder */
uint8_t vcp_id; uint8_t vcp_id;
/* number of slots required for the DP stream in transport packet */ /* number of slots required for the DP stream in transport packet */
......
...@@ -497,6 +497,38 @@ void dcn10_log_hw_state(struct dc *dc, ...@@ -497,6 +497,38 @@ void dcn10_log_hw_state(struct dc *dc,
DTN_INFO("\n"); DTN_INFO("\n");
} }
/* log DP HPO L_ENC section if any hpo_dp_link_enc exists */
for (i = 0; i < dc->link_count; i++)
if (dc->links[i]->hpo_dp_link_enc)
hpo_dp_link_enc_count++;
if (hpo_dp_link_enc_count) {
DTN_INFO("DP HPO L_ENC: Enabled Mode Lanes Stream Slots VC Rate X VC Rate Y\n");
for (i = 0; i < dc->link_count; i++) {
struct hpo_dp_link_encoder *hpo_dp_link_enc = dc->links[i]->hpo_dp_link_enc;
struct hpo_dp_link_enc_state hpo_dp_le_state = {0};
if (hpo_dp_link_enc && hpo_dp_link_enc->funcs->read_state) {
hpo_dp_link_enc->funcs->read_state(hpo_dp_link_enc, &hpo_dp_le_state);
DTN_INFO("[%d]: %d %6s %d %d %d %d %d\n",
hpo_dp_link_enc->inst,
hpo_dp_le_state.link_enc_enabled,
(hpo_dp_le_state.link_mode == 0) ? "TPS1" :
(hpo_dp_le_state.link_mode == 1) ? "TPS2" :
(hpo_dp_le_state.link_mode == 2) ? "ACTIVE" : "TEST",
hpo_dp_le_state.lane_count,
hpo_dp_le_state.stream_src[0],
hpo_dp_le_state.slot_count[0],
hpo_dp_le_state.vc_rate_x[0],
hpo_dp_le_state.vc_rate_y[0]);
DTN_INFO("\n");
}
}
DTN_INFO("\n");
}
} }
DTN_INFO_END(); DTN_INFO_END();
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
DCN31 = dcn31_resource.o dcn31_hubbub.o dcn31_hwseq.o dcn31_init.o dcn31_hubp.o \ DCN31 = dcn31_resource.o dcn31_hubbub.o dcn31_hwseq.o dcn31_init.o dcn31_hubp.o \
dcn31_dccg.o dcn31_optc.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ dcn31_dccg.o dcn31_optc.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \
dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o
ifdef CONFIG_X86 ifdef CONFIG_X86
CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o := -msse CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o := -msse
......
...@@ -320,6 +320,10 @@ void dcn31_link_encoder_construct( ...@@ -320,6 +320,10 @@ void dcn31_link_encoder_construct(
enc10->base.features.flags.bits.IS_HBR3_CAPABLE = enc10->base.features.flags.bits.IS_HBR3_CAPABLE =
bp_cap_info.DP_HBR3_EN; bp_cap_info.DP_HBR3_EN;
enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE;
enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN;
enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN;
enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
enc10->base.features.flags.bits.DP_IS_USB_C = enc10->base.features.flags.bits.DP_IS_USB_C =
bp_cap_info.DP_IS_USB_C; bp_cap_info.DP_IS_USB_C;
} else { } else {
......
/*
* Copyright 2019 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dc_bios_types.h"
#include "dcn31_hpo_dp_link_encoder.h"
#include "reg_helper.h"
#include "dc_link.h"
#include "stream_encoder.h"
#define DC_LOGGER \
enc3->base.ctx->logger
#define REG(reg)\
(enc3->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
enc3->hpo_le_shift->field_name, enc3->hpo_le_mask->field_name
#define CTX \
enc3->base.ctx
enum {
DP_SAT_UPDATE_MAX_RETRY = 200
};
void dcn31_hpo_dp_link_enc_enable(
struct hpo_dp_link_encoder *enc,
enum dc_lane_count num_lanes)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
uint32_t dp_link_enabled;
/* get current status of link enabled */
REG_GET(DP_DPHY_SYM32_STATUS,
STATUS, &dp_link_enabled);
/* Enable clocks first */
REG_UPDATE(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, 1);
/* Reset DPHY. Only reset if going from disable to enable */
if (!dp_link_enabled) {
REG_UPDATE(DP_DPHY_SYM32_CONTROL, DPHY_RESET, 1);
REG_UPDATE(DP_DPHY_SYM32_CONTROL, DPHY_RESET, 0);
}
/* Configure DPHY settings */
REG_UPDATE_3(DP_DPHY_SYM32_CONTROL,
DPHY_ENABLE, 1,
PRECODER_ENABLE, 1,
NUM_LANES, num_lanes == LANE_COUNT_ONE ? 0 : num_lanes == LANE_COUNT_TWO ? 1 : 3);
}
void dcn31_hpo_dp_link_enc_disable(
struct hpo_dp_link_encoder *enc)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
/* Configure DPHY settings */
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
DPHY_ENABLE, 0);
/* Shut down clock last */
REG_UPDATE(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, 0);
}
void dcn31_hpo_dp_link_enc_set_link_test_pattern(
struct hpo_dp_link_encoder *enc,
struct encoder_set_dp_phy_pattern_param *tp_params)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
uint32_t tp_custom;
switch (tp_params->dp_phy_pattern) {
case DP_TEST_PATTERN_VIDEO_MODE:
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_LINK_ACTIVE);
break;
case DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE:
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_LINK_TRAINING_TPS1);
break;
case DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE:
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_LINK_TRAINING_TPS2);
break;
case DP_TEST_PATTERN_128b_132b_TPS1:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_TPS1,
TP_SELECT1, DP_DPHY_TP_SELECT_TPS1,
TP_SELECT2, DP_DPHY_TP_SELECT_TPS1,
TP_SELECT3, DP_DPHY_TP_SELECT_TPS1);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_128b_132b_TPS2:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_TPS2,
TP_SELECT1, DP_DPHY_TP_SELECT_TPS2,
TP_SELECT2, DP_DPHY_TP_SELECT_TPS2,
TP_SELECT3, DP_DPHY_TP_SELECT_TPS2);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS7:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS7,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS7,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS7,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS7);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS9:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS9,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS9,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS9,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS9);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS11:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS11,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS11,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS11,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS11);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS15:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS15,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS15,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS15,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS15);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS23:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS23,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS23,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS23,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS23);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_PRBS31:
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_PRBS_SEL0, DP_DPHY_TP_PRBS31,
TP_PRBS_SEL1, DP_DPHY_TP_PRBS31,
TP_PRBS_SEL2, DP_DPHY_TP_PRBS31,
TP_PRBS_SEL3, DP_DPHY_TP_PRBS31);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_264BIT_CUSTOM:
tp_custom = (tp_params->custom_pattern[2] << 16) | (tp_params->custom_pattern[1] << 8) | tp_params->custom_pattern[0];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM0, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[5] << 16) | (tp_params->custom_pattern[4] << 8) | tp_params->custom_pattern[3];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM1, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[8] << 16) | (tp_params->custom_pattern[7] << 8) | tp_params->custom_pattern[6];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM2, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[11] << 16) | (tp_params->custom_pattern[10] << 8) | tp_params->custom_pattern[9];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM3, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[14] << 16) | (tp_params->custom_pattern[13] << 8) | tp_params->custom_pattern[12];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM4, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[17] << 16) | (tp_params->custom_pattern[16] << 8) | tp_params->custom_pattern[15];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM5, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[20] << 16) | (tp_params->custom_pattern[19] << 8) | tp_params->custom_pattern[18];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM6, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[23] << 16) | (tp_params->custom_pattern[22] << 8) | tp_params->custom_pattern[21];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM7, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[26] << 16) | (tp_params->custom_pattern[25] << 8) | tp_params->custom_pattern[24];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM8, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[29] << 16) | (tp_params->custom_pattern[28] << 8) | tp_params->custom_pattern[27];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM9, 0, TP_CUSTOM, tp_custom);
tp_custom = (tp_params->custom_pattern[32] << 16) | (tp_params->custom_pattern[31] << 8) | tp_params->custom_pattern[30];
REG_SET(DP_DPHY_SYM32_TP_CUSTOM10, 0, TP_CUSTOM, tp_custom);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_CUSTOM,
TP_SELECT1, DP_DPHY_TP_SELECT_CUSTOM,
TP_SELECT2, DP_DPHY_TP_SELECT_CUSTOM,
TP_SELECT3, DP_DPHY_TP_SELECT_CUSTOM);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
case DP_TEST_PATTERN_SQUARE_PULSE:
REG_SET(DP_DPHY_SYM32_TP_SQ_PULSE, 0,
TP_SQ_PULSE_WIDTH, tp_params->custom_pattern[0]);
REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
TP_SELECT0, DP_DPHY_TP_SELECT_SQUARE,
TP_SELECT1, DP_DPHY_TP_SELECT_SQUARE,
TP_SELECT2, DP_DPHY_TP_SELECT_SQUARE,
TP_SELECT3, DP_DPHY_TP_SELECT_SQUARE);
REG_UPDATE(DP_DPHY_SYM32_CONTROL,
MODE, DP2_TEST_PATTERN);
break;
default:
break;
}
}
static void fill_stream_allocation_row_info(
const struct link_mst_stream_allocation *stream_allocation,
uint32_t *src,
uint32_t *slots)
{
const struct hpo_dp_stream_encoder *stream_enc = stream_allocation->hpo_dp_stream_enc;
if (stream_enc && (stream_enc->id >= ENGINE_ID_HPO_DP_0)) {
*src = stream_enc->id - ENGINE_ID_HPO_DP_0;
*slots = stream_allocation->slot_count;
} else {
*src = 0;
*slots = 0;
}
}
/* programs DP VC payload allocation */
void dcn31_hpo_dp_link_enc_update_stream_allocation_table(
struct hpo_dp_link_encoder *enc,
const struct link_mst_stream_allocation_table *table)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
uint32_t slots = 0;
uint32_t src = 0;
/* --- Set MSE Stream Attribute -
* Setup VC Payload Table on Tx Side,
* Issue allocation change trigger
* to commit payload on both tx and rx side
*/
/* we should clean-up table each time */
if (table->stream_count >= 1) {
fill_stream_allocation_row_info(
&table->stream_allocations[0],
&src,
&slots);
} else {
src = 0;
slots = 0;
}
REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC0,
SAT_STREAM_SOURCE, src,
SAT_SLOT_COUNT, slots);
if (table->stream_count >= 2) {
fill_stream_allocation_row_info(
&table->stream_allocations[1],
&src,
&slots);
} else {
src = 0;
slots = 0;
}
REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC1,
SAT_STREAM_SOURCE, src,
SAT_SLOT_COUNT, slots);
if (table->stream_count >= 3) {
fill_stream_allocation_row_info(
&table->stream_allocations[2],
&src,
&slots);
} else {
src = 0;
slots = 0;
}
REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC2,
SAT_STREAM_SOURCE, src,
SAT_SLOT_COUNT, slots);
if (table->stream_count >= 4) {
fill_stream_allocation_row_info(
&table->stream_allocations[3],
&src,
&slots);
} else {
src = 0;
slots = 0;
}
REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC3,
SAT_STREAM_SOURCE, src,
SAT_SLOT_COUNT, slots);
/* --- wait for transaction finish */
/* send allocation change trigger (ACT)
* this step first sends the ACT,
* then double buffers the SAT into the hardware
* making the new allocation active on the DP MST mode link
*/
/* SAT_UPDATE:
* 0 - No Action
* 1 - Update SAT with trigger
* 2 - Update SAT without trigger
*/
REG_UPDATE(DP_DPHY_SYM32_SAT_UPDATE,
SAT_UPDATE, 1);
/* wait for update to complete
* (i.e. SAT_UPDATE_PENDING field is set to 0)
* No need for HW to enforce keepout.
*/
/* Best case and worst case wait time for SAT_UPDATE_PENDING
* best: 109 us
* worst: 868 us
*/
REG_WAIT(DP_DPHY_SYM32_STATUS,
SAT_UPDATE_PENDING, 0,
10, DP_SAT_UPDATE_MAX_RETRY);
}
void dcn31_hpo_dp_link_enc_set_throttled_vcp_size(
struct hpo_dp_link_encoder *enc,
uint32_t stream_encoder_inst,
struct fixed31_32 avg_time_slots_per_mtp)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
uint32_t x = dc_fixpt_floor(
avg_time_slots_per_mtp);
uint32_t y = dc_fixpt_ceil(
dc_fixpt_shl(
dc_fixpt_sub_int(
avg_time_slots_per_mtp,
x),
25));
switch (stream_encoder_inst) {
case 0:
REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, 0,
STREAM_VC_RATE_X, x,
STREAM_VC_RATE_Y, y);
break;
case 1:
REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL1, 0,
STREAM_VC_RATE_X, x,
STREAM_VC_RATE_Y, y);
break;
case 2:
REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL2, 0,
STREAM_VC_RATE_X, x,
STREAM_VC_RATE_Y, y);
break;
case 3:
REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL3, 0,
STREAM_VC_RATE_X, x,
STREAM_VC_RATE_Y, y);
break;
default:
ASSERT(0);
}
/* Best case and worst case wait time for RATE_UPDATE_PENDING
* best: 116 ns
* worst: 903 ns
*/
/* wait for update to be completed on the link */
REG_WAIT(DP_DPHY_SYM32_STATUS,
RATE_UPDATE_PENDING, 0,
1, 10);
}
static bool dcn31_hpo_dp_link_enc_is_in_alt_mode(
struct hpo_dp_link_encoder *enc)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
uint32_t dp_alt_mode_disable = 0;
ASSERT((enc->transmitter >= TRANSMITTER_UNIPHY_A) && (enc->transmitter <= TRANSMITTER_UNIPHY_E));
/* if value == 1 alt mode is disabled, otherwise it is enabled */
REG_GET(RDPCSTX_PHY_CNTL6[enc->transmitter], RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable);
return (dp_alt_mode_disable == 0);
}
void dcn31_hpo_dp_link_enc_read_state(
struct hpo_dp_link_encoder *enc,
struct hpo_dp_link_enc_state *state)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
ASSERT(state);
REG_GET(DP_DPHY_SYM32_STATUS,
STATUS, &state->link_enc_enabled);
REG_GET(DP_DPHY_SYM32_CONTROL,
NUM_LANES, &state->lane_count);
REG_GET(DP_DPHY_SYM32_CONTROL,
MODE, (uint32_t *)&state->link_mode);
REG_GET_2(DP_DPHY_SYM32_SAT_VC0,
SAT_STREAM_SOURCE, &state->stream_src[0],
SAT_SLOT_COUNT, &state->slot_count[0]);
REG_GET_2(DP_DPHY_SYM32_SAT_VC1,
SAT_STREAM_SOURCE, &state->stream_src[1],
SAT_SLOT_COUNT, &state->slot_count[1]);
REG_GET_2(DP_DPHY_SYM32_SAT_VC2,
SAT_STREAM_SOURCE, &state->stream_src[2],
SAT_SLOT_COUNT, &state->slot_count[2]);
REG_GET_2(DP_DPHY_SYM32_SAT_VC3,
SAT_STREAM_SOURCE, &state->stream_src[3],
SAT_SLOT_COUNT, &state->slot_count[3]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL0,
STREAM_VC_RATE_X, &state->vc_rate_x[0],
STREAM_VC_RATE_Y, &state->vc_rate_y[0]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL1,
STREAM_VC_RATE_X, &state->vc_rate_x[1],
STREAM_VC_RATE_Y, &state->vc_rate_y[1]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL2,
STREAM_VC_RATE_X, &state->vc_rate_x[2],
STREAM_VC_RATE_Y, &state->vc_rate_y[2]);
REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL3,
STREAM_VC_RATE_X, &state->vc_rate_x[3],
STREAM_VC_RATE_Y, &state->vc_rate_y[3]);
}
static enum bp_result link_transmitter_control(
struct dcn31_hpo_dp_link_encoder *enc3,
struct bp_transmitter_control *cntl)
{
enum bp_result result;
struct dc_bios *bp = enc3->base.ctx->dc_bios;
result = bp->funcs->transmitter_control(bp, cntl);
return result;
}
/* enables DP PHY output for 128b132b encoding */
void dcn31_hpo_dp_link_enc_enable_dp_output(
struct hpo_dp_link_encoder *enc,
const struct dc_link_settings *link_settings,
enum transmitter transmitter)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
/* Set the transmitter */
enc3->base.transmitter = transmitter;
/* Enable the PHY */
cntl.action = TRANSMITTER_CONTROL_ENABLE;
cntl.engine_id = ENGINE_ID_UNKNOWN;
cntl.transmitter = enc3->base.transmitter;
//cntl.pll_id = clock_source;
cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
cntl.lanes_number = link_settings->lane_count;
cntl.hpd_sel = enc3->base.hpd_source;
cntl.pixel_clock = link_settings->link_rate * 1000;
cntl.color_depth = COLOR_DEPTH_UNDEFINED;
cntl.hpo_engine_id = enc->inst + ENGINE_ID_HPO_DP_0;
result = link_transmitter_control(enc3, &cntl);
if (result != BP_RESULT_OK) {
DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
}
}
void dcn31_hpo_dp_link_enc_disable_output(
struct hpo_dp_link_encoder *enc,
enum signal_type signal)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
/* disable transmitter */
cntl.action = TRANSMITTER_CONTROL_DISABLE;
cntl.transmitter = enc3->base.transmitter;
cntl.hpd_sel = enc3->base.hpd_source;
cntl.signal = signal;
result = link_transmitter_control(enc3, &cntl);
if (result != BP_RESULT_OK) {
DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
return;
}
/* disable encoder */
dcn31_hpo_dp_link_enc_disable(enc);
}
void dcn31_hpo_dp_link_enc_set_ffe(
struct hpo_dp_link_encoder *enc,
const struct dc_link_settings *link_settings,
uint8_t ffe_preset)
{
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
struct bp_transmitter_control cntl = { 0 };
enum bp_result result;
/* disable transmitter */
cntl.transmitter = enc3->base.transmitter;
cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
cntl.lanes_number = link_settings->lane_count;
cntl.pixel_clock = link_settings->link_rate * 1000;
cntl.lane_settings = ffe_preset;
result = link_transmitter_control(enc3, &cntl);
if (result != BP_RESULT_OK) {
DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
__func__);
BREAK_TO_DEBUGGER();
return;
}
}
static struct hpo_dp_link_encoder_funcs dcn31_hpo_dp_link_encoder_funcs = {
.enable_link_phy = dcn31_hpo_dp_link_enc_enable_dp_output,
.disable_link_phy = dcn31_hpo_dp_link_enc_disable_output,
.link_enable = dcn31_hpo_dp_link_enc_enable,
.link_disable = dcn31_hpo_dp_link_enc_disable,
.set_link_test_pattern = dcn31_hpo_dp_link_enc_set_link_test_pattern,
.update_stream_allocation_table = dcn31_hpo_dp_link_enc_update_stream_allocation_table,
.set_throttled_vcp_size = dcn31_hpo_dp_link_enc_set_throttled_vcp_size,
.is_in_alt_mode = dcn31_hpo_dp_link_enc_is_in_alt_mode,
.read_state = dcn31_hpo_dp_link_enc_read_state,
.set_ffe = dcn31_hpo_dp_link_enc_set_ffe,
};
void hpo_dp_link_encoder31_construct(struct dcn31_hpo_dp_link_encoder *enc31,
struct dc_context *ctx,
uint32_t inst,
const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask)
{
enc31->base.ctx = ctx;
enc31->base.inst = inst;
enc31->base.funcs = &dcn31_hpo_dp_link_encoder_funcs;
enc31->base.hpd_source = HPD_SOURCEID_UNKNOWN;
enc31->base.transmitter = TRANSMITTER_UNKNOWN;
enc31->regs = hpo_le_regs;
enc31->hpo_le_shift = hpo_le_shift;
enc31->hpo_le_mask = hpo_le_mask;
}
/*
* Copyright 2019 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#ifndef __DAL_DCN31_HPO_DP_LINK_ENCODER_H__
#define __DAL_DCN31_HPO_DP_LINK_ENCODER_H__
#include "link_encoder.h"
#define DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(hpo_dp_link_encoder)\
container_of(hpo_dp_link_encoder, struct dcn31_hpo_dp_link_encoder, base)
#define DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id) \
SRI(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id), \
SRI(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CONFIG, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_PRBS_SEED0, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_PRBS_SEED1, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_PRBS_SEED2, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_PRBS_SEED3, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_SQ_PULSE, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM0, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM1, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM2, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM3, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM4, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM5, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM6, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM7, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM8, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM9, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_TP_CUSTOM10, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_SAT_VC0, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_SAT_VC1, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_SAT_VC2, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_SAT_VC3, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_VC_RATE_CNTL0, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \
SRI(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id)
#define DCN3_1_RDPCSTX_REG_LIST(id) \
SRII(RDPCSTX_PHY_CNTL6, RDPCSTX, id)
#define DCN3_1_HPO_DP_LINK_ENC_REGS \
uint32_t DP_LINK_ENC_CLOCK_CONTROL;\
uint32_t DP_DPHY_SYM32_CONTROL;\
uint32_t DP_DPHY_SYM32_STATUS;\
uint32_t DP_DPHY_SYM32_TP_CONFIG;\
uint32_t DP_DPHY_SYM32_TP_PRBS_SEED0;\
uint32_t DP_DPHY_SYM32_TP_PRBS_SEED1;\
uint32_t DP_DPHY_SYM32_TP_PRBS_SEED2;\
uint32_t DP_DPHY_SYM32_TP_PRBS_SEED3;\
uint32_t DP_DPHY_SYM32_TP_SQ_PULSE;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM0;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM1;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM2;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM3;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM4;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM5;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM6;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM7;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM8;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM9;\
uint32_t DP_DPHY_SYM32_TP_CUSTOM10;\
uint32_t DP_DPHY_SYM32_SAT_VC0;\
uint32_t DP_DPHY_SYM32_SAT_VC1;\
uint32_t DP_DPHY_SYM32_SAT_VC2;\
uint32_t DP_DPHY_SYM32_SAT_VC3;\
uint32_t DP_DPHY_SYM32_VC_RATE_CNTL0;\
uint32_t DP_DPHY_SYM32_VC_RATE_CNTL1;\
uint32_t DP_DPHY_SYM32_VC_RATE_CNTL2;\
uint32_t DP_DPHY_SYM32_VC_RATE_CNTL3;\
uint32_t DP_DPHY_SYM32_SAT_UPDATE
struct dcn31_hpo_dp_link_encoder_registers {
DCN3_1_HPO_DP_LINK_ENC_REGS;
uint32_t RDPCSTX_PHY_CNTL6[5];
};
#define DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(mask_sh)\
SE_SF(DP_LINK_ENC0_DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, DPHY_RESET, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, DPHY_ENABLE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, PRECODER_ENABLE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, MODE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, NUM_LANES, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, STATUS, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, SAT_UPDATE_PENDING, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, RATE_UPDATE_PENDING, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CUSTOM0, TP_CUSTOM, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT0, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT1, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT2, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT3, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL0, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL1, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL2, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL3, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_SQ_PULSE, TP_SQ_PULSE_WIDTH, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_STREAM_SOURCE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_SLOT_COUNT, mask_sh),\
SE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_X, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_Y, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_UPDATE, SAT_UPDATE, mask_sh)
#define DCN3_1_HPO_DP_LINK_ENC_REG_FIELD_LIST(type) \
type DP_LINK_ENC_CLOCK_EN;\
type DPHY_RESET;\
type DPHY_ENABLE;\
type PRECODER_ENABLE;\
type NUM_LANES;\
type MODE;\
type STATUS;\
type SAT_UPDATE_PENDING;\
type RATE_UPDATE_PENDING;\
type TP_CUSTOM;\
type TP_SELECT0;\
type TP_SELECT1;\
type TP_SELECT2;\
type TP_SELECT3;\
type TP_PRBS_SEL0;\
type TP_PRBS_SEL1;\
type TP_PRBS_SEL2;\
type TP_PRBS_SEL3;\
type TP_SQ_PULSE_WIDTH;\
type SAT_STREAM_SOURCE;\
type SAT_SLOT_COUNT;\
type STREAM_VC_RATE_X;\
type STREAM_VC_RATE_Y;\
type SAT_UPDATE;\
type RDPCS_PHY_DPALT_DISABLE
struct dcn31_hpo_dp_link_encoder_shift {
DCN3_1_HPO_DP_LINK_ENC_REG_FIELD_LIST(uint8_t);
};
struct dcn31_hpo_dp_link_encoder_mask {
DCN3_1_HPO_DP_LINK_ENC_REG_FIELD_LIST(uint32_t);
};
struct dcn31_hpo_dp_link_encoder {
struct hpo_dp_link_encoder base;
const struct dcn31_hpo_dp_link_encoder_registers *regs;
const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift;
const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask;
};
void hpo_dp_link_encoder31_construct(struct dcn31_hpo_dp_link_encoder *enc31,
struct dc_context *ctx,
uint32_t inst,
const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask);
void dcn31_hpo_dp_link_enc_enable_dp_output(
struct hpo_dp_link_encoder *enc,
const struct dc_link_settings *link_settings,
enum transmitter transmitter);
void dcn31_hpo_dp_link_enc_disable_output(
struct hpo_dp_link_encoder *enc,
enum signal_type signal);
void dcn31_hpo_dp_link_enc_enable(
struct hpo_dp_link_encoder *enc,
enum dc_lane_count num_lanes);
void dcn31_hpo_dp_link_enc_disable(
struct hpo_dp_link_encoder *enc);
void dcn31_hpo_dp_link_enc_set_link_test_pattern(
struct hpo_dp_link_encoder *enc,
struct encoder_set_dp_phy_pattern_param *tp_params);
void dcn31_hpo_dp_link_enc_update_stream_allocation_table(
struct hpo_dp_link_encoder *enc,
const struct link_mst_stream_allocation_table *table);
void dcn31_hpo_dp_link_enc_set_throttled_vcp_size(
struct hpo_dp_link_encoder *enc,
uint32_t stream_encoder_inst,
struct fixed31_32 avg_time_slots_per_mtp);
void dcn31_hpo_dp_link_enc_read_state(
struct hpo_dp_link_encoder *enc,
struct hpo_dp_link_enc_state *state);
void dcn31_hpo_dp_link_enc_set_ffe(
struct hpo_dp_link_encoder *enc,
const struct dc_link_settings *link_settings,
uint8_t ffe_preset);
#endif // __DAL_DCN31_HPO_LINK_ENCODER_H__
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include "dcn30/dcn30_afmt.h" #include "dcn30/dcn30_afmt.h"
#include "dcn30/dcn30_dio_stream_encoder.h" #include "dcn30/dcn30_dio_stream_encoder.h"
#include "dcn31/dcn31_hpo_dp_stream_encoder.h" #include "dcn31/dcn31_hpo_dp_stream_encoder.h"
#include "dcn31/dcn31_hpo_dp_link_encoder.h"
#include "dcn31/dcn31_apg.h" #include "dcn31/dcn31_apg.h"
#include "dcn31/dcn31_dio_link_encoder.h" #include "dcn31/dcn31_dio_link_encoder.h"
#include "dce/dce_clock_source.h" #include "dce/dce_clock_source.h"
...@@ -585,6 +586,29 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { ...@@ -585,6 +586,29 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = {
DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK)
}; };
#define hpo_dp_link_encoder_reg_list(id)\
[id] = {\
DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\
DCN3_1_RDPCSTX_REG_LIST(0),\
DCN3_1_RDPCSTX_REG_LIST(1),\
DCN3_1_RDPCSTX_REG_LIST(2),\
DCN3_1_RDPCSTX_REG_LIST(3),\
DCN3_1_RDPCSTX_REG_LIST(4)\
}
static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = {
hpo_dp_link_encoder_reg_list(0),
hpo_dp_link_encoder_reg_list(1),
};
static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = {
DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT)
};
static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = {
DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK)
};
static const struct dcn3_dpp_registers dpp_regs[] = { static const struct dcn3_dpp_registers dpp_regs[] = {
dpp_regs(0), dpp_regs(0),
dpp_regs(1), dpp_regs(1),
...@@ -922,6 +946,7 @@ static const struct resource_caps res_cap_dcn31 = { ...@@ -922,6 +946,7 @@ static const struct resource_caps res_cap_dcn31 = {
.num_stream_encoder = 5, .num_stream_encoder = 5,
.num_dig_link_enc = 5, .num_dig_link_enc = 5,
.num_hpo_dp_stream_encoder = 4, .num_hpo_dp_stream_encoder = 4,
.num_hpo_dp_link_encoder = 2,
.num_pll = 5, .num_pll = 5,
.num_dwb = 1, .num_dwb = 1,
.num_ddc = 5, .num_ddc = 5,
...@@ -1398,6 +1423,22 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( ...@@ -1398,6 +1423,22 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create(
return &hpo_dp_enc31->base; return &hpo_dp_enc31->base;
} }
static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create(
uint8_t inst,
struct dc_context *ctx)
{
struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31;
/* allocate HPO link encoder */
hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst,
&hpo_dp_link_enc_regs[inst],
&hpo_dp_le_shift, &hpo_dp_le_mask);
return &hpo_dp_enc31->base;
}
static struct dce_hwseq *dcn31_hwseq_create( static struct dce_hwseq *dcn31_hwseq_create(
struct dc_context *ctx) struct dc_context *ctx)
{ {
...@@ -1416,6 +1457,7 @@ static const struct resource_create_funcs res_create_funcs = { ...@@ -1416,6 +1457,7 @@ static const struct resource_create_funcs res_create_funcs = {
.create_audio = dcn31_create_audio, .create_audio = dcn31_create_audio,
.create_stream_encoder = dcn31_stream_encoder_create, .create_stream_encoder = dcn31_stream_encoder_create,
.create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create,
.create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create,
.create_hwseq = dcn31_hwseq_create, .create_hwseq = dcn31_hwseq_create,
}; };
...@@ -1424,6 +1466,7 @@ static const struct resource_create_funcs res_create_maximus_funcs = { ...@@ -1424,6 +1466,7 @@ static const struct resource_create_funcs res_create_maximus_funcs = {
.create_audio = NULL, .create_audio = NULL,
.create_stream_encoder = NULL, .create_stream_encoder = NULL,
.create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create,
.create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create,
.create_hwseq = dcn31_hwseq_create, .create_hwseq = dcn31_hwseq_create,
}; };
...@@ -1461,6 +1504,13 @@ static void dcn31_resource_destruct(struct dcn31_resource_pool *pool) ...@@ -1461,6 +1504,13 @@ static void dcn31_resource_destruct(struct dcn31_resource_pool *pool)
} }
} }
for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) {
if (pool->base.hpo_dp_link_enc[i] != NULL) {
kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i]));
pool->base.hpo_dp_link_enc[i] = NULL;
}
}
for (i = 0; i < pool->base.res_cap->num_dsc; i++) { for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
if (pool->base.dscs[i] != NULL) if (pool->base.dscs[i] != NULL)
dcn20_dsc_destroy(&pool->base.dscs[i]); dcn20_dsc_destroy(&pool->base.dscs[i]);
......
...@@ -249,6 +249,8 @@ struct resource_pool { ...@@ -249,6 +249,8 @@ struct resource_pool {
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
unsigned int hpo_dp_stream_enc_count; unsigned int hpo_dp_stream_enc_count;
struct hpo_dp_stream_encoder *hpo_dp_stream_enc[MAX_HPO_DP2_ENCODERS]; struct hpo_dp_stream_encoder *hpo_dp_stream_enc[MAX_HPO_DP2_ENCODERS];
unsigned int hpo_dp_link_enc_count;
struct hpo_dp_link_encoder *hpo_dp_link_enc[MAX_HPO_DP2_LINK_ENCODERS];
#endif #endif
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
struct dc_3dlut *mpc_lut[MAX_PIPES]; struct dc_3dlut *mpc_lut[MAX_PIPES];
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#define MAX_DWB_PIPES 1 #define MAX_DWB_PIPES 1
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
#define MAX_HPO_DP2_ENCODERS 4 #define MAX_HPO_DP2_ENCODERS 4
#define MAX_HPO_DP2_LINK_ENCODERS 2
#endif #endif
struct gamma_curve { struct gamma_curve {
......
...@@ -210,4 +210,91 @@ struct link_enc_assignment { ...@@ -210,4 +210,91 @@ struct link_enc_assignment {
enum engine_id eng_id; enum engine_id eng_id;
}; };
#if defined(CONFIG_DRM_AMD_DC_DCN)
enum dp2_link_mode {
DP2_LINK_TRAINING_TPS1,
DP2_LINK_TRAINING_TPS2,
DP2_LINK_ACTIVE,
DP2_TEST_PATTERN
};
enum dp2_phy_tp_select {
DP_DPHY_TP_SELECT_TPS1,
DP_DPHY_TP_SELECT_TPS2,
DP_DPHY_TP_SELECT_PRBS,
DP_DPHY_TP_SELECT_CUSTOM,
DP_DPHY_TP_SELECT_SQUARE
};
enum dp2_phy_tp_prbs {
DP_DPHY_TP_PRBS7,
DP_DPHY_TP_PRBS9,
DP_DPHY_TP_PRBS11,
DP_DPHY_TP_PRBS15,
DP_DPHY_TP_PRBS23,
DP_DPHY_TP_PRBS31
};
struct hpo_dp_link_enc_state {
uint32_t link_enc_enabled;
uint32_t link_mode;
uint32_t lane_count;
uint32_t slot_count[4];
uint32_t stream_src[4];
uint32_t vc_rate_x[4];
uint32_t vc_rate_y[4];
};
struct hpo_dp_link_encoder {
const struct hpo_dp_link_encoder_funcs *funcs;
struct dc_context *ctx;
int inst;
enum engine_id preferred_engine;
enum transmitter transmitter;
enum hpd_source_id hpd_source;
};
struct hpo_dp_link_encoder_funcs {
void (*enable_link_phy)(struct hpo_dp_link_encoder *enc,
const struct dc_link_settings *link_settings,
enum transmitter transmitter);
void (*disable_link_phy)(struct hpo_dp_link_encoder *link_enc,
enum signal_type signal);
void (*link_enable)(
struct hpo_dp_link_encoder *enc,
enum dc_lane_count num_lanes);
void (*link_disable)(
struct hpo_dp_link_encoder *enc);
void (*set_link_test_pattern)(
struct hpo_dp_link_encoder *enc,
struct encoder_set_dp_phy_pattern_param *tp_params);
void (*update_stream_allocation_table)(
struct hpo_dp_link_encoder *enc,
const struct link_mst_stream_allocation_table *table);
void (*set_throttled_vcp_size)(
struct hpo_dp_link_encoder *enc,
uint32_t stream_encoder_inst,
struct fixed31_32 avg_time_slots_per_mtp);
bool (*is_in_alt_mode) (
struct hpo_dp_link_encoder *enc);
void (*read_state)(
struct hpo_dp_link_encoder *enc,
struct hpo_dp_link_enc_state *state);
void (*set_ffe)(
struct hpo_dp_link_encoder *enc,
const struct dc_link_settings *link_settings,
uint8_t ffe_preset);
};
#endif
#endif /* LINK_ENCODER_H_ */ #endif /* LINK_ENCODER_H_ */
...@@ -51,6 +51,7 @@ struct resource_caps { ...@@ -51,6 +51,7 @@ struct resource_caps {
unsigned int num_dig_link_enc; // Total number of DIGs (digital encoders) in DIO (Display Input/Output). unsigned int num_dig_link_enc; // Total number of DIGs (digital encoders) in DIO (Display Input/Output).
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
int num_hpo_dp_stream_encoder; int num_hpo_dp_stream_encoder;
int num_hpo_dp_link_encoder;
#endif #endif
int num_mpc_3dlut; int num_mpc_3dlut;
}; };
...@@ -74,6 +75,10 @@ struct resource_create_funcs { ...@@ -74,6 +75,10 @@ struct resource_create_funcs {
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
struct hpo_dp_stream_encoder *(*create_hpo_dp_stream_encoder)( struct hpo_dp_stream_encoder *(*create_hpo_dp_stream_encoder)(
enum engine_id eng_id, struct dc_context *ctx); enum engine_id eng_id, struct dc_context *ctx);
struct hpo_dp_link_encoder *(*create_hpo_dp_link_encoder)(
uint8_t inst,
struct dc_context *ctx);
#endif #endif
struct dce_hwseq *(*create_hwseq)( struct dce_hwseq *(*create_hwseq)(
......
...@@ -114,13 +114,30 @@ enum dp_test_pattern { ...@@ -114,13 +114,30 @@ enum dp_test_pattern {
DP_TEST_PATTERN_CP2520_2, DP_TEST_PATTERN_CP2520_2,
DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE = DP_TEST_PATTERN_CP2520_2, DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE = DP_TEST_PATTERN_CP2520_2,
DP_TEST_PATTERN_CP2520_3, DP_TEST_PATTERN_CP2520_3,
#if defined(CONFIG_DRM_AMD_DC_DCN)
DP_TEST_PATTERN_128b_132b_TPS1,
DP_TEST_PATTERN_128b_132b_TPS2,
DP_TEST_PATTERN_PRBS9,
DP_TEST_PATTERN_PRBS11,
DP_TEST_PATTERN_PRBS15,
DP_TEST_PATTERN_PRBS23,
DP_TEST_PATTERN_PRBS31,
DP_TEST_PATTERN_264BIT_CUSTOM,
DP_TEST_PATTERN_SQUARE_PULSE,
#endif
/* Link Training Patterns */ /* Link Training Patterns */
DP_TEST_PATTERN_TRAINING_PATTERN1, DP_TEST_PATTERN_TRAINING_PATTERN1,
DP_TEST_PATTERN_TRAINING_PATTERN2, DP_TEST_PATTERN_TRAINING_PATTERN2,
DP_TEST_PATTERN_TRAINING_PATTERN3, DP_TEST_PATTERN_TRAINING_PATTERN3,
DP_TEST_PATTERN_TRAINING_PATTERN4, DP_TEST_PATTERN_TRAINING_PATTERN4,
#if defined(CONFIG_DRM_AMD_DC_DCN)
DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE,
DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE,
DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE,
#else
DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_TRAINING_PATTERN4, DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_TRAINING_PATTERN4,
#endif
/* link test patterns*/ /* link test patterns*/
DP_TEST_PATTERN_COLOR_SQUARES, DP_TEST_PATTERN_COLOR_SQUARES,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment