drm/amd/display: Add no_native_i2c codepath

[Why]
ASICs which do not have native DDC capability must use a different
codepath to access the AUX channel.

[How]
- BIOS cap NO_DDC_PIN is set to 1 for links which do not have the DDC pin.
- dp_connector_no_native_i2c in dc_config must also be set to true to
  use this codepath.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Matthew Stewart <Matthew.Stewart2@amd.com>
Signed-off-by: Ray Wu <ray.wu@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Matthew Stewart 2026-05-18 21:34:57 -04:00 committed by Alex Deucher
parent 9aef3d167a
commit 6750a2316f
12 changed files with 380 additions and 69 deletions

View File

@ -718,6 +718,69 @@ static enum bp_result bios_parser_get_gpio_pin_info(
return BP_RESULT_NORECORD;
}
static enum bp_result bios_parser_get_connector_aux_info(struct dc_bios *dcb,
struct graphics_object_id id,
struct graphics_object_i2c_info *info)
{
uint32_t offset;
struct atom_display_object_path_v2 *object;
struct atom_display_object_path_v3 *object_path_v3;
struct atom_common_record_header *header;
struct atom_i2c_record *record;
struct bios_parser *bp = BP_FROM_DCB(dcb);
if (!info)
return BP_RESULT_BADINPUT;
switch (bp->object_info_tbl.revision.minor) {
case 4:
default:
object = get_bios_object(bp, id);
if (!object)
return BP_RESULT_BADINPUT;
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
break;
case 5:
object_path_v3 = get_bios_object_from_path_v3(bp, id);
if (!object_path_v3)
return BP_RESULT_BADINPUT;
offset = object_path_v3->disp_recordoffset + bp->object_info_tbl_offset;
break;
}
for (;;) {
header = GET_IMAGE(struct atom_common_record_header, offset);
if (!header)
return BP_RESULT_BADBIOSTABLE;
if (header->record_type == LAST_RECORD_TYPE ||
!header->record_size)
break;
if (header->record_type == ATOM_I2C_RECORD_TYPE
&& sizeof(struct atom_i2c_record) <=
header->record_size) {
/* get_connector_aux_info - which aux instance is used it is based
* on record->i2c_id field only, does not need GPIO DDC
*/
record = (struct atom_i2c_record *)header;
info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;
return BP_RESULT_OK;
}
offset += header->record_size;
}
return BP_RESULT_NORECORD;
}
static struct device_id device_type_from_device_id(uint16_t device_id)
{
@ -2349,6 +2412,9 @@ static enum bp_result bios_parser_get_disp_connector_caps_info(
? 1 : 0;
info->INTERNAL_DISPLAY_BL = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)
? 1 : 0;
// All aux transactions for this connector should rely only on aux instance, not on ddc instance
info->NO_DDC_PIN = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_DP_PLUS_PLUS_TYPE2_ONLY) ? 1 : 0;
break;
}
@ -3717,6 +3783,7 @@ static const struct dc_vbios_funcs vbios_funcs = {
.get_lttpr_interop = bios_parser_get_lttpr_interop,
.get_connector_speed_cap_info = bios_parser_get_connector_speed_cap_info,
.get_connector_aux_info = bios_parser_get_connector_aux_info,
};
static bool bios_parser2_construct(

View File

@ -559,6 +559,7 @@ struct dc_config {
bool enable_dpia_pre_training;
bool unify_link_enc_assignment;
bool enable_cursor_offload;
bool dp_connector_no_native_i2c;
bool frame_update_cmd_version2;
struct spl_sharpness_range dcn_sharpness_range;
struct spl_sharpness_range dcn_override_sharpness_range;
@ -1652,6 +1653,13 @@ struct dc_scratch_space {
struct dc_link_training_overrides preferred_training_settings;
struct dp_audio_test_data audio_test_data;
/* On ASICs with dp_connector_no_native_i2c cap set and no_ddc_pin cap
* set by IFWI, link aux_hw_inst is used in aux layer functions instead
* of ddc_pin to know which aux instance is associated with link.
*/
bool no_ddc_pin;
enum gpio_ddc_line aux_hw_inst;
enum gpio_ddc_line ddc_hw_inst;
uint8_t hpd_src;

View File

@ -172,6 +172,10 @@ struct dc_vbios_funcs {
struct dc_bios *bios,
struct graphics_object_id object_id,
struct bp_connector_speed_cap_info *info);
enum bp_result(*get_connector_aux_info)(
struct dc_bios *dcb,
struct graphics_object_id id,
struct graphics_object_i2c_info *info);
};
struct bios_registers {

View File

@ -102,8 +102,8 @@ bool dm_atomic_write_poll_read_i2c(
if (!link)
return false;
const bool over_aux = false;
const uint32_t ddc_line = link->ddc->ddc_pin->pin_data->en;
const bool over_aux = link->no_ddc_pin;
const uint32_t ddc_line = over_aux ? link->aux_hw_inst : link->ddc->ddc_pin->pin_data->en;
union dmub_rb_cmd commands[3] = { 0 };
const bool converted = op_i2c_convert(&commands[0], write, FUSED_REQUEST_WRITE, ddc_line, over_aux)

View File

@ -274,8 +274,14 @@ static void submit_channel_request(
}
REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE,
request->action, request->address, request->length, request->data);
if (engine->ddc) {
EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE,
request->action, request->address, request->length, request->data);
} else {
EVENT_LOG_AUX_REQ(engine->inst, EVENT_LOG_AUX_ORIGIN_NATIVE,
request->action, request->address, request->length, request->data);
}
}
static int read_channel_reply(struct dce_aux *engine, uint32_t size,
@ -421,6 +427,21 @@ static bool acquire(
return true;
}
static bool acquire_aux_engine_without_ddc_pin(
struct dce_aux *engine,
struct ddc *ddc)
{
(void)ddc;
if ((engine == NULL) || !is_engine_available(engine))
return false;
if (!acquire_engine(engine)) {
release_engine(engine);
return false;
}
return true;
}
void dce110_engine_destroy(struct dce_aux **engine)
{
@ -431,6 +452,73 @@ void dce110_engine_destroy(struct dce_aux **engine)
}
static uint32_t dce_aux_configure_timeout_without_ddc_pin(struct ddc_service *ddc,
uint32_t timeout_in_us)
{
uint32_t multiplier = 0;
uint32_t length = 0;
uint32_t prev_length = 0;
uint32_t prev_mult = 0;
uint32_t prev_timeout_val = 0;
struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc->link->aux_hw_inst];
struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine);
/* 1-Update polling timeout period */
aux110->polling_timeout_period = timeout_in_us * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER;
/* 2-Update aux timeout period length and multiplier */
if (timeout_in_us == 0) {
multiplier = DEFAULT_AUX_ENGINE_MULT;
length = DEFAULT_AUX_ENGINE_LENGTH;
} else if (timeout_in_us <= TIME_OUT_INCREMENT) {
multiplier = 0;
length = timeout_in_us / TIME_OUT_MULTIPLIER_8;
if (timeout_in_us % TIME_OUT_MULTIPLIER_8 != 0)
length++;
} else if (timeout_in_us <= 2 * TIME_OUT_INCREMENT) {
multiplier = 1;
length = timeout_in_us / TIME_OUT_MULTIPLIER_16;
if (timeout_in_us % TIME_OUT_MULTIPLIER_16 != 0)
length++;
} else if (timeout_in_us <= 4 * TIME_OUT_INCREMENT) {
multiplier = 2;
length = timeout_in_us / TIME_OUT_MULTIPLIER_32;
if (timeout_in_us % TIME_OUT_MULTIPLIER_32 != 0)
length++;
} else if (timeout_in_us > 4 * TIME_OUT_INCREMENT) {
multiplier = 3;
length = timeout_in_us / TIME_OUT_MULTIPLIER_64;
if (timeout_in_us % TIME_OUT_MULTIPLIER_64 != 0)
length++;
}
length = (length < MAX_TIMEOUT_LENGTH) ? length : MAX_TIMEOUT_LENGTH;
REG_GET_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, &prev_length, AUX_RX_TIMEOUT_LEN_MUL, &prev_mult);
switch (prev_mult) {
case 0:
prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_8;
break;
case 1:
prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_16;
break;
case 2:
prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_32;
break;
case 3:
prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_64;
break;
default:
prev_timeout_val = DEFAULT_AUX_ENGINE_LENGTH * TIME_OUT_MULTIPLIER_8;
break;
}
REG_UPDATE_SEQ_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, length, AUX_RX_TIMEOUT_LEN_MUL, multiplier);
return prev_timeout_val;
}
static uint32_t dce_aux_configure_timeout(struct ddc_service *ddc,
uint32_t timeout_in_us)
{
@ -440,6 +528,10 @@ static uint32_t dce_aux_configure_timeout(struct ddc_service *ddc,
uint32_t prev_mult = 0;
uint32_t prev_timeout_val = 0;
struct ddc *ddc_pin = ddc->ddc_pin;
if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin)
return dce_aux_configure_timeout_without_ddc_pin(ddc, timeout_in_us);
struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine);
@ -560,11 +652,20 @@ int dce_aux_transfer_raw(struct ddc_service *ddc,
struct aux_payload *payload,
enum aux_return_code_type *operation_result)
{
if (ddc->ctx->dc->debug.enable_dmub_aux_for_legacy_ddc ||
!ddc->ddc_pin) {
return dce_aux_transfer_dmub_raw(ddc, payload, operation_result);
if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) {
/* Check whether aux to be processed via dmub or dcn directly */
if (ddc->ctx->dc->debug.enable_dmub_aux_for_legacy_ddc) {
return dce_aux_transfer_dmub_raw(ddc, payload, operation_result);
} else {
return dce_aux_transfer_raw_without_ddc_pin(ddc, payload, operation_result);
}
} else {
return dce_aux_transfer_raw_with_ddc_pin(ddc, payload, operation_result);
if (ddc->ctx->dc->debug.enable_dmub_aux_for_legacy_ddc ||
!ddc->ddc_pin) {
return dce_aux_transfer_dmub_raw(ddc, payload, operation_result);
} else {
return dce_aux_transfer_raw_with_ddc_pin(ddc, payload, operation_result);
}
}
}
@ -625,6 +726,59 @@ int dce_aux_transfer_raw_with_ddc_pin(struct ddc_service *ddc,
return res;
}
int dce_aux_transfer_raw_without_ddc_pin(struct ddc_service *ddc,
struct aux_payload *payload,
enum aux_return_code_type *operation_result)
{
struct ddc *ddc_pin = ddc->ddc_pin;
struct dce_aux *aux_engine;
struct aux_request_transaction_data aux_req;
uint8_t returned_bytes = 0;
int res = -1;
uint32_t status;
memset(&aux_req, 0, sizeof(aux_req));
aux_engine = ddc->ctx->dc->res_pool->engines[ddc->link->aux_hw_inst];
if (!acquire_aux_engine_without_ddc_pin(aux_engine, ddc_pin)) {
*operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
return -1;
}
if (payload->i2c_over_aux)
aux_req.type = AUX_TRANSACTION_TYPE_I2C;
else
aux_req.type = AUX_TRANSACTION_TYPE_DP;
aux_req.action = i2caux_action_from_payload(payload);
aux_req.address = payload->address;
aux_req.delay = 0;
aux_req.length = payload->length;
aux_req.data = payload->data;
submit_channel_request(aux_engine, &aux_req);
*operation_result = get_channel_status(aux_engine, &returned_bytes);
if (*operation_result == AUX_RET_SUCCESS) {
int __maybe_unused bytes_replied = 0;
bytes_replied = read_channel_reply(aux_engine, payload->length,
payload->data, payload->reply,
&status);
EVENT_LOG_AUX_REP(aux_engine->inst,
EVENT_LOG_AUX_ORIGIN_NATIVE, *payload->reply,
bytes_replied, payload->data);
res = returned_bytes;
} else {
res = -1;
}
release_engine(aux_engine);
return res;
}
int dce_aux_transfer_dmub_raw(struct ddc_service *ddc,
struct aux_payload *payload,
enum aux_return_code_type *operation_result)
@ -641,6 +795,16 @@ int dce_aux_transfer_dmub_raw(struct ddc_service *ddc,
release_engine(aux_engine);
}
if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) {
struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc->link->aux_hw_inst];
if (!acquire_aux_engine_without_ddc_pin(aux_engine, ddc_pin)) {
*operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
return -1;
}
release_engine(aux_engine);
}
return dm_helper_dmub_aux_transfer_sync(ddc->ctx, ddc->link, payload, operation_result);
}
@ -729,6 +893,11 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
aux110 = FROM_AUX_ENGINE(aux_engine);
}
if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) {
aux_engine = ddc->ctx->dc->res_pool->engines[ddc->link->aux_hw_inst];
aux110 = FROM_AUX_ENGINE(aux_engine);
}
if (!payload->reply) {
payload_reply = false;
payload->reply = &reply;

View File

@ -308,6 +308,10 @@ int dce_aux_transfer_raw_with_ddc_pin(struct ddc_service *ddc,
struct aux_payload *cmd,
enum aux_return_code_type *operation_result);
int dce_aux_transfer_raw_without_ddc_pin(struct ddc_service *ddc,
struct aux_payload *cmd,
enum aux_return_code_type *operation_result);
int dce_aux_transfer_dmub_raw(struct ddc_service *ddc,
struct aux_payload *payload,
enum aux_return_code_type *operation_result);

View File

@ -40,6 +40,7 @@
#include "link_enc_cfg.h"
#include "../hw_sequencer.h"
#include "dio/dcn10/dcn10_dio.h"
#include "gpio_service_interface.h"
#define DC_LOGGER_INIT(logger)
@ -319,6 +320,32 @@ void dcn401_init_hw(struct dc *dc)
backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
}
if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) {
struct graphics_object_i2c_info i2c_info;
struct ddc *ddc_pin;
struct gpio_ddc_hw_info hw_info;
if (link->ctx->dc_bios->funcs->get_i2c_info(dcb, link->link_id, &i2c_info) == BP_RESULT_OK) {
hw_info.ddc_channel = i2c_info.i2c_line;
hw_info.hw_supported = i2c_info.i2c_hw_assist;
ddc_pin = dal_gpio_create_ddc(
link->ctx->gpio_service,
i2c_info.gpio_info.clk_a_register_index,
1 << i2c_info.gpio_info.clk_a_shift,
&hw_info);
if (ddc_pin) {
// need to switch pad to aux mode, one time only
// TODO: Handle result
dal_ddc_open(ddc_pin, GPIO_MODE_HARDWARE,
GPIO_DDC_CONFIG_TYPE_MODE_AUX);
dal_gpio_destroy_ddc(&ddc_pin);
}
}
}
}
for (i = 0; i < dc->res_pool->pipe_count; i++) {

View File

@ -415,40 +415,43 @@ static enum channel_id get_ddc_line(struct dc_link *link)
channel = CHANNEL_ID_UNKNOWN;
ddc = get_ddc_pin(link->ddc);
if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) {
channel = link->aux_hw_inst + 1;
} else {
ddc = get_ddc_pin(link->ddc);
if (ddc) {
switch (dal_ddc_get_line(ddc)) {
case GPIO_DDC_LINE_DDC1:
channel = CHANNEL_ID_DDC1;
break;
case GPIO_DDC_LINE_DDC2:
channel = CHANNEL_ID_DDC2;
break;
case GPIO_DDC_LINE_DDC3:
channel = CHANNEL_ID_DDC3;
break;
case GPIO_DDC_LINE_DDC4:
channel = CHANNEL_ID_DDC4;
break;
case GPIO_DDC_LINE_DDC5:
channel = CHANNEL_ID_DDC5;
break;
case GPIO_DDC_LINE_DDC6:
channel = CHANNEL_ID_DDC6;
break;
case GPIO_DDC_LINE_DDC_VGA:
channel = CHANNEL_ID_DDC_VGA;
break;
case GPIO_DDC_LINE_I2C_PAD:
channel = CHANNEL_ID_I2C_PAD;
break;
default:
BREAK_TO_DEBUGGER();
break;
if (ddc) {
switch (dal_ddc_get_line(ddc)) {
case GPIO_DDC_LINE_DDC1:
channel = CHANNEL_ID_DDC1;
break;
case GPIO_DDC_LINE_DDC2:
channel = CHANNEL_ID_DDC2;
break;
case GPIO_DDC_LINE_DDC3:
channel = CHANNEL_ID_DDC3;
break;
case GPIO_DDC_LINE_DDC4:
channel = CHANNEL_ID_DDC4;
break;
case GPIO_DDC_LINE_DDC5:
channel = CHANNEL_ID_DDC5;
break;
case GPIO_DDC_LINE_DDC6:
channel = CHANNEL_ID_DDC6;
break;
case GPIO_DDC_LINE_DDC_VGA:
channel = CHANNEL_ID_DDC_VGA;
break;
case GPIO_DDC_LINE_I2C_PAD:
channel = CHANNEL_ID_I2C_PAD;
break;
default:
BREAK_TO_DEBUGGER();
break;
}
}
}
return channel;
}
@ -546,6 +549,7 @@ static bool construct_phy(struct dc_link *link,
bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info);
link->is_internal_display = (disp_connect_caps_info.INTERNAL_DISPLAY != 0);
DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display);
link->no_ddc_pin = disp_connect_caps_info.NO_DDC_PIN != 0;
}
if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
@ -568,15 +572,19 @@ static bool construct_phy(struct dc_link *link,
goto ddc_create_fail;
}
/* Embedded display connectors such as LVDS may not have DDC. */
if (!link->ddc->ddc_pin &&
!dc_is_embedded_signal(link->connector_signal)) {
DC_ERROR("Failed to get I2C info for connector!\n");
goto ddc_create_fail;
}
if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) {
link->ddc_hw_inst = link->aux_hw_inst;
} else {
/* Embedded display connectors such as LVDS may not have DDC. */
if (!link->ddc->ddc_pin &&
!dc_is_embedded_signal(link->connector_signal)) {
DC_ERROR("Failed to get I2C info for connector!\n");
goto ddc_create_fail;
}
link->ddc_hw_inst =
dal_ddc_get_line(get_ddc_pin(link->ddc));
link->ddc_hw_inst =
dal_ddc_get_line(get_ddc_pin(link->ddc));
}
enc_init_data.ctx = dc_ctx;
enc_init_data.connector = link->link_id;

View File

@ -119,25 +119,32 @@ static void ddc_service_construct(
ddc_service->link = init_data->link;
ddc_service->ctx = init_data->ctx;
if (init_data->is_dpia_link ||
dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info) != BP_RESULT_OK) {
ddc_service->ddc_pin = NULL;
} else {
DC_LOGGER_INIT(ddc_service->ctx->logger);
DC_LOG_DC("BIOS object table - i2c_line: %d", i2c_info.i2c_line);
DC_LOG_DC("BIOS object table - i2c_engine_id: %d", i2c_info.i2c_engine_id);
if (ddc_service->link && ddc_service->ctx->dc->config.dp_connector_no_native_i2c &&
ddc_service->link->no_ddc_pin) {
// Obtain aux instance info from i2c_info without GPIO DDC pin info
if (dcb->funcs->get_connector_aux_info(dcb, init_data->id, &i2c_info) == BP_RESULT_OK)
ddc_service->link->aux_hw_inst = (uint8_t)i2c_info.i2c_line;
} else {
if (init_data->is_dpia_link ||
dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info) != BP_RESULT_OK) {
ddc_service->ddc_pin = NULL;
} else {
DC_LOGGER_INIT(ddc_service->ctx->logger);
DC_LOG_DC("BIOS object table - i2c_line: %d", i2c_info.i2c_line);
DC_LOG_DC("BIOS object table - i2c_engine_id: %d", i2c_info.i2c_engine_id);
hw_info.ddc_channel = i2c_info.i2c_line;
if (ddc_service->link != NULL)
hw_info.hw_supported = i2c_info.i2c_hw_assist;
else
hw_info.hw_supported = false;
hw_info.ddc_channel = i2c_info.i2c_line;
if (ddc_service->link != NULL)
hw_info.hw_supported = i2c_info.i2c_hw_assist;
else
hw_info.hw_supported = false;
ddc_service->ddc_pin = dal_gpio_create_ddc(
gpio_service,
i2c_info.gpio_info.clk_a_register_index,
1 << i2c_info.gpio_info.clk_a_shift,
&hw_info);
ddc_service->ddc_pin = dal_gpio_create_ddc(
gpio_service,
i2c_info.gpio_info.clk_a_register_index,
1 << i2c_info.gpio_info.clk_a_shift,
&hw_info);
}
}
ddc_service->flags.EDID_QUERY_DONE_ONCE = false;
@ -518,11 +525,18 @@ bool try_to_configure_aux_timeout(struct ddc_service *ddc,
if (ddc->link->ep_type != DISPLAY_ENDPOINT_PHY)
return true;
if (ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout) {
ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout);
result = true;
}
if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) {
if (ddc->ctx->dc->res_pool->engines[ddc->link->aux_hw_inst]->funcs->configure_timeout) {
ddc->ctx->dc->res_pool->engines[ddc->link->aux_hw_inst]->funcs->configure_timeout(ddc, timeout);
result = true;
}
} else {
if (ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout) {
ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout);
result = true;
}
}
return result;
}

View File

@ -2570,6 +2570,12 @@ bool dp_is_sink_present(struct dc_link *link)
(connector_id == CONNECTOR_ID_EDP) ||
(connector_id == CONNECTOR_ID_USBC));
/* We can't perform the step below for ASICs with no Native
* I2C signaling support on DP connectors, so skip it.
*/
if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin)
return present;
ddc = get_ddc_pin(link->ddc);
if (!ddc) {

View File

@ -788,7 +788,10 @@ bool edp_setup_psr(struct dc_link *link,
}
}
psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel;
if (dc->config.dp_connector_no_native_i2c && link->no_ddc_pin)
psr_context->channel = (enum channel_id)link->aux_hw_inst;
else
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;

View File

@ -317,6 +317,7 @@ struct bp_spread_spectrum_parameters {
struct bp_disp_connector_caps_info {
uint32_t INTERNAL_DISPLAY : 1;
uint32_t INTERNAL_DISPLAY_BL : 1;
uint32_t NO_DDC_PIN : 1;
};
struct bp_encoder_cap_info {