|
| 1 | +/* |
| 2 | + * Copyright 2023 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 | +#include "link_hwss_dio.h" |
| 26 | +#include "link_hwss_dio_fixed_vs_pe_retimer.h" |
| 27 | +#include "link_enc_cfg.h" |
| 28 | + |
| 29 | +uint8_t dp_dio_fixed_vs_pe_retimer_lane_cfg_to_hw_cfg(struct dc_link *link) |
| 30 | +{ |
| 31 | + // TODO: Get USB-C cable orientation |
| 32 | + if (link->cur_link_settings.lane_count == LANE_COUNT_FOUR) |
| 33 | + return 0xF2; |
| 34 | + else |
| 35 | + return 0x12; |
| 36 | +} |
| 37 | + |
| 38 | +void dp_dio_fixed_vs_pe_retimer_exit_manual_automation(struct dc_link *link) |
| 39 | +{ |
| 40 | + const uint8_t dp_type = dp_dio_fixed_vs_pe_retimer_lane_cfg_to_hw_cfg(link); |
| 41 | + const uint8_t vendor_lttpr_exit_manual_automation_0[4] = {0x1, 0x11, 0x0, 0x06}; |
| 42 | + const uint8_t vendor_lttpr_exit_manual_automation_1[4] = {0x1, 0x50, dp_type, 0x0}; |
| 43 | + const uint8_t vendor_lttpr_exit_manual_automation_2[4] = {0x1, 0x50, 0x50, 0x0}; |
| 44 | + const uint8_t vendor_lttpr_exit_manual_automation_3[4] = {0x1, 0x51, 0x50, 0x0}; |
| 45 | + const uint8_t vendor_lttpr_exit_manual_automation_4[4] = {0x1, 0x10, 0x58, 0x0}; |
| 46 | + const uint8_t vendor_lttpr_exit_manual_automation_5[4] = {0x1, 0x10, 0x59, 0x0}; |
| 47 | + const uint8_t vendor_lttpr_exit_manual_automation_6[4] = {0x1, 0x30, 0x51, 0x0}; |
| 48 | + const uint8_t vendor_lttpr_exit_manual_automation_7[4] = {0x1, 0x30, 0x52, 0x0}; |
| 49 | + const uint8_t vendor_lttpr_exit_manual_automation_8[4] = {0x1, 0x30, 0x54, 0x0}; |
| 50 | + const uint8_t vendor_lttpr_exit_manual_automation_9[4] = {0x1, 0x30, 0x55, 0x0}; |
| 51 | + |
| 52 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 53 | + &vendor_lttpr_exit_manual_automation_0[0], sizeof(vendor_lttpr_exit_manual_automation_0)); |
| 54 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 55 | + &vendor_lttpr_exit_manual_automation_1[0], sizeof(vendor_lttpr_exit_manual_automation_1)); |
| 56 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 57 | + &vendor_lttpr_exit_manual_automation_2[0], sizeof(vendor_lttpr_exit_manual_automation_2)); |
| 58 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 59 | + &vendor_lttpr_exit_manual_automation_3[0], sizeof(vendor_lttpr_exit_manual_automation_3)); |
| 60 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 61 | + &vendor_lttpr_exit_manual_automation_4[0], sizeof(vendor_lttpr_exit_manual_automation_4)); |
| 62 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 63 | + &vendor_lttpr_exit_manual_automation_5[0], sizeof(vendor_lttpr_exit_manual_automation_5)); |
| 64 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 65 | + &vendor_lttpr_exit_manual_automation_6[0], sizeof(vendor_lttpr_exit_manual_automation_6)); |
| 66 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 67 | + &vendor_lttpr_exit_manual_automation_7[0], sizeof(vendor_lttpr_exit_manual_automation_7)); |
| 68 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 69 | + &vendor_lttpr_exit_manual_automation_8[0], sizeof(vendor_lttpr_exit_manual_automation_8)); |
| 70 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 71 | + &vendor_lttpr_exit_manual_automation_9[0], sizeof(vendor_lttpr_exit_manual_automation_9)); |
| 72 | +} |
| 73 | + |
| 74 | +static bool set_dio_fixed_vs_pe_retimer_dp_link_test_pattern_override(struct dc_link *link, |
| 75 | + const struct link_resource *link_res, struct encoder_set_dp_phy_pattern_param *tp_params, |
| 76 | + const struct link_hwss *link_hwss) |
| 77 | +{ |
| 78 | + struct encoder_set_dp_phy_pattern_param hw_tp_params = { 0 }; |
| 79 | + const uint8_t pltpat_custom[10] = {0x1F, 0x7C, 0xF0, 0xC1, 0x07, 0x1F, 0x7C, 0xF0, 0xC1, 0x07}; |
| 80 | + const uint8_t vendor_lttpr_write_data_pg0[4] = {0x1, 0x11, 0x0, 0x0}; |
| 81 | + const uint8_t vendor_lttpr_exit_manual_automation_0[4] = {0x1, 0x11, 0x0, 0x06}; |
| 82 | + |
| 83 | + |
| 84 | + if (tp_params == NULL) |
| 85 | + return false; |
| 86 | + |
| 87 | + if (link->current_test_pattern >= DP_TEST_PATTERN_SQUARE_BEGIN && |
| 88 | + link->current_test_pattern <= DP_TEST_PATTERN_SQUARE_END) { |
| 89 | + // Deprogram overrides from previous test pattern |
| 90 | + dp_dio_fixed_vs_pe_retimer_exit_manual_automation(link); |
| 91 | + } |
| 92 | + |
| 93 | + switch (tp_params->dp_phy_pattern) { |
| 94 | + case DP_TEST_PATTERN_80BIT_CUSTOM: |
| 95 | + if (tp_params->custom_pattern_size == 0 || memcmp(tp_params->custom_pattern, |
| 96 | + pltpat_custom, tp_params->custom_pattern_size) != 0) |
| 97 | + return false; |
| 98 | + break; |
| 99 | + case DP_TEST_PATTERN_D102: |
| 100 | + break; |
| 101 | + default: |
| 102 | + if (link->current_test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM || |
| 103 | + link->current_test_pattern == DP_TEST_PATTERN_D102) |
| 104 | + // Deprogram overrides from previous test pattern |
| 105 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 106 | + &vendor_lttpr_exit_manual_automation_0[0], |
| 107 | + sizeof(vendor_lttpr_exit_manual_automation_0)); |
| 108 | + |
| 109 | + return false; |
| 110 | + } |
| 111 | + |
| 112 | + hw_tp_params.dp_phy_pattern = tp_params->dp_phy_pattern; |
| 113 | + hw_tp_params.dp_panel_mode = tp_params->dp_panel_mode; |
| 114 | + |
| 115 | + if (link_hwss->ext.set_dp_link_test_pattern) |
| 116 | + link_hwss->ext.set_dp_link_test_pattern(link, link_res, &hw_tp_params); |
| 117 | + |
| 118 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 119 | + &vendor_lttpr_write_data_pg0[0], sizeof(vendor_lttpr_write_data_pg0)); |
| 120 | + |
| 121 | + return true; |
| 122 | +} |
| 123 | + |
| 124 | +static void set_dio_fixed_vs_pe_retimer_dp_link_test_pattern(struct dc_link *link, |
| 125 | + const struct link_resource *link_res, |
| 126 | + struct encoder_set_dp_phy_pattern_param *tp_params) |
| 127 | +{ |
| 128 | + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); |
| 129 | + |
| 130 | + if (!set_dio_fixed_vs_pe_retimer_dp_link_test_pattern_override( |
| 131 | + link, link_res, tp_params, get_dio_link_hwss())) { |
| 132 | + link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params); |
| 133 | + } |
| 134 | + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); |
| 135 | +} |
| 136 | + |
| 137 | +void enable_dio_fixed_vs_pe_retimer_program_4lane_output(struct dc_link *link) |
| 138 | +{ |
| 139 | + const uint8_t vendor_lttpr_write_data_4lane_1[4] = {0x1, 0x6E, 0xF2, 0x19}; |
| 140 | + const uint8_t vendor_lttpr_write_data_4lane_2[4] = {0x1, 0x6B, 0xF2, 0x01}; |
| 141 | + const uint8_t vendor_lttpr_write_data_4lane_3[4] = {0x1, 0x6D, 0xF2, 0x18}; |
| 142 | + const uint8_t vendor_lttpr_write_data_4lane_4[4] = {0x1, 0x6C, 0xF2, 0x03}; |
| 143 | + const uint8_t vendor_lttpr_write_data_4lane_5[4] = {0x1, 0x03, 0xF3, 0x06}; |
| 144 | + |
| 145 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 146 | + &vendor_lttpr_write_data_4lane_1[0], sizeof(vendor_lttpr_write_data_4lane_1)); |
| 147 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 148 | + &vendor_lttpr_write_data_4lane_2[0], sizeof(vendor_lttpr_write_data_4lane_2)); |
| 149 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 150 | + &vendor_lttpr_write_data_4lane_3[0], sizeof(vendor_lttpr_write_data_4lane_3)); |
| 151 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 152 | + &vendor_lttpr_write_data_4lane_4[0], sizeof(vendor_lttpr_write_data_4lane_4)); |
| 153 | + link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, |
| 154 | + &vendor_lttpr_write_data_4lane_5[0], sizeof(vendor_lttpr_write_data_4lane_5)); |
| 155 | +} |
| 156 | + |
| 157 | +static void enable_dio_fixed_vs_pe_retimer_dp_link_output(struct dc_link *link, |
| 158 | + const struct link_resource *link_res, |
| 159 | + enum signal_type signal, |
| 160 | + enum clock_source_id clock_source, |
| 161 | + const struct dc_link_settings *link_settings) |
| 162 | +{ |
| 163 | + if (link_settings->lane_count == LANE_COUNT_FOUR) |
| 164 | + enable_dio_fixed_vs_pe_retimer_program_4lane_output(link); |
| 165 | + |
| 166 | + enable_dio_dp_link_output(link, link_res, signal, clock_source, link_settings); |
| 167 | +} |
| 168 | + |
| 169 | +static const struct link_hwss dio_fixed_vs_pe_retimer_link_hwss = { |
| 170 | + .setup_stream_encoder = setup_dio_stream_encoder, |
| 171 | + .reset_stream_encoder = reset_dio_stream_encoder, |
| 172 | + .setup_stream_attribute = setup_dio_stream_attribute, |
| 173 | + .disable_link_output = disable_dio_link_output, |
| 174 | + .setup_audio_output = setup_dio_audio_output, |
| 175 | + .enable_audio_packet = enable_dio_audio_packet, |
| 176 | + .disable_audio_packet = disable_dio_audio_packet, |
| 177 | + .ext = { |
| 178 | + .set_throttled_vcp_size = set_dio_throttled_vcp_size, |
| 179 | + .enable_dp_link_output = enable_dio_fixed_vs_pe_retimer_dp_link_output, |
| 180 | + .set_dp_link_test_pattern = set_dio_fixed_vs_pe_retimer_dp_link_test_pattern, |
| 181 | + .set_dp_lane_settings = set_dio_dp_lane_settings, |
| 182 | + .update_stream_allocation_table = update_dio_stream_allocation_table, |
| 183 | + }, |
| 184 | +}; |
| 185 | + |
| 186 | +bool requires_fixed_vs_pe_retimer_dio_link_hwss(const struct dc_link *link) |
| 187 | +{ |
| 188 | + if (!(link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)) |
| 189 | + return false; |
| 190 | + |
| 191 | + if (!link->dpcd_caps.lttpr_caps.main_link_channel_coding.bits.DP_128b_132b_SUPPORTED) |
| 192 | + return false; |
| 193 | + |
| 194 | + return true; |
| 195 | +} |
| 196 | + |
| 197 | +const struct link_hwss *get_dio_fixed_vs_pe_retimer_link_hwss(void) |
| 198 | +{ |
| 199 | + return &dio_fixed_vs_pe_retimer_link_hwss; |
| 200 | +} |
0 commit comments