sync code with last fixes and improvements from OpenBSD
This commit is contained in:
parent
f960599e67
commit
691f97cc10
215 changed files with 1520 additions and 11518 deletions
|
@ -40,6 +40,9 @@
|
|||
#include "dc/dc_stat.h"
|
||||
#include "amdgpu_dm_trace.h"
|
||||
#include "dc/inc/dc_link_ddc.h"
|
||||
#include "dpcd_defs.h"
|
||||
#include "dc/inc/link_dpcd.h"
|
||||
#include "link_service_types.h"
|
||||
|
||||
#include "vid.h"
|
||||
#include "amdgpu.h"
|
||||
|
@ -211,7 +214,7 @@ static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm);
|
|||
|
||||
static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
|
||||
struct amdgpu_dm_connector *amdgpu_dm_connector,
|
||||
uint32_t link_index,
|
||||
u32 link_index,
|
||||
struct amdgpu_encoder *amdgpu_encoder);
|
||||
static int amdgpu_dm_encoder_init(struct drm_device *dev,
|
||||
struct amdgpu_encoder *aencoder,
|
||||
|
@ -263,7 +266,7 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
|
|||
static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
|
||||
u32 *vbl, u32 *position)
|
||||
{
|
||||
uint32_t v_blank_start, v_blank_end, h_position, v_position;
|
||||
u32 v_blank_start, v_blank_end, h_position, v_position;
|
||||
|
||||
if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
|
||||
return -EINVAL;
|
||||
|
@ -391,7 +394,7 @@ static void dm_pflip_high_irq(void *interrupt_params)
|
|||
struct amdgpu_device *adev = irq_params->adev;
|
||||
unsigned long flags;
|
||||
struct drm_pending_vblank_event *e;
|
||||
uint32_t vpos, hpos, v_blank_start, v_blank_end;
|
||||
u32 vpos, hpos, v_blank_start, v_blank_end;
|
||||
bool vrr_active;
|
||||
|
||||
amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP);
|
||||
|
@ -405,12 +408,12 @@ static void dm_pflip_high_irq(void *interrupt_params)
|
|||
|
||||
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
|
||||
|
||||
if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
|
||||
DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n",
|
||||
amdgpu_crtc->pflip_status,
|
||||
AMDGPU_FLIP_SUBMITTED,
|
||||
amdgpu_crtc->crtc_id,
|
||||
amdgpu_crtc);
|
||||
if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
|
||||
DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p]\n",
|
||||
amdgpu_crtc->pflip_status,
|
||||
AMDGPU_FLIP_SUBMITTED,
|
||||
amdgpu_crtc->crtc_id,
|
||||
amdgpu_crtc);
|
||||
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
@ -678,7 +681,7 @@ static void dmub_hpd_callback(struct amdgpu_device *adev,
|
|||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
struct dc_link *link;
|
||||
uint8_t link_index = 0;
|
||||
u8 link_index = 0;
|
||||
struct drm_device *dev;
|
||||
|
||||
if (adev == NULL)
|
||||
|
@ -779,7 +782,7 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
|
|||
struct amdgpu_device *adev = irq_params->adev;
|
||||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
struct dmcub_trace_buf_entry entry = { 0 };
|
||||
uint32_t count = 0;
|
||||
u32 count = 0;
|
||||
struct dmub_hpd_work *dmub_hpd_wrk;
|
||||
struct dc_link *plink = NULL;
|
||||
|
||||
|
@ -858,7 +861,7 @@ static int dm_set_powergating_state(void *handle,
|
|||
}
|
||||
|
||||
/* Prototypes of private functions */
|
||||
static int dm_early_init(void* handle);
|
||||
static int dm_early_init(void *handle);
|
||||
|
||||
/* Allocate memory for FBC compressed data */
|
||||
static void amdgpu_dm_fbc_init(struct drm_connector *connector)
|
||||
|
@ -1047,7 +1050,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
|
|||
struct dmub_srv_hw_params hw_params;
|
||||
enum dmub_status status;
|
||||
const unsigned char *fw_inst_const, *fw_bss_data;
|
||||
uint32_t i, fw_inst_const_size, fw_bss_data_size;
|
||||
u32 i, fw_inst_const_size, fw_bss_data_size;
|
||||
bool has_hw_support;
|
||||
|
||||
if (!dmub_srv)
|
||||
|
@ -1208,10 +1211,10 @@ static void dm_dmub_hw_resume(struct amdgpu_device *adev)
|
|||
|
||||
static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config)
|
||||
{
|
||||
uint64_t pt_base;
|
||||
uint32_t logical_addr_low;
|
||||
uint32_t logical_addr_high;
|
||||
uint32_t agp_base, agp_bot, agp_top;
|
||||
u64 pt_base;
|
||||
u32 logical_addr_low;
|
||||
u32 logical_addr_high;
|
||||
u32 agp_base, agp_bot, agp_top;
|
||||
PHYSICAL_ADDRESS_LOC page_table_start, page_table_end, page_table_base;
|
||||
|
||||
memset(pa_config, 0, sizeof(*pa_config));
|
||||
|
@ -1259,7 +1262,7 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
|
|||
pa_config->system_aperture.start_addr = (uint64_t)logical_addr_low << 18;
|
||||
pa_config->system_aperture.end_addr = (uint64_t)logical_addr_high << 18;
|
||||
|
||||
pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24 ;
|
||||
pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24;
|
||||
pa_config->system_aperture.agp_bot = (uint64_t)agp_bot << 24;
|
||||
pa_config->system_aperture.agp_top = (uint64_t)agp_top << 24;
|
||||
|
||||
|
@ -1275,6 +1278,21 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
|
|||
|
||||
}
|
||||
|
||||
static void force_connector_state(
|
||||
struct amdgpu_dm_connector *aconnector,
|
||||
enum drm_connector_force force_state)
|
||||
{
|
||||
struct drm_connector *connector = &aconnector->base;
|
||||
|
||||
mutex_lock(&connector->dev->mode_config.mutex);
|
||||
aconnector->base.force = force_state;
|
||||
mutex_unlock(&connector->dev->mode_config.mutex);
|
||||
|
||||
mutex_lock(&aconnector->hpd_lock);
|
||||
drm_kms_helper_connector_hotplug_event(connector);
|
||||
mutex_unlock(&aconnector->hpd_lock);
|
||||
}
|
||||
|
||||
static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
|
||||
{
|
||||
struct hpd_rx_irq_offload_work *offload_work;
|
||||
|
@ -1283,6 +1301,9 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
|
|||
struct amdgpu_device *adev;
|
||||
enum dc_connection_type new_connection_type = dc_connection_none;
|
||||
unsigned long flags;
|
||||
union test_response test_response;
|
||||
|
||||
memset(&test_response, 0, sizeof(test_response));
|
||||
|
||||
offload_work = container_of(work, struct hpd_rx_irq_offload_work, work);
|
||||
aconnector = offload_work->offload_wq->aconnector;
|
||||
|
@ -1306,16 +1327,58 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
|
|||
if (amdgpu_in_reset(adev))
|
||||
goto skip;
|
||||
|
||||
if (offload_work->data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
|
||||
offload_work->data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
|
||||
dm_handle_mst_sideband_msg_ready_event(&aconnector->mst_mgr, DOWN_OR_UP_MSG_RDY_EVENT);
|
||||
spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
|
||||
offload_work->offload_wq->is_handling_mst_msg_rdy_event = false;
|
||||
spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
mutex_lock(&adev->dm.dc_lock);
|
||||
if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST)
|
||||
if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
|
||||
dc_link_dp_handle_automated_test(dc_link);
|
||||
else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
|
||||
|
||||
if (aconnector->timing_changed) {
|
||||
/* force connector disconnect and reconnect */
|
||||
force_connector_state(aconnector, DRM_FORCE_OFF);
|
||||
drm_msleep(100);
|
||||
force_connector_state(aconnector, DRM_FORCE_UNSPECIFIED);
|
||||
}
|
||||
|
||||
test_response.bits.ACK = 1;
|
||||
|
||||
core_link_write_dpcd(
|
||||
dc_link,
|
||||
DP_TEST_RESPONSE,
|
||||
&test_response.raw,
|
||||
sizeof(test_response));
|
||||
} else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
|
||||
hpd_rx_irq_check_link_loss_status(dc_link, &offload_work->data) &&
|
||||
dc_link_dp_allow_hpd_rx_irq(dc_link)) {
|
||||
dc_link_dp_handle_link_loss(dc_link);
|
||||
/* offload_work->data is from handle_hpd_rx_irq->
|
||||
* schedule_hpd_rx_offload_work.this is defer handle
|
||||
* for hpd short pulse. upon here, link status may be
|
||||
* changed, need get latest link status from dpcd
|
||||
* registers. if link status is good, skip run link
|
||||
* training again.
|
||||
*/
|
||||
union hpd_irq_data irq_data;
|
||||
|
||||
memset(&irq_data, 0, sizeof(irq_data));
|
||||
|
||||
/* before dc_link_dp_handle_link_loss, allow new link lost handle
|
||||
* request be added to work queue if link lost at end of dc_link_
|
||||
* dp_handle_link_loss
|
||||
*/
|
||||
spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
|
||||
offload_work->offload_wq->is_handling_link_loss = false;
|
||||
spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags);
|
||||
|
||||
if ((read_hpd_rx_irq_data(dc_link, &irq_data) == DC_OK) &&
|
||||
hpd_rx_irq_check_link_loss_status(dc_link, &irq_data))
|
||||
dc_link_dp_handle_link_loss(dc_link);
|
||||
}
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
|
||||
|
@ -1484,7 +1547,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
rw_init(&adev->dm.audio_lock, "dmaud");
|
||||
mtx_init(&adev->dm.vblank_lock, IPL_TTY);
|
||||
|
||||
if(amdgpu_dm_irq_init(adev)) {
|
||||
if (amdgpu_dm_irq_init(adev)) {
|
||||
DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
|
||||
goto error;
|
||||
}
|
||||
|
@ -1619,9 +1682,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
if (amdgpu_dc_debug_mask & DC_DISABLE_STUTTER)
|
||||
adev->dm.dc->debug.disable_stutter = true;
|
||||
|
||||
if (amdgpu_dc_debug_mask & DC_DISABLE_DSC) {
|
||||
if (amdgpu_dc_debug_mask & DC_DISABLE_DSC)
|
||||
adev->dm.dc->debug.disable_dsc = true;
|
||||
}
|
||||
|
||||
if (amdgpu_dc_debug_mask & DC_DISABLE_CLOCK_GATING)
|
||||
adev->dm.dc->debug.disable_clock_gate = true;
|
||||
|
@ -1842,8 +1904,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
|
|||
mutex_destroy(&adev->dm.audio_lock);
|
||||
mutex_destroy(&adev->dm.dc_lock);
|
||||
mutex_destroy(&adev->dm.dpia_aux_lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int load_dmcu_fw(struct amdgpu_device *adev)
|
||||
|
@ -1852,7 +1912,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
|
|||
int r;
|
||||
const struct dmcu_firmware_header_v1_0 *hdr;
|
||||
|
||||
switch(adev->asic_type) {
|
||||
switch (adev->asic_type) {
|
||||
#if defined(CONFIG_DRM_AMD_DC_SI)
|
||||
case CHIP_TAHITI:
|
||||
case CHIP_PITCAIRN:
|
||||
|
@ -2538,7 +2598,7 @@ struct amdgpu_dm_connector *
|
|||
amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
uint32_t i;
|
||||
u32 i;
|
||||
struct drm_connector_state *new_con_state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_crtc *crtc_from_state;
|
||||
|
@ -2644,7 +2704,7 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
|
|||
struct dc_scaling_info scaling_infos[MAX_SURFACES];
|
||||
struct dc_flip_addrs flip_addrs[MAX_SURFACES];
|
||||
struct dc_stream_update stream_update;
|
||||
} * bundle;
|
||||
} *bundle;
|
||||
int k, m;
|
||||
|
||||
bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
|
||||
|
@ -2674,8 +2734,6 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
|
|||
|
||||
cleanup:
|
||||
kfree(bundle);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int dm_resume(void *handle)
|
||||
|
@ -2889,8 +2947,7 @@ static const struct amd_ip_funcs amdgpu_dm_funcs = {
|
|||
.set_powergating_state = dm_set_powergating_state,
|
||||
};
|
||||
|
||||
const struct amdgpu_ip_block_version dm_ip_block =
|
||||
{
|
||||
const struct amdgpu_ip_block_version dm_ip_block = {
|
||||
.type = AMD_IP_BLOCK_TYPE_DCE,
|
||||
.major = 1,
|
||||
.minor = 0,
|
||||
|
@ -2947,9 +3004,12 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
|
|||
caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
|
||||
caps->aux_support = false;
|
||||
|
||||
if (caps->ext_caps->bits.oled == 1 /*||
|
||||
caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
|
||||
caps->ext_caps->bits.hdr_aux_backlight_control == 1*/)
|
||||
if (caps->ext_caps->bits.oled == 1
|
||||
/*
|
||||
* ||
|
||||
* caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
|
||||
* caps->ext_caps->bits.hdr_aux_backlight_control == 1
|
||||
*/)
|
||||
caps->aux_support = true;
|
||||
|
||||
if (amdgpu_backlight == 0)
|
||||
|
@ -3078,6 +3138,10 @@ void amdgpu_dm_update_connector_after_detect(
|
|||
aconnector->edid);
|
||||
}
|
||||
|
||||
aconnector->timing_requested = kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL);
|
||||
if (!aconnector->timing_requested)
|
||||
dm_error("%s: failed to create aconnector->requested_timing\n", __func__);
|
||||
|
||||
drm_connector_update_edid_property(connector, aconnector->edid);
|
||||
amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
|
||||
update_connector_ext_caps(aconnector);
|
||||
|
@ -3089,6 +3153,8 @@ void amdgpu_dm_update_connector_after_detect(
|
|||
dc_sink_release(aconnector->dc_sink);
|
||||
aconnector->dc_sink = NULL;
|
||||
aconnector->edid = NULL;
|
||||
kfree(aconnector->timing_requested);
|
||||
aconnector->timing_requested = NULL;
|
||||
#ifdef CONFIG_DRM_AMD_DC_HDCP
|
||||
/* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */
|
||||
if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
|
||||
|
@ -3133,6 +3199,8 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
|
|||
if (aconnector->fake_enable)
|
||||
aconnector->fake_enable = false;
|
||||
|
||||
aconnector->timing_changed = false;
|
||||
|
||||
if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
|
||||
DRM_ERROR("KMS: Failed to detect connector\n");
|
||||
|
||||
|
@ -3172,84 +3240,6 @@ static void handle_hpd_irq(void *param)
|
|||
|
||||
}
|
||||
|
||||
static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
|
||||
{
|
||||
uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
|
||||
uint8_t dret;
|
||||
bool new_irq_handled = false;
|
||||
int dpcd_addr;
|
||||
int dpcd_bytes_to_read;
|
||||
|
||||
const int max_process_count = 30;
|
||||
int process_count = 0;
|
||||
|
||||
const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
|
||||
|
||||
if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
|
||||
dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
|
||||
/* DPCD 0x200 - 0x201 for downstream IRQ */
|
||||
dpcd_addr = DP_SINK_COUNT;
|
||||
} else {
|
||||
dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
|
||||
/* DPCD 0x2002 - 0x2005 for downstream IRQ */
|
||||
dpcd_addr = DP_SINK_COUNT_ESI;
|
||||
}
|
||||
|
||||
dret = drm_dp_dpcd_read(
|
||||
&aconnector->dm_dp_aux.aux,
|
||||
dpcd_addr,
|
||||
esi,
|
||||
dpcd_bytes_to_read);
|
||||
|
||||
while (dret == dpcd_bytes_to_read &&
|
||||
process_count < max_process_count) {
|
||||
uint8_t retry;
|
||||
dret = 0;
|
||||
|
||||
process_count++;
|
||||
|
||||
DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
|
||||
/* handle HPD short pulse irq */
|
||||
if (aconnector->mst_mgr.mst_state)
|
||||
drm_dp_mst_hpd_irq(
|
||||
&aconnector->mst_mgr,
|
||||
esi,
|
||||
&new_irq_handled);
|
||||
|
||||
if (new_irq_handled) {
|
||||
/* ACK at DPCD to notify down stream */
|
||||
const int ack_dpcd_bytes_to_write =
|
||||
dpcd_bytes_to_read - 1;
|
||||
|
||||
for (retry = 0; retry < 3; retry++) {
|
||||
uint8_t wret;
|
||||
|
||||
wret = drm_dp_dpcd_write(
|
||||
&aconnector->dm_dp_aux.aux,
|
||||
dpcd_addr + 1,
|
||||
&esi[1],
|
||||
ack_dpcd_bytes_to_write);
|
||||
if (wret == ack_dpcd_bytes_to_write)
|
||||
break;
|
||||
}
|
||||
|
||||
/* check if there is new irq to be handled */
|
||||
dret = drm_dp_dpcd_read(
|
||||
&aconnector->dm_dp_aux.aux,
|
||||
dpcd_addr,
|
||||
esi,
|
||||
dpcd_bytes_to_read);
|
||||
|
||||
new_irq_handled = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (process_count == max_process_count)
|
||||
DRM_DEBUG_DRIVER("Loop exceeded max iterations\n");
|
||||
}
|
||||
|
||||
static void schedule_hpd_rx_offload_work(struct hpd_rx_irq_offload_work_queue *offload_wq,
|
||||
union hpd_irq_data hpd_irq_data)
|
||||
{
|
||||
|
@ -3282,7 +3272,7 @@ static void handle_hpd_rx_irq(void *param)
|
|||
union hpd_irq_data hpd_irq_data;
|
||||
bool link_loss = false;
|
||||
bool has_left_work = false;
|
||||
int idx = aconnector->base.index;
|
||||
int idx = dc_link->link_index;
|
||||
struct hpd_rx_irq_offload_work_queue *offload_wq = &adev->dm.hpd_rx_offload_wq[idx];
|
||||
|
||||
memset(&hpd_irq_data, 0, sizeof(hpd_irq_data));
|
||||
|
@ -3311,7 +3301,23 @@ static void handle_hpd_rx_irq(void *param)
|
|||
if (dc_link_dp_allow_hpd_rx_irq(dc_link)) {
|
||||
if (hpd_irq_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
|
||||
hpd_irq_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
|
||||
dm_handle_mst_sideband_msg(aconnector);
|
||||
bool skip = false;
|
||||
|
||||
/*
|
||||
* DOWN_REP_MSG_RDY is also handled by polling method
|
||||
* mgr->cbs->poll_hpd_irq()
|
||||
*/
|
||||
spin_lock(&offload_wq->offload_lock);
|
||||
skip = offload_wq->is_handling_mst_msg_rdy_event;
|
||||
|
||||
if (!skip)
|
||||
offload_wq->is_handling_mst_msg_rdy_event = true;
|
||||
|
||||
spin_unlock(&offload_wq->offload_lock);
|
||||
|
||||
if (!skip)
|
||||
schedule_hpd_rx_offload_work(offload_wq, hpd_irq_data);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -3404,7 +3410,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
|
|||
aconnector = to_amdgpu_dm_connector(connector);
|
||||
dc_link = aconnector->dc_link;
|
||||
|
||||
if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) {
|
||||
if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
|
||||
int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
|
||||
int_params.irq_source = dc_link->irq_source_hpd;
|
||||
|
||||
|
@ -3413,7 +3419,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
|
|||
(void *) aconnector);
|
||||
}
|
||||
|
||||
if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
|
||||
if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
|
||||
|
||||
/* Also register for DP short pulse (hpd_rx). */
|
||||
int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
|
||||
|
@ -3422,11 +3428,11 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
|
|||
amdgpu_dm_irq_register_interrupt(adev, &int_params,
|
||||
handle_hpd_rx_irq,
|
||||
(void *) aconnector);
|
||||
|
||||
if (adev->dm.hpd_rx_offload_wq)
|
||||
adev->dm.hpd_rx_offload_wq[connector->index].aconnector =
|
||||
aconnector;
|
||||
}
|
||||
|
||||
if (adev->dm.hpd_rx_offload_wq)
|
||||
adev->dm.hpd_rx_offload_wq[connector->index].aconnector =
|
||||
aconnector;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3439,7 +3445,7 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
|
|||
struct dc_interrupt_params int_params = {0};
|
||||
int r;
|
||||
int i;
|
||||
unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
|
||||
unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
|
||||
|
||||
int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
|
||||
int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
|
||||
|
@ -3453,11 +3459,12 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
|
|||
* Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
|
||||
* coming from DC hardware.
|
||||
* amdgpu_dm_irq_handler() will re-direct the interrupt to DC
|
||||
* for acknowledging and handling. */
|
||||
* for acknowledging and handling.
|
||||
*/
|
||||
|
||||
/* Use VBLANK interrupt */
|
||||
for (i = 0; i < adev->mode_info.num_crtc; i++) {
|
||||
r = amdgpu_irq_add_id(adev, client_id, i+1 , &adev->crtc_irq);
|
||||
r = amdgpu_irq_add_id(adev, client_id, i + 1, &adev->crtc_irq);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to add crtc irq id!\n");
|
||||
return r;
|
||||
|
@ -3465,7 +3472,7 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
|
|||
|
||||
int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
|
||||
int_params.irq_source =
|
||||
dc_interrupt_to_irq_source(dc, i+1 , 0);
|
||||
dc_interrupt_to_irq_source(dc, i + 1, 0);
|
||||
|
||||
c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1];
|
||||
|
||||
|
@ -3521,7 +3528,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
|
|||
struct dc_interrupt_params int_params = {0};
|
||||
int r;
|
||||
int i;
|
||||
unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
|
||||
unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
|
||||
|
||||
if (adev->family >= AMDGPU_FAMILY_AI)
|
||||
client_id = SOC15_IH_CLIENTID_DCE;
|
||||
|
@ -3538,7 +3545,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
|
|||
* Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
|
||||
* coming from DC hardware.
|
||||
* amdgpu_dm_irq_handler() will re-direct the interrupt to DC
|
||||
* for acknowledging and handling. */
|
||||
* for acknowledging and handling.
|
||||
*/
|
||||
|
||||
/* Use VBLANK interrupt */
|
||||
for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) {
|
||||
|
@ -3987,7 +3995,7 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
|
|||
}
|
||||
|
||||
static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
|
||||
unsigned *min, unsigned *max)
|
||||
unsigned int *min, unsigned int *max)
|
||||
{
|
||||
if (!caps)
|
||||
return 0;
|
||||
|
@ -4007,7 +4015,7 @@ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
|
|||
static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps,
|
||||
uint32_t brightness)
|
||||
{
|
||||
unsigned min, max;
|
||||
unsigned int min, max;
|
||||
|
||||
if (!get_brightness_range(caps, &min, &max))
|
||||
return brightness;
|
||||
|
@ -4020,7 +4028,7 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *c
|
|||
static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
|
||||
uint32_t brightness)
|
||||
{
|
||||
unsigned min, max;
|
||||
unsigned int min, max;
|
||||
|
||||
if (!get_brightness_range(caps, &min, &max))
|
||||
return brightness;
|
||||
|
@ -4238,12 +4246,12 @@ static void amdgpu_set_panel_orientation(struct drm_connector *connector);
|
|||
static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
int32_t i;
|
||||
s32 i;
|
||||
struct amdgpu_dm_connector *aconnector = NULL;
|
||||
struct amdgpu_encoder *aencoder = NULL;
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
uint32_t link_cnt;
|
||||
int32_t primary_planes;
|
||||
u32 link_cnt;
|
||||
s32 primary_planes;
|
||||
enum dc_connection_type new_connection_type = dc_connection_none;
|
||||
const struct dc_plane_cap *plane;
|
||||
bool psr_feature_enabled = false;
|
||||
|
@ -4501,7 +4509,6 @@ fail:
|
|||
static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
|
||||
{
|
||||
drm_atomic_private_obj_fini(&dm->atomic_obj);
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -4770,7 +4777,7 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state,
|
|||
static int
|
||||
fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
|
||||
const struct drm_plane_state *plane_state,
|
||||
const uint64_t tiling_flags,
|
||||
const u64 tiling_flags,
|
||||
struct dc_plane_info *plane_info,
|
||||
struct dc_plane_address *address,
|
||||
bool tmz_surface,
|
||||
|
@ -4979,7 +4986,7 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
|
|||
uint32_t num_clips;
|
||||
bool bb_changed;
|
||||
bool fb_changed;
|
||||
uint32_t i = 0;
|
||||
u32 i = 0;
|
||||
|
||||
flip_addrs->dirty_rect_count = 0;
|
||||
|
||||
|
@ -5113,7 +5120,7 @@ static enum dc_color_depth
|
|||
convert_color_depth_from_display_info(const struct drm_connector *connector,
|
||||
bool is_y420, int requested_bpc)
|
||||
{
|
||||
uint8_t bpc;
|
||||
u8 bpc;
|
||||
|
||||
if (is_y420) {
|
||||
bpc = 8;
|
||||
|
@ -5227,6 +5234,7 @@ static bool adjust_colour_depth_from_display_info(
|
|||
{
|
||||
enum dc_color_depth depth = timing_out->display_color_depth;
|
||||
int normalized_clk;
|
||||
|
||||
do {
|
||||
normalized_clk = timing_out->pix_clk_100hz / 10;
|
||||
/* YCbCr 4:2:0 requires additional adjustment of 1/2 */
|
||||
|
@ -5442,6 +5450,7 @@ create_fake_sink(struct amdgpu_dm_connector *aconnector)
|
|||
{
|
||||
struct dc_sink_init_data sink_init_data = { 0 };
|
||||
struct dc_sink *sink = NULL;
|
||||
|
||||
sink_init_data.link = aconnector->dc_link;
|
||||
sink_init_data.sink_signal = aconnector->dc_link->connector_signal;
|
||||
|
||||
|
@ -5565,7 +5574,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
|
|||
return &aconnector->freesync_vid_base;
|
||||
|
||||
/* Find the preferred mode */
|
||||
list_for_each_entry (m, list_head, head) {
|
||||
list_for_each_entry(m, list_head, head) {
|
||||
if (m->type & DRM_MODE_TYPE_PREFERRED) {
|
||||
m_pref = m;
|
||||
break;
|
||||
|
@ -5589,7 +5598,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
|
|||
* For some monitors, preferred mode is not the mode with highest
|
||||
* supported refresh rate.
|
||||
*/
|
||||
list_for_each_entry (m, list_head, head) {
|
||||
list_for_each_entry(m, list_head, head) {
|
||||
current_refresh = drm_mode_vrefresh(m);
|
||||
|
||||
if (m->hdisplay == m_pref->hdisplay &&
|
||||
|
@ -5657,8 +5666,8 @@ static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector,
|
|||
uint32_t max_dsc_target_bpp_limit_override)
|
||||
{
|
||||
const struct dc_link_settings *verified_link_cap = NULL;
|
||||
uint32_t link_bw_in_kbps;
|
||||
uint32_t edp_min_bpp_x16, edp_max_bpp_x16;
|
||||
u32 link_bw_in_kbps;
|
||||
u32 edp_min_bpp_x16, edp_max_bpp_x16;
|
||||
struct dc *dc = sink->ctx->dc;
|
||||
struct dc_dsc_bw_range bw_range = {0};
|
||||
struct dc_dsc_config dsc_cfg = {0};
|
||||
|
@ -5715,17 +5724,15 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
|
|||
struct dsc_dec_dpcd_caps *dsc_caps)
|
||||
{
|
||||
struct drm_connector *drm_connector = &aconnector->base;
|
||||
uint32_t link_bandwidth_kbps;
|
||||
uint32_t max_dsc_target_bpp_limit_override = 0;
|
||||
u32 link_bandwidth_kbps;
|
||||
struct dc *dc = sink->ctx->dc;
|
||||
uint32_t max_supported_bw_in_kbps, timing_bw_in_kbps;
|
||||
uint32_t dsc_max_supported_bw_in_kbps;
|
||||
u32 max_supported_bw_in_kbps, timing_bw_in_kbps;
|
||||
u32 dsc_max_supported_bw_in_kbps;
|
||||
u32 max_dsc_target_bpp_limit_override =
|
||||
drm_connector->display_info.max_dsc_bpp;
|
||||
|
||||
link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
|
||||
dc_link_get_link_cap(aconnector->dc_link));
|
||||
if (stream->link && stream->link->local_sink)
|
||||
max_dsc_target_bpp_limit_override =
|
||||
stream->link->local_sink->edid_caps.panel_patch.max_dsc_target_bpp_limit;
|
||||
|
||||
/* Set DSC policy according to dsc_clock_en */
|
||||
dc_dsc_policy_set_enable_dsc_when_not_needed(
|
||||
|
@ -5862,7 +5869,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
|
|||
* This may not be an error, the use case is when we have no
|
||||
* usermode calls to reset and set mode upon hotplug. In this
|
||||
* case, we call set mode ourselves to restore the previous mode
|
||||
* and the modelist may not be filled in in time.
|
||||
* and the modelist may not be filled in time.
|
||||
*/
|
||||
DRM_DEBUG_DRIVER("No preferred mode found\n");
|
||||
} else {
|
||||
|
@ -5886,9 +5893,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
|
|||
drm_mode_set_crtcinfo(&mode, 0);
|
||||
|
||||
/*
|
||||
* If scaling is enabled and refresh rate didn't change
|
||||
* we copy the vic and polarities of the old timings
|
||||
*/
|
||||
* If scaling is enabled and refresh rate didn't change
|
||||
* we copy the vic and polarities of the old timings
|
||||
*/
|
||||
if (!scale || mode_refresh != preferred_refresh)
|
||||
fill_stream_properties_from_drm_display_mode(
|
||||
stream, &mode, &aconnector->base, con_state, NULL,
|
||||
|
@ -5898,6 +5905,14 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
|
|||
stream, &mode, &aconnector->base, con_state, old_stream,
|
||||
requested_bpc);
|
||||
|
||||
if (aconnector->timing_changed) {
|
||||
DC_LOG_DEBUG("%s: overriding timing for automated test, bpc %d, changing to %d\n",
|
||||
__func__,
|
||||
stream->timing.display_color_depth,
|
||||
aconnector->timing_requested->display_color_depth);
|
||||
stream->timing = *aconnector->timing_requested;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
/* SST DSC determination policy */
|
||||
update_dsc_caps(aconnector, sink, stream, &dsc_caps);
|
||||
|
@ -6542,6 +6557,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
|
|||
|
||||
if (!state->duplicated) {
|
||||
int max_bpc = conn_state->max_requested_bpc;
|
||||
|
||||
is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
|
||||
aconnector->force_yuv420_output;
|
||||
color_depth = convert_color_depth_from_display_info(connector,
|
||||
|
@ -6862,7 +6878,7 @@ static bool is_duplicate_mode(struct amdgpu_dm_connector *aconnector,
|
|||
{
|
||||
struct drm_display_mode *m;
|
||||
|
||||
list_for_each_entry (m, &aconnector->base.probed_modes, head) {
|
||||
list_for_each_entry(m, &aconnector->base.probed_modes, head) {
|
||||
if (drm_mode_equal(m, mode))
|
||||
return true;
|
||||
}
|
||||
|
@ -6875,7 +6891,7 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
|
|||
const struct drm_display_mode *m;
|
||||
struct drm_display_mode *new_mode;
|
||||
uint i;
|
||||
uint32_t new_modes_count = 0;
|
||||
u32 new_modes_count = 0;
|
||||
|
||||
/* Standard FPS values
|
||||
*
|
||||
|
@ -6889,7 +6905,7 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
|
|||
* 60 - Commonly used
|
||||
* 48,72,96,120 - Multiples of 24
|
||||
*/
|
||||
static const uint32_t common_rates[] = {
|
||||
static const u32 common_rates[] = {
|
||||
23976, 24000, 25000, 29970, 30000,
|
||||
48000, 50000, 60000, 72000, 96000, 120000
|
||||
};
|
||||
|
@ -6905,8 +6921,8 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
|
|||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(common_rates); i++) {
|
||||
uint64_t target_vtotal, target_vtotal_diff;
|
||||
uint64_t num, den;
|
||||
u64 target_vtotal, target_vtotal_diff;
|
||||
u64 num, den;
|
||||
|
||||
if (drm_mode_vrefresh(m) * 1000 < common_rates[i])
|
||||
continue;
|
||||
|
@ -6974,13 +6990,7 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
|
|||
drm_add_modes_noedid(connector, 640, 480);
|
||||
} else {
|
||||
amdgpu_dm_connector_ddc_get_modes(connector, edid);
|
||||
/* most eDP supports only timings from its edid,
|
||||
* usually only detailed timings are available
|
||||
* from eDP edid. timings which are not from edid
|
||||
* may damage eDP
|
||||
*/
|
||||
if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
|
||||
amdgpu_dm_connector_add_common_modes(encoder, connector);
|
||||
amdgpu_dm_connector_add_common_modes(encoder, connector);
|
||||
amdgpu_dm_connector_add_freesync_modes(connector, edid);
|
||||
}
|
||||
amdgpu_dm_fbc_init(connector);
|
||||
|
@ -7012,6 +7022,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
|
|||
aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */
|
||||
aconnector->audio_inst = -1;
|
||||
rw_init(&aconnector->hpd_lock, "dmhpd");
|
||||
rw_init(&aconnector->handle_mst_msg_ready, "dmmr");
|
||||
|
||||
/*
|
||||
* configure support HPD hot plug connector_>polled default value is 0
|
||||
|
@ -7156,7 +7167,7 @@ create_i2c(struct ddc_service *ddc_service,
|
|||
*/
|
||||
static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
|
||||
struct amdgpu_dm_connector *aconnector,
|
||||
uint32_t link_index,
|
||||
u32 link_index,
|
||||
struct amdgpu_encoder *aencoder)
|
||||
{
|
||||
int res = 0;
|
||||
|
@ -7167,7 +7178,6 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
|
|||
|
||||
link->priv = aconnector;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s()\n", __func__);
|
||||
|
||||
i2c = create_i2c(link->ddc, link->link_index, &res);
|
||||
if (!i2c) {
|
||||
|
@ -7647,8 +7657,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
struct drm_crtc *pcrtc,
|
||||
bool wait_for_vblank)
|
||||
{
|
||||
uint32_t i;
|
||||
uint64_t timestamp_ns;
|
||||
u32 i;
|
||||
u64 timestamp_ns;
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane_state *old_plane_state, *new_plane_state;
|
||||
struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc);
|
||||
|
@ -7659,7 +7669,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc));
|
||||
int planes_count = 0, vpos, hpos;
|
||||
unsigned long flags;
|
||||
uint32_t target_vblank, last_flip_vblank;
|
||||
u32 target_vblank, last_flip_vblank;
|
||||
bool vrr_active = amdgpu_dm_vrr_active(acrtc_state);
|
||||
bool cursor_update = false;
|
||||
bool pflip_present = false;
|
||||
|
@ -7761,7 +7771,15 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
* Only allow immediate flips for fast updates that don't
|
||||
* change memory domain, FB pitch, DCC state, rotation or
|
||||
* mirroring.
|
||||
*
|
||||
* dm_crtc_helper_atomic_check() only accepts async flips with
|
||||
* fast updates.
|
||||
*/
|
||||
if (crtc->state->async_flip &&
|
||||
acrtc_state->update_type != UPDATE_TYPE_FAST)
|
||||
drm_warn_once(state->dev,
|
||||
"[PLANE:%d:%s] async flip with non-fast update\n",
|
||||
plane->base.id, plane->name);
|
||||
bundle->flip_addrs[planes_count].flip_immediate =
|
||||
crtc->state->async_flip &&
|
||||
acrtc_state->update_type == UPDATE_TYPE_FAST &&
|
||||
|
@ -7804,8 +7822,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
* DRI3/Present extension with defined target_msc.
|
||||
*/
|
||||
last_flip_vblank = amdgpu_get_vblank_counter_kms(pcrtc);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* For variable refresh rate mode only:
|
||||
* Get vblank of last completed flip to avoid > 1 vrr
|
||||
* flips per video frame by use of throttling, but allow
|
||||
|
@ -8100,7 +8117,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
struct dm_atomic_state *dm_state;
|
||||
struct dc_state *dc_state = NULL, *dc_state_temp = NULL;
|
||||
uint32_t i, j;
|
||||
u32 i, j;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
unsigned long flags;
|
||||
|
@ -8132,8 +8149,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
dc_resource_state_copy_construct_current(dm->dc, dc_state);
|
||||
}
|
||||
|
||||
for_each_oldnew_crtc_in_state (state, crtc, old_crtc_state,
|
||||
new_crtc_state, i) {
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
|
||||
new_crtc_state, i) {
|
||||
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
|
||||
|
||||
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
|
||||
|
@ -8156,9 +8173,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
|
||||
|
||||
drm_dbg_state(state->dev,
|
||||
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
|
||||
"planes_changed:%d, mode_changed:%d,active_changed:%d,"
|
||||
"connectors_changed:%d\n",
|
||||
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
|
||||
acrtc->crtc_id,
|
||||
new_crtc_state->enable,
|
||||
new_crtc_state->active,
|
||||
|
@ -8643,8 +8658,8 @@ static int do_aquire_global_lock(struct drm_device *dev,
|
|||
&commit->flip_done, 10*HZ);
|
||||
|
||||
if (ret == 0)
|
||||
DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done "
|
||||
"timed out\n", crtc->base.id, crtc->name);
|
||||
DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done timed out\n",
|
||||
crtc->base.id, crtc->name);
|
||||
|
||||
drm_crtc_commit_put(commit);
|
||||
}
|
||||
|
@ -8729,8 +8744,9 @@ is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
|
|||
return false;
|
||||
}
|
||||
|
||||
static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state) {
|
||||
uint64_t num, den, res;
|
||||
static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state)
|
||||
{
|
||||
u64 num, den, res;
|
||||
struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
|
||||
|
||||
dm_new_crtc_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
|
||||
|
@ -8852,9 +8868,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
|
|||
goto skip_modeset;
|
||||
|
||||
drm_dbg_state(state->dev,
|
||||
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
|
||||
"planes_changed:%d, mode_changed:%d,active_changed:%d,"
|
||||
"connectors_changed:%d\n",
|
||||
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
|
||||
acrtc->crtc_id,
|
||||
new_crtc_state->enable,
|
||||
new_crtc_state->active,
|
||||
|
@ -8883,8 +8897,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
|
|||
old_crtc_state)) {
|
||||
new_crtc_state->mode_changed = false;
|
||||
DRM_DEBUG_DRIVER(
|
||||
"Mode change not required for front porch change, "
|
||||
"setting mode_changed to %d",
|
||||
"Mode change not required for front porch change, setting mode_changed to %d",
|
||||
new_crtc_state->mode_changed);
|
||||
|
||||
set_freesync_fixed_config(dm_new_crtc_state);
|
||||
|
@ -8896,9 +8909,8 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
|
|||
struct drm_display_mode *high_mode;
|
||||
|
||||
high_mode = get_highest_refresh_rate_mode(aconnector, false);
|
||||
if (!drm_mode_equal(&new_crtc_state->mode, high_mode)) {
|
||||
if (!drm_mode_equal(&new_crtc_state->mode, high_mode))
|
||||
set_freesync_fixed_config(dm_new_crtc_state);
|
||||
}
|
||||
}
|
||||
|
||||
ret = dm_atomic_get_state(state, &dm_state);
|
||||
|
@ -9066,6 +9078,7 @@ static bool should_reset_plane(struct drm_atomic_state *state,
|
|||
*/
|
||||
for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) {
|
||||
struct amdgpu_framebuffer *old_afb, *new_afb;
|
||||
|
||||
if (other->type == DRM_PLANE_TYPE_CURSOR)
|
||||
continue;
|
||||
|
||||
|
@ -9164,11 +9177,12 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
|
|||
}
|
||||
|
||||
/* Core DRM takes care of checking FB modifiers, so we only need to
|
||||
* check tiling flags when the FB doesn't have a modifier. */
|
||||
* check tiling flags when the FB doesn't have a modifier.
|
||||
*/
|
||||
if (!(fb->flags & DRM_MODE_FB_MODIFIERS)) {
|
||||
if (adev->family < AMDGPU_FAMILY_AI) {
|
||||
linear = AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_2D_TILED_THIN1 &&
|
||||
AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
|
||||
AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
|
||||
AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE) == 0;
|
||||
} else {
|
||||
linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0;
|
||||
|
@ -9381,12 +9395,12 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
|
|||
/* On DCE and DCN there is no dedicated hardware cursor plane. We get a
|
||||
* cursor per pipe but it's going to inherit the scaling and
|
||||
* positioning from the underlying pipe. Check the cursor plane's
|
||||
* blending properties match the underlying planes'. */
|
||||
* blending properties match the underlying planes'.
|
||||
*/
|
||||
|
||||
new_cursor_state = drm_atomic_get_new_plane_state(state, cursor);
|
||||
if (!new_cursor_state || !new_cursor_state->fb) {
|
||||
if (!new_cursor_state || !new_cursor_state->fb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_get_oriented_plane_size(new_cursor_state, &cursor_src_w, &cursor_src_h);
|
||||
cursor_scale_w = new_cursor_state->crtc_w * 1000 / cursor_src_w;
|
||||
|
@ -9432,6 +9446,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
|
|||
struct drm_connector_state *conn_state, *old_conn_state;
|
||||
struct amdgpu_dm_connector *aconnector = NULL;
|
||||
int i;
|
||||
|
||||
for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
|
||||
if (!conn_state->crtc)
|
||||
conn_state = old_conn_state;
|
||||
|
@ -9874,7 +9889,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|||
}
|
||||
|
||||
/* Store the overall update type for use later in atomic check. */
|
||||
for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) {
|
||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
struct dm_crtc_state *dm_new_crtc_state =
|
||||
to_dm_crtc_state(new_crtc_state);
|
||||
|
||||
|
@ -9896,7 +9911,7 @@ fail:
|
|||
else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS)
|
||||
DRM_DEBUG_DRIVER("Atomic check stopped due to signal.\n");
|
||||
else
|
||||
DRM_DEBUG_DRIVER("Atomic check failed with err: %d \n", ret);
|
||||
DRM_DEBUG_DRIVER("Atomic check failed with err: %d\n", ret);
|
||||
|
||||
trace_amdgpu_dm_atomic_check_finish(state, ret);
|
||||
|
||||
|
@ -9906,7 +9921,7 @@ fail:
|
|||
static bool is_dp_capable_without_timing_msa(struct dc *dc,
|
||||
struct amdgpu_dm_connector *amdgpu_dm_connector)
|
||||
{
|
||||
uint8_t dpcd_data;
|
||||
u8 dpcd_data;
|
||||
bool capable = false;
|
||||
|
||||
if (amdgpu_dm_connector->dc_link &&
|
||||
|
@ -9925,7 +9940,7 @@ static bool is_dp_capable_without_timing_msa(struct dc *dc,
|
|||
static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
|
||||
unsigned int offset,
|
||||
unsigned int total_length,
|
||||
uint8_t *data,
|
||||
u8 *data,
|
||||
unsigned int length,
|
||||
struct amdgpu_hdmi_vsdb_info *vsdb)
|
||||
{
|
||||
|
@ -9981,7 +9996,7 @@ static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
|
|||
}
|
||||
|
||||
static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
|
||||
uint8_t *edid_ext, int len,
|
||||
u8 *edid_ext, int len,
|
||||
struct amdgpu_hdmi_vsdb_info *vsdb_info)
|
||||
{
|
||||
int i;
|
||||
|
@ -10022,7 +10037,7 @@ static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
|
|||
}
|
||||
|
||||
static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm,
|
||||
uint8_t *edid_ext, int len,
|
||||
u8 *edid_ext, int len,
|
||||
struct amdgpu_hdmi_vsdb_info *vsdb_info)
|
||||
{
|
||||
int i;
|
||||
|
@ -10038,7 +10053,7 @@ static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm,
|
|||
}
|
||||
|
||||
static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
|
||||
uint8_t *edid_ext, int len,
|
||||
u8 *edid_ext, int len,
|
||||
struct amdgpu_hdmi_vsdb_info *vsdb_info)
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
|
||||
|
@ -10052,7 +10067,7 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
|
|||
static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
|
||||
struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
|
||||
{
|
||||
uint8_t *edid_ext = NULL;
|
||||
u8 *edid_ext = NULL;
|
||||
int i;
|
||||
bool valid_vsdb_found = false;
|
||||
|
||||
|
@ -10228,7 +10243,7 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev)
|
|||
}
|
||||
|
||||
void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
|
||||
uint32_t value, const char *func_name)
|
||||
u32 value, const char *func_name)
|
||||
{
|
||||
#ifdef DM_CHECK_ADDR_0
|
||||
if (address == 0) {
|
||||
|
@ -10243,7 +10258,7 @@ void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
|
|||
uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
|
||||
const char *func_name)
|
||||
{
|
||||
uint32_t value;
|
||||
u32 value;
|
||||
#ifdef DM_CHECK_ADDR_0
|
||||
if (address == 0) {
|
||||
DC_ERR("invalid register read; address = 0\n");
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_plane.h>
|
||||
#include "link_service_types.h"
|
||||
|
||||
/*
|
||||
* This file contains the definition for amdgpu_display_manager
|
||||
|
@ -192,6 +193,11 @@ struct hpd_rx_irq_offload_work_queue {
|
|||
* we're handling link loss
|
||||
*/
|
||||
bool is_handling_link_loss;
|
||||
/**
|
||||
* @is_handling_mst_msg_rdy_event: Used to prevent inserting mst message
|
||||
* ready event when we're already handling mst message ready event
|
||||
*/
|
||||
bool is_handling_mst_msg_rdy_event;
|
||||
/**
|
||||
* @aconnector: The aconnector that this work queue is attached to
|
||||
*/
|
||||
|
@ -613,6 +619,8 @@ struct amdgpu_dm_connector {
|
|||
struct drm_dp_mst_port *port;
|
||||
struct amdgpu_dm_connector *mst_port;
|
||||
struct drm_dp_aux *dsc_aux;
|
||||
struct rwlock handle_mst_msg_ready;
|
||||
|
||||
/* TODO see if we can merge with ddc_bus or make a dm_connector */
|
||||
struct amdgpu_i2c_adapter *i2c;
|
||||
|
||||
|
@ -650,6 +658,10 @@ struct amdgpu_dm_connector {
|
|||
|
||||
/* Record progress status of mst*/
|
||||
uint8_t mst_status;
|
||||
|
||||
/* Automated testing */
|
||||
bool timing_changed;
|
||||
struct dc_crtc_timing *timing_requested;
|
||||
};
|
||||
|
||||
static inline void amdgpu_dm_set_mst_status(uint8_t *status,
|
||||
|
|
|
@ -406,6 +406,18 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only allow async flips for fast updates that don't change the FB
|
||||
* pitch, the DCC state, rotation, etc.
|
||||
*/
|
||||
if (crtc_state->async_flip &&
|
||||
dm_crtc_state->update_type != UPDATE_TYPE_FAST) {
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"[CRTC:%d:%s] async flips are only supported for fast updates\n",
|
||||
crtc->base.id, crtc->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* In some use cases, like reset, no stream is attached */
|
||||
if (!dm_crtc_state->stream)
|
||||
return 0;
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
#include "amdgpu_dm.h"
|
||||
#include "amdgpu_dm_irq.h"
|
||||
#include "amdgpu_dm_mst_types.h"
|
||||
#include "dpcd_defs.h"
|
||||
#include "dc/inc/core_types.h"
|
||||
#include "dc_link_dp.h"
|
||||
|
||||
#include "dm_helpers.h"
|
||||
#include "ddc_service_types.h"
|
||||
|
@ -1056,6 +1059,128 @@ void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream)
|
|||
sizeof(new_downspread));
|
||||
}
|
||||
|
||||
bool dm_helpers_dp_handle_test_pattern_request(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_link *link,
|
||||
union link_test_pattern dpcd_test_pattern,
|
||||
union test_misc dpcd_test_params)
|
||||
{
|
||||
enum dp_test_pattern test_pattern;
|
||||
enum dp_test_pattern_color_space test_pattern_color_space =
|
||||
DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
|
||||
enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
|
||||
enum dc_pixel_encoding requestPixelEncoding = PIXEL_ENCODING_UNDEFINED;
|
||||
struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
|
||||
struct pipe_ctx *pipe_ctx = NULL;
|
||||
struct amdgpu_dm_connector *aconnector = link->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
if (pipes[i].stream == NULL)
|
||||
continue;
|
||||
|
||||
if (pipes[i].stream->link == link && !pipes[i].top_pipe &&
|
||||
!pipes[i].prev_odm_pipe) {
|
||||
pipe_ctx = &pipes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pipe_ctx == NULL)
|
||||
return false;
|
||||
|
||||
switch (dpcd_test_pattern.bits.PATTERN) {
|
||||
case LINK_TEST_PATTERN_COLOR_RAMP:
|
||||
test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
|
||||
break;
|
||||
case LINK_TEST_PATTERN_VERTICAL_BARS:
|
||||
test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
|
||||
break; /* black and white */
|
||||
case LINK_TEST_PATTERN_COLOR_SQUARES:
|
||||
test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
|
||||
TEST_DYN_RANGE_VESA ?
|
||||
DP_TEST_PATTERN_COLOR_SQUARES :
|
||||
DP_TEST_PATTERN_COLOR_SQUARES_CEA);
|
||||
break;
|
||||
default:
|
||||
test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dpcd_test_params.bits.CLR_FORMAT == 0)
|
||||
test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
|
||||
else
|
||||
test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
|
||||
DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
|
||||
DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
|
||||
|
||||
switch (dpcd_test_params.bits.BPC) {
|
||||
case 0: // 6 bits
|
||||
requestColorDepth = COLOR_DEPTH_666;
|
||||
break;
|
||||
case 1: // 8 bits
|
||||
requestColorDepth = COLOR_DEPTH_888;
|
||||
break;
|
||||
case 2: // 10 bits
|
||||
requestColorDepth = COLOR_DEPTH_101010;
|
||||
break;
|
||||
case 3: // 12 bits
|
||||
requestColorDepth = COLOR_DEPTH_121212;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dpcd_test_params.bits.CLR_FORMAT) {
|
||||
case 0:
|
||||
requestPixelEncoding = PIXEL_ENCODING_RGB;
|
||||
break;
|
||||
case 1:
|
||||
requestPixelEncoding = PIXEL_ENCODING_YCBCR422;
|
||||
break;
|
||||
case 2:
|
||||
requestPixelEncoding = PIXEL_ENCODING_YCBCR444;
|
||||
break;
|
||||
default:
|
||||
requestPixelEncoding = PIXEL_ENCODING_RGB;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((requestColorDepth != COLOR_DEPTH_UNDEFINED
|
||||
&& pipe_ctx->stream->timing.display_color_depth != requestColorDepth)
|
||||
|| (requestPixelEncoding != PIXEL_ENCODING_UNDEFINED
|
||||
&& pipe_ctx->stream->timing.pixel_encoding != requestPixelEncoding)) {
|
||||
DC_LOG_DEBUG("%s: original bpc %d pix encoding %d, changing to %d %d\n",
|
||||
__func__,
|
||||
pipe_ctx->stream->timing.display_color_depth,
|
||||
pipe_ctx->stream->timing.pixel_encoding,
|
||||
requestColorDepth,
|
||||
requestPixelEncoding);
|
||||
pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
|
||||
pipe_ctx->stream->timing.pixel_encoding = requestPixelEncoding;
|
||||
|
||||
dp_update_dsc_config(pipe_ctx);
|
||||
|
||||
aconnector->timing_changed = true;
|
||||
/* store current timing */
|
||||
if (aconnector->timing_requested)
|
||||
*aconnector->timing_requested = pipe_ctx->stream->timing;
|
||||
else
|
||||
DC_LOG_ERROR("%s: timing storage failed\n", __func__);
|
||||
|
||||
}
|
||||
|
||||
dc_link_dp_set_test_pattern(
|
||||
(struct dc_link *) link,
|
||||
test_pattern,
|
||||
test_pattern_color_space,
|
||||
NULL,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz)
|
||||
{
|
||||
// TODO
|
||||
|
|
|
@ -590,8 +590,118 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
|||
return connector;
|
||||
}
|
||||
|
||||
void dm_handle_mst_sideband_msg_ready_event(
|
||||
struct drm_dp_mst_topology_mgr *mgr,
|
||||
enum mst_msg_ready_type msg_rdy_type)
|
||||
{
|
||||
uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
|
||||
uint8_t dret;
|
||||
bool new_irq_handled = false;
|
||||
int dpcd_addr;
|
||||
uint8_t dpcd_bytes_to_read;
|
||||
const uint8_t max_process_count = 30;
|
||||
uint8_t process_count = 0;
|
||||
u8 retry;
|
||||
struct amdgpu_dm_connector *aconnector =
|
||||
container_of(mgr, struct amdgpu_dm_connector, mst_mgr);
|
||||
|
||||
|
||||
const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
|
||||
|
||||
if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
|
||||
dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
|
||||
/* DPCD 0x200 - 0x201 for downstream IRQ */
|
||||
dpcd_addr = DP_SINK_COUNT;
|
||||
} else {
|
||||
dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
|
||||
/* DPCD 0x2002 - 0x2005 for downstream IRQ */
|
||||
dpcd_addr = DP_SINK_COUNT_ESI;
|
||||
}
|
||||
|
||||
mutex_lock(&aconnector->handle_mst_msg_ready);
|
||||
|
||||
while (process_count < max_process_count) {
|
||||
u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
|
||||
|
||||
process_count++;
|
||||
|
||||
dret = drm_dp_dpcd_read(
|
||||
&aconnector->dm_dp_aux.aux,
|
||||
dpcd_addr,
|
||||
esi,
|
||||
dpcd_bytes_to_read);
|
||||
|
||||
if (dret != dpcd_bytes_to_read) {
|
||||
DRM_DEBUG_KMS("DPCD read and acked number is not as expected!");
|
||||
break;
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
|
||||
|
||||
switch (msg_rdy_type) {
|
||||
case DOWN_REP_MSG_RDY_EVENT:
|
||||
/* Only handle DOWN_REP_MSG_RDY case*/
|
||||
esi[1] &= DP_DOWN_REP_MSG_RDY;
|
||||
break;
|
||||
case UP_REQ_MSG_RDY_EVENT:
|
||||
/* Only handle UP_REQ_MSG_RDY case*/
|
||||
esi[1] &= DP_UP_REQ_MSG_RDY;
|
||||
break;
|
||||
default:
|
||||
/* Handle both cases*/
|
||||
esi[1] &= (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!esi[1])
|
||||
break;
|
||||
|
||||
/* handle MST irq */
|
||||
if (aconnector->mst_mgr.mst_state)
|
||||
drm_dp_mst_hpd_irq_handle_event(&aconnector->mst_mgr,
|
||||
esi,
|
||||
ack,
|
||||
&new_irq_handled);
|
||||
|
||||
if (new_irq_handled) {
|
||||
/* ACK at DPCD to notify down stream */
|
||||
for (retry = 0; retry < 3; retry++) {
|
||||
ssize_t wret;
|
||||
|
||||
wret = drm_dp_dpcd_writeb(&aconnector->dm_dp_aux.aux,
|
||||
dpcd_addr + 1,
|
||||
ack[1]);
|
||||
if (wret == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (retry == 3) {
|
||||
DRM_ERROR("Failed to ack MST event.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
drm_dp_mst_hpd_irq_send_new_request(&aconnector->mst_mgr);
|
||||
|
||||
new_irq_handled = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&aconnector->handle_mst_msg_ready);
|
||||
|
||||
if (process_count == max_process_count)
|
||||
DRM_DEBUG_DRIVER("Loop exceeded max iterations\n");
|
||||
}
|
||||
|
||||
static void dm_handle_mst_down_rep_msg_ready(struct drm_dp_mst_topology_mgr *mgr)
|
||||
{
|
||||
dm_handle_mst_sideband_msg_ready_event(mgr, DOWN_REP_MSG_RDY_EVENT);
|
||||
}
|
||||
|
||||
static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
|
||||
.add_connector = dm_dp_add_mst_connector,
|
||||
.poll_hpd_irq = dm_handle_mst_down_rep_msg_ready,
|
||||
};
|
||||
|
||||
void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
|
||||
|
@ -673,15 +783,18 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p
|
|||
int count,
|
||||
int k)
|
||||
{
|
||||
struct drm_connector *drm_connector;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
drm_connector = ¶ms[i].aconnector->base;
|
||||
|
||||
memset(¶ms[i].timing->dsc_cfg, 0, sizeof(params[i].timing->dsc_cfg));
|
||||
if (vars[i + k].dsc_enabled && dc_dsc_compute_config(
|
||||
params[i].sink->ctx->dc->res_pool->dscs[0],
|
||||
¶ms[i].sink->dsc_caps.dsc_dec_caps,
|
||||
params[i].sink->ctx->dc->debug.dsc_min_slice_height_override,
|
||||
params[i].sink->edid_caps.panel_patch.max_dsc_target_bpp_limit,
|
||||
drm_connector->display_info.max_dsc_bpp,
|
||||
0,
|
||||
params[i].timing,
|
||||
¶ms[i].timing->dsc_cfg)) {
|
||||
|
@ -723,12 +836,16 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
|
|||
struct dc_dsc_config dsc_config;
|
||||
u64 kbps;
|
||||
|
||||
struct drm_connector *drm_connector = ¶m.aconnector->base;
|
||||
uint32_t max_dsc_target_bpp_limit_override =
|
||||
drm_connector->display_info.max_dsc_bpp;
|
||||
|
||||
kbps = div_u64((u64)pbn * 994 * 8 * 54, 64);
|
||||
dc_dsc_compute_config(
|
||||
param.sink->ctx->dc->res_pool->dscs[0],
|
||||
¶m.sink->dsc_caps.dsc_dec_caps,
|
||||
param.sink->ctx->dc->debug.dsc_min_slice_height_override,
|
||||
param.sink->edid_caps.panel_patch.max_dsc_target_bpp_limit,
|
||||
max_dsc_target_bpp_limit_override,
|
||||
(int) kbps, param.timing, &dsc_config);
|
||||
|
||||
return dsc_config.bits_per_pixel;
|
||||
|
|
|
@ -49,6 +49,13 @@
|
|||
#define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B 1031
|
||||
#define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B 1000
|
||||
|
||||
enum mst_msg_ready_type {
|
||||
NONE_MSG_RDY_EVENT = 0,
|
||||
DOWN_REP_MSG_RDY_EVENT = 1,
|
||||
UP_REQ_MSG_RDY_EVENT = 2,
|
||||
DOWN_OR_UP_MSG_RDY_EVENT = 3
|
||||
};
|
||||
|
||||
struct amdgpu_display_manager;
|
||||
struct amdgpu_dm_connector;
|
||||
|
||||
|
@ -61,6 +68,10 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
|
|||
void
|
||||
dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev);
|
||||
|
||||
void dm_handle_mst_sideband_msg_ready_event(
|
||||
struct drm_dp_mst_topology_mgr *mgr,
|
||||
enum mst_msg_ready_type msg_rdy_type);
|
||||
|
||||
struct dsc_mst_fairness_vars {
|
||||
int pbn;
|
||||
bool dsc_enabled;
|
||||
|
|
|
@ -86,6 +86,11 @@ static int dcn31_get_active_display_cnt_wa(
|
|||
stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
|
||||
stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
|
||||
tmds_present = true;
|
||||
|
||||
/* Checking stream / link detection ensuring that PHY is active*/
|
||||
if (dc_is_dp_signal(stream->signal) && !stream->dpms_off)
|
||||
display_count++;
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->link_count; i++) {
|
||||
|
|
|
@ -3115,7 +3115,7 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
|
|||
return max_link_cap;
|
||||
}
|
||||
|
||||
static enum dc_status read_hpd_rx_irq_data(
|
||||
enum dc_status read_hpd_rx_irq_data(
|
||||
struct dc_link *link,
|
||||
union hpd_irq_data *irq_data)
|
||||
{
|
||||
|
@ -4264,124 +4264,6 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
|
|||
test_pattern_size);
|
||||
}
|
||||
|
||||
static void dp_test_send_link_test_pattern(struct dc_link *link)
|
||||
{
|
||||
union link_test_pattern dpcd_test_pattern;
|
||||
union test_misc dpcd_test_params;
|
||||
enum dp_test_pattern test_pattern;
|
||||
enum dp_test_pattern_color_space test_pattern_color_space =
|
||||
DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
|
||||
enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
|
||||
struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
|
||||
struct pipe_ctx *pipe_ctx = NULL;
|
||||
int i;
|
||||
|
||||
memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
|
||||
memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
if (pipes[i].stream == NULL)
|
||||
continue;
|
||||
|
||||
if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
|
||||
pipe_ctx = &pipes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pipe_ctx == NULL)
|
||||
return;
|
||||
|
||||
/* get link test pattern and pattern parameters */
|
||||
core_link_read_dpcd(
|
||||
link,
|
||||
DP_TEST_PATTERN,
|
||||
&dpcd_test_pattern.raw,
|
||||
sizeof(dpcd_test_pattern));
|
||||
core_link_read_dpcd(
|
||||
link,
|
||||
DP_TEST_MISC0,
|
||||
&dpcd_test_params.raw,
|
||||
sizeof(dpcd_test_params));
|
||||
|
||||
switch (dpcd_test_pattern.bits.PATTERN) {
|
||||
case LINK_TEST_PATTERN_COLOR_RAMP:
|
||||
test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
|
||||
break;
|
||||
case LINK_TEST_PATTERN_VERTICAL_BARS:
|
||||
test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
|
||||
break; /* black and white */
|
||||
case LINK_TEST_PATTERN_COLOR_SQUARES:
|
||||
test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
|
||||
TEST_DYN_RANGE_VESA ?
|
||||
DP_TEST_PATTERN_COLOR_SQUARES :
|
||||
DP_TEST_PATTERN_COLOR_SQUARES_CEA);
|
||||
break;
|
||||
default:
|
||||
test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dpcd_test_params.bits.CLR_FORMAT == 0)
|
||||
test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
|
||||
else
|
||||
test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
|
||||
DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
|
||||
DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
|
||||
|
||||
switch (dpcd_test_params.bits.BPC) {
|
||||
case 0: // 6 bits
|
||||
requestColorDepth = COLOR_DEPTH_666;
|
||||
break;
|
||||
case 1: // 8 bits
|
||||
requestColorDepth = COLOR_DEPTH_888;
|
||||
break;
|
||||
case 2: // 10 bits
|
||||
requestColorDepth = COLOR_DEPTH_101010;
|
||||
break;
|
||||
case 3: // 12 bits
|
||||
requestColorDepth = COLOR_DEPTH_121212;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dpcd_test_params.bits.CLR_FORMAT) {
|
||||
case 0:
|
||||
pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
|
||||
break;
|
||||
case 1:
|
||||
pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR422;
|
||||
break;
|
||||
case 2:
|
||||
pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR444;
|
||||
break;
|
||||
default:
|
||||
pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (requestColorDepth != COLOR_DEPTH_UNDEFINED
|
||||
&& pipe_ctx->stream->timing.display_color_depth != requestColorDepth) {
|
||||
DC_LOG_DEBUG("%s: original bpc %d, changing to %d\n",
|
||||
__func__,
|
||||
pipe_ctx->stream->timing.display_color_depth,
|
||||
requestColorDepth);
|
||||
pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
|
||||
}
|
||||
|
||||
dp_update_dsc_config(pipe_ctx);
|
||||
|
||||
dc_link_dp_set_test_pattern(
|
||||
link,
|
||||
test_pattern,
|
||||
test_pattern_color_space,
|
||||
NULL,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
|
||||
{
|
||||
union audio_test_mode dpcd_test_mode = {0};
|
||||
|
@ -4494,8 +4376,25 @@ void dc_link_dp_handle_automated_test(struct dc_link *link)
|
|||
test_response.bits.ACK = 0;
|
||||
}
|
||||
if (test_request.bits.LINK_TEST_PATTRN) {
|
||||
dp_test_send_link_test_pattern(link);
|
||||
test_response.bits.ACK = 1;
|
||||
union test_misc dpcd_test_params;
|
||||
union link_test_pattern dpcd_test_pattern;
|
||||
|
||||
memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
|
||||
memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
|
||||
|
||||
/* get link test pattern and pattern parameters */
|
||||
core_link_read_dpcd(
|
||||
link,
|
||||
DP_TEST_PATTERN,
|
||||
&dpcd_test_pattern.raw,
|
||||
sizeof(dpcd_test_pattern));
|
||||
core_link_read_dpcd(
|
||||
link,
|
||||
DP_TEST_MISC0,
|
||||
&dpcd_test_params.raw,
|
||||
sizeof(dpcd_test_params));
|
||||
test_response.bits.ACK = dm_helpers_dp_handle_test_pattern_request(link->ctx, link,
|
||||
dpcd_test_pattern, dpcd_test_params) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (test_request.bits.AUDIO_TEST_PATTERN) {
|
||||
|
|
|
@ -3293,7 +3293,8 @@ void dcn10_wait_for_mpcc_disconnect(
|
|||
if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
|
||||
struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
|
||||
|
||||
if (pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
|
||||
if (pipe_ctx->stream_res.tg &&
|
||||
pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
|
||||
res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
|
||||
pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
|
||||
hubp->funcs->set_blank(hubp, true);
|
||||
|
|
|
@ -65,7 +65,7 @@ static const struct dc_debug_options debug_defaults_drv = {
|
|||
.timing_trace = false,
|
||||
.clock_trace = true,
|
||||
.disable_pplib_clock_request = true,
|
||||
.pipe_split_policy = MPC_SPLIT_DYNAMIC,
|
||||
.pipe_split_policy = MPC_SPLIT_AVOID,
|
||||
.force_single_disp_pipe_split = false,
|
||||
.disable_dcc = DCC_ENABLE,
|
||||
.vsr_support = true,
|
||||
|
|
|
@ -156,6 +156,12 @@ enum dc_edid_status dm_helpers_read_local_edid(
|
|||
struct dc_link *link,
|
||||
struct dc_sink *sink);
|
||||
|
||||
bool dm_helpers_dp_handle_test_pattern_request(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_link *link,
|
||||
union link_test_pattern dpcd_test_pattern,
|
||||
union test_misc dpcd_test_params);
|
||||
|
||||
void dm_set_dcn_clocks(
|
||||
struct dc_context *ctx,
|
||||
struct dc_clocks *clks);
|
||||
|
|
|
@ -82,6 +82,10 @@ bool perform_link_training_with_retries(
|
|||
enum amd_signal_type signal,
|
||||
bool do_fallback);
|
||||
|
||||
enum dc_status read_hpd_rx_irq_data(
|
||||
struct dc_link *link,
|
||||
union hpd_irq_data *irq_data);
|
||||
|
||||
bool hpd_rx_irq_check_link_loss_status(
|
||||
struct dc_link *link,
|
||||
union hpd_irq_data *hpd_irq_dpcd_data);
|
||||
|
|
|
@ -1927,12 +1927,16 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu,
|
|||
*size = 4;
|
||||
break;
|
||||
case AMDGPU_PP_SENSOR_GFX_MCLK:
|
||||
ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
|
||||
ret = sienna_cichlid_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_UCLK,
|
||||
(uint32_t *)data);
|
||||
*(uint32_t *)data *= 100;
|
||||
*size = 4;
|
||||
break;
|
||||
case AMDGPU_PP_SENSOR_GFX_SCLK:
|
||||
ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
|
||||
ret = sienna_cichlid_get_smu_metrics_data(smu,
|
||||
METRICS_AVERAGE_GFXCLK,
|
||||
(uint32_t *)data);
|
||||
*(uint32_t *)data *= 100;
|
||||
*size = 4;
|
||||
break;
|
||||
|
|
|
@ -940,7 +940,7 @@ static int smu_v13_0_7_read_sensor(struct smu_context *smu,
|
|||
break;
|
||||
case AMDGPU_PP_SENSOR_GFX_MCLK:
|
||||
ret = smu_v13_0_7_get_smu_metrics_data(smu,
|
||||
METRICS_AVERAGE_UCLK,
|
||||
METRICS_CURR_UCLK,
|
||||
(uint32_t *)data);
|
||||
*(uint32_t *)data *= 100;
|
||||
*size = 4;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue