struct dc_link_status link_status;
struct dprx_states dprx_states;
- struct gpio *hpd_gpio;
enum dc_link_fec_state fec_state;
bool is_dds;
bool is_display_mux_present;
.destroy = dce110_link_encoder_destroy,
.get_max_link_cap = dce110_link_encoder_get_max_link_cap,
.get_dig_frontend = dce110_get_dig_frontend,
+ .get_hpd_state = dce110_get_hpd_state,
+ .program_hpd_filter = dce110_program_hpd_filter,
};
static enum bp_result link_transmitter_control(
enc110->base.ctx = init_data->ctx;
enc110->base.id = init_data->encoder;
+ enc110->base.hpd_gpio = init_data->hpd_gpio;
enc110->base.hpd_source = init_data->hpd_source;
enc110->base.connector = init_data->connector;
void dce110_link_encoder_destroy(struct link_encoder **enc)
{
+ if ((*enc)->hpd_gpio) {
+ dal_gpio_destroy_irq(&(*enc)->hpd_gpio);
+ (*enc)->hpd_gpio = NULL;
+ }
+
kfree(TO_DCE110_LINK_ENC(*enc));
*enc = NULL;
}
*link_settings = max_link_cap;
}
+bool dce110_get_hpd_state(struct link_encoder *enc)
+{
+ uint32_t state = 0;
+
+ if (!enc->hpd_gpio)
+ return false;
+
+ dal_gpio_lock_pin(enc->hpd_gpio);
+ dal_gpio_get_value(enc->hpd_gpio, &state);
+ dal_gpio_unlock_pin(enc->hpd_gpio);
+
+ return state;
+}
+
+bool dce110_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms)
+{
+ /* Setup HPD filtering */
+ if (enc->hpd_gpio && dal_gpio_lock_pin(enc->hpd_gpio) == GPIO_RESULT_OK) {
+ struct gpio_hpd_config config;
+
+ config.delay_on_connect = delay_on_connect_in_ms;
+ config.delay_on_disconnect = delay_on_disconnect_in_ms;
+
+ dal_irq_setup_hpd_filter(enc->hpd_gpio, &config);
+
+ dal_gpio_unlock_pin(enc->hpd_gpio);
+
+ return true;
+ } else {
+ ASSERT(0);
+ return false;
+ }
+}
+
#if defined(CONFIG_DRM_AMD_DC_SI)
static const struct link_encoder_funcs dce60_lnk_enc_funcs = {
.validate_output_with_stream =
.is_dig_enabled = dce110_is_dig_enabled,
.destroy = dce110_link_encoder_destroy,
.get_max_link_cap = dce110_link_encoder_get_max_link_cap,
- .get_dig_frontend = dce110_get_dig_frontend
+ .get_dig_frontend = dce110_get_dig_frontend,
+ .get_hpd_state = dce110_get_hpd_state,
+ .program_hpd_filter = dce110_program_hpd_filter,
};
void dce60_link_encoder_construct(
enc110->base.ctx = init_data->ctx;
enc110->base.id = init_data->encoder;
+ enc110->base.hpd_gpio = init_data->hpd_gpio;
enc110->base.hpd_source = init_data->hpd_source;
enc110->base.connector = init_data->connector;
SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \
SR(DCI_MEM_PWR_STATUS)
-#define LE_DCN10_REG_LIST(id)\
- LE_COMMON_REG_LIST_BASE(id), \
- SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
- SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
- SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id)
struct dce110_link_enc_aux_registers {
uint32_t AUX_CONTROL;
void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings);
+bool dce110_get_hpd_state(struct link_encoder *enc);
+bool dce110_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms);
+
#endif /* __DC_LINK_ENCODER__DCE110_H__ */
.fec_is_active = enc2_fec_is_active,
.is_in_alt_mode = dcn201_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn201_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn201_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
.get_dig_frontend = dcn10_get_dig_frontend,
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn21_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
.get_dig_mode = dcn10_get_dig_mode,
.destroy = dcn10_link_encoder_destroy,
.get_max_link_cap = dcn10_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
+
static enum bp_result link_transmitter_control(
struct dcn10_link_encoder *enc10,
struct bp_transmitter_control *cntl)
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
void dcn10_link_encoder_destroy(struct link_encoder **enc)
{
+ if ((*enc)->hpd_gpio) {
+ dal_gpio_destroy_irq(&(*enc)->hpd_gpio);
+ (*enc)->hpd_gpio = NULL;
+ }
+
kfree(TO_DCN10_LINK_ENC(*enc));
*enc = NULL;
}
*link_settings = max_link_cap;
}
+
+bool dcn10_get_hpd_state(struct link_encoder *enc)
+{
+ uint32_t state = 0;
+
+ if (!enc->hpd_gpio)
+ return false;
+
+ dal_gpio_lock_pin(enc->hpd_gpio);
+ dal_gpio_get_value(enc->hpd_gpio, &state);
+ dal_gpio_unlock_pin(enc->hpd_gpio);
+
+ return state;
+}
+
+bool dcn10_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms)
+{
+ /* Setup HPD filtering */
+ if (enc->hpd_gpio && dal_gpio_lock_pin(enc->hpd_gpio) == GPIO_RESULT_OK) {
+ struct gpio_hpd_config config;
+
+ config.delay_on_connect = delay_on_connect_in_ms;
+ config.delay_on_disconnect = delay_on_disconnect_in_ms;
+
+ dal_irq_setup_hpd_filter(enc->hpd_gpio, &config);
+
+ dal_gpio_unlock_pin(enc->hpd_gpio);
+
+ return true;
+ } else {
+ ASSERT(0);
+ return false;
+ }
+}
struct dcn10_link_enc_hpd_registers {
uint32_t DC_HPD_CONTROL;
+ uint32_t DC_HPD_INT_STATUS;
+ uint32_t DC_HPD_TOGGLE_FILT_CNTL;
};
struct dcn10_link_enc_registers {
type TMDS_CTL0;\
type AUX_HPD_SEL;\
type AUX_LS_READ_EN;\
- type AUX_RX_RECEIVE_WINDOW
+ type AUX_RX_RECEIVE_WINDOW;\
+ type DC_HPD_SENSE;\
+ type DC_HPD_CONNECT_INT_DELAY;\
+ type DC_HPD_DISCONNECT_INT_DELAY
#define DCN20_LINK_ENCODER_DPCS_REG_FIELD_LIST(type) \
void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings);
+
+bool dcn10_get_hpd_state(struct link_encoder *enc);
+bool dcn10_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms);
+
#endif /* __DC_LINK_ENCODER__DCN10_H__ */
.get_dig_frontend = dcn10_get_dig_frontend,
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn20_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
.get_dig_mode = dcn10_get_dig_mode,
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn30_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
.get_dig_mode = dcn10_get_dig_mode,
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn301_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
.is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn31_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn31_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
.is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn32_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn321_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
.enable_dpia_output = dcn35_link_encoder_enable_dpia_output,
.disable_dpia_output = dcn35_link_encoder_disable_dpia_output,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn35_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
.is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn401_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
{
struct dc_context *ctx = link->ctx;
struct graphics_object_id connector = link->link_enc->connector;
- struct gpio *hpd;
bool edp_hpd_high = false;
uint32_t time_elapsed = 0;
uint32_t timeout = power_up ?
* we need to wait until SENSE bit is high/low.
*/
- /* obtain HPD */
- /* TODO what to do with this? */
- hpd = ctx->dc->link_srv->get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service);
-
- if (!hpd) {
- BREAK_TO_DEBUGGER();
- return;
- }
-
if (link->panel_config.pps.extra_t3_ms > 0) {
int extra_t3_in_ms = link->panel_config.pps.extra_t3_ms;
msleep(extra_t3_in_ms);
}
- dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
-
/* wait until timeout or panel detected */
do {
- uint32_t detected = 0;
-
- dal_gpio_get_value(hpd, &detected);
-
- if (!(detected ^ power_up)) {
+ if (!(link->dc->link_srv->get_hpd_state(link) ^ power_up)) {
edp_hpd_high = true;
break;
}
time_elapsed += HPD_CHECK_INTERVAL;
} while (time_elapsed < timeout);
- dal_gpio_close(hpd);
-
- dal_gpio_destroy_irq(&hpd);
-
/* ensure that the panel is detected */
if (!edp_hpd_high)
DC_LOG_DC("%s: wait timed out!\n", __func__);
struct encoder_init_data {
enum channel_id channel;
struct graphics_object_id connector;
+ struct gpio *hpd_gpio;
enum hpd_source_id hpd_source;
/* TODO: in DAL2, here was pointer to EventManagerInterface */
struct graphics_object_id encoder;
enum engine_id analog_engine;
struct encoder_feature_support features;
enum transmitter transmitter;
+ struct gpio *hpd_gpio;
enum hpd_source_id hpd_source;
bool usbc_combo_phy;
};
void (*disable_dpia_output)(struct link_encoder *link_enc,
uint8_t dpia_id,
uint8_t digmode);
+ bool (*get_hpd_state)(struct link_encoder *enc);
+ bool (*program_hpd_filter)(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms);
};
/*
struct dc_sink_init_data *init_data);
void (*remove_remote_sink)(struct dc_link *link, struct dc_sink *sink);
bool (*get_hpd_state)(struct dc_link *link);
- struct gpio *(*get_hpd_gpio)(struct dc_bios *dcb,
- struct graphics_object_id link_id,
- struct gpio_service *gpio_service);
void (*enable_hpd)(const struct dc_link *link);
void (*disable_hpd)(const struct dc_link *link);
void (*enable_hpd_filter)(struct dc_link *link, bool enable);
*/
bool link_detect_connection_type(struct dc_link *link, enum dc_connection_type *type)
{
- uint32_t is_hpd_high = 0;
-
if (link->connector_signal == SIGNAL_TYPE_LVDS) {
*type = dc_connection_single;
return true;
}
- if (!query_hpd_status(link, &is_hpd_high))
- goto hpd_gpio_failure;
-
- if (is_hpd_high) {
+ if (link_get_hpd_state(link)) {
*type = dc_connection_single;
/* TODO: need to do the actual detection */
} else {
}
return true;
-
-hpd_gpio_failure:
- return false;
}
bool link_detect(struct dc_link *link, enum dc_detect_reason reason)
link_srv->add_remote_sink = link_add_remote_sink;
link_srv->remove_remote_sink = link_remove_remote_sink;
link_srv->get_hpd_state = link_get_hpd_state;
- link_srv->get_hpd_gpio = link_get_hpd_gpio;
link_srv->enable_hpd = link_enable_hpd;
link_srv->disable_hpd = link_disable_hpd;
link_srv->enable_hpd_filter = link_enable_hpd_filter;
{
int i;
- if (link->hpd_gpio) {
- dal_gpio_destroy_irq(&link->hpd_gpio);
- link->hpd_gpio = NULL;
- }
-
if (link->ddc)
link_destroy_ddc_service(&link->ddc);
if (link->dc->res_pool->funcs->link_init)
link->dc->res_pool->funcs->link_init(link);
- link->hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,
+ ddc_service_init_data.ctx = link->ctx;
+ ddc_service_init_data.id = link->link_id;
+ ddc_service_init_data.link = link;
+ link->ddc = link_create_ddc_service(&ddc_service_init_data);
+
+ if (!link->ddc) {
+ DC_ERROR("Failed to create ddc_service!\n");
+ goto ddc_create_fail;
+ }
+
+ if (!link->ddc->ddc_pin) {
+ 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));
+
+ enc_init_data.ctx = dc_ctx;
+ enc_init_data.connector = link->link_id;
+ enc_init_data.channel = get_ddc_line(link);
+ enc_init_data.transmitter = transmitter_from_encoder;
+ enc_init_data.encoder = link_encoder;
+ enc_init_data.analog_engine = link_analog_engine;
+ enc_init_data.hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,
link->ctx->gpio_service);
- if (link->hpd_gpio) {
- dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT);
- dal_gpio_unlock_pin(link->hpd_gpio);
- link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);
+ if (enc_init_data.hpd_gpio) {
+ dal_gpio_open(enc_init_data.hpd_gpio, GPIO_MODE_INTERRUPT);
+ dal_gpio_unlock_pin(enc_init_data.hpd_gpio);
+ link->irq_source_hpd = dal_irq_get_source(enc_init_data.hpd_gpio);
+ enc_init_data.hpd_source = get_hpd_line(link);
+ link->hpd_src = enc_init_data.hpd_source;
+
+ DC_LOG_DC("BIOS object table - hpd_gpio id: %d", enc_init_data.hpd_gpio->id);
+ DC_LOG_DC("BIOS object table - hpd_gpio en: %d", enc_init_data.hpd_gpio->en);
+ } else {
+ struct graphics_object_hpd_info hpd_info;
+
+ if (link->ctx->dc_bios->funcs->get_hpd_info(link->ctx->dc_bios, link->link_id, &hpd_info) == BP_RESULT_OK) {
+ link->hpd_src = hpd_info.hpd_int_gpio_uid - 1;
+ link->irq_source_hpd = DC_IRQ_SOURCE_HPD1 + link->hpd_src;
+ enc_init_data.hpd_source = link->hpd_src;
+ DC_LOG_DC("BIOS object table - hpd_int_gpio_uid id: %d", hpd_info.hpd_int_gpio_uid);
+ } else {
+ ASSERT(0);
+ enc_init_data.hpd_source = HPD_SOURCEID_UNKNOWN;
+ }
+ }
- DC_LOG_DC("BIOS object table - hpd_gpio id: %d", link->hpd_gpio->id);
- DC_LOG_DC("BIOS object table - hpd_gpio en: %d", link->hpd_gpio->en);
+ link->link_enc =
+ link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);
+
+ if (!link->link_enc) {
+ DC_ERROR("Failed to create link encoder!\n");
+ goto link_enc_create_fail;
}
+ DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
+ DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
+
switch (link->link_id.id) {
case CONNECTOR_ID_HDMI_TYPE_A:
link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
- if (link->hpd_gpio)
+ if (link->link_enc->hpd_gpio)
link->irq_source_read_request =
- dal_irq_get_read_request(link->hpd_gpio);
+ dal_irq_get_read_request(link->link_enc->hpd_gpio);
+ else if (link->hpd_src != HPD_SOURCEID_UNKNOWN)
+ link->irq_source_read_request = DC_IRQ_SOURCE_DCI2C_RR_DDC1 + link->hpd_src;
break;
case CONNECTOR_ID_SINGLE_LINK_DVID:
case CONNECTOR_ID_SINGLE_LINK_DVII:
case CONNECTOR_ID_USBC:
link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
- if (link->hpd_gpio)
+ if (link->link_enc->hpd_gpio)
link->irq_source_hpd_rx =
- dal_irq_get_rx_source(link->hpd_gpio);
+ dal_irq_get_rx_source(link->link_enc->hpd_gpio);
+ else if (link->hpd_src != HPD_SOURCEID_UNKNOWN)
+ link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
break;
case CONNECTOR_ID_EDP:
goto create_fail;
link->connector_signal = SIGNAL_TYPE_EDP;
+ if (!link->dc->config.allow_edp_hotplug_detection
+ && !is_smartmux_suported(link))
+ link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
- if (link->hpd_gpio) {
- if (!link->dc->config.allow_edp_hotplug_detection
- && !is_smartmux_suported(link))
- link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
-
- switch (link->dc->config.allow_edp_hotplug_detection) {
- case HPD_EN_FOR_ALL_EDP:
+ switch (link->dc->config.allow_edp_hotplug_detection) {
+ case HPD_EN_FOR_ALL_EDP:
+ if (link->link_enc->hpd_gpio) {
link->irq_source_hpd_rx =
- dal_irq_get_rx_source(link->hpd_gpio);
- break;
- case HPD_EN_FOR_PRIMARY_EDP_ONLY:
- if (link->link_index == 0)
+ dal_irq_get_rx_source(link->link_enc->hpd_gpio);
+ } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
+ link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
+ }
+ break;
+ case HPD_EN_FOR_PRIMARY_EDP_ONLY:
+ if (link->link_index == 0) {
+ if (link->link_enc->hpd_gpio) {
link->irq_source_hpd_rx =
- dal_irq_get_rx_source(link->hpd_gpio);
- else
- link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
- break;
- case HPD_EN_FOR_SECONDARY_EDP_ONLY:
- if (link->link_index == 1)
+ dal_irq_get_rx_source(link->link_enc->hpd_gpio);
+ } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
+ link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
+ }
+ } else
+ link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
+ break;
+ case HPD_EN_FOR_SECONDARY_EDP_ONLY:
+ if (link->link_index == 1) {
+ if (link->link_enc->hpd_gpio) {
link->irq_source_hpd_rx =
- dal_irq_get_rx_source(link->hpd_gpio);
- else
- link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
- break;
- default:
+ dal_irq_get_rx_source(link->link_enc->hpd_gpio);
+ } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
+ link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
+ }
+ } else
link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
- break;
- }
+ break;
+ default:
+ link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
+ break;
}
-
break;
case CONNECTOR_ID_LVDS:
link->connector_signal = SIGNAL_TYPE_LVDS;
init_params->connector_index,
signal_type_to_string(link->connector_signal));
- ddc_service_init_data.ctx = link->ctx;
- ddc_service_init_data.id = link->link_id;
- ddc_service_init_data.link = link;
- link->ddc = link_create_ddc_service(&ddc_service_init_data);
-
- if (!link->ddc) {
- DC_ERROR("Failed to create ddc_service!\n");
- goto ddc_create_fail;
- }
-
- if (!link->ddc->ddc_pin) {
- 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));
-
- enc_init_data.ctx = dc_ctx;
- enc_init_data.connector = link->link_id;
- enc_init_data.channel = get_ddc_line(link);
- enc_init_data.hpd_source = get_hpd_line(link);
- enc_init_data.transmitter = transmitter_from_encoder;
- enc_init_data.encoder = link_encoder;
- enc_init_data.analog_engine = link_analog_engine;
-
- link->hpd_src = enc_init_data.hpd_source;
-
- link->link_enc =
- link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);
-
- if (!link->link_enc) {
- DC_ERROR("Failed to create link encoder!\n");
- goto link_enc_create_fail;
- }
-
- DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
- DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
-
/* Update link encoder tracking variables. These are used for the dynamic
* assignment of link encoders to streams.
*/
DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__);
return true;
device_tag_fail:
- link->link_enc->funcs->destroy(&link->link_enc);
link_enc_create_fail:
- if (link->panel_cntl != NULL)
- link->panel_cntl->funcs->destroy(&link->panel_cntl);
panel_cntl_create_fail:
- link_destroy_ddc_service(&link->ddc);
ddc_create_fail:
create_fail:
-
- if (link->hpd_gpio) {
- dal_gpio_destroy_irq(&link->hpd_gpio);
- link->hpd_gpio = NULL;
- }
+ if (link->ddc)
+ link_destroy_ddc_service(&link->ddc);
+ if (link->panel_cntl)
+ link->panel_cntl->funcs->destroy(&link->panel_cntl);
+ if (link->link_enc)
+ link->link_enc->funcs->destroy(&link->link_enc);
DC_LOG_DC("BIOS object table - %s failed.\n", __func__);
return false;
bool link_get_hpd_state(struct dc_link *link)
{
- uint32_t state = 0;
-
- dal_gpio_lock_pin(link->hpd_gpio);
- dal_gpio_get_value(link->hpd_gpio, &state);
- dal_gpio_unlock_pin(link->hpd_gpio);
-
- return state;
+ if (link->link_enc)
+ return link->link_enc->funcs->get_hpd_state(link->link_enc);
+ else
+ return false;
}
void link_enable_hpd(const struct dc_link *link)
{
- struct link_encoder *encoder = link->link_enc;
-
- if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
- encoder->funcs->enable_hpd(encoder);
+ if (link->link_enc)
+ link->link_enc->funcs->enable_hpd(link->link_enc);
}
void link_disable_hpd(const struct dc_link *link)
{
- struct link_encoder *encoder = link->link_enc;
-
- if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
- encoder->funcs->disable_hpd(encoder);
+ if (link->link_enc)
+ link->link_enc->funcs->disable_hpd(link->link_enc);
}
void link_enable_hpd_filter(struct dc_link *link, bool enable)
{
- struct gpio *hpd;
-
if (enable) {
link->is_hpd_filter_disabled = false;
program_hpd_filter(link);
} else {
link->is_hpd_filter_disabled = true;
- /* Obtain HPD handle */
- hpd = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
-
- if (!hpd)
- return;
-
- /* Setup HPD filtering */
- if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
- struct gpio_hpd_config config;
+ if (link->link_enc)
+ link->link_enc->funcs->program_hpd_filter(link->link_enc, 0, 0);
+ }
+}
- config.delay_on_connect = 0;
- config.delay_on_disconnect = 0;
+bool program_hpd_filter(const struct dc_link *link)
+{
+ int delay_on_connect_in_ms = 0;
+ int delay_on_disconnect_in_ms = 0;
- dal_irq_setup_hpd_filter(hpd, &config);
+ if (link->is_hpd_filter_disabled || !link->link_enc) {
+ ASSERT(link->link_enc);
+ return false;
+ }
- dal_gpio_close(hpd);
- } else {
- ASSERT_CRITICAL(false);
- }
- /* Release HPD handle */
- dal_gpio_destroy_irq(&hpd);
+ /* Verify feature is supported */
+ switch (link->connector_signal) {
+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
+ case SIGNAL_TYPE_DVI_DUAL_LINK:
+ case SIGNAL_TYPE_HDMI_TYPE_A:
+ /* Program hpd filter */
+ delay_on_connect_in_ms = 500;
+ delay_on_disconnect_in_ms = 100;
+ break;
+ case SIGNAL_TYPE_DISPLAY_PORT:
+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
+ /* Program hpd filter to allow DP signal to settle */
+ /* 500: not able to detect MST <-> SST switch as HPD is low for
+ * only 100ms on DELL U2413
+ * 0: some passive dongle still show aux mode instead of i2c
+ * 20-50: not enough to hide bouncing HPD with passive dongle.
+ * also see intermittent i2c read issues.
+ */
+ delay_on_connect_in_ms = 80;
+ delay_on_disconnect_in_ms = 0;
+ break;
+ case SIGNAL_TYPE_LVDS:
+ case SIGNAL_TYPE_EDP:
+ default:
+ /* Don't program hpd filter */
+ return false;
}
+
+ return link->link_enc->funcs->program_hpd_filter(link->link_enc, delay_on_connect_in_ms, delay_on_disconnect_in_ms);
}
struct gpio *link_get_hpd_gpio(struct dc_bios *dcb,
hpd_info.hpd_int_gpio_uid, &pin_info);
if (bp_result != BP_RESULT_OK) {
- ASSERT(bp_result == BP_RESULT_NORECORD);
return NULL;
}
pin_info.mask);
}
-bool query_hpd_status(struct dc_link *link, uint32_t *is_hpd_high)
-{
- struct gpio *hpd_pin = link_get_hpd_gpio(
- link->ctx->dc_bios, link->link_id,
- link->ctx->gpio_service);
- if (!hpd_pin)
- return false;
-
- dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT);
- dal_gpio_get_value(hpd_pin, is_hpd_high);
- dal_gpio_close(hpd_pin);
- dal_gpio_destroy_irq(&hpd_pin);
- return true;
-}
-
enum hpd_source_id get_hpd_line(struct dc_link *link)
{
struct gpio *hpd;
return hpd_id;
}
-
-bool program_hpd_filter(const struct dc_link *link)
-{
- bool result = false;
- struct gpio *hpd;
- int delay_on_connect_in_ms = 0;
- int delay_on_disconnect_in_ms = 0;
-
- if (link->is_hpd_filter_disabled)
- return false;
- /* Verify feature is supported */
- switch (link->connector_signal) {
- case SIGNAL_TYPE_DVI_SINGLE_LINK:
- case SIGNAL_TYPE_DVI_DUAL_LINK:
- case SIGNAL_TYPE_HDMI_TYPE_A:
- /* Program hpd filter */
- delay_on_connect_in_ms = 500;
- delay_on_disconnect_in_ms = 100;
- break;
- case SIGNAL_TYPE_DISPLAY_PORT:
- case SIGNAL_TYPE_DISPLAY_PORT_MST:
- /* Program hpd filter to allow DP signal to settle */
- /* 500: not able to detect MST <-> SST switch as HPD is low for
- * only 100ms on DELL U2413
- * 0: some passive dongle still show aux mode instead of i2c
- * 20-50: not enough to hide bouncing HPD with passive dongle.
- * also see intermittent i2c read issues.
- */
- delay_on_connect_in_ms = 80;
- delay_on_disconnect_in_ms = 0;
- break;
- case SIGNAL_TYPE_LVDS:
- case SIGNAL_TYPE_EDP:
- default:
- /* Don't program hpd filter */
- return false;
- }
-
- /* Obtain HPD handle */
- hpd = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,
- link->ctx->gpio_service);
-
- if (!hpd)
- return result;
-
- /* Setup HPD filtering */
- if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
- struct gpio_hpd_config config;
-
- config.delay_on_connect = delay_on_connect_in_ms;
- config.delay_on_disconnect = delay_on_disconnect_in_ms;
-
- dal_irq_setup_hpd_filter(hpd, &config);
-
- dal_gpio_close(hpd);
-
- result = true;
- } else {
- ASSERT_CRITICAL(false);
- }
-
- /* Release HPD handle */
- dal_gpio_destroy_irq(&hpd);
-
- return result;
-}
* Returns true if HPD high.
*/
bool dpia_query_hpd_status(struct dc_link *link);
-bool query_hpd_status(struct dc_link *link, uint32_t *is_hpd_high);
bool link_get_hpd_state(struct dc_link *link);
struct gpio *link_get_hpd_gpio(struct dc_bios *dcb,
struct graphics_object_id link_id,
AUX_REG_LIST_RI(id), SRI_ARR(AUX_DPHY_TX_CONTROL, DP_AUX, id)
/* HDP */
-#define HPD_REG_LIST_RI(id) SRI_ARR(DC_HPD_CONTROL, HPD, id)
+#define HPD_REG_LIST_RI(id) \
+ (SRI_ARR(DC_HPD_CONTROL, HPD, id), \
+ SRI_ARR(DC_HPD_INT_STATUS, HPD, id), \
+ SRI_ARR(DC_HPD_TOGGLE_FILT_CNTL, HPD, id))
/* Link encoder */
#define LE_DCN3_REG_LIST_RI(id) \