mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-23 05:14:51 +07:00
drm/amd/display: linux enable oled panel support dc part
[Why] old panel has been enabled for window driver but not linux. [How] enable oled panel support for linux. this patch is dc part. Signed-off-by: Hersen Wu <hersenxs.wu@amd.com> Reviewed-by: Harry Wentland <Harry.Wentland@amd.com> Reviewed-by: Hersen Wu <hersenxs.wu@amd.com> Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
9edf202d27
commit
96577cf82a
@ -599,6 +599,9 @@ static bool detect_dp(
|
||||
|
||||
if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
|
||||
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
|
||||
|
||||
dpcd_set_source_specific_data(link);
|
||||
|
||||
if (!detect_dp_sink_caps(link))
|
||||
return false;
|
||||
|
||||
@ -769,8 +772,16 @@ static bool dc_link_detect_helper(struct dc_link *link,
|
||||
|
||||
if ((link->connector_signal == SIGNAL_TYPE_LVDS ||
|
||||
link->connector_signal == SIGNAL_TYPE_EDP) &&
|
||||
link->local_sink)
|
||||
link->local_sink) {
|
||||
|
||||
// need to re-write OUI and brightness in resume case
|
||||
if (link->connector_signal == SIGNAL_TYPE_EDP) {
|
||||
dpcd_set_source_specific_data(link);
|
||||
dc_link_set_default_brightness_aux(link); //TODO: use cached
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (false == dc_link_detect_sink(link, &new_connection_type)) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
@ -818,6 +829,10 @@ static bool dc_link_detect_helper(struct dc_link *link,
|
||||
}
|
||||
|
||||
case SIGNAL_TYPE_EDP: {
|
||||
read_current_link_settings_on_detect(link);
|
||||
|
||||
dpcd_set_source_specific_data(link);
|
||||
|
||||
detect_edp_sink_caps(link);
|
||||
read_current_link_settings_on_detect(link);
|
||||
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
|
||||
@ -1492,6 +1507,7 @@ static enum dc_status enable_link_dp(
|
||||
bool fec_enable;
|
||||
int i;
|
||||
bool apply_seamless_boot_optimization = false;
|
||||
uint32_t bl_oled_enable_delay = 50; // in ms
|
||||
|
||||
// check for seamless boot
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
@ -1515,6 +1531,9 @@ static enum dc_status enable_link_dp(
|
||||
if (state->clk_mgr && !apply_seamless_boot_optimization)
|
||||
state->clk_mgr->funcs->update_clocks(state->clk_mgr, state, false);
|
||||
|
||||
// during mode switch we do DP_SET_POWER off then on, and OUI is lost
|
||||
dpcd_set_source_specific_data(link);
|
||||
|
||||
skip_video_pattern = true;
|
||||
|
||||
if (link_settings.link_rate == LINK_RATE_LOW)
|
||||
@ -1538,6 +1557,17 @@ static enum dc_status enable_link_dp(
|
||||
fec_enable = true;
|
||||
|
||||
dp_set_fec_enable(link, fec_enable);
|
||||
|
||||
// during mode set we do DP_SET_POWER off then on, aux writes are lost
|
||||
if (link->dpcd_sink_ext_caps.bits.oled == 1 ||
|
||||
link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1 ||
|
||||
link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1) {
|
||||
dc_link_set_default_brightness_aux(link); // TODO: use cached if known
|
||||
if (link->dpcd_sink_ext_caps.bits.oled == 1)
|
||||
msleep(bl_oled_enable_delay);
|
||||
dc_link_backlight_enable_aux(link, true);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,14 @@
|
||||
|
||||
#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50
|
||||
|
||||
#define DP_SOURCE_TABLE_REVISION 0x310
|
||||
#define DP_SOURCE_PAYLOAD_SIZE 0x311
|
||||
#define DP_SOURCE_SINK_CAP 0x317
|
||||
#define DP_SOURCE_BACKLIGHT_LEVEL 0x320
|
||||
#define DP_SOURCE_BACKLIGHT_CURRENT_PEAK 0x326
|
||||
#define DP_SOURCE_BACKLIGHT_CONTROL 0x32E
|
||||
#define DP_SOURCE_BACKLIGHT_ENABLE 0x32F
|
||||
|
||||
/* maximum pre emphasis level allowed for each voltage swing level*/
|
||||
static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = {
|
||||
PRE_EMPHASIS_LEVEL3,
|
||||
@ -3166,6 +3174,23 @@ static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
|
||||
link->wa_flags.dp_keep_receiver_powered = false;
|
||||
}
|
||||
|
||||
/* Read additional sink caps defined in source specific DPCD area
|
||||
* This function currently only reads from SinkCapability address (DP_SOURCE_SINK_CAP)
|
||||
*/
|
||||
static bool dpcd_read_sink_ext_caps(struct dc_link *link)
|
||||
{
|
||||
uint8_t dpcd_data;
|
||||
|
||||
if (!link)
|
||||
return false;
|
||||
|
||||
if (core_link_read_dpcd(link, DP_SOURCE_SINK_CAP, &dpcd_data, 1) != DC_OK)
|
||||
return false;
|
||||
|
||||
link->dpcd_sink_ext_caps.raw = dpcd_data;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool retrieve_link_cap(struct dc_link *link)
|
||||
{
|
||||
/* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
|
||||
@ -3438,6 +3463,9 @@ static bool retrieve_link_cap(struct dc_link *link)
|
||||
sizeof(link->dpcd_caps.dsc_caps.dsc_ext_caps.raw));
|
||||
}
|
||||
|
||||
if (!dpcd_read_sink_ext_caps(link))
|
||||
link->dpcd_sink_ext_caps.raw = 0;
|
||||
|
||||
/* Connectivity log: detection */
|
||||
CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
|
||||
|
||||
@ -3590,6 +3618,8 @@ void detect_edp_sink_caps(struct dc_link *link)
|
||||
}
|
||||
}
|
||||
link->verified_link_cap = link->reported_link_cap;
|
||||
|
||||
dc_link_set_default_brightness_aux(link);
|
||||
}
|
||||
|
||||
void dc_link_dp_enable_hpd(const struct dc_link *link)
|
||||
@ -4147,3 +4177,141 @@ void dp_set_fec_enable(struct dc_link *link, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
void dpcd_set_source_specific_data(struct dc_link *link)
|
||||
{
|
||||
struct dpcd_amd_signature amd_signature;
|
||||
const uint32_t post_oui_delay = 30; // 30ms
|
||||
|
||||
amd_signature.AMD_IEEE_TxSignature_byte1 = 0x0;
|
||||
amd_signature.AMD_IEEE_TxSignature_byte2 = 0x0;
|
||||
amd_signature.AMD_IEEE_TxSignature_byte3 = 0x1A;
|
||||
amd_signature.device_id_byte1 =
|
||||
(uint8_t)(link->ctx->asic_id.chip_id);
|
||||
amd_signature.device_id_byte2 =
|
||||
(uint8_t)(link->ctx->asic_id.chip_id >> 8);
|
||||
memset(&amd_signature.zero, 0, 4);
|
||||
amd_signature.dce_version =
|
||||
(uint8_t)(link->ctx->dce_version);
|
||||
amd_signature.dal_version_byte1 = 0x0; // needed? where to get?
|
||||
amd_signature.dal_version_byte2 = 0x0; // needed? where to get?
|
||||
|
||||
core_link_write_dpcd(link, DP_SOURCE_OUI,
|
||||
(uint8_t *)(&amd_signature),
|
||||
sizeof(amd_signature));
|
||||
|
||||
// Sink may need to configure internals based on vendor, so allow some
|
||||
// time before proceeding with possibly vendor specific transactions
|
||||
msleep(post_oui_delay);
|
||||
}
|
||||
|
||||
bool dc_link_set_backlight_level_nits(struct dc_link *link,
|
||||
bool isHDR,
|
||||
uint32_t backlight_millinits,
|
||||
uint32_t transition_time_in_ms)
|
||||
{
|
||||
struct dpcd_source_backlight_set dpcd_backlight_set;
|
||||
uint8_t backlight_control = isHDR ? 1 : 0;
|
||||
|
||||
if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
|
||||
link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
|
||||
return false;
|
||||
|
||||
// OLEDs have no PWM, they can only use AUX
|
||||
if (link->dpcd_sink_ext_caps.bits.oled == 1)
|
||||
backlight_control = 1;
|
||||
|
||||
*(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
|
||||
*(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
|
||||
|
||||
|
||||
if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
|
||||
(uint8_t *)(&dpcd_backlight_set),
|
||||
sizeof(dpcd_backlight_set)) != DC_OK)
|
||||
return false;
|
||||
|
||||
if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
|
||||
&backlight_control, 1) != DC_OK)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_link_get_backlight_level_nits(struct dc_link *link,
|
||||
uint32_t *backlight_millinits_avg,
|
||||
uint32_t *backlight_millinits_peak)
|
||||
{
|
||||
union dpcd_source_backlight_get dpcd_backlight_get;
|
||||
|
||||
memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get));
|
||||
|
||||
if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
|
||||
link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
|
||||
return false;
|
||||
|
||||
if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,
|
||||
dpcd_backlight_get.raw,
|
||||
sizeof(union dpcd_source_backlight_get)))
|
||||
return false;
|
||||
|
||||
*backlight_millinits_avg =
|
||||
dpcd_backlight_get.bytes.backlight_millinits_avg;
|
||||
*backlight_millinits_peak =
|
||||
dpcd_backlight_get.bytes.backlight_millinits_peak;
|
||||
|
||||
/* On non-supported panels dpcd_read usually succeeds with 0 returned */
|
||||
if (*backlight_millinits_avg == 0 ||
|
||||
*backlight_millinits_avg > *backlight_millinits_peak)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable)
|
||||
{
|
||||
uint8_t backlight_enable = enable ? 1 : 0;
|
||||
|
||||
if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
|
||||
link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
|
||||
return false;
|
||||
|
||||
if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
|
||||
&backlight_enable, 1) != DC_OK)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// we read default from 0x320 because we expect BIOS wrote it there
|
||||
// regular get_backlight_nit reads from panel set at 0x326
|
||||
bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits)
|
||||
{
|
||||
if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
|
||||
link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
|
||||
return false;
|
||||
|
||||
if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
|
||||
(uint8_t *) backlight_millinits,
|
||||
sizeof(uint32_t)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_link_set_default_brightness_aux(struct dc_link *link)
|
||||
{
|
||||
uint32_t default_backlight;
|
||||
|
||||
if (link &&
|
||||
(link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
|
||||
link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)) {
|
||||
if (!dc_link_read_default_bl_aux(link, &default_backlight))
|
||||
default_backlight = 150000;
|
||||
// if < 5 nits or > 5000, it might be wrong readback
|
||||
if (default_backlight < 5000 || default_backlight > 5000000)
|
||||
default_backlight = 150000; //
|
||||
|
||||
return dc_link_set_backlight_level_nits(link, true,
|
||||
default_backlight, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -980,6 +980,20 @@ struct dpcd_caps {
|
||||
|
||||
};
|
||||
|
||||
union dpcd_sink_ext_caps {
|
||||
struct {
|
||||
/* 0 - Sink supports backlight adjust via PWM during SDR/HDR mode
|
||||
* 1 - Sink supports backlight adjust via AUX during SDR/HDR mode.
|
||||
*/
|
||||
uint8_t sdr_aux_backlight_control : 1;
|
||||
uint8_t hdr_aux_backlight_control : 1;
|
||||
uint8_t reserved_1 : 2;
|
||||
uint8_t oled : 1;
|
||||
uint8_t reserved : 3;
|
||||
} bits;
|
||||
uint8_t raw;
|
||||
};
|
||||
|
||||
#include "dc_link.h"
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -432,6 +432,40 @@ struct dp_sink_hw_fw_revision {
|
||||
uint8_t ieee_fw_rev[2];
|
||||
};
|
||||
|
||||
struct dpcd_amd_signature {
|
||||
uint8_t AMD_IEEE_TxSignature_byte1;
|
||||
uint8_t AMD_IEEE_TxSignature_byte2;
|
||||
uint8_t AMD_IEEE_TxSignature_byte3;
|
||||
uint8_t device_id_byte1;
|
||||
uint8_t device_id_byte2;
|
||||
uint8_t zero[4];
|
||||
uint8_t dce_version;
|
||||
uint8_t dal_version_byte1;
|
||||
uint8_t dal_version_byte2;
|
||||
};
|
||||
|
||||
struct dpcd_source_backlight_set {
|
||||
struct {
|
||||
uint8_t byte0;
|
||||
uint8_t byte1;
|
||||
uint8_t byte2;
|
||||
uint8_t byte3;
|
||||
} backlight_level_millinits;
|
||||
|
||||
struct {
|
||||
uint8_t byte0;
|
||||
uint8_t byte1;
|
||||
} backlight_transition_time_ms;
|
||||
};
|
||||
|
||||
union dpcd_source_backlight_get {
|
||||
struct {
|
||||
uint32_t backlight_millinits_peak; /* 326h */
|
||||
uint32_t backlight_millinits_avg; /* 32Ah */
|
||||
} bytes;
|
||||
uint8_t raw[8];
|
||||
};
|
||||
|
||||
/*DPCD register of DP receiver capability field bits-*/
|
||||
union edp_configuration_cap {
|
||||
struct {
|
||||
|
@ -128,6 +128,7 @@ struct dc_link {
|
||||
enum edp_revision edp_revision;
|
||||
bool psr_feature_enabled;
|
||||
bool psr_allow_active;
|
||||
union dpcd_sink_ext_caps dpcd_sink_ext_caps;
|
||||
|
||||
/* MST record stream using this link */
|
||||
struct link_flags {
|
||||
@ -178,6 +179,21 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link,
|
||||
uint32_t backlight_pwm_u16_16,
|
||||
uint32_t frame_ramp);
|
||||
|
||||
/* Set/get nits-based backlight level of an embedded panel (eDP, LVDS). */
|
||||
bool dc_link_set_backlight_level_nits(struct dc_link *link,
|
||||
bool isHDR,
|
||||
uint32_t backlight_millinits,
|
||||
uint32_t transition_time_in_ms);
|
||||
|
||||
bool dc_link_get_backlight_level_nits(struct dc_link *link,
|
||||
uint32_t *backlight_millinits,
|
||||
uint32_t *backlight_millinits_peak);
|
||||
|
||||
bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable);
|
||||
|
||||
bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits);
|
||||
bool dc_link_set_default_brightness_aux(struct dc_link *link);
|
||||
|
||||
int dc_link_get_backlight_level(const struct dc_link *dc_link);
|
||||
|
||||
bool dc_link_set_abm_disable(const struct dc_link *dc_link);
|
||||
|
@ -71,6 +71,8 @@
|
||||
#define PANEL_POWER_UP_TIMEOUT 300
|
||||
#define PANEL_POWER_DOWN_TIMEOUT 500
|
||||
#define HPD_CHECK_INTERVAL 10
|
||||
#define OLED_POST_T7_DELAY 100
|
||||
#define OLED_PRE_T11_DELAY 150
|
||||
|
||||
#define CTX \
|
||||
hws->ctx
|
||||
@ -936,9 +938,21 @@ void dce110_edp_backlight_control(
|
||||
if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON)
|
||||
edp_receiver_ready_T7(link);
|
||||
link_transmitter_control(ctx->dc_bios, &cntl);
|
||||
|
||||
if (enable && link->dpcd_sink_ext_caps.bits.oled)
|
||||
msleep(OLED_POST_T7_DELAY);
|
||||
|
||||
if (link->dpcd_sink_ext_caps.bits.oled ||
|
||||
link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
|
||||
link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)
|
||||
dc_link_backlight_enable_aux(link, enable);
|
||||
|
||||
/*edp 1.2*/
|
||||
if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF)
|
||||
edp_receiver_ready_T9(link);
|
||||
|
||||
if (!enable && link->dpcd_sink_ext_caps.bits.oled)
|
||||
msleep(OLED_PRE_T11_DELAY);
|
||||
}
|
||||
|
||||
void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
|
||||
|
@ -78,6 +78,8 @@ void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode);
|
||||
|
||||
bool dp_overwrite_extended_receiver_cap(struct dc_link *link);
|
||||
|
||||
void dpcd_set_source_specific_data(struct dc_link *link);
|
||||
|
||||
void dp_set_fec_ready(struct dc_link *link, bool ready);
|
||||
void dp_set_fec_enable(struct dc_link *link, bool enable);
|
||||
bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable);
|
||||
|
Loading…
Reference in New Issue
Block a user