mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
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:
parent
9aef3d167a
commit
6750a2316f
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user